Android 通知点击:活动已打开
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12043671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Notification click: activity already open
提问by PX Developer
I have an application with notifications that open a certain activity if I click them. I want that, if I click the notification and the activity is already opened, it's notstarted again, but just brought to front.
我有一个带有通知的应用程序,如果我点击它们会打开某个活动。我想要那个,如果我点击通知并且活动已经打开,它不会再次启动,而是被带到前面。
I thought I could do it with the flag FLAG_ACTIVITY_BROUGHT_TO_FRONT
or FLAG_ACTIVITY_REORDER_TO_FRONT
, but it keeps opening it again so I have the activity twice.
我以为我可以用标志FLAG_ACTIVITY_BROUGHT_TO_FRONT
或来完成它FLAG_ACTIVITY_REORDER_TO_FRONT
,但它不断地再次打开它,所以我有两次活动。
This is my code:
这是我的代码:
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);
Can I manage it with flags or should I store a variable in SharedPreferences to check if it's opened or not?
我可以用标志来管理它还是应该在 SharedPreferences 中存储一个变量来检查它是否打开?
Thanks!
谢谢!
回答by Devunwired
You need to set the launchMode
attribute of the Activity
you are starting to singleTop
. This will cause incoming Intents to be delivered to the existing instance rather than starting a new instance when that Activity
is already at the top of the task's stack.
您需要设置您要开始的launchMode
属性。这将导致传入的 Intent 被传递到现有实例,而不是在该实例已经位于任务堆栈的顶部时启动一个新实例。Activity
singleTop
Activity
This is done in the manifest by adding android:launchMode="singleTop"
to the <activity>
element. To access the latest Intent (if you are interested in any data that may have passed in with it), override onNewIntent()
in your Activity
.
这是通过添加android:launchMode="singleTop"
到<activity>
元素在清单中完成的。要访问最新的 Intent(如果您对随它传入的任何数据感兴趣),请onNewIntent()
在您的Activity
.
回答by quietmint
Try setting the flags to Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
instead.
尝试将标志设置为Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
。
From the documentation for FLAG_ACTIVITY_CLEAR_TOP(emphasis mine):
来自FLAG_ACTIVITY_CLEAR_TOP的文档(强调我的):
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.
The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().
如果设置,并且正在启动的活动已经在当前任务中运行,那么它不会启动该活动的新实例,而是将关闭它之上的所有其他活动,并且此 Intent 将被传递到(现在在顶部)旧活动作为新意图。
例如,考虑一个由活动组成的任务:A、B、C、D。如果 D 使用解析为活动 B 组件的 Intent 调用 startActivity(),则 C 和 D 将完成并且 B 接收给定的 Intent ,导致堆栈现在是:A,B。
上例中当前正在运行的活动 B 实例将接收您在其 onNewIntent() 方法中开始的新意图,或者自己完成并使用新意图重新启动。如果它已经声明它的启动模式为“multiple”(默认)并且你没有在同一个意图中设置 FLAG_ACTIVITY_SINGLE_TOP,那么它将被完成并重新创建;对于所有其他启动模式,或者如果 FLAG_ACTIVITY_SINGLE_TOP 被设置,那么这个 Intent 将被传递到当前实例的 onNewIntent()。
回答by Afjalur Rahman Rana
Use onNewIntent()
for handling new data from notification click and refresh the activity.
使用onNewIntent()
从通知点击处理新数据并刷新活动。
In onNewIntent
get the new data from the new intent(which served by the new notification) and catch them, for example:
在onNewIntent
得到新的目的,新的数据(其中担任由新通知),并抓住他们,例如:
title = intent.getStringExtra("title")
title = intent.getStringExtra("title")
in onCreate
previously :)
在 onCreate
以前:)
It will refresh present activity with new notification data.
它将使用新的通知数据刷新当前活动。
You can also follow this tutorial.
您也可以按照本教程进行操作。
回答by Afjalur Rahman Rana
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());
Just Copy the code and paste it in your main launcher activity.
只需复制代码并将其粘贴到您的主启动器活动中即可。
回答by Carlos Alberto Gonzalez
I think you should add some logic to make it work, maybe this can help:
我认为你应该添加一些逻辑来使它工作,也许这可以帮助:
For example I have a Splash Screen (Launcher and MAIN) of APP:
例如,我有一个 APP 的启动画面(启动器和主):
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);
}
}
}
And in my FirebaseService I have done the following:
在我的 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());
}
}
回答by Manjunath
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, new Random().nextInt(), intent, 0);