Consider the following scenario:
A notification is created with a pending intent (with some extras) to open some activity (let's say ActivityA) inside the app WHILE the app is running
The Activity in focus (ActivityFocus) at the time when the notification comes in overrides the onPause() method to open ANOTHER activity
#Override
public void onPause() {
startActivity(new Intent(this, ActivityB.class));
}
The user taps on the notification - now according to the onPause() documentation, the intent inside ActivityFocus will fire BEFORE the intent inside the PendingIntent
When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A's onPause() returns, so be sure to not do anything lengthy here.
- From Android Documentation
Finally, the app launches ActivityB and completely ignores the PendingIntent
How can I fix this (without removing the onPause()) so that either:
The PendingIntent will fire AFTER onPause() execution is finished
The intent inside onPause() is somehow overridden by the intent inside the PendingIntent
Hopefully my question makes sense. Thanks in advance.
Related
Suppose I have two activities A and B activity A which contains a button I want to start Activity B when I press Button without intent.
According the Oficial Documentation:
An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.
So you have to use it to open activities with no exceptions or workarounds, if you do that, you are ignoring the entire system architecture.
There is no way to start an activity from anotherone without an intent.
If the reason of not using Intent that you don't want the the user to re-enter the previous activity
You can use finish() to finish that activity intent after you done work with
if(currentUser == null){
startActivity(new Intent(MainActivity.this,StartActivity.class));
finish();
}
So user will be unable to back again
If you want to do some code while the activity is finishing
You can use onDestroy() override method, Sometimes it can also be called if the activity is being killed by the android itself so you can add
isFinishing() function
Inside onDestroy() method which checks whether the application is closing by the call finish() returning true or otherwise by anything else returning false then you can easily specify your code for each situation.
#Override
protected void onDestroy() {
super.onDestroy();
if(isFinishing()){
// Activity is being destroyed by the function `finish()`
// What to do...
}else{
// Activity is being destroyed anonymously without `finish()`
// What to do...
}
}
Put your activity inside a Fragment and start the fragment fromo the button.
These are the possible ways to start any Activity
1st
startActivity(new Intent(Activity_A.this, Activity_B.class));
2nd
Intent intent = new Intent(Activity_A.this, Activity_B.class);
startActivity(intent);
3rd
Intent intent = new Intent(Activity_A.this, Activity_B.class);
startActivityForResult(intent,code);
My app issues notifications. By clicking the notification, the app needs to be launched or brought to the front. Here is the intent for the notification:
Intent launch_intent = new Intent("android.intent.action.MAIN");
launch_intent.setComponent(new ComponentName("com.example.helloworld","com.example.helloworld.MainActivity"));
launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launch_intent.addCategory(Intent.CATEGORY_LAUNCHER);
launch_intent.putExtra("some_data", "value");
And in my app I want to determine if it's launched or brought to the front by the notification click, so I use putExtra there. Then in MainActivity's onResume I check the intent data. This works fine is the app is launched by the notification click.
However, if the app is brought to the front by the notification click, in MainActivity's onResume there is no intent data.
I think the reason is: MainActivity is the root activity, and it's the splash screen. There could be any number of activities on top of it when the app is brought to the front. And when it's brought to the front, I want to keep its state.
What is the right way of doing this?
Override onNewIntent() in your activity and check the value there. If you want future calls to getIntent() to return this new intent, you can call setIntent() and pass the new intent.
Try in onNewIntent() method
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String value = intent.getStringExtra("some_data");
}
I have an activity that shows some information based on the intent that initiates the activity. The app icon starts this activity without any extra information and the activity displays correctly. The app widget also starts this activity, but with some extra information and is handled correctly. In this scenario, the app does not work as expected:
The user enters the activity using home screen shortcut.
The user uses the home key to send the app to the background.
The user uses the widget shortcut to enter the app
in this scenario, in onResume() the intent is the old one not the one from widget.
How can I solve this problem?
This is exactly why onNewIntent() exists: it is called:
when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
An activity will always be paused before receiving a new intent, so you can count on onResume() being called after this method.
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.
Therefore add code such as:
#Override
protected void onNewIntent (Intent intent) {
setIntent(intent);
}
And/or move your code from onResume() into a method such as handleIntent() and call it from both your onCreate() and from onNewIntent().
I have a singleTop activity, this activity is launched via Intent:
Intent intent = new Intent(GCMIntentService.this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
onNewIntent is called.
My problem is that then I hit home button, and then launch application again (from background) onNewIntent is called again with the same intent, and I can not find a way to discard this Intent.
I tried to putExtra flag to this intent, but it is not persisted between application state changes.
Is it possible to stop calling onNewIntent() when application comes to foreground?
In your manifest add the line below to your MainActivity
android:finishOnTaskLaunch="true"
I would like to put a notification with an intent.
My intent is basically action = DEFAULT and category = LAUNCHER in order to bring the activity that was launched into the front.
When the app is not shown, there is no problem, the intent works perfectly and launches the last activity seen but when there is already an activity launched, onNewIntent is not called (activity is in singleTop mode).
I'm wondering how to relaunch the app from an intent to the last activity seen and call onNewIntent when the activity is already launched.
the problem is that your activity is defined as
android:launchMode="singleTop"
when there is already an activity
launched, onNewIntent is not called
implement the onDestroy method::
#Override
public void onDestroy(){
super.onDestroy();
}