android集成友盟推送,点击通知,先启动应用,然后再跳指定 界面;应用前台,接收推送,应用内弹框

版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明。
本文链接:https://www.jianshu.com/p/a3744cae1b52


友情提示:在看本文前,最好对友盟推送的集成文档看个差不多,不然可能有些概念不是太清楚。
友盟集成文档:https://developer.umeng.com/docs/66632/detail/98581
本文demo下载地址:https://github.com/274800562/umengtest.git
----------------分割线--------------------
应用分为在线状态和离线状态,以应用进程是否存在为判断依据。

通知分为在线通知和离线通知,同样以应用进程是否存在时为判断依据。进程存在时接收到的通知即在线通知,离线时接收到的通知为离线通知。

一 、需求描述:

1.应用离线时,收到通知,点击通知,启动应用,启动SplashActivity->MainActivity,然后根据需要跳转相应界面。

2.应用在线:
1)应用在前台时,收到通知,应用内弹框,点击跳转响应界面;
2)应用在后台时,收到通知,存储通知数据,待应用切回到前台时再弹框,点击跳转响应界面。

二、需求实现
首先,我们设定有SplashActivity、MainActivity、DetailActivity、ListActvity四个类,我们通过UMessage对象的extra字段配置数据:type,id,title等,type=1时,跳转DetailActivity;type=2时,跳转ListActvity。

3B1AAB823985FD8669D0F853FE0CF9B6.jpg

1.友盟推送可以集成厂商通道,以接收离线通知。通过继承UmengNotifyClickActivity类,重写onMessage(),点击时回调此方法。

public class UmengClickActivityextends UmengNotifyClickActivity {
        private static StringTAG = UmengClickActivity.class.getName();
        @Override
        public void onMessage(Intent intent0) {
            super.onMessage(intent0);  //此方法必须调用,否则无法统计打开数
            String body = intent0.getStringExtra(AgooConstants.MESSAGE_BODY);
            Log.e(TAG, "body:" + body);
            Gson gson = new Gson();
            UmengClickBean bean = gson.fromJson(body, UmengClickBean.class);
            //ExtraBean包含三个字段:type,id,title,根据type跳转相应界面
            ExtraBean extraBean = bean.getExtra();
            if (null != bean) {
                Intent intent = new Intent(this, SplashActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必须
                intent.putExtra("bean", extraBean);
                intent.putExtra("tag", 1);//标志位,点击跳过去的,区别于正常逻辑跳转
                startActivity(intent);
                finish();
             }
        }
}

接着,启动SplashActivity->MainActivity。

public class SplashActivity extends AppCompatActivity {
    public static final String TAG = "SplashActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        int tag = getIntent().getIntExtra("tag", 0);
        //1.其他操作 省略

        //2.跳主界面
        Intent intent = new Intent(this,MainActivity.class);
        //tag==1时说明是点击离线通知过来的,需要携带数据跳转
        if (tag == 1) {
            ExtraBean extraBean= (ExtraBean) getIntent().getSerializableExtra("bean");
            intent.putExtra("bean", extraBean);
            intent.putExtra("tag", tag);
        }
        startActivity(intent);
    }
}
public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        int tag = getIntent().getIntExtra("tag", 0);
        if (tag == 1) {//点击通知跳转过来的,有携带数据,需要执行跳转逻辑,根据type跳对应界面
            ExtraBean extraBean = (ExtraBean) getIntent().getSerializableExtra("bean");
            int type = extraBean.getType();
            Log.e(TAG, "umeng  type:" + type);
            Intent intent = null;
            if (type == 1) {
                intent = new Intent(this, DetailActivity.class);
            } else {
                intent = new Intent(this, ListActivity.class);
            }
            intent.putExtra("bean", extraBean);
            startActivity(intent);
        }
    }
}

DetailActivity、ListActivity代码相同:

public class DetailActivity extends AppCompatActivity {
    public static final String TAG = "DetailActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ExtraBean extraBean= (ExtraBean) getIntent().getSerializableExtra("bean");
        String id = String.valueOf(extraBean.getId());
        String title = extraBean.getTitle();

