Android notification intent creates new instance instead of opening existing instance - java

If I click my notification while the app is minimized it opens the app and the UI is reset. I would like the notification to open the existing instance. I've been trying to make it use the existing instance.
This is my notification code:
mBuilder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Title")
.setContentText("Tuned in to " + radiostation);
Intent resultIntent = new Intent(getApplicationContext(), RadioChooser.class);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addParentStack(RadioChooser.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
getApplicationContext(), 0,
resultIntent, 0
);
mBuilder.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder.setOngoing(true);
mNotificationManager.notify(1, mBuilder.build());
AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".RadioChooser"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:configChanges="orientation|keyboardHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true" android:name=".MusicPlayer" />
</application>

Well, nomatter how you try to do this, the Activity will most likely be restarted if it has been minimized(sometimes it is not though). You need to prepare for it to ALWAYS be restarted. The way to go about this is, in our onSaveInstanceState() method, store all of the UI related variables. Then, either in onCreate or onRestoreInstanceState(), re-initialize those variables and build your UI back up from their value. So, if you use fragments to display different pages of your app, when the main activity is stopped and onSaveInstance() is called, store the name or number or some identifier of which fragment it was in the Bundle object that onSaveInstance() passes. When the activity is recreated, your code should take those variables from the bundle passed in onCreate(), and use them to display the correct fragment, with the correct information.

Related

Intent is not working for moving fragment to activity

I'm having trouble moving intent class fragment to activity. I'm trying to send intent from one Fragment to another Activity.
Here is the code:
Intent intent = new Intent(getActivity(), MainActivity.class);
getActivity().startActivity(intent);
Here is my Manifest File
<activity android:name=".activities.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustNothing"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
but it's not working for me and on another side, I have done some RND but all are same for me.
How can I Solve the issue
Thanks In Advance.
remove this android:launchMode="singleTask"
which looks like this
<activity android:name=".activities.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:windowSoftInputMode="adjustNothing"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
if your current activity is mainactivity and you are launching it again , it will not work because launchmode is set to single task in manifest
Solution :- remove this tag
android:launchMode="singleTask"

No Activity found to handle Intent with action and data

I have written two different Android applications.
I wish for one application to create an intent and in turn, start an activity in the other application.
The first application which creates the intent has the following code:
Intent intent = new Intent();
intent.setAction("com.example.printtest.ACTION_PRINT");
Uri.Builder builder = new Uri.Builder();
builder.scheme("PrintAPI")
.authority("StartPrintJob")
.appendQueryParameter("appId", "aaa");
Uri uri = builder.build();
intent.setData(uri);
startActivity(intent);
The second application which I want to receive the intent has the following defined in it's manifest:
<activity android:name=".PrintActivity">
<intent-filter>
<action android:name="com.example.printtest.ACTION_PRINT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
From what I understand, the activity in the second application should be recognized as the one to start this intent. However, the same exception is thrown each time. The exception being thrown is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapp, PID: 21665
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.example.printtest.ACTION_PRINT dat=PrintAPI://StartPrintJob?appId=aaa }
Is there something that I'm missing?
Is it valid to start an activity in another application just by setting action and data on an intent?
Any help or advice is greatly appreciated.
You forgot to add data part
<activity android:name=".PrintActivity"
android:exported="true">
<intent-filter>
<action android:name="com.example.printtest.ACTION_PRINT"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="PrintAPI"></data>
</intent-filter>
</activity>

Android: start an activity with an Intent or an intent-filter

I always start activities with Intents, but in the book which I'm reading an activity is started with an action parameter:
Not in this classical way
Intent intent = new Intent(this,ActivityResult.class);
But in this way:
String PICK_BUS_ACTION = "com.example.utente.decompilare" + ".action.PICK_BUS_ACTION";
Intent intent = new Intent(PICK_BUS_ACTION);
And in the manifest there is an intent-filter:
<activity android:name=".ActivityResult">
<intent-filter>
<action android:name="com.example.utente.decompilare.action.PICK_BUS_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
I tried both the ways but I didn't find differences. What is better? What is the difference?
The second one is used for starting of another apps.

Prevent Android system from resuming task if the new Intent is the same with initial Intent that launches the app

This question is related to deep link. For example, I have four activities in my app, namely MainActivity, FirstActivity, SecondActivity, and DeepLinkActivity. Here are the activities in the manifest file.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".FirstActivity" />
<activity android:name=".SecondActivity" />
<activity android:name=".DeepLinkActivity"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="launch" />
</intent-filter>
</activity>
DeepLinkActivity will launch whether FirstActivity, SecondActivity, or MainActivity depending on the URI received:
public class DeepLinkActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
launchIntent(getIntent());
}
private void launchIntent(Intent intent) {
Intent newIntent = null;
switch (intent.getData().getHost()) {
case "first":
newIntent = new Intent(this, FirstActivity.class);
break;
case "second":
newIntent = new Intent(this, SecondActivity.class);
break;
default:
newIntent = new Intent(this, MainActivity.class);
break;
}
startActivity(newIntent);
finish();
}
}
The problem is, Android system seems to record the initial Intent that launched the app, then uses it to resume whatever Activity is currently running in the foreground -if- the new Intent is the same with initial Intent.
Consider the following case:
User click launch://first deep link → FirstActivity is opened.
User minimize the app then click launch://second → SecondActivity is opened on top of FirstActivity.
User minimize the app again then click launch://first.
After step 3, what I expect is the OS open FirstActivity. But actually it resumes the task, so SecondActivity (from step 2) reappears. This happens because the deep link on step 1 and 3 is the same, hence the OS regards them as the same Intent.
How can I prevent the Android system from resuming task in this particular case?
After some trials this is what I did to get it working.
Setting the Flags for the newIntent before starting it:
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
However, setting the flags alone didn't do the job, the app is still resumed to the last activity. Then I add the launchMode to DeepLinkActivity:
<activity android:name=".DeepLinkActivity"
android:theme="#android:style/Theme.NoDisplay"
android:launchMode="singleTask">
Now the the app is restarted and open the expected activity! Note that the launchMode can be singleInstance as well.
You can try defining something on the Activities OnPause function, to reset the intent every time the activity is paused.

Go back to the First/Main activity without reloading it

I am developing an android app. I need to call my MainActivity without reloading it as it has huge amount of data fetch from internet.
Suppose, I am on third activity now and I want to go back to MainActivity.
If I use:
Intent i = new Intent(Third.this,Main.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
it will load MainActivity but I don't want to reload it. like from Second Activity I call finish() and it does exactly want i need.
This is how to do it:
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
metntion it in your AndroidManifest.xml file
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation">
do nothing inside the method onResume() and onstart() when coming back to this activity
and try intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); instead of addFlags() method
In Third activity when you want to go to first activity, put finish() mwthod there.
In Second activity, after onCreate() method, put
#Override
public void onResume(){
super.onResume();
finish();
}
I think this code will work for you, jus try it.
Try adding this to your manifest:
android:configChanges="keyboard|keyboardHidden|orientation">
add this line to the activity in your manifest like this:
<activity android:name=".Main"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Categories