从通知中恢复应用程序和堆栈

时间:2011-03-31 15:35:41

标签: android

我想通过状态栏通知恢复我的应用,方式与用户在启动器中点按其图标的方式完全相同。

那就是:我希望堆栈处于与用户离开之前相同的状态。

在通知上设置待处理意图时的问题是它始终以特定活动为目标。我不想要这个。我需要像启动器那样恢复应用程序。

因此,如果用户处于活动A中,我想恢复活动A.如果他已经从活动A启动了活动B,那么我希望在用户点击通知时显示B,并且要恢复堆栈当用户点击B中的后退按钮时,A恢复。

还有其他几个问题与类似的标题,但没有一个解决我的问题。

8 个答案:

答案 0 :(得分:143)

使用Android启动应用时使用的相同意图过滤器:

final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

由于您在通知栏中创建的用于打开Intent的{​​{1}}与用于启动应用的Android相同,因此将显示之前打开的Activity而非创建新的。

答案 1 :(得分:24)

对于您不希望/无法对启动器活动进行硬编码的情况,此解决方案可以正常运行

Intent i = getPackageManager()
    .getLaunchIntentForPackage(getPackageName())
    .setPackage(null)
    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);

return new NotificationCompat.Builder(context)
        ...
        .setContentIntent(pendingIntent)
        .build();

setPackage(null)部分是关键在我的情况下,因为没有它,应用程序没有恢复到以前的任务。我将我的意图与Android启动器的意图进行了比较,并注意到pkg没有设置在那里,所以我想出了如何从意图中删除包名。

我的特殊情况是通知是在库中创建的,所以我无法知道启动器活动是什么。

答案 2 :(得分:4)

创建活动,然后设置类别和相应的标志...... 这就是这对我有用的方式,我必须这样做,因为我这样做是为了支持 Api lvl 8

intent.addCategory(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClass(this, YourActivity.class);

intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT|
                Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 
                   PendingIntent.FLAG_UPDATE_CURRENT);

并在AndroidManifest中

android:launchMode="singleTask"

所以诀窍是Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT以及清单中设置的行。

希望对其他人有所帮助。

答案 3 :(得分:3)

我也有同样的问题并尝试解决问题,如@ GrAnd的答案:

final Intent notificationIntent = new Intent(context,YourActivity.class);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

这是有效的,毫无疑问,但问题是当你将你的意图设置为ACTION_MAIN时。然后,您将无法设置任何捆绑到意图。我的意思是,不会从目标活动接收原始数据,因为ACTION_MAIN不能包含任何额外数据。

除此之外,您可以将您的活动设置为singleTask并正常调用您的意图而不设置ACTION_MAIN并从目标活动的onNewIntent()方法接收意图。

但要注意,如果你打电话,super.onNewIntent(意图);然后将创建活动的第二个实例。

答案 4 :(得分:0)

这很简单 打开您的清单文件,并在您的活动属性中设置属性启动模式 singleTop

答案 5 :(得分:0)

最佳解决方案:Notification to restore a task rather than a specific activity?

public class YourRootActivity extends Activity 
    {
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
    
            if (!isTaskRoot()) // checks if this root activity is at root, if not, we presented it from notification and we are resuming the app from previous open state
            {
                 val extras = intent.extras // do stuffs with extras.
                 finish();
                 return;
            }
             // OtherWise start the app as usual
        }
    }

答案 6 :(得分:-1)

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />

private void bringApplicationToForeground(){
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

      List<ActivityManager.AppTask> tasksList = am.getAppTasks();
      for (ActivityManager.AppTask task : tasksList){
        task.moveToFront();
      }
    }else{

      List<ActivityManager.RunningTaskInfo> tasksList = am.getRunningTasks(Integer.MAX_VALUE);
      if(!tasksList.isEmpty()){
        int nSize = tasksList.size();
        for(int i = 0; i < nSize;  i++){
          if(tasksList.get(i).topActivity.getPackageName().equals(getPackageName())){
            am.moveTaskToFront(tasksList.get(i).id, 0);
          }
        }
      }
    }
}

答案 7 :(得分:-4)

可能有一种更简单的方法,但您可以将数据存储在sqlite数据库中,每当您重新启动应用程序时,无论您保存到数据库的状态如何,都可以检索并将值设置为它们所需的值。