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

时间:2011-07-04 20:17:35

标签: android android-activity notifications

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

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

我想允许用户点击通知来恢复当前的活动。我了解如何恢复特定活动,但想知道是否有办法恢复用户所在的最后一个活动?当然我可以跟踪最后一个,然后从Notification回调中调用它,但是认为在任务级别可能有办法吗?

感谢您提供任何建议。

6 个答案:

答案 0 :(得分:60)

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

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。

答案 1 :(得分:27)

非常好,谢谢大卫!以下类检查应用程序是否已在运行,如果没有,则在完成之前启动它(如David在选项2中所建议的那样)。

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();
    }
}

答案 2 :(得分:13)

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

答案 3 :(得分:4)

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

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

答案 4 :(得分:4)

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

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

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

但请注意,如果你打电话,super.onNewIntent(意图);然后将创建活动的第二个实例。只是不要打电话给超级方法。

答案 5 :(得分:0)

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