Using ActivityLifecycleCallbacks to reference current Activity - android

I would like to be able to receive a reference to the currently running activity from an arbitrary class (Utils, etc) without explicitly passing a reference.
I have considered something like this and would like some feedback about possible issues / alternatives.
public class MyApp extends Application implements ActivityLifeCycleCallbacks {
private Activity currentActivity;
public void onActivityResumed(Activity activity){
this.currentActivity = activity;
}
public void onActivityPaused(Activity activity){
if(this.currentActivity == activity)
this.currentActivity = null;
}
public Activity getCurrentActivity(){
return this.currentActivity;
}
}
Theoretically this should only hold a reference to the last resumed activity and allow other activities to be properly collected

Related

Communication between activity and separate class

I have an Activity:
public class MyActivity extends Activity {
#Override
protected void onDestroy() {
// TODO: send event to other class
}
}
and a separate class:
public class MyClass{
MyClass(Context context){
// I have the context of activity
}
// This needs to be called by MyActivity in all other instantiates
void onActivityDestroy(){
}
}
MyClass is instantiated in other places and I want onActivityDestroy to be called in those instantiates. The place where MyClass is instantiated is not accessible.
I am looking for a solution that uses interfaces, listener, messages... but not static fields.
You can maintain the list of MyClass instances at application level then access that list in OnDestroy method of activity. And execute onActivityDestroy() version of each instance.
You should maintain list of instances in your Application class, whenever MyClass instance is created, you push that instance to the list maintained at Application Class
// this is to push the MyClass instance.
Context.getApplication().getMyClassInstanceList().add(new MyClass());
public class MyActivity extends Activity {
#Override
protected void onDestroy() {
List<Myclass> myClassObjects = Context.getApplication.getMyClassInstaceList();
for(Myclass myclass : myClassObjects)
{
myclass.onActivityDestroy();
}
}
}

get activity().finish() not killing activity

I have a launcher Activity A which calls to an Activity B. B has multiple fragments. Now what I want is to be able to kill B from one of those fragments. I used getActivity().finish() but it would just kill the fragment.
How do I kill the activity/exit app from a fragment?
There is a way discussed in docs: http://developer.android.com/training/basics/fragments/communicating.html
Make Fragment define an interface which the Activity implements. Then make call to the Activity and then let the Activity to finish(or something else).
public class MyActivity extends Activity
implements MyFragment.MyListener {
public void onMyCancel() {
finish();
}
}
public class MyFragment extends Fragment {
private MyListener callback;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback= (MyListener) activity;
}
public interface MyListener {
public void onMyCancel();
}
public void btnCancel(View v) {
callback.onMyCancel();
}
}
you can only call finish() in your activity B , this would close your current activity.
if you want to close your app you can simply use:
System.exit(0);
this will kill whole application process.

finish() not finishing the activity: Android

I have an Activity in whose onCreate() method i call a Utility function.
This utility functions requires a callback class instance as a parameter, in which it returns the info that i need. this is:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utility.functionA(new functionACallBack() {
/**
*
*/
private static final long serialVersionUID = -7896922737679366614L;
#Override
public void onResponse(String error) {
((MyActivity) AppClass.getAppContext()).finish();
}
});
}
Once I have obtained that info, I want to close the activity. so i called finish() from inside the anonymous class that i created for the callback.
But the activity is not getting finished. I thought maybe i need to call finish() from UI thread so i did runOnUiThread(), in inside it also i tried calling finish(). But it just doesn't work.
Could someone please help me with this issue?
UPDATE:
I am storing APP context and then trying to use that but to no avail.
public class AppClass extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
AppClass.mContext = getApplicationContext();
}
public static Context getAppContext(){
return AppClass.mContext;
}
}
Simply call something like this:
#Override
public void onResponse(String error) {
((Activity) context).finish();
}
As this is a static function, you'll have to be able to access your Context in a static way. You can save that as a Class variable, but you'll have to be aware about its handling as it might lead to memory leaks.
To avoid them, you can declare a class that extends Application and save here your context, so this way you won't ever have a memory leak.
Try using this code:
((Activity) ActivityClass.this).finish();
Remember, use the Activity class, not the Application one.

Registering for an activity's events

Is there a way to register for an activity's events? I'm specifically interested in the onStart / onStop events, and I don't want to add special operations in the activity for that.
One way to get events from the lifecycle of other activities is to register your class as an Application.ActivityLifecycleCallbacks with the main Application instance and filter events for the Activity you're interested in.
This is a short example (you may want to register the callbacks from another method/class other than MainActivity.onCreate or you'll miss that message ;) and you may have a dependency there that you don't want)
On the activity you want to spy:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Register a spy for this activity
getApplication().registerActivityLifecycleCallbacks(new ActivitySpy(this));
}
}
Then the Spy code looks something like:
public class ActivitySpy implements ActivityLifecycleCallbacks {
private final Activity mActivity;
public ActivitySpy(Activity activity) {
mActivity = activity;
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (mActivity == activity)
Log.i("SPY", "Activity Created");
}
#Override
public void onActivityDestroyed(Activity activity) {
if (mActivity == activity)
Log.i("SPY", "Activity Destroyed");
}
// (...) Other overrides
}
You can also register the spy from another place if you have a reference to the Activity you want to follow.
I hope this helps :)
EDIT: I forgot to mention, this will only work on API Level 14 and above...

Finishing an activity from a standard java class

I am currently working on an android project and I have an activity, lets call it MyActivity and this activity calls a standard Java class called MyClass.
I need MyClass to finish the MyActivity activity but I can't find out how to do this. I thought I might be able to pass the context to the standard java class and call context.finish() but this doesn't appear to be available.
How can I do this, thanks for any help you can offer.
You can pass the Context, but you will need to cast it to an Activity (or simply pass the Activity itself), although this in general seems like a bad practice.
The most secure solution uses listener and a Handler. It is complex, but ensures a non direct call to finish activity.
Your listener:
interface OnWantToCloseListener{
public void onWantToClose();
}
Class that should close activity.
class MyClass {
private OnWantToCloseListener listener;
public void setWantToCloseListener(OnWantToCloseListener listener){
this.listener = listener;
}
private void fireOnWantToClose(){
if(this.listener != null)
listener.onWantToClose();
}
}
When you want to close your activity you must call fireOnWantToClose() method.
public MyActivity extends Activity{
public void onCreate(){
final int CLOSE = 1; //number to identify what happens
MyClass my_class = new MyClass();
final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == CLOSE)
MyActivity.this.finish();
}
});
my_class.setOnWantToCloseListener(new OnWantToCloseListener(){
public void onWantToClose(){
handler.sendEmptyMessage(CLOSE);
}
});
}
}
This is secure because Activity is not finished directly by MyClass object, it is finished through a listener that orders a handler to finish activity. Even if you run MyClass object on a second thread this code will works nice.
EDIT: CLOSE var added I forget to declare and initialize this.
Pass the MyActivity to MyClass as an Activity. From there you can call myActivity.finish();
For example:
private Activity myActivity;
public MyClass(Activity myActivity){
this.myActivity = myActivity;
}
public void stopMyActivity(){
myActivity.finish();
}
And in MyActivity:
MyClass myClass = new MyClass(this);
This is risky, because you're holding a reference to an Activity, which can cause memory leaks.
If your java class is a nested inner class, you can use:
public class MyActivity extends Activity {
public static class JavaClass {
public void finishActivity() {
MyActivity.finish();
}
}
}
Otherwise you'll have to pass the java class a Context (i.e. pass it a reference to this, since Activity extends Context) and store it as a private instance variable.

Categories

Resources