恢复任务而不是特定活动的通知



我有一个前台服务,只要用户登录到应用程序,它就会保持与服务器的连接打开。这样,即使用户按Home键将应用程序发送到后台,连接也可以保持活动状态,并可以直接从服务器接收消息。

该应用程序有许多Activities,当它被发送到后台时,其中任何一个都可能是活动的。

我希望允许用户单击通知以恢复当前"活动"。我知道如何恢复特定的活动,但想知道是否有办法恢复用户上一次参加的"活动"?当然,我可以跟踪最后一个,然后从Notification回调调用它,但我认为在任务级别可能有一种方法?

谢谢你的建议。

您需要的只是一个什么都不做的简单活动。这里有一个例子:

public class NotificationActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Now finish, which will drop the user in to the activity that was at the top
        //  of the task stack
        finish();
    }
}

设置通知以启动此活动。确保在清单中,此活动的任务相关性与应用程序中其他活动的任务亲和力相同(默认情况下,如果您没有显式设置android:taskAffinity,则为(。

当用户选择此通知时,如果您的应用程序正在运行,则NotificationActivity将在应用程序任务中最顶部活动的顶部启动,并且该任务将显示在前台。NotificationActivity完成后,它将简单地将用户返回到应用程序中最顶层的活动(即:用户进入后台时将其留在的任何位置(。

如果您的应用程序尚未运行,这将不起作用。然而,你有两个选择来处理:

  1. 确保应用程序未运行时通知栏中不存在通知。

  2. 在NotificationActivity的onCreate((方法中,检查应用程序是否正在运行,如果它没有运行,请调用startActivity((并启动应用程序。如果执行此操作,请确保设置标志Intent。启动应用程序时FLAG_ACTIVITY_NEW_TASK,以便任务的根活动不是NotificationActivity。

工作得很好,谢谢David!下面的类检查应用程序是否已经在运行,如果没有,则在完成之前启动它(如选项2中David所建议的(。

public class NotificationActivity extends Activity 
{
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        // If this activity is the root activity of the task, the app is not running
        if (isTaskRoot())
        {
            // Start the app before finishing
            Intent startAppIntent = new Intent(getApplicationContext(), MainActivity.class);
            startAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(startAppIntent);
        }
        finish();
    }
}

有一个更简单的解决方案,不需要额外的活动。有关详细信息,请参阅本文。基本上,通知启动(可能存在(任务的方式与在应用程序位于后台时单击启动器图标时启动的方式相同。

我的解决方案,它模拟启动器的行为(将任务带到前台(:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName(MyApplication.class.getPackage().getName(), MainActivity.class.getName());
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

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

相反,您可以将您的活动设置为singleTask,并在不设置ACTION_MAIN的情况下正常调用您的intent,并从目标活动的onNewIntent((方法接收intent。

但要注意,如果你打电话给super.onNewIntent(intent(;则将创建该活动的第二个实例。只是不要调用超级方法。

我结合了David Wasser和Raginmari的解决方案,通过对应用程序的根活动执行这种方法,当应用程序已经启动或尚未启动时,它将适用于这两种情况。

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
        }
    }

最新更新