开发者

resuming an activity from a notification

I have a notification in the status bar for my app:

    Notification notification = new Notification(R.drawable.icon, null, System.currentTimeMill开发者_开发百科is());

    Intent notificationIntent = new Intent(this.parent, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this.parent, 0, notificationIntent, 0);

    ...

    notification.flags = Notification.FLAG_ONGOING_EVENT;        
    mNotificationManager.notify(NOTIFICATION_ID, notification);

The problem with this is that when you press the home button from the app (pushing it to the background) then press on the notification in the list accessed from the status bar, it starts a fresh copy of the activity. All I want to do is resume the app (like when you longpress the home button and press on the app's icon). Is there a way of creating an Intent to do this?


I've solved this issue by changing the launchMode of my activity to singleTask in the androidManifest.xml file.

The default value for this property is standard, which allows any number of instances to run.

"singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task. [...]

The "singleTask" and "singleInstance" modes also differ from each other in only one respect: A "singleTask" activity allows other activities to be part of its task. It's always at the root of its task, but other activities (necessarily "standard" and "singleTop" activities) can be launched into that task. A "singleInstance" activity, on the other hand, permits no other activities to be part of its task. It's the only activity in the task. If it starts another activity, that activity is assigned to a different task — as if FLAG_ACTIVITY_NEW_TASK was in the intent.

you can find a detailed explanation in the Android Developers' Guide

I hope this helps


I was having a similar problem and the proper way to handle this is to use the flags: Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_SINGLE_TOP like so

notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

From the documentation this will:

FLAG_ACTIVITY_CLEAR_TOP

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

FLAG_ACTIVITY_SINGLE_TOP

If set, the activity will not be launched if it is already running at the top of the history stack.


I had inconsistent behaviour between devices with some intents loosing extras and the MainActivity´s OnNewIntent and onCreate methods both being called.

What did not work:

Manifest:

    <activity android:name=".MainActivity"
        android:launchMode="singleTask">

Service:

    Intent notificationIntent = new Intent(this.getBaseContext(), MainActivity.class);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    notificationIntent.putExtra("TEST", 1);

What did work:

Manifest:

    <activity android:name=".MainActivity"
        android:launchMode="singleTask">

Service:

    PackageManager pm = getPackageManager();
    Intent launchIntent = m.getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);
    launchIntent.putExtra("TEST", 2);


I have just found a solution this issue: I created getPreviousIntent method and gave it to PendingIntent that`s all:

private Intent getPreviousIntent(Intent newIntent) {
    final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    final List<ActivityManager.RecentTaskInfo> recentTaskInfos = am.getRecentTasks(1024,0);
    String myPkgNm = getPackageName();

    if (!recentTaskInfos.isEmpty()) {
        ActivityManager.RecentTaskInfo recentTaskInfo;
        for (int i = 0; i < recentTaskInfos.size(); i++) {
            recentTaskInfo = recentTaskInfos.get(i);
            if (recentTaskInfo.baseIntent.getComponent().getPackageName().equals(myPkgNm)) {
                newIntent = recentTaskInfo.baseIntent;
                newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
        }
    }
    return newIntent;
}


Add this line to the corresponding activity in manifest file of your app.

android:launchMode="singleTask"

eg:

<activity
    android:name=".Main_Activity"
    android:label="@string/title_main_activity"
    android:theme="@style/AppTheme.NoActionBar"
    android:launchMode="singleTask" />


You can simulate a launch intent (as if the user clicked on your app icon to launch it):

val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)

val contentIntent = PendingIntent.getActivity(context, 0, launchIntent, 0)

This way, you do not have to mark your app as "singleTask" or "singleInstance" in Manifest (which would create other issues). Thus this should be the proper solution.

Note, however, the above solution may not work directly for you, due to an alleged android bug. Discussions about the android bug and a workaround can be found in this question.


I use:

notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.setAction(Intent.ACTION_MAIN);

Not sure these are the values you need to set, but the answer is in those methods/flags.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