当收到聊天消息的推送消息时,我的应用程序会显示一条通知。当我单击该消息时,我想启动该应用程序(如果尚未启动),该应用程序应直接转发到特定的聊天屏幕(而不是主屏幕)。如果该应用程序已经存在于该屏幕中,它将更新显示的消息(实际上类似于WhatsApp)。
当前,除以下情况外,这在大多数情况下似乎都可以很好地工作:
请注意:无论我收到哪个通知,以及我往返聊天屏幕的频率如何,在最初以正常方式启动应用程序时(始终不能通过通知点击)正确地处理通知点击即可。
一些信息和代码:
我的应用程序有多个活动,其中最重要的活动是MainActivity,LoginActivity和InitializationActivity(后者是启动器,并选择应启动其他两个中的哪个)。这是相关的清单部分:
<activity
android:name=".activity.InitializationActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".activity.LoginActivity"
android:launchMode="singleTop"/>
<activity
android:name=".activity.MainActivity"
android:launchMode="singleTop"/>
初始化活动:
@Override
protected void onStart()
{
super.onStart();
decideStartUpMode();
}
@Override
protected void onNewIntent(Intent intent)
{
// Just to be sure the intent from a notification is also saved through this method.
// However, should not be required, because this activity is always destroyed before starting a new one.
// Doesn't appear to be called in any case (decideStartUpMode is always called through onStart)
super.onNewIntent(intent);
setIntent(intent);
decideStartUpMode();
}
private void decideStartUpMode()
{
if (!isUserLoggedIn())
{
startLoginActivity();
}
else
{
// Starts some API calls to collect the required user info.
// When the data is collected we callback to this class and start the MainActivity.
startInitialization();
}
}
...
private void startMainActivity()
{
Intent intentActivityMain = new Intent(this, MainActivity.class);
intentActivityMain.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Collect (Pending)Intent from eg. notification - if present - and add this to the new activity
Intent intentInitializationActivity = getIntent();
intentActivityMain.setAction(intentInitializationActivity.getAction());
intentActivityMain.setData(intentInitializationActivity.getData());
Bundle extras = intentInitializationActivity.getExtras();
if (extras != null)
{ // Extra's from notification
intentActivityMain.putExtras(extras);
}
startActivity(intentActivityMain);
finish();
}
MainActivity:
// INTENT_HANDLER will handle the actions from clicked push notifications
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
INTENT_HANDLER.doIntentAction(getIntent(), this); // If activity is started through InitializationActivity
}
@Override
protected void onNewIntent(Intent newIntent)
{
super.onNewIntent(newIntent);
INTENT_HANDLER.doIntentAction(newIntent, this); // If activity was already active
}
最后创建具有启动器意图的通知:
public void showChatNotification(Context context, ChatNotification chatNotificationData)
{
Bundle bundle = new Bundle();
bundle.putSerializable(CHAT_NOTIFICATION_DATA, chatNotificationData);
PendingIntent onNotificationClickIntent = getAppLauncherIntent(context, CHAT_NOTIFICATION, notificationId, extras);
String channelId = // ... also create channel if not exists ...
NotificationCompat.Builder notification = new NotificationCompat.Builder(getContext(), channelId);
notification.setContentIntent(onNotificationClickIntent);
notification.setAutoCancel(true);
// ... Set other notification data: title, message, etc...
context.getSystemService(Context.NOTIFICATION_SERVICE)
.notify(notificationId.id, notification.build());
}
private PendingIntent getAppLauncherIntent(Context context, String action, NotificationId notificationId, Bundle extras)
{
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
intent.setAction(action);
intent.putExtras(extras);
return PendingIntent.getActivity(context, notificationId.id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
在通常情况下,始终通过InitialActivity(onCreate
> onStart
> startInitialization
> startMainActivity
)和MainActivity({{1 }}或onCreate
)。但是,当我最初通过另一个通知(上述方法或onHandleIntent都未启动)启动应用程序后,单击通知时未调用InitializationActivity。
为什么在这种特定情况下会出错,而所有其他通知点击都得到正确处理?我的应用是否通过带有onHandleIntent
的通知错误地初始化了(可能是由于使用了标志),因此它不再能够处理新的通知?
答案 0 :(得分:1)
从Notification
启动应用程序时,如果该应用程序尚未运行,则Android会为该应用程序创建一个新任务,并将Activity
启动到该任务中。 Android会记住用于启动任务的Intent
。
如果以后用户从Notification
启动应用程序,则Android会将现有任务置于前台,因为用于启动应用程序的Intent
与该任务最初的Intent
相匹配用AND启动的Intent
包含FLAG_ACTIVITY_NEW_TASK
。这就是为什么在最初从Notification
启动应用程序时看到这种奇怪行为的原因。
为防止此行为,您需要将FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
添加到Intent
中使用的Notification
中。这将防止Android记住用户使用此Intent
启动了应用程序。
答案 1 :(得分:0)
我的问题通过将清单更改为
<activity
android:name=".activity.InitializationActivity"
android:launchMode="singleTop">
到
<activity
android:name=".activity.InitializationActivity"
android:launchMode="singleTask">
我不完全理解为什么(是的,我确实阅读了两个标志的文档),因此在注释中给出清晰的解释将非常有用。