通知点击:活动已开启
Posted
技术标签:
【中文标题】通知点击:活动已开启【英文标题】:Notification click: activity already open 【发布时间】:2012-08-16 03:18:50 【问题描述】:我有一个带有通知的应用程序,如果我单击它们会打开某个活动。我想要这样,如果我点击通知并且活动已经打开,它不会再次开始,而只是被带到前面。
我以为我可以使用标志 FLAG_ACTIVITY_BROUGHT_TO_FRONT
或 FLAG_ACTIVITY_REORDER_TO_FRONT
来做到这一点,但它会再次打开它,所以我有两次活动。
这是我的代码:
event_notification = new Notification(R.drawable.icon,
mContext.getString(R.string.event_notif_message), System.currentTimeMillis());
Intent notificationIntent = new Intent(mContext, EventListActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
sendNotification(event_notification, notificationIntent, mContext.getString(R.string.event_notif_title),
body, Utils.PA_NOTIFICATIONS_ID);
我可以用标志来管理它,还是应该在 SharedPreferences 中存储一个变量来检查它是否打开?
谢谢!
【问题讨论】:
我使用intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NO_HISTORY); 【参考方案1】:您需要将您开始的Activity
的launchMode
属性设置为singleTop
。当Activity
已经位于任务堆栈的顶部时,这将导致传入的 Intent 被传递到现有实例,而不是启动一个新实例。
这是通过将android:launchMode="singleTop"
添加到<activity>
元素在清单中完成的。要访问最新的 Intent(如果您对可能随它传入的任何数据感兴趣),请在您的 Activity
中覆盖 onNewIntent()
。
【讨论】:
我遇到了许多答案,说将意图标志设置为各种事物。这没有用。这是因为意图,不管它的标志是什么,都会去一个新创建的活动?我问是因为 Devunwired 说 launchMode 属性会改变 Intent 的传递位置。 文档页面位于developer.android.com/guide/topics/manifest/… 我看到如果您在从主屏幕启动的 Activity 上使用这种方法,那么每次启动应用程序时都会从根 Activity 开始,从而破坏之前显示在顶部的所有 Activity。对于将应用程序置于后台并在不同的活动中并重新打开它的用户来说,这当然不是预期的行为。 将启动模式添加到清单解决了我的用户在运行 Android 7.1.1 的摩托罗拉 E4 上报告它的问题,但奇怪的是问题没有出现在等效的模拟设备上,也没有出现在装有 Android 11 的(真实)Pixel 2 上。【参考方案2】:尝试将标志设置为 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
。
来自documentation for FLAG_ACTIVITY_CLEAR_TOP(强调我的):
如果设置,并且正在启动的活动已经在 当前任务,而不是启动该任务的新实例 活动,除此之外的所有其他活动都将关闭,并且 此 Intent 将作为 新意图。
例如,考虑一个由以下活动组成的任务:A、B、C、D。 如果 D 调用 startActivity() 的 Intent 解析为 活动 B 的组成部分,然后 C 和 D 将完成,B 收到 给定的 Intent,导致堆栈现在是:A,B。
上例中当前正在运行的活动 B 实例将 要么接收您从这里开始的新意图 onNewIntent() 方法,或者自己完成并使用新的重新启动 意图。如果它已将其启动模式声明为“多重”( 默认值)并且您没有设置 FLAG_ACTIVITY_SINGLE_TOP 相同 意图,然后它将完成并重新创建;对于所有其他发射 模式或 如果设置了 FLAG_ACTIVITY_SINGLE_TOP 那么这个 Intent 将是 传递到当前实例的 onNewIntent()。
【讨论】:
这是我需要的。只需添加我们需要将此标志添加到意图的描述:new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
。【参考方案3】:
使用onNewIntent()
处理来自通知点击和刷新活动的新数据。
在onNewIntent
中从新意图(由新通知提供服务)中获取新数据并捕获它们,例如:
title = intent.getStringExtra("title")
以前在onCreate
:)
它将使用新的通知数据刷新当前活动。
你也可以关注this tutorial.
【讨论】:
【参考方案4】:Notification.Builder mBuilder =
new Notification.Builder(this)
.setSmallIcon(R.drawable.cmplayer)
.setContentTitle("CoderoMusicPlayer")
.setContentText("PLayer0!");
Intent resultIntent = new Intent(this,
AndroidBuildingMusicPlayerActivity.class);
resultIntent.setAction(Intent.ACTION_MAIN);
resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, 0);
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
只需复制代码并将其粘贴到您的主启动器活动中即可。
Here is Original Answer
【讨论】:
【参考方案5】:我认为您应该添加一些逻辑以使其工作,也许这会有所帮助:
例如,我有一个 APP 的启动画面(启动器和 MAIN):
public class SplashScreen extends AppCompatActivity
private final int TIME_OUT = 2000;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
// Suscribirse al tema Notificaciones
FirebaseMessaging.getInstance().subscribeToTopic("NOTA");
if (getIntent().getExtras() != null)
if (getIntent().getExtras().size()>1)
Intent home_activity = new Intent(getApplicationContext(), Home.class);
home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (getIntent().getExtras() != null)
for (String key : getIntent().getExtras().keySet())
String value = "" + getIntent().getExtras().getString(key);
Log.d("TAG", key + "=" + value);
switch (key)
case "url":
home_activity.putExtra("url", value);
break;
startActivity(home_activity);
finish();
else
new Handler().postDelayed(new Runnable()
@Override
public void run()
try
Intent home_activity = new Intent(getApplicationContext(), Home.class);
home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(home_activity);
finish();
catch (Exception ex)
ex.printStackTrace();
, TIME_OUT);
else
new Handler().postDelayed(new Runnable()
@Override
public void run()
try
Intent home_activity = new Intent(getApplicationContext(), Home.class);
home_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(home_activity);
finish();
catch (Exception ex)
ex.printStackTrace();
, TIME_OUT);
在我的 FirebaseService 中,我做了以下事情:
public class FCMessagingService extends FirebaseMessagingService
private final String TAG = "PUSH";
private String body = "";
private static String _url = "";
private static int numMessage = 0;
@Override
public void onMessageReceived(RemoteMessage remoteMessage)
super.onMessageReceived(remoteMessage);
String from = remoteMessage.getFrom();
Log.d(TAG, "Mensaje recibido de: " + from);
if (remoteMessage.getNotification() != null)
Log.d(TAG, "Notificación: " + remoteMessage.getNotification().getBody());
if (remoteMessage.getData().size() > 0)
Log.d(TAG, "Data: " + remoteMessage.getData());
try
JSONObject data = new JSONObject(remoteMessage.getData());
String url = data.getString("url");
Log.d(TAG, "onMessageReceived: \n" + "Extra Information: " + url);
this._url = url;
Log.d("_URL",_url);
mostrarNotificacion(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
mensaje(url, remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
catch (JSONException e)
e.printStackTrace();
private void mensaje(String url, String title, String body)
boolean acti = Util.comprobarActivityALaVista(getApplicationContext(), "com.dev.android.subagan.MainActivity");
if(acti)
Intent imain = new Intent(MainActivity.URL);
imain.putExtra("key_url",url);
imain.putExtra("key_title",title);
imain.putExtra("key_body",body);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(imain);
else
Intent ihome = new Intent(Home.URL);
ihome.putExtra("key_url",url);
ihome.putExtra("key_title",title);
ihome.putExtra("key_body",body);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(ihome);
private void mostrarNotificacion(String title, String body)
final int NOTIFICATION_ID = 3000;
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("url",_url);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT );
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(soundUri)
.setTicker(body)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
【讨论】:
【参考方案6】:Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, new Random().nextInt(), intent, 0);
【讨论】:
请解释您的代码如何帮助解决问题中提到的问题。对于面临相同/类似问题的其他读者来说,这可能并不明显。以上是关于通知点击:活动已开启的主要内容,如果未能解决你的问题,请参考以下文章