Resume previous activity from broadcast receiver - java

here's my problem:
I'm in activity A
Activity A starts a new activity B to call a number (Intent.ACTION_CALL)
How is it possible to resume activity A - I don't want to finish activity B, I simply want to bring activity A to the front
At the moment I have a broadcastReceiver which is able to start a new instance of activity A when the call takes place. If I start activity A from there with "FLAG_ACTIVITY_SINGLE_TOP", I get the error
Calling startActivity() from outside of an Activity
context requires the FLAG_ACTIVITY_NEW_TASK flag.
Is this really what you want?
But I don't want a new task, I want to RESUME activity A
Thanks a lot!
EDIT:
Perhaps I could simply simulate a click on the BACK-button?

Considering your use case - BroadcastReceiver that doesn't have a tasks in which to start the activity - singleTask in the manifest should do what you want.
"singleTask"
The system creates a new task and instantiates the activity at the root of
the new task. However, if an instance of the activity already exists in a
separate task, the system routes the intent to the existing instance through
a call to its onNewIntent() method, rather than creating a new instance.
Only one instance of the activity can exist at a time.
Note: Although the activity starts in a new task, the Back
button still returns the user to the previous activity.
Taken from: http://developer.android.com/guide/components/tasks-and-back-stack.html

Have you tried using FLAG_ACTIVITY_REORDER_TO_FRONT ?
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_REORDER_TO_FRONT
It seems to do exactly what you need.

Related

How to modify content of an activity from an IntentService that have been started from another activity?

Here is my situation:
I want to make an Activity A which start an IntentService, and write the ResultReciever on Activity B. In another words, I have an Activity A that have some works to do but the results should be written in Activity B, any solution to do this? Note that I don't know when the work of the service finishes.

How to find out from an activity that another activity got terminated

I have 2 activities
Activity A has a registered receiver that updates a static generic list.
Activity B accesses the static generic list in Activity A.
The problem is:
If Activity A ended (killed by the system), the registered receiver stops, which makes the data in the static generic list unreliable, as it depends on the registered receiver to be updated.
And the biggest problem that the static generic list doesn't get terminated (null / zeroed) along with the registered receiver, though both of them created by the same activity.
So there's no way for me to know that my static generic list has become unreliable to reload it all over with fresh data when Activity B gets created.
Also there's no way - listener - to listen to the registered receiver termination, where I'd have terminated the generic static list, and check it in Activity B creation, if it's null, I'll reload a fresh data.
And as you know it's not guaranteed that onDestroy will get called when the system terminates the activity, otherwise I'd have terminated the generic static list.
I even added a static Boolean var (mAlive) to Activity A that has a default value (false) and becomes (true) in onCreate, in hope that when Activity A gets destroyed, (mAlive) will become false (the default value in its declaration), which I could check in Activity B to know that the registered receiver is terminated and the data is unreliable and reload it again, but it turns out, that even destroying Activity A, doesn't reset static Boolean var (mAlive) to its default value (false).
So, any suggestions please, I got a brain freeze trying to find a solution in the past 2 weeks.
Thank you
You seem to be greatly misunderstanding the Activity Lifecycle.
Only one Activity at a time can be running. The current one is suspended when a new one starts and you cannot access directly anything contained in one Activity from a different Activity. Static variables can hold simple data but that is not recommended as a way to avoid dealing with the Activity Lifecycle.
To pass data between activities, you use Intents and Extras.
How do I pass data between Activities in Android application?
If you want two Activities to share the same data, you could use a Service that contains the data which can be accessed from both Activities.
You can fire a Broadcast(BroadcastReceiver Example) from your desired activity's onDestroy() method. Afterwards Receive broadcast in your required activity.
You can put your data into a separate object so you don't dipend on your activity A's lifecycle. You can see an example here at Finder section
I think you could make a parent activity extended by both your Activity A and B. In your parent activity you could register your receiver into its onResume method and then unregister it into its onPause method. By this way you should have always your receiver registered to the current activity.
Then if you have read the previous link, if you make a Finder responsible to keep your fresh data and you reference it into your parent Activity (so you have a reference into both Activity A and Acitivity B) you should be sufficiently sure that a variable referenced by the current active activity can't be destroyed by the system.
I'm not sure to have understood what you need, let me know

Activity B notify a Activity A after calling finish()

I start Activity B from Activity A. Activity B does something to my Data and at some point I call finish();, however Activity B is still doing something with my Database in the background and when its finished I want to get notified in Activity A, that this process is finished.
Because there is no way to my knowledge to call a method from another activity I tried to solve this problem with startActivityForResult but because Im calling finish(); before actually setting a Result this does not seem to work either.
Any Idea on how to solve this problem?
Don't do task in Activity that may live beyond Activity lifecycle. In that case do your task in Service and notify the Result to Activity. There are some ways to communicate between Activity and Service using BroadcastReceiver , Messenger, Handler, Bound Service . You can also use EventBus library for this communication.
Check this and this thread for communicating between Activity and Service
Try to close your database, and after it's been closed successfully, 'notify' your activity A about this result and finish activity. Quite an imprecise question, frankly :P
And if you want to invoke some method from another class, pass the activity's Context.

