美文网首页
Android 推送跳转逻辑

Android 推送跳转逻辑

作者: wuchao226 | 来源:发表于2019-01-14 16:05 被阅读11次

本文例子已极光推送为例,极光推送集成连接如下: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

相关文章

网友评论

      本文标题:Android 推送跳转逻辑

      本文链接:https://www.haomeiwen.com/subject/bunddqtx.html