如何在创建后更改活动来处理推送通知意图?

How can I handle a push notification intent with changing activities after creation?

我有一个双activity android 应用程序(活动都是单顶),我正在处理推送通知。每个推送通知场景都为我完美处理,除了一个,这是因为推送通知意图的构建方式。

未按预期执行的场景是当用户在一个 activity 中时推送通知进来,然后他们导航到另一个 activity,然后他们决定从 phone 的下拉栏中 select 推送通知。我的问题是该应用程序然后尝试返回到创建通知时处于活动状态的 activity,这不是我想要的。我希望它仍然以相同的方式执行它对通知及其数据所做的一切,而是在当前 activity 上执行而不是切换回来。

我知道为什么会这样,因为通知创建代码是这样设计的:

// create notification
        val builder = NotificationCompat.Builder(context,
                channelId)
// more things are done to set up the builder...


// here is why the problem is happening

        val notificationIntent = if (we_are_in_activity_one)
                Intent(context, ActivityOne::class.java) 
            else
                Intent(context, ActivityTwo::class.java)

        notificationIntent.putExtras(data_from_notification)

        builder.setContentIntent(PendingIntent.getActivity(context,
                notificationId,
                notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT))
        //Auto cancel
        builder.setAutoCancel(true)

        builder.priority = NotificationCompat.PRIORITY_HIGH

        //Return the generated notification
        return builder

我想知道可以做些什么或改变什么,以便当用户 select 发出通知时,它不会自动启动它最初与 if 捆绑在一起的 activity情况已经改变。是否有一个明显的标志我可以使用?

另一条可能有用的信息是,只有当它们处于 activity 2 时才会出现问题,因为 activity 1 是启动器 activity。因此,如果通知是在 2 中创建的,但它们导航回 1,则 Activity 2 将不再处于活动状态。当他们点击通知时,它会重新启动 activity 2,这不是我想要的。我只希望通知实际上返回 Activity 2 如果它仍然处于活动状态(也就是用户仍在它上面)。

提前致谢,如果我能提供更多有用的信息,请告诉我

如果我没理解错的话,你想收到关于用户当前 activity 的通知吗?

您可以按如下方式进行。

您需要验证第二个 activity 是 运行。如果不是,您的通知将在主屏幕上打开。如果是,通知将在 onNewIntent().

中打开。

实现此目的的简单方法是:

  public static boolean isActivityActive(Activity activity) {
   return !activity.isFinishing() && !activity.isDestroyed();
  }

然后

  Intent intent = new Intent(context, !isActivityActive(new ActivityTwo()) ? ActivityOne.class : ActivityTwo.class);

如果 activity 打开,此方法将 return 为真。 或者你可以使用:

  activity.getWindow().getDecorView().isShown();

in isActivityActive(Activity) 由该表达式编辑的值 return 在 onStart() / onStop()

中发生变化

如果上述方法没有提供您期望的结果,您可以创建一个 class 以供重复使用,并将 activity 状态保存到您可以在任何 [=108= 中使用的共享密钥].

只需要几行代码。

首先执行以下操作:

 public class MyPreference {

   private Context c;
   private SharedPreferences.Editor editor;
   private SharedPreferences preferences;
   
   public MyPreference (Context c) {
    this.c = c;
    preferences = c.getSharedPreferences("shared_preferences", Context.MODE_PRIVATE);
   }
   
   public void save (String preference, boolean value) {
    editor = preferences.edit();
    editor.putBoolean(preference, value);
    editor.apply();
   }

   public boolean boo (String preference) {
    return preferences.getBoolean(preference, false);
   }
   
   public String is_second_activity_active = "is_second_activity_active";
   
 }

