I have an app with several activities and the action to perform on destruction is actually the same, no matter what the Activity is at that moment (deleting some data and performing a HTTP call).
Is there a way to have all activities share the onDestroy method?
Another solution would be to factorize a method in some other static class and have each Activity invoke it during destruction, but a trait-like behaviour would be actually nicer.
Create an abstract BaseActivity, override the onDestroy, and all your other activities should just extend the BaseActivity?
Why go with singletons, statics, factories etc if what you are describing is a classic OOP trait? :)
From you description, I understood that you want a common onDestroy() method which will be call by all the activities when calling onDestroy().
Here is the code:
package com.demo.application;
import android.app.Activity;
import android.app.Application;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
public class AppGlobal extends Application {
#Override
public void onCreate() {
super.onCreate();
// register to be informed of activities starting up
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// new activity created; force its orientation to portrait
activity.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
} //End of onCreate
}
You need to add a property within application tag of your manifest.xml file:
android:name="com.demo.application.AppGlobal"
Try and let me know your experience.
Use singleton class and create static method in which do what u want to do and in onDestroy call this method.
Easiest way for this is creating an Application class and registering for the life cycle callbacks.
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
//Perform common action here
}
});
}
}
Add the Application class in the manifest.
<application
android:allowBackup="true"
android:name=".MyApp"
android:icon="#mipmap/ic_launcher"
Related
I have a video player app where I need to access the lifecycle of an abstract activity from another class in Android. In my abstract activity, I've tried using LifecycleRegistry, but this is getting me the lifecycle owner not the actually lifecycle of the abstract class. How can I access the lifecycle of an abstract activity from another class?
Here is my abstract activity:
abstract public class MainActivity extends AppCompatActivity {
private LifecycleRegistry lifecycleRegistry;
VideoPlayer videoPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
setContentView(R.layout.activity_main);
videoPlayer = new VideoPlayer();
playVideo();
}
public void playVideo(){
videoPlayer.init();
//calls function in VideoPlayer class
}
#Override
protected void onResume() {
super.onResume();
lifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED);
}
#Override
protected void onDestroy() {
super.onDestroy();
lifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
}
}
Here is the class where I need to get the lifecycle of my abstract MainActivity:
public class VideoPlayer {
public void init() {
playVideo();
}
public void playVideo() {
//async call happens here, I need getLifeCycle() from MainActivity
}
}
Don't know a know about the context of you feature, but you You can do smth
public class VideoPlayer {
private Lifecycle mLifecycle;
public VideoPlayer(Lifecycle lifecycle) {
mLifecycle = lifecycle;
}
public void init() {
playVideo();
}
public void playVideo() {
//you have mLifecycle now
}
}
In Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
videoPlayer = new VideoPlayer(getLifecycle());
}
Do we need to override onBackPressed() method for every screen? I do not see any other ways to do so. Please let me know if there is a more simpler way to do so.
make a super class for all of your activities e.g.
class BaseActivity extends AppCompatActivity {
#Override
void onBackPressed() { }
}
and then make all of your activities inherit from this class
class MyActivity1 extends BaseActivity { ... }
class MyActivity2 extends BaseActivity { ... }
class MyActivity3 extends BaseActivity { ... }
And all of your activities now wouldn't react to any back press event!
Create a BaseActivity and override onBackPressed() method with required logic
And extend BaseActivity in all Activity
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onBackPressed() {
//super.onBackPressed()
}
}
extend this BaseActivity instead of AppCompatActivity
class MainActivity : BaseActivity() {
//Your code
}
If you want to handle back button manually for some Activity then just override it for those Activity.
If you are using FragmentActivity or AppCompatActivity you can do this with OnBackPressedDispatcher that controls dispatching system back presses.
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(#NonNull Activity activity,
#Nullable Bundle savedInstanceState) {
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getOnBackPressedDispatcher()
.addCallback(new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
// nothing to do
}
});
}
}
#Override
public void onActivityStarted(#NonNull Activity activity) {
}
#Override
public void onActivityResumed(#NonNull Activity activity) {
}
#Override
public void onActivityPaused(#NonNull Activity activity) {
}
#Override
public void onActivityStopped(#NonNull Activity activity) {
}
#Override
public void onActivitySaveInstanceState(#NonNull Activity activity,
#NonNull Bundle outState) {
}
#Override
public void onActivityDestroyed(#NonNull Activity activity) {
}
});
}
}
AndroidManifest.xml:
<application
android:name=".App"
...
/>
I want to play music in the background of my application:
public class BackgroundSoundService extends Service {
MediaPlayer mediaPlayer;
#Override
public void onCreate() {
super.onCreate();
mediaPlayer = MediaPlayer.create(this, R.raw.airport_lounge);
mediaPlayer.setLooping(true);
mediaPlayer.setVolume(100,100);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
mediaPlayer.release();
}
#Override
public void onLowMemory() {
super.onLowMemory();
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Then in my MainActivity :
public static Intent musicIntent;
//Start music service
musicIntent = new Intent(this, BackgroundSoundService.class);
startService(musicIntent);
#Override
protected void onPause() {
super.onPause();
stopService(musicIntent);
}
#Override
protected void onResume() {
super.onResume();
startService(musicIntent);
}
I stop it in my onPause the service because if the user switches the Application and doesn't close it the music would continue to play. The problem is that when we change Activity the onPaused is also called but I want the music to continue playing through the entire application.
So in my another Activity :
//start music
startService(MainActivity.musicIntent);
But the music restarts and it's not very good to hear. Any solutions?
You can use ActivityLifecycleCallbacks in your application class.
public class MusicApplication extends Application implements ActivityLifecycleCallbacks {
int activitiesOnTop = 0;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityResumed(Activity activity) {
// one of application activities is visible
activitiesOnTop ++;
}
#Override
public void onActivityStopped(Activity activity) {
activitiesOnTop --;
if(activitiesOnTop == 0){
// none of activities are on foreground
}
}
}
There are other solutions mentioned in the How to check if activity is in foreground or in visible background?.
It depends on the application structure, for example, if you build some tab or navigationDrawer based navigation, you will likely build some fragments and your MainActivity will be your only activity, so it's onPause method will only be called if user closes your application. But this scenario won't hold as your application grows (unless it's quite simple).
So another approach is to launch your service in your application instance, in case you use it.
I want to call method of Other activity. I searched alot and tried by myself but failed. It work when i call from class to class like classA m=new classA();
m.function();
But i want to call from another activity method. Please help
public void onNotificationPosted(StatusBarNotification sbn) {
ChatActivity ch=new ChatActivity();
ch.location();
}
public class ApplicationContext extends Application {
public ActivityMain activityMain;
public void setActivityMain(ActivityMain activityMain) {
this.activityMain = activityMain;
}
public ActivityMain getActivityMain() {
return activityMain;
}
In ActivityMain.class
public class ActivityMain extends BaseProject implements MainView {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationContext.getInstance().setActivityMain(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
ApplicationContext.getInstance().setActivityMain(null);
}
Use it anywhere like Activity, Fragments, Broadcast Receiver or Service like
if (ApplicationContext.getInstance().getActivityMain()!=null){
ApplicationContext.getInstance().getActivityMain().callAnyMethod();
}
Enjoy :)
I'm new to android and I'm trying to get a hang of creating and using Fragments.
I have a fragment that shows a simple list of multiple dates to choose from and implements an onClickListener. The idea is once a user chooses a date, the fragments sends the date back to the MainActivity which then runs a query in database and sends the database response to another fragment.
I'm stuck on the point of sending the date back to MainActivity, elegantly. I can't find much info. I found this:
Activity activity = getActivity();
if(activity instanceof MyActivity){
MyActivity myactivity = (MyActivity) activity;
myactivity.myMethod();
}
I'm very new to this but this seems hacky to me. Is this the right way or is there another way?
Any input is appreciated
I prefer the interface based approach because is very clean. You can declare a nested interface in your Fragment or an external one:
interface OnMyStuffListener {
void myMethod();
}
Make the Activity to implement that interface:
public class MainActivity extends Activity implements OnMyStuffListener {
#Override
public void myMethod() {
// Do whatever you want.
}
}
The Fragment will be attached to the Activity so you can check the instance of the Context and cast it to the Activity:
public class MyFragment extends Fragment implements View.OnClickListener {
private OnMyStuffListener mListener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMyStuffListener) {
mListener = (OnMyStuffListener) context;
} else {
throw new IllegalArgumentException("The context " + context.getClass().getName() +
"must implement " + OnMyStuffListener.class.getName());
}
}
#Override
public void onDetach() {
super.onDetach();
// Release it avoiding memory leak.
mListener = null;
}
#Override
public void onClick(View v) {
mListener.myMethod();
}
}
YES this is absolutely right. You can use this, if you are not sure that your Fragment is attached to Activity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~