【问题标题】:Resume singleTask activity恢复 singleTask 活动
【发布时间】:2015-03-23 23:18:13
【问题描述】:

我正在尝试“恢复”单个任务活动,以便在用户单击我的通知时显示在前台。 (与用户从应用程序菜单中点击应用程序图标的行为相同。)

我的通知创建了一个 PendingIntent,它广播了我的广播接收器接收到的操作。如果应用程序不在前台,我会尝试恢复应用程序。此外,我试图通过意图将消息传递给我的 onResume 函数。但是,我遇到了一个错误:

Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

尽管出现此错误,但我的应用程序正在恢复...不明白为什么。但是,我的额外内容没有传递给我的 onResume 函数。

首先我创建一个通知。

public static class MyNotificationCreator {

  private static final int MY_NOTIFICATION_ID = 987;

  public static void createNotification(Context context) {
    Intent openAppIntent = new Intent(context, MyReceiver.class);
    openAppIntent.setAction("PleaseOpenApp");
    PendingIntent pi = PendingIntent.getBroadcast(context, /*requestCode*/0, openAppIntent, /*flags*/0);

    Notification notification = ne Notification.Builder(context)
      .setContentTitle("")
      .setContentText("Open app")
      .setSmallIcon(context.getApplicationInfo().icon)
      .setContentIntent(pi)
      .build();

    NotificationManager notificationManager = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(MY_NOTIFICATION_ID, notification);  }
}

为 MyReceiver 广播“PleaseOpenApp”。

public class MyReceiver extends BroadcastReceiver {
  @Override
  public void onRecieve(Context context, Intent intent) {
    if (intent.action() == "PleaseOpenApp" && !MyPlugin.isForeground) {
      PackageManager pm = context.getPackageManager();
      //Perhaps I'm not supposed to use a "launch" intent?
      Intent launchIntent = pm.getLaunchIntentForPackage(context.getPackageName());
      //I'm adding the FLAG_ACTIVITY_NEW_TASK, but I'm still hitting an error saying my intent does not have the FLAG_ACTIVITY_NEW_TASK...
      launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      launchIntent.putExtra("foo", "bar");
      context.startActivity(launchActivity);
    } else {
      //do other stuff
    }
  }
}

我的插件会跟踪我们是否在前台。此外,它会在我的接收器尝试启动应用程序后尝试获取“食物”。

public class MyPlugin extends CordovaPlugin {

  public static boolean isForeground = false;

  @Override
  public void initialize(CordovaInterface cordova, CordovaWebView webview) {
    super.initialize(cordova, webview);
    isForeground = true;
  }

  @Override
  public void onResume(boolean multitasking) {
    isForeground = true;
    String foo = activity.getIntent().getStringExtra("foo");
    Log.d("MyPlugin", foo); //foo is null after clicking the notification!
  }

  @Override
  public void onPause(boolean multitasking) {
    isForeground = false;
  }

  @Override
  public void onDestroy() {
    isForeground = false;
  }
}

注意:因为我使用的是 cordova,所以我的活动有一个 singleTask 启动模式。

此外,我是 Android 开发的新手,因此对于恢复不在前台的活动与恢复已被破坏的活动以及有关我不理解的一般概念/最佳实践的信息的任何帮助,我们将不胜感激!

【问题讨论】:

    标签: android cordova android-intent notifications


    【解决方案1】:

    我认为您的广播/广播接收器模式没有必要。

    Intents 可以用来直接启动一个activity,当你构建Intent 时,你可以添加额外的东西。然后,您的活动 onResume() 可以直接提取它们。

    这是一个可以在通知中发送的示例 Intent 和 PendingIntent 构造:

    Intent startActivity = new Intent(context, MyActivity.class);
    // You can experiment with the FLAGs passed here to see what they change
    startActivity.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
                        .putExtra("Extra1", myExtra1)
                        .putExtra("Extra2", myExtra2)
                        // ADDING THIS MAKES SURE THE EXTRAS ATTACH
                        .setAction("SomeString"); 
    
    // Then, create the PendingIntent
    // You can experiment with the FLAG passed here to see what it changes
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startActivity, PendingIntent.FLAG_UPDATE_CURRENT);
    
    // Then, create and show the notification
    Notification notif = new NotificationCompat.Builder(context)
                .setSmallIcon(R.drawable.my_small_icon)
                .setContentTitle(myTitle)
                .setContentText(myContent)
                .setOngoing(isOngoingNotif)
                .setAutoCancel(shouldAutoCancel)
                .setOnlyAlertOnce(shouldAlertOnce)
                .setContentIntent(pendingIntent)
                .build();
    
    NotificationManagerCompat manager = NotificationManagerCompat.from(context);
    manager.notify(MY_NOTIFICATION_ID, notif);
    

    【讨论】:

    • 但是如果我需要额外的逻辑来确定是否需要重新启动活动怎么办?如果它在前台,我不想重新启动活动。在那种情况下,我想做点别的事情。
    • 这就是标志的来源。Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK 会将活动带回前台或在进程不存在时启动它。
    • 您能进一步解释一下吗?如何执行具有不同标志的自定义代码?我想如果应用程序在前台,我应该指定我想做一些特定的事情。
    • 您可以使用 Activity 生命周期方法 #onNewIntent(Intent intent) 处理“已经在前台,做其他事情”的情况
    • 好吧,很有趣。我会看看并玩弄旗帜。
    【解决方案2】:

    在您的代码中,您正在使用“启动意图”来恢复您的应用程序。您已向 Intent 添加了“附加”,但它们永远不会被看到。

    如果您的应用程序正在运行,但在后台运行,并且您使用“启动 Intent”调用 startActivity(),所有这一切都会将您的任务从后台带到前台。 它不会将Intent 传递给Activity

    “启动意图”的作用与您在主屏幕上按下应用程序图标时的作用完全相同(如果它已经在运行,但在后台)。这只是将现有任务从后台带到前台。

    如果您想向您的应用交付“附加”,则不能使用“启动 Intent”。您必须使用常规的 'Intent. Depending on your architecture, you could either start a newActivity(which would get the "extras" inonCreate(), or you could start an existingActivity(which would get the "extras" inonNewIntent()`。

    【讨论】:

      猜你喜欢
      • 2014-11-17
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多