您现在可以通过启动 MyPreference 来保存第二个 activity 的生命周期,如下所示:

 public class ActivityTwo extends AppCompatActivity {

   MyPreference p;
   
   @Override
   protected void onCreate(Bundle state) {
    super.onCreate(state);
    p = new MyPreference(context);
    // some source...
   }
   
   @Override
   protected void onStart() {
    super.onStart();
    p.save(p.is_second_activity_active, true);
    // your activity is active
   }
   
   @Override
   protected void onStop() {
    super.onStop();
    p.save(p.is_second_activity_active, false);
    // your activity is not active
   }
 }

你可以了解Activityhere

的生命周期

最后,在您的通知 class 中,检索您的第二个 activity:

的状态
  // create notification
  // ...    

  MyPreference p = new MyPreference(context);

  Intent intent = new Intent
   (context, p.boo(p.is_second_activity_active) ? ActivityTwo.class : ActivityOne.class);

  // continue...

对不起我的英语,我不流利。我希望你明白。 我不会用kotlin写,所以你可以转换代码。

如果对您有帮助,请告诉我。 谢谢你。 > <



更改



以一种方式创建通知后,无法更改通知的行为。您可以在情况发生变化时更新通知。

您需要在 NotificationCompat.Builder 中定义 setOnlyAlertOnce (true),然后发送与旧通知相同 id 的新通知。

如果 idsetOnlyAlertOnce (true) 相同,您的通知将在没有弹出窗口、声音或振动警告的情况下更新。您可以为每次更新使用相同的生成器。

虽然这很好用,但文档本身警告说,如果通知在短时间内多次更新,有些通知将不会被打包。

Caution: Android applies a rate limit when updating a notification. If you post updates to a notification too frequently (many in less than one second), the system might drop some updates. Documentation

在您的情况下,每当用户登录和注销时都需要更新通知 ActivityTwo.class,这不是一件好事。

或者,我建议您试试这个。

不是通过通知直接打开 activity,而是从 BroadcastReceiver 打开它, 然后决定打开哪个 activity..

要广播您的通知,您的 Intent 需要如下所示

 // create notification
 // ...  
 
 Intent intent = new Intent();
 intent.setAction(MyNotification.ACTION_OPEN);
 intent.putExtra("get", "something");
 
 // use getBroadCast instead of getActivity
 PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

 builder.setContentIntent(pIntent);
 // configure your builder normally

现在在您的 BroadcastReceiver 中,确保用户打开了他们的通知,以及他们打开通知时 activity 在什么地方。

 public class MyNotification extends BroadcastReceiver {

    public static String ACTION_OPEN = "com.example.intent.action.NOTIFICATION_OPEN";
 
    @Override
    public void onReceive(Context context, Intent intent) {
      
      MyPreference m = new MyPreference(context);
      boolean open_notification = ACTION_OPEN.equals(intent.getAction());

      if (open_notification ) {
        boolean is_active = m.boo(m.is_second_activity_active);
        String log = is_active ? "Open in ActivityTwo" : "Open in ActivityOne";
        
        Intent new_intent = new Intent(context, is_active ? two.class : one.class);
        new_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        new_intent.putExtra("get", intent.getExtras());
        context.startActivity(new_intent);
        
        Log.e("log", log);
      }
    }
 }

如果您愿意,可以使用您的方法找出用户是否在第二个 activity,或者使用我之前提到的示例。

NOTE: The onStart () and onStop () methods are actually better than onResume () and onDestroy () to check if the user is still in the activity. onDestroy () is never called when the user closes the application, from recent applications.

最后,在您的 AndroidManifest.xml

中声明您的广播
  <receiver android:name=".MyNotification"
        android:exported="false">
        <intent-filter>
            <action android:name="com.example.intent.action.NOTIFICATION_OPEN" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
  </receiver>

不要忘记将 android:launchMode="singleTop" 添加到您的 ActivityOneActivityTwo

通知将根据用户的 activity 打开,无论它是在何处创建的。

因此,如果 activity 是唯一发生变化的内容,则无需在情况发生变化时更新通知。

现在应该可以了。 x-x