仅在当前不存在时才启动应用 运行
Starting app only if its not currently running
我正在向用户发送推送通知,点击它会打开应用程序。
我的问题是当应用程序已经打开时,点击通知再次启动应用程序。
我只希望它在尚未启动应用程序时启动它 运行。
我在通知中使用待定意向:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);
我看到帖子说使用:
<activity
android:name=".Splash"
android:launchMode="singleTask"
但问题是我的 运行 应用程序是 运行 其他 activity 然后是应用程序启动 7 秒后完成的启动,所以当应用程序是 运行 Splash 不是当前 activity
不要在通知点击时显示启动画面 activity,而是显示您的 MainActivity,因为您的启动画面 activity 将在一段时间后关闭,但 MainActivity 将保持打开状态
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
为您的应用使用 "launch Intent
",如下所示:
PackageManager pm = getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("your.package.name");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);
将 "your.package.name" 替换为 Android 清单中的包名称。
此外,您应该从清单中删除特殊的 launchMode="singleTask"
。标准 Android 行为将如您所愿。
尝试将此添加到您的意图中,如果 运行 在后台
,则将 activity 置于最前面
Intent intent = new Intent(this, Splash.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
首先在清单文件的 Application
元素中设置默认任务 android:taskAffinity="com.example.testp.yourPreferredName"
。在 SplashActivity
上保持 android:launchMode="singleTask"
。现在,由于您的 SplashActivity 是您的主要条目,因此将此代码添加到 onResume()
、onNewIntent()
和 onCreate()
(再考虑一下,不建议使用 onResume()) - 按照代码中的注释
//Note these following lines of code will work like magic only if its UPVOTED.
//so upvote before you try it.-or it will crash with SecurityException
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1000);
for(int i =0; i< taskInfo.size(); i++){
String PackageName = taskInfo.get(i).baseActivity.getPackageName();
if(PackageName.equals("packagename.appname")){// suppose Whosebug.answerer.Elltz
//if the current runing actiivity is not the splash activity. it will be 1
//only if this is the first time your <taskAffinity> is be called as a task
if(taskInfo.get(i).numActivities >1){
//other activities are running, so kill this splash dead!! reload!!
finish();
// i am dying in onCreate..(the user didnt see nothing, that's the good part)
//about this code. its a silent assassin
}
//Operation kill the Splash is done so retreat to base.
break;
}
}
此代码不适用于 api 21+
;要使其工作,您需要使用 AppTask,这将为您节省额外的代码行,因为您不会在循环中找到您的 Task
.
希望对您有所帮助
当通知被点击并且您的代码重定向到您想要的屏幕时,只需通过调用此方法替换该代码并根据 "true/false" 结果重定向到特定屏幕。
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
并且也许不要启动 Splash Activity 并重新打开(置于前面)MainActivity 并使用告诉您的侦听器更新 UI,您有一个新的通知(带有标志 - 布尔值或带有创建监听器的接口)。
您可以使用有序广播来完成此操作。
1) 将您的 PendingIntent
更改为启动 BroadcastReceiver
,这将决定是启动 activity 还是什么都不做:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, DecisionReceiver.class), 0);
2) 创建决策 BroadcastReceiver
:
public class DecisionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.sendOrderedBroadcast(new Intent(MainActivity.NOTIFICATION_ACTION), null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == MainActivity.IS_ALIVE) {
// Activity is in the foreground
}
else {
// Activity is not in the foreground
}
}
}, null, 0, null, null);
}
}
3) 在你的 activity 中创建一个 BroadcastReceiver
来表示它还活着:
public static final String NOTIFICATION_ACTION = "com.mypackage.myapplication.NOTIFICATION";
public static final int IS_ALIVE = 1;
private BroadcastReceiver mAliveReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setResultCode(IS_ALIVE);
}
};
// Register onResume, unregister onPause
// Essentially receiver only responds if the activity is the foreground activity
@Override
protected void onResume() {
super.onResume();
registerReceiver(mAliveReceiver, new IntentFilter(NOTIFICATION_ACTION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mAliveReceiver);
}
String appPackageName = "";
private void isApplicationInForeground() throws Exception {
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final List<ActivityManager.RunningAppProcessInfo> processInfos = am
.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo processInfo = processInfos
.get(0);
// for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
// getting process at 0th index means our application is on top on all apps or currently open
appPackageName = (Arrays.asList(processInfo.pkgList).get(0));
}
// }
}
else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = null;
componentInfo = taskInfo.get(0).topActivity;
appPackageName = componentInfo.getPackageName();
}
}
private void notifyMessage(String text) {
if (appPackageName.contains("com.example.test")) {
// do not notify
}
else {
// create notification and notify user
}
}
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtras(bundle);
PendingIntent pintent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
使用 Splash 作为 Fragment 而不是 Activity。保留 Splash 片段(7 秒),将其替换为所需的片段(着陆页)。
将 launchMode="singleTask" 添加到清单中。
正如 Rahul 所述,如果应用程序已经 运行 则调用 onNewIntent()
否则 onCreate()
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
}
或
接受 的回答,看起来很有希望。
对于那些使用Xamarin.Android的人。
David Wasser 的答案的 Xamarin 版本如下:
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
Intent uiIntent = PackageManager.GetLaunchIntentForPackage("com.company.app");
//Create the notification
var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);
//Auto-cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
//Set the notification info
//we use the pending intent, passing our ui intent over, which will get called
//when the notification is tapped.
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.OneShot));
//Show the notification
notificationManager.Notify(0, notification);
我正在向用户发送推送通知,点击它会打开应用程序。
我的问题是当应用程序已经打开时,点击通知再次启动应用程序。
我只希望它在尚未启动应用程序时启动它 运行。
我在通知中使用待定意向:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);
我看到帖子说使用:
<activity
android:name=".Splash"
android:launchMode="singleTask"
但问题是我的 运行 应用程序是 运行 其他 activity 然后是应用程序启动 7 秒后完成的启动,所以当应用程序是 运行 Splash 不是当前 activity
不要在通知点击时显示启动画面 activity,而是显示您的 MainActivity,因为您的启动画面 activity 将在一段时间后关闭,但 MainActivity 将保持打开状态
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
为您的应用使用 "launch Intent
",如下所示:
PackageManager pm = getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("your.package.name");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);
将 "your.package.name" 替换为 Android 清单中的包名称。
此外,您应该从清单中删除特殊的 launchMode="singleTask"
。标准 Android 行为将如您所愿。
尝试将此添加到您的意图中,如果 运行 在后台
,则将 activity 置于最前面Intent intent = new Intent(this, Splash.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
首先在清单文件的 Application
元素中设置默认任务 android:taskAffinity="com.example.testp.yourPreferredName"
。在 SplashActivity
上保持 android:launchMode="singleTask"
。现在,由于您的 SplashActivity 是您的主要条目,因此将此代码添加到 onResume()
、onNewIntent()
和 onCreate()
(再考虑一下,不建议使用 onResume()) - 按照代码中的注释
//Note these following lines of code will work like magic only if its UPVOTED.
//so upvote before you try it.-or it will crash with SecurityException
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1000);
for(int i =0; i< taskInfo.size(); i++){
String PackageName = taskInfo.get(i).baseActivity.getPackageName();
if(PackageName.equals("packagename.appname")){// suppose Whosebug.answerer.Elltz
//if the current runing actiivity is not the splash activity. it will be 1
//only if this is the first time your <taskAffinity> is be called as a task
if(taskInfo.get(i).numActivities >1){
//other activities are running, so kill this splash dead!! reload!!
finish();
// i am dying in onCreate..(the user didnt see nothing, that's the good part)
//about this code. its a silent assassin
}
//Operation kill the Splash is done so retreat to base.
break;
}
}
此代码不适用于 api 21+
;要使其工作,您需要使用 AppTask,这将为您节省额外的代码行,因为您不会在循环中找到您的 Task
.
希望对您有所帮助
当通知被点击并且您的代码重定向到您想要的屏幕时,只需通过调用此方法替换该代码并根据 "true/false" 结果重定向到特定屏幕。
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
并且也许不要启动 Splash Activity 并重新打开(置于前面)MainActivity 并使用告诉您的侦听器更新 UI,您有一个新的通知(带有标志 - 布尔值或带有创建监听器的接口)。
您可以使用有序广播来完成此操作。
1) 将您的 PendingIntent
更改为启动 BroadcastReceiver
,这将决定是启动 activity 还是什么都不做:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, DecisionReceiver.class), 0);
2) 创建决策 BroadcastReceiver
:
public class DecisionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.sendOrderedBroadcast(new Intent(MainActivity.NOTIFICATION_ACTION), null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == MainActivity.IS_ALIVE) {
// Activity is in the foreground
}
else {
// Activity is not in the foreground
}
}
}, null, 0, null, null);
}
}
3) 在你的 activity 中创建一个 BroadcastReceiver
来表示它还活着:
public static final String NOTIFICATION_ACTION = "com.mypackage.myapplication.NOTIFICATION";
public static final int IS_ALIVE = 1;
private BroadcastReceiver mAliveReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setResultCode(IS_ALIVE);
}
};
// Register onResume, unregister onPause
// Essentially receiver only responds if the activity is the foreground activity
@Override
protected void onResume() {
super.onResume();
registerReceiver(mAliveReceiver, new IntentFilter(NOTIFICATION_ACTION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mAliveReceiver);
}
String appPackageName = "";
private void isApplicationInForeground() throws Exception {
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final List<ActivityManager.RunningAppProcessInfo> processInfos = am
.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo processInfo = processInfos
.get(0);
// for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
// getting process at 0th index means our application is on top on all apps or currently open
appPackageName = (Arrays.asList(processInfo.pkgList).get(0));
}
// }
}
else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = null;
componentInfo = taskInfo.get(0).topActivity;
appPackageName = componentInfo.getPackageName();
}
}
private void notifyMessage(String text) {
if (appPackageName.contains("com.example.test")) {
// do not notify
}
else {
// create notification and notify user
}
}
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtras(bundle);
PendingIntent pintent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
使用 Splash 作为 Fragment 而不是 Activity。保留 Splash 片段(7 秒),将其替换为所需的片段(着陆页)。
将 launchMode="singleTask" 添加到清单中。
正如 Rahul 所述,如果应用程序已经 运行 则调用 onNewIntent()
否则 onCreate()
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
}
或
接受
对于那些使用Xamarin.Android的人。 David Wasser 的答案的 Xamarin 版本如下:
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
Intent uiIntent = PackageManager.GetLaunchIntentForPackage("com.company.app");
//Create the notification
var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);
//Auto-cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
//Set the notification info
//we use the pending intent, passing our ui intent over, which will get called
//when the notification is tapped.
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.OneShot));
//Show the notification
notificationManager.Notify(0, notification);