从推送的消息跳转到指定的页面分两种情况(主要是Activity的生命周期和内存释放引起):
1) App在前台或在后台未被系统回收。
2) App进程已经被系统回收。
点击消息,弹出Dialog提醒用户消息内容,使用PendingIntent这种情况下是无法获取到Dialog所需要的Context(注意不能用getApplicationContext()),可以采用Dialog样式的Activity来实现。
设置Activity样式
AndroidManifest.xml
".getui.AlertDialogActivity"
android:theme="@style/AlertDialogActivityTheme">
此处需要注意的是这里的Activity继承的是AppCompatActivity,如果是继承Activity,则一些属性设置需要微调,比如去掉标题要改为
<item name="android:windowNoTitle">trueitem>
以上设置以后还需要设置弹框的大小
public class AlertDialogActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_activity);
//设置弹框大小,此处宽度为屏幕宽度减去160像素
getWindow().setLayout(DeviceUtil.getDisplayParametersW(this)-160, ViewGroup.LayoutParams.WRAP_CONTENT);
getWindow().setGravity(Gravity.CENTER);
initView();
}
}
如果是App进程已经被系统回收,直接在PendingIntent中传目标Activity的Intent,则在退出目标Activity时会直接退出应用,感觉像是闪退了一样;如果是跳转到首页,然后在首页中检测是否是由点击通知进入应用的来进行跳转,这样的话首页就会闪屏。综上方法都不是很理想,一个比较好的解决方案是给PendingIntent传递一个Intent数组,分别放置目标Activity和首页,这样效果比较好。
//关键的地方
PendingIntent contentIntent = PendingIntent.getActivities(context, 0, intents, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
//省略其他的一些设置
.setContentIntent(contentIntent)
//省略其他的一些设置
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify((int) System.currentTimeMillis() / 1000, notification);
上面关键的改动就在PendingIntent,里面的intents参数存放首页Activity和目标Activity,比如:
Intent[] intents = new Intent[2];
Intent intent_main = new Intent(getApplicationContext(), MainActivity.class);
Intent intent_target = new Intent(getApplicationContext(), TargetActivity.class);
intents[0] = intent_main;
intents[1] = intent_target;
通过以上的设置后,点击通知栏就会打开TargetActivity,从TargetActivity返回后会打开MainActivity,而不会直接退出
需要注意的是,MainActivity需要设置启动模式为singleInstance
AndroidManifest.xml
<activity
android:name=".ui.main.MainActivity"
android:launchMode="singleInstance" />
判断应用所在的线程是否存在
/**
* 判断应用是否已经启动
*
* @param context 一个context
* @param packageName 要判断应用的包名
* @return boolean
*/
public static boolean isAppAlive(Context context, StringpackageName) {
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List processInfos
= activityManager.getRunningAppProcesses();
for (int i = 0; i < processInfos.size(); i++) {
if (processInfos.get(i).processName.equals(packageName)) {
Log.i("NotificationLaunch",
String.format("the %s is running, isAppAlive return true", packageName));
return true;
}
}
Log.i("NotificationLaunch",
String.format("the %s is not running, isAppAlive return false", packageName));
return false;
}
补充
获取某个应用启动Intent:
Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage("应用包名");//获取应用的启动Intent
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
注意要添加Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP 标识,因为要启动单独的Task放目标的Activity,否则就会在当前Task中创建目标Activity。