Activities and Intents

To regularly remind the user that something has to be done, I use a timer to periodically refresh a Notification with a new message. This process must only stop when the user clicks on the Notification, which causes the corresponding Activity to be launched with an Intent containing a flag specifying that the Activity is started by a Notification. In the onResume function of my main Activity, I retrieve this flag and check it. If it is set, I do what is necessary to stop the periodic reminder.
I obtain this behaviour if my application is not active when the user clicks on the Notification, but if the Activity is already launched, the periodic reminder continues again and again. I specify that my Activity is launched in singleInstance mode.
How can I do to receive and treat the Intent sent by the Notification in my already active Activity?
Thanks in advance for the time you will spend trying to help me.
When you are using singleInstance mode.You would need to override onNewIntent(Intent) to receive new Intents for the Activity and do your work there
Also, you may want to call setIntent(intent) in onNewIntent to make sure future calls to getIntent() within the Activity lifecycle get the most recent Intent data.

Android "single top" launch mode and onNewIntent method

I read in the Android documentation that by setting my Activity's launchMode property to singleTop OR by adding the FLAG_ACTIVITY_SINGLE_TOP flag to my Intent, that calling startActivity(intent) would reuse a single Activity instance and give me the Intent in the onNewIntent callback. I did both of these things, and onNewIntent never fires and onCreate fires every time. The docs also say that this.getIntent() returns the intent that was first passed to the Activity when it was first created. In onCreate I'm calling getIntent and I'm getting a new one every time (I'm creating the intent object in another activity and adding an extra to it...this extra should be the same every time if it was returning me the same intent object). All this leads me to believe that my activity is not acting like a "single top", and I don't understand why.
To add some background in case I'm simply missing a required step, here's my Activity declaration in the manifest and the code I'm using to launch the activity. The Activity itself doesn't do anything worth mentioning in regards to this:
in AndroidManifest.xml:
<activity
android:name=".ArtistActivity"
android:label="Artist"
android:launchMode="singleTop">
</activity>
in my calling Activity:
Intent i = new Intent();
i.putExtra(EXTRA_KEY_ARTIST, id);
i.setClass(this, ArtistActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
Did you check if onDestroy() was called as well? That's probably why onCreate() gets invoked every time instead of onNewIntent(), which would only be called if the activity is already existing.
For example if you leave your activity via the BACK-button it gets destroyed by default. But if you go up higher on the activity stack into other activities and from there call your ArtistActivity.class again it will skip onCreate() and go directly to onNewIntent(), because the activity has already been created and since you defined it as singleTop Android won't create a new instance of it, but take the one that is already lying around.
What I do to see what's going on I implement dummy functions for all the different states of each activity so I always now what's going on:
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
Same for onRestart(), onStart(), onResume(), onPause(), onDestroy()
If the above (BACK-button) wasn't your problem, implementing these dummies will at least help you debugging it a bit better.
The accepted answer is not quite correct. If onDestroy() was called previously, then yes, onCreate() would always be called. However, this statement is wrong:
"If you go up higher on the activity stack into other activities and from there call your ArtistActivity.class again it will skip onCreate() and go directly to onNewIntent()"
The "singleTop" section of http://developer.android.com/guide/components/tasks-and-back-stack.html explains plainly how it works (attention to bold text below; I've also proven this through my own debugging):
"For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default "standard"launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance of D receives the intent through onNewIntent(), because it's at the top of the stackā€”the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is "singleTop"."
In other words, starting an activity through SINGLE_TOP will only reuse the existing activity if it is already at the top of the stack. It won't work if another activity in that same task is at the top (for example, the activity that is executing startActivity(SINGLE_TOP)); a new instance will be created instead.
Here are two ways to fix this so that you get the SINGLE_TOP behavior that you want -- the general purpose of which is to reuse an existing activity, instead of creating a new one...
First way (as described in the comment section of the accepted
answer): You could add a launchMode of "singleTask" to your Activity. This would force onNewIntent() because singleTask means there can only be ONE instance of a particular activity in a given task. This is a somewhat hacky solution though because if your app needs multiple instances of that activity in a particular situation (like I do for my project), you're screwed.
Second way (better):
Instead of FLAG_ACTIVITY_SINGLE_TOP, use FLAG_ACTIVITY_REORDER_TO_FRONT. This will reuse the existing activity instance by moving it to the top of the stack (onNewIntent() will be called as expected).
The main purpose of FLAG_ACTIVITY_SINGLE_TOP is to prevent the creation of multiple instances of an Activity. For instance, when that activity can be launched via an intent that comes from outside of your application's main task. For internal switching between activities in my app, I've found that FLAG_ACTIVITY_REORDER_TO_FRONT is generally what I want instead.
Set this flag to your intent:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)

Categories

Resources