本文例子已极光推送为例,极光推送集成连接如下:https://docs.jiguang.cn/jpush/client/Android/android_guide/
创建消息的实体类
首先准备消息的实体类(根据需求添加):
/**
* @desciption: 极光推送消息实体,包含所有的数据字段。
*/
public class PushMessage extends BaseModel {
/**
* 消息类型
*/
public String messageType = null;
/**
* 连接
*/
public String messageUrl = null;
/**
* 详情内容
*/
public String messageContent = null;
}
创建 JPushReceiver消息接收器
然后创建JPushReceiver类用于接收极光服务广播出来的推送消息,实现跳转逻辑。
/**
* @desciption: 接收极光服务广播出来的推送消息,实现跳转逻辑
*/
public class JPushReceiver extends BroadcastReceiver {
private static final String TAG = JPushReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Log.d(TAG, "[JPushReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));
}
if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
if (bundle != null) {
int notificationId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
Log.d(TAG, "[JPushReceiver] 接收到推送下来的通知的ID: " + notificationId);
}
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
/**
* 此处可以通过写一个方法,决定出要跳转到那些页面,一些细节的处理,可以通过是不是从推送过来的,去多一个分支去处理。
* 1.应用未启动,------>启动主页----->不需要登陆信息类型,直接跳转到消息展示页面
* ----->需要登陆信息类型,由于应用都未启动,肯定不存在已经登陆这种情况------>跳转到登陆页面
* ----->登陆完毕,跳转到信息展示页面。
* ----->取消登陆,返回首页。
* 2.如果应用已经启动,------>不需要登陆的信息类型,直接跳转到信息展示页面。
* ------>需要登陆的信息类型------>已经登陆----->直接跳转到信息展示页面。
* ------>未登陆------->则跳转到登陆页面
* ----->登陆完毕,跳转到信息展示页面。
* ----->取消登陆,回到首页。
*
* 3.startActivities(Intent[]);在推送中的妙用,注意startActivities在生命周期上的一个细节,
* 前面的Activity是不会真正创建的,直到要到对应的页面
* 4.如果为了复用,可以将极光推送封装到一个Manager类中,为外部提供init, setTag, setAlias,
* setNotificationCustom等一系列常用的方法。
*/
if (bundle != null) {
PushMessage pushMessage = (PushMessage) ResponseEntityToModule
.parseJsonToModule(bundle.getString(JPushInterface.EXTRA_EXTRA), PushMessage.class);
//如果应用已经启动(无论前台还是后台)
if (getCurrentTask(context)) {
Intent pushIntent = new Intent();
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pushIntent.putExtra("pushMessage", pushMessage);
//需要登陆且当前没有登陆才去登陆页面
if (pushMessage.messageType != null && pushMessage.messageType.equals("2")
&& !UserManager.getInstance().hasLogined()) {
pushIntent.setClass(context, LoginActivity.class);
pushIntent.putExtra("formPush", true);
} else {
//不需要登陆或者已经登陆的Case,直接跳转到内容显示页面
pushIntent.setClass(context, PushMessageActivity.class);
}
context.startActivity(pushIntent);
}
//应用没有启动
else {
//这里只分了两种类型,如果消息类型很多的话,用switch--case去匹配
Intent mainIntent = new Intent(context, HomeActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (pushMessage.messageType != null
&& pushMessage.messageType.equals("2")) {
Intent loginIntent = new Intent(context, LoginActivity.class);
loginIntent.putExtra("fromPush", true);
loginIntent.putExtra("pushMessage", pushMessage);
context.startActivities(new Intent[]{mainIntent, loginIntent});
} else {
Intent pushIntent = new Intent(context, PushMessageActivity.class);
pushIntent.putExtra("pushMessage", pushMessage);
context.startActivities(new Intent[]{mainIntent, pushIntent});
}
}
}
}
}
/**
* 打印所有的 intent extra 数据
*
* @param bundle
* @return
*/
private static String printBundle(Bundle bundle) {
StringBuilder sb = new StringBuilder();
for (String key : bundle.keySet()) {
if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
} else if (key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)) {
sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
} else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
if (bundle.getString(JPushInterface.EXTRA_EXTRA).isEmpty()) {
Log.i(TAG, "This message has no Extra data");
continue;
}
try {
/**
* 先将JSON字符串转化为对象,再取其中的字段
*/
JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
Iterator<String> it = json.keys();
while (it.hasNext()) {
String myKey = it.next().toString();
sb.append("\nkey:" + key + ", value: [" + myKey + " - " + json.optString(myKey) + "]");
}
} catch (JSONException e) {
Log.e(TAG, "Get message extra JSON error!");
}
} else {
sb.append("\nkey:" + key + ", value:" + bundle.getString(key));
}
}
return sb.toString();
}
/**
* 获取指定包名的应用程序是否在运行(无论前台还是后台)
*/
private boolean getCurrentTask(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> appProcessInfos = activityManager.getRunningTasks(50);
for (ActivityManager.RunningTaskInfo process : appProcessInfos) {
if (process.baseActivity.getPackageName().equals(context.getPackageName())
|| process.topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
}
推送逻辑跳转分为应用启动和未启动两种情况:
通过包名判断当前应用是否在运行:
/**
* 获取指定包名的应用程序是否在运行(无论前台还是后台)
*/
private boolean getCurrentTask(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> appProcessInfos = activityManager.getRunningTasks(50);
for (ActivityManager.RunningTaskInfo process : appProcessInfos) {
if(process.baseActivity.getPackageName().equals(context.getPackageName())
|| process.topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
应用已启动
应用启动的流程图如下所示:
应用启动流程.png应用已经启动的关键代码如下:
//如果应用已经启动(无论前台还是后台)
if (getCurrentTask(context)) {
Intent pushIntent = new Intent();
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pushIntent.putExtra("pushMessage", pushMessage);
//需要登陆且当前没有登陆才去登陆页面
if (pushMessage.messageType != null && pushMessage.messageType.equals("2")
&& !UserManager.getInstance().hasLogined()) {
pushIntent.setClass(context, LoginActivity.class);
pushIntent.putExtra("formPush", true);
} else {
//不需要登陆或者已经登陆的Case,直接跳转到内容显示页面
pushIntent.setClass(context, PushMessageActivity.class);
}
context.startActivity(pushIntent);
}
登录页的处理
在登录页面的处理如下:
/**
* 推送过来的消息
*/
private PushMessage mPushMessage;
/**
* 是否从推送到此页面
*/
private boolean fromPush;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_layout);;
initData();
initView();
}
private void initData() {
Intent intent = getIntent();
if (intent.hasExtra("pushMessage")) {
mPushMessage = (PushMessage) intent.getSerializableExtra("pushMessage");
}
fromPush = intent.getBooleanExtra("fromPush", false);
}
发起登录请求时需要判断是否是推送需要的登录
if (fromPush) {
Intent intent = new Intent(LoginActivity.this, PushMessageActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("pushMessage", mPushMessage);
startActivity(intent);
}
应用未启动
应用未启动的流程图如下所示:
应用未启动流程.png
应用未启动的关键代码如下:
//这里只分了两种类型,如果消息类型很多的话,用switch--case去匹配
Intent mainIntent = new Intent(context, HomeActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (pushMessage.messageType != null
&& pushMessage.messageType.equals("2")) {
Intent loginIntent = new Intent(context, LoginActivity.class);
loginIntent.putExtra("fromPush", true);
loginIntent.putExtra("pushMessage", pushMessage);
context.startActivities(new Intent[]{mainIntent, loginIntent});
} else {
Intent pushIntent = new Intent(context,PushMessageActivity.class);
pushIntent.putExtra("pushMessage", pushMessage);
context.startActivities(new Intent[]{mainIntent, pushIntent});
}
startActivities
启动多个activity到task中,显示的是最后一个intent指向的activity,但用back键返回时会发现 Intent[]数组中的每个都在task中。
例如通过 startActivities 启动A,B,C三个Activity
Intent intent1 = new Intent(this, IntentActivityA.class);
Intent intent2 = new Intent(this, IntentActivityB.class);
Intent intent3 = new Intent(this, IntentActivityC.class);
startActivities(new Intent[]{intent1, intent2, intent3});
可以知道先创建了ActivityC,等到ActivityC finish掉之后,再开始创建ActivityB,等到ActivityB finish掉之后,再创建ActivityA
网友评论