        TextView textView = findViewById(R.id.textview);
        textView.setText("id:"+id+"\n"+"title:"+title);
    }
}

按上面的代码执行是没有什么问题的,但是有一种情况时,收到离线通知,不去点击,启动app,再去点击。这时候依然会去执行UmengClickActivity里的onMessage()方法。按照上边的逻辑会启动SplashActivity,而不是根据type值启动对应的Activity。
我的实现思路是,在onMessage()方法内部添加判断,根据结果执行不同逻辑。

public class UmengClickActivity extends UmengNotifyClickActivity {
    private static String TAG = UmengClickActivity.class.getName();

    @Override
    public void onMessage(Intent intent0) {
        super.onMessage(intent0);  //此方法必须调用,否则无法统计打开数

        String body = intent0.getStringExtra(AgooConstants.MESSAGE_BODY);
        Log.e(TAG, "body:" + body);

        Gson gson = new Gson();
        //将接收到的body信息装换成UmengClickBean
        UmengClickBean bean = gson.fromJson(body, UmengClickBean.class);
        //ExtraBean包含三个字段:type,id,title,根据type跳转相应界面
        ExtraBean extraBean = bean.getExtra();
        if (null != bean) {
            int type = extraBean.getType();
            Intent intent = null;
            /**
             * 判断栈中是否有MainActivity,有则意味着程序已启动,否则没有
             */
            if (isExistMainActivity(MainActivity.class)) {
                if (type == 1) {
                    intent = new Intent(this, DetailActivity.class);
                } else {
                    intent = new Intent(this, ListActivity.class);
                }
            } else {
                intent = new Intent(this, SplashActivity.class);
                intent.putExtra("tag", 1);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            intent.putExtra("bean", extraBean);
            startActivity(intent);
            finish();
        }
    }

    @TargetApi(Build.VERSION_CODES.Q)
    private boolean isExistMainActivity(Class<?> activity) {
        Intent intent = new Intent(this, activity);
        ComponentName cmpName = intent.resolveActivity(getPackageManager());
        boolean flag = false;
        if (cmpName != null) { // 说明系统中存在这个activity    
            ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
            List<ActivityManager.RunningTaskInfo> taskInfoList = 
                    am.getRunningTasks(10);
            //这里获取的是APP栈的数量,一般也就两个
            ActivityManager.RunningTaskInfo runningTaskInfo = taskInfoList.get(0);
            // 只是拿当前运行的栈
            int numActivities = taskInfoList.get(0).numActivities;
            for (ActivityManager.RunningTaskInfo taskInfo : taskInfoList) {
                if (taskInfo.baseActivity.equals(cmpName)) {// 说明它已经启动了
                    flag = true;
                    break;//跳出循环,优化效率
                }
            }
        }
        return flag;
    }
}

2.应用在前台时,接收推送,弹框;在后台时存数据,待应用切到前台时再弹框。
在前台时,在umeng 封装类里的setMessageHandler()方法内部,重写某个方法,我们是重写dealWithNotificationMessage()。
UmengHelper.java

public class UmPushHelper {
    public static final String TAG = "UmPushHelper";
    static UmPushHelper umPushHelper;
    Context context = MyApplacation.getMyApplication();
    private PushAgent mPushAgent;

    public static UmPushHelper getInstance() {
        if (null == umPushHelper) {
            umPushHelper = new UmPushHelper();
        }
        return umPushHelper;
    }

    /**
     * 友盟初始化
     * <p>
     * 友盟初始化及相关配置
     * 注册
     * 通道配置
     */
    public void init() {
//
        UMConfigure.init(context, "Appkey", "Umeng",
                UMConfigure.DEVICE_TYPE_PHONE, "Umeng Message Secret");
        UMConfigure.setLogEnabled(true);//日志输出,上线关闭
        mPushAgent = PushAgent.getInstance(context);
        mPushAgent.register(new IUmengRegisterCallback() {
            @Override
            public void onSuccess(String deviceToken) {
                //注册成功会返回deviceToken deviceToken是推送消息的唯一标志
                Log.i(TAG, "注册成功:deviceToken:-------->  " + deviceToken);
            }
            @Override
            public void onFailure(String s, String s1) {
                Log.e(TAG, "注册失败:-------->  " + "s:" + s + ",s1:" + s1);
            }
        });
        //小米通道
        MiPushRegistar.register(context, "xiaomiId", "xiaomiKey");
        //华为通道
        HuaWeiRegister.register(MyApplacation.getMyApplication());
        //魅族通道
        MeizuRegister.register(context, "appId", "appKey");
        mPushAgent.onAppStart();
        //最多展示条数
        mPushAgent.setDisplayNotificationNumber(10);
        //通知或消息接收
        setMessageHandler();
        //通知点击
        setNotificationClickHandler();
    }
    /**
     * MessageHandler有很多回调方法,根据自己需要选择
     */
    private void setMessageHandler() {
        UmengMessageHandler messageHandler = new UmengMessageHandler() {
            @Override
            public void dealWithNotificationMessage(Context context, UMessage uMessage) {
                super.dealWithNotificationMessage(context, uMessage);
                Log.e(TAG, "um notification msg.extra" + uMessage.extra);
                try {
                    JSONObject object = new JSONObject(uMessage.extra);

                    int type = object.getInt("type");
                    Long id = object.getLong("id");
                    String title = object.getString("title");

                    ExtraBean bean = new ExtraBean();
                    bean.setId(id);
                    bean.setType(type);
                    bean.setTitle(title);
                    /**
                     * 应用不在前台时,不弹框,并把推送的数据存起来
                     *
                     * 在前台时直接弹框
                     */

                    if (MyApplacation.getMyApplication().getActivityCount() == 0) {
                        ExtraBeanDao dao = MyApplacation.getMyApplication().getDaoSession().getExtraBeanDao();
                        dao.insertOrReplace(bean);
                        return;
                    }
                    Intent intent = new Intent(context, NotificationDialogActivity.class);
                    intent.putExtra("bean", bean);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };
        PushAgent.getInstance(context).setMessageHandler(messageHandler);
    }
    private void setNotificationClickHandler() {
        /**
         * 自定义行为的回调处理,参考文档:高级功能-通知的展示及提醒-自定义通知打开动作
         * UmengNotificationClickHandler是在BroadcastReceiver中被调用,故
         * 如果需启动Activity,需添加Intent.FLAG_ACTIVITY_NEW_TASK
         * */
        UmengNotificationClickHandler notificationClickHandler = new UmengNotificationClickHandler() {

            @Override
            public void launchApp(Context context, UMessage msg) {
                Log.e("umenguuu", "helper launchApp extra:" + msg.extra.toString());
                super.launchApp(context, msg);
            }

            @Override
            public void openUrl(Context context, UMessage msg) {
                Log.e("umenguuu", "helper openUrl extra:" + msg.extra.toString());
                super.openUrl(context, msg);
            }

            @Override
            public void openActivity(Context context, UMessage msg) {
                //获取extra字段值
                Log.e("umenguuu", "helper openActivity extra:" + msg.extra.toString());
                try {
                    JSONObject object = new JSONObject(msg.extra);
                    int type = object.getInt("type");
                    long id = object.getLong("id");
                    String title = object.getString("title");
                    ExtraBean extraBean = new ExtraBean();
                    extraBean.setId(id);
                    extraBean.setType(type);
                    extraBean.setTitle(title);
                    Intent intent;
                    Log.e("umenguuu", "helper type:" + type);

                    /**
                     * type=1 跳详情界面
                     * type=2 跳列表界面
                     */
                    if (type == 1) {
                        intent = new Intent(context, DetailActivity.class);
                    } else {
                        intent = new Intent(context, ListActivity.class);
                    }
                    intent.putExtra("bean", extraBean);

                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void dealWithCustomAction(Context context, UMessage msg) {
                Log.e("umenguuu", "helper dealWithCustomAction extra:" + msg.extra.toString());
            }
        };
        //使用自定义的NotificationHandler   PushAgent.getInstance(context).setNotificationClickHandler(notificationClickHandler);
    }
}

应用在前台还是在后台的判断是在MyApplication.java内部, mActivityCount==0时,意味着应用在后台。

public class MyApplacation extends Application {
    public static final String TAG = "MyApplication";
    private static MyApplacation app;
    private DaoSession daoSession;
    private int mActivityCount = 0;
    public static MyApplacation getMyApplication() {
        return app;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        app = this;//
        UmPushHelper.getInstance().init();//初始化友盟推送
        initDb();//初始化数据库
        /**
         * 通过mActivityCount判断当前应用在前台还是在后台
         */
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                Log.d(TAG, "onActivityCreated");
            }

            @Override
            public void onActivityStarted(Activity activity) {
                Log.d(TAG, "onActivityStarted");
                mActivityCount++;
            }

            @Override
            public void onActivityResumed(Activity activity) {
                Log.d(TAG, "onActivityResumed");
                /**
                 * 后台切前台的时候,判断是否有未弹框的通知消息,如果有遍历弹框
                 *
                 * 说明:此处设计的是弹框叠加,如果只弹一个框,luanchMode="SingleTop"
                 * 并在NotificationDialogActivity内的onNewIntent()方法内处理逻辑
                 *
                 */
                List<ExtraBean> list = getDaoSession().getExtraBeanDao().queryBuilder().list();
                if (null != list && list.size() > 0) {
                    for (ExtraBean bean : list) {
                        Intent intent = new Intent(activity, NotificationDialogActivity.class);
                        intent.putExtra("bean", bean);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必须
                        activity.startActivity(intent);
                    }
                    getDaoSession().getExtraBeanDao().deleteAll();
                }
            }

            @Override
            public void onActivityPaused(Activity activity) {
                Log.d(TAG, "onActivityPaused");
            }

            @Override
            public void onActivityStopped(Activity activity) {
                Log.d(TAG, "onActivityStopped");
                mActivityCount--;
                if (mActivityCount == 0) {//此时切后台
                }
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                Log.d(TAG, "onActivitySaveInstanceState");
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                Log.d(TAG, "onActivityDestroyed");
            }
        });
    }

    public int getActivityCount(){
        return mActivityCount;
    }

    public void initDb() {
        MyOpenHelper helper = new MyOpenHelper(this, "test.db", null);
        //对数据库库加密
//        Database db = helper.getEncryptedWritableDb(UUID);
        //不加密,uyi
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }
    public DaoSession getDaoSession() {
        return daoSession;
    }
}

弹框:用一个透明activity实现假弹框,叠加弹框默认lanuchMode即可,只弹一个lanuchMode="singleTop",并重写onNewIntent()方法。

public class NotificationDialogActivity extends AppCompatActivity {
    private ExtraBean extraBean;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_show_notification);


        textView = findViewById(R.id.textview);
        TextView tvCancel = findViewById(R.id.tv_cancel);
        TextView tvConfirm = findViewById(R.id.tv_confirm);


        extraBean = (ExtraBean) getIntent().getSerializableExtra("bean");

        textView.setText(extraBean.getTitle());
        final int type = extraBean.getType();

       tvConfirm.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Intent intent=null;
               if (type == 1) {
                   intent = new Intent(NotificationDialogActivity.this, DetailActivity.class);
               } else {
                   intent = new Intent(NotificationDialogActivity.this, ListActivity.class);
               }
               intent.putExtra("bean", extraBean);
               startActivity(intent);
               finish();
           }
       });
       tvCancel.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               finish();
           }
       });

    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        extraBean = (ExtraBean) intent.getSerializableExtra("bean");
        textView.setText(extraBean.getTitle());
    }
}

其他类在demo里,demo下载地址:https://github.com/274800562/umengtest.git
如果您觉得此文章对您有帮助,请多多支持。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343