接入友盟推送的實戰(zhàn)總結(jié)

接入友盟推送實戰(zhàn)

標簽(空格分隔): Android

請注意:###

  • 消息推送SDK 不支持在QEMU模擬器上調(diào)試亲配,調(diào)試時請盡量使用真機吸耿。
  • 友盟推送為什么對“廣播”的發(fā)送次數(shù)有3次限制抠蚣?博客
  • 友盟消息推送API調(diào)用有什么頻率或者次數(shù)的限制 博客
    如果分別下發(fā)了兩條消息嚣潜,卻只收到了一條巷懈,先不要著急。因為同一臺設(shè)備在1分鐘內(nèi)收到同一個應(yīng)用的多條通知時览绿,不會重復(fù)提醒策严,同時在通知欄里新的通知會替換掉舊的通知。

1饿敲、首先是自己申請一個APPKey妻导,不能偷懶,媽的怀各!我就是想偷一下懶栗竖,直接用主管的demo里的APPKey,結(jié)果搞了半天沒出渠啤,因為可能他在友盟上已經(jīng)注銷了這個AppKey對應(yīng)的應(yīng)用或者關(guān)閉了對這個應(yīng)用的推送功能狐肢,所以肯定是不能收到推送的。

2沥曹、然后是最坑的一個Bug份名,可能是中國人的軟肋吧碟联,就是依賴中文,雖然自己是個程序員僵腺,但是很多時候還是用能用中文就盡量用中文吧鲤孵。所以導(dǎo)致今天在友盟的官網(wǎng)上出現(xiàn)了用中文起名的悲劇,圖中的用圓圈畫住的部分辰如,千萬不要用中文普监,不然會出現(xiàn)意想不到的Bug×鸲担總的開說,在代碼的世界里凯正,最好一切都用英文!M泱廊散!


捕獲.PNG

3、第三個就是自己真的太粗心了梧疲,竟然認為所以然就沒有加上這一步允睹,真是該打!
原文:

在所有的Activity 的onCreate方法或在應(yīng)用的BaseActivity的onCreate方法中添加:
PushAgent.getInstance(context).onAppStart();
**注意**: 此方法與統(tǒng)計分析sdk中統(tǒng)計日活的方法無關(guān)幌氮!請務(wù)必調(diào)用此方法缭受!
 如果不調(diào)用此方法,不僅會導(dǎo)致按照"幾天不活躍"條件來推送失效该互,還將導(dǎo)致廣播發(fā)送不成功以及設(shè)備描述紅色等問題發(fā)生贯涎。可以只在應(yīng)用的主Activity中調(diào)用此方法慢洋,但是由于SDK的日志發(fā)送策略,有可能由于主activity的日志沒有發(fā)送成功陆盘,而導(dǎo)致未統(tǒng)計到日活數(shù)據(jù)普筹。

我竟然還沒看完就認為這行代碼只是用來統(tǒng)計App啟動的次數(shù)的,真是日了狗隘马!殊不知沒有這行代碼的話太防,是無法接收到推送的,這行代碼跟統(tǒng)計App的啟動次數(shù)是兩碼事酸员!

4蜒车、為什么一旦把應(yīng)用關(guān)了就收不到推送?
除了跟著官方文檔的說明步驟第四大步驟:輕松集成外幔嗦,還要記得在自的項目中添加權(quán)限和在application標簽中添加相應(yīng)的組件酿愧,這樣才能使應(yīng)用不再運行在前臺時,還可以開啟一個在后臺服務(wù)接受推送邀泉,才不會只能在應(yīng)用開啟時才能接到推送嬉挡!
權(quán)限如下:

//下面列出的是必選的權(quán)限钝鸽,還有可選的權(quán)限沒有列出,例如前臺是否可以顯示通知這個可選權(quán)限
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    

添加相應(yīng)的友盟組件如下:

//注意一共有三處地方要將友盟得包名改為自己的包名

        <receiver
            android:name="com.umeng.message.NotificationProxyBroadcastReceiver"
            android:exported="false" >
        </receiver>
        <receiver
            android:name="com.umeng.message.SystemReceiver"
            android:process=":push" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="com.umeng.message.MessageReceiver"
            android:exported="false"
            android:process=":push" >
            <intent-filter>
                <action android:name="org.agoo.android.intent.action.RECEIVE" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="com.umeng.message.ElectionReceiver"
            android:process=":push" >
            <intent-filter>
                <action android:name="org.agoo.android.intent.action.ELECTION_RESULT_V4" />
                <category android:name="umeng" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="com.umeng.message.RegistrationReceiver"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.zun1.whenask.intent.action.COMMAND" />//這是第一處地方要將友盟得包名改為自己的包名
            </intent-filter>
        </receiver>
        <receiver android:name="com.umeng.message.UmengMessageBootReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <service
            android:name="com.umeng.message.UmengService"
            android:label="PushService"
            android:exported="true"
            android:process=":push" >
            <intent-filter>
                <action android:name="com.zun1.whenask.intent.action.START" />//這是第二處地方要將友盟得包名改為自己的包名
            </intent-filter>
            <intent-filter>
                <action android:name="com.zun1.whenask.intent.action.COCKROACH" />//這是第三處地方要將友盟得包名改為自己的包名
            </intent-filter>
            <intent-filter>
                <action android:name="org.agoo.android.intent.action.PING_V4" />
                <category android:name="umeng" />
            </intent-filter>
        </service>

        <service android:name="com.umeng.message.UmengIntentService"
            android:process=":push" />

        <service
            android:name="com.umeng.message.UmengMessageIntentReceiverService"
            android:process=":push"
            android:exported="true" >
            <intent-filter>
                <action android:name="org.android.agoo.client.MessageReceiverService" />
            </intent-filter>
            <intent-filter>
                <action android:name="org.android.agoo.client.ElectionReceiverService" />
            </intent-filter>
        </service>

        <service android:name="com.umeng.message.UmengMessageCallbackHandlerService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.umeng.messge.registercallback.action" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.umeng.message.unregistercallback.action"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.umeng.message.message.handler.action"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.umeng.message.autoupdate.handler.action"/>
            </intent-filter>
        </service>
        <service android:name="com.umeng.message.UmengDownloadResourceService" />
        

5庞钢、關(guān)于獲取不到device_token的問題——參考友盟官方論壇
本人證實可行的方法:
【原理:因為首次獲取device_token時用到的是 mPushAgent.enable(new IUmengRegisterCallback(),這種異步回調(diào)來獲取device_token基括。注意點有兩個:
第一:正是因為是異步回調(diào)的獲取,所以不能保證在用到device_token的時候就已經(jīng)完成了異步回調(diào)獲取河爹,所以會造成device_token還沒獲取到就已經(jīng)執(zhí)行了調(diào)用device_token的代碼,造成device_token為空的原因揪阶,所以解決方法是一定要把那些用到device_token的全部代碼放在獲取到device_token的代碼的后面昌抠,如第39-39行
第二:注意到第一點沒有鲁僚?首次獲取device_token時用到的是 mPushAgent.enable(new IUmengRegisterCallback(),因為是首次啟動應(yīng)用及安裝后運行的這種情況才會執(zhí)行到它冰沙,如果退出應(yīng)用后再次打開時就不走這個方法了侨艾,所以要做好是否第一次啟動應(yīng)用的判斷,如第10-11行拓挥、36-37行、40-41行都是對是否第一次啟動應(yīng)用的判斷以及數(shù)值記錄】

private PushAgent mPushAgent;
private String device_token;
private static final int REQUEST_CODE=200;
private SharedPreferences sp;
private SharedPreferences.Editor editor;
    
mPushAgent = PushAgent.getInstance(this);
        mPushAgent.onAppStart();
      //在這里判斷是否是第一次啟動應(yīng)用
        Boolean isFirstOpen=sp.getBoolean("isFirstOpen",true);//默認是true当叭,第一次啟動盖灸!
        if(isFirstOpen){//如果是第一次啟動
            Log.i("Lee","第一次啟動應(yīng)用");
             mPushAgent.enable(new IUmengRegisterCallback() {//用這種回調(diào)方法的話,只有在首次安裝時才會執(zhí)行醉箕!用于初次獲取測試設(shè)備的Device Token。
            @Override
            public void onRegistered(final String s) {
                Log.i("Lee","go into onRegistered()");
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("Lee","go into run()");
                        int count=0;
                        do {//關(guān)鍵是在這里一直循環(huán)獲取device_token讥裤,這里是在主線程不斷循環(huán)姻报,為什么不會造成ANR?難道是異步回調(diào)的原因嗎剧辐?
                            count++;
                            device_token = UmengRegistrar.getRegistrationId(SetLanguage.this);
                            // device_token = mPushAgent.getRegistrationId();
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e)
                            {
                                Log.i("LeeInterruptedException",e.getMessage());
                            }
                        } while (TextUtils.isEmpty(device_token));//當device_token為null或""時,即還沒獲取到device_token溉奕,若是就繼續(xù)循環(huán)
                        Log.i("Lee count",""+count);
                        Log.i("Lee ——onRegistered", "device_token=" + device_token);

                        editor.putBoolean("isFirstOpen",false);//已運行過應(yīng)用一次忍啤,
                        editor.commit();
                        //以下是添加拿到device_token后的操作
                         AAAAAA..................
        }else {
            Log.i("Lee","不是第一次啟動應(yīng)用");
            //mPushAgent.enable();//因為上面已經(jīng)開啟了mPushAgent.enable(new IUmengRegisterCallback(),所以不用再次開啟mPushAgent.enable()
            //device_token = UmengRegistrar.getRegistrationId(this);//使用這一句跟下面這句是一樣的
            device_token = mPushAgent.getRegistrationId();
            Log.i("Lee ——Not onRegistered", "device_token=" + device_token);
            //以下是添加拿到device_token后的操作
         AAAAAA..................
        }

下面這個是對上面代碼的一些優(yōu)化鳄梅,因為經(jīng)過試驗未檩,就算是寫了循環(huán)去獲取device_token ,但是結(jié)果顯示循環(huán)只執(zhí)行了一次孙蒙,所以說用不著循環(huán)(如果你過大膽的話悲雳,不過建議還是要用循環(huán)比較安全保守)

PushAgent mPushAgent = PushAgent.getInstance(this);
         mPushAgent.onAppStart();
         mPushAgent.enable(new IUmengRegisterCallback() {
            @Override
            public void onRegistered(final String registrationId) {
            //onRegistered方法的參數(shù)registrationId即是device_token
                //new Handler().post(new Runnable() {
                //    @Override
                //    public void run() {
                //        Log.i("xiyuan", "device_token=" + registrationId);
                //    }
               // });
//其實可以直接不寫一個handler來執(zhí)行一個runnable,然后再Run方法里打log坦胶,可以直接在onRegistered里直接打一個Log(不用寫handler晴楔,如下)                Log.i("xiyuan", "device_token=" + s);
            }
        });
        //mPushAgent.enable();//因為上面已經(jīng)開啟了mPushAgent.enable(new IUmengRegisterCallback(),所以不用再次開啟mPushAgent.enable()
       //String device_token = UmengRegistrar.getRegistrationId(this);//使用這一句跟下面這句是一樣的
//關(guān)鍵點是這里税弃,不要在onRegistered方法里獲取device_token钙皮,雖然onRegistered方法的參數(shù)registrationId就是device_token顽决,但是經(jīng)過本人實踐短条,是獲取不到的才菠!所以才會在enable后加上下面這句赋访。
       String device_token = mPushAgent.getRegistrationId();
        Log.i("xiyuani 2", "device_token=" + device_token);

下面是自己另外做的調(diào)試代碼缓待,錯誤例子:

   //不使用異步的回調(diào)去一次獲取device_token,第一次安裝時獲取不到渠牲,但那時第二次啟動時可以獲取到
//        mPushAgent.enable();
//        device_token = mPushAgent.getRegistrationId();
//        //device_token = UmengRegistrar.getRegistrationId(SetLanguage.this);
//        Log.i("Lee —NoCallBack", "device_token=" + device_token);

        //不使用異步的回調(diào)去循環(huán)獲取device_token,這樣的不斷循環(huán)會出現(xiàn)ANR!
//        mPushAgent.enable();
//        int count=0;
//        do {//關(guān)鍵是在這里一直循環(huán)獲取device_token
//            count++;
//            device_token = mPushAgent.getRegistrationId();
//            //device_token = UmengRegistrar.getRegistrationId(SetLanguage.this);
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e)
//            {
//                Log.i("LeeInterruptedException",e.getMessage());
//            }
//        } while (TextUtils.isEmpty(device_token));//判斷device_token是否為空瘫镇,若是就繼續(xù)循環(huán)
//        Log.i("Lee count",""+count);
//        Log.i("Lee —NoCallBack", "device_token=" + device_token);

下面這個是用計時器去不斷獲取device_token 答姥,但那時還沒驗證

 if (device_token.isEmpty()) {
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (device_token.isEmpty() && count < 10) {
                        String temp = UmengRegistrar.getRegistrationId(SetLanguage.this);
                        if (temp == null || temp.isEmpty()) {
                            count++;
                        } else {
                            device_token = temp;
                            count = 0;
                        }
                    } else {
                        count = 0;
                        cancel();
                        Log.d("device_token1", "task has cancle and deviceToken=" + device_token);
                    }
                }
            }, 0, 800);
        }

6、關(guān)于API23 6.0的系統(tǒng)集成友盟時尚粘,權(quán)限android.permission.WRITE_SETTINGS"——系統(tǒng)設(shè)置權(quán)限的授權(quán)的解決方案

android.permission.WRITE_SETTINGS不能自動授權(quán)敲长,也不能運行時請求授權(quán),咋整靶屑痢钳降?通過打開Intent來讓用戶設(shè)置。貌似SETTINGS的權(quán)限只能這么處理铲觉,from CommonsWare research Android 6.0 changes

 @TargetApi(Build.VERSION_CODES.M)//當現(xiàn)在運行程序的系統(tǒng)是API23時才會執(zhí)行這個方法
    public void permissionToWRITE_SETTINGS(){
        if(Build.VERSION.SDK_INT >= 23){
            if(!Settings.System.canWrite(this)){
            //打開設(shè)置界面讓用戶設(shè)置是否授權(quán)系統(tǒng)設(shè)置權(quán)限
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, REQUEST_CODE);
            }
        }

    }
    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE) {
            if (Settings.System.canWrite(this)) {
                //檢查返回結(jié)果
                Toast.makeText(SetLanguage.this, "WRITE_SETTINGS permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(SetLanguage.this, "WRITE_SETTINGS permission not granted", Toast.LENGTH_SHORT).show();
            }
        }
    }

7撵幽、在友盟注冊時忽略的一個小問題導(dǎo)致接收不到推送
官方文檔說明如下:


此處輸入圖片的描述
此處輸入圖片的描述

app_master_secret要填寫在安卓端的androidmanifest中還是只是填寫在服務(wù)器的配置中礁击?還是兩個都要填寫?不管怎樣链烈,兩個端都寫上就最安全挚躯!
使用情況:在有自己的服務(wù)器轉(zhuǎn)接友盟的推送時,記得加上自己的服務(wù)器IP地址


此處輸入圖片的描述
此處輸入圖片的描述
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末漩勤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子触幼,更是在濱河造成了極大的恐慌眉尸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霉祸,死亡現(xiàn)場離奇詭異袱蜡,居然都是意外死亡,警方通過查閱死者的電腦和手機奔穿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門敏晤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人男摧,你說我怎么就攤上這事译打。” “怎么了乔询?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵韵洋,是天一觀的道長。 經(jīng)常有香客問我食拜,道長勉吻,這世上最難降的妖魔是什么旅赢? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任惑惶,我火速辦了婚禮带污,結(jié)果婚禮上香到,老公的妹妹穿的比我還像新娘。我一直安慰自己悠就,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布荸型。 她就那樣靜靜地躺著炸茧,像睡著了一般梭冠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上控漠,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天润脸,我揣著相機與錄音,去河邊找鬼毙驯。 笑死,一個胖子當著我的面吹牛垦巴,可吹牛的內(nèi)容都是我干的铭段。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憔披,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了望门?” 一聲冷哼從身側(cè)響起锰霜,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厨剪,沒想到半個月后友存,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡钾唬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年抡秆,在試婚紗的時候發(fā)現(xiàn)自己被綠了吟策。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡着撩,死狀恐怖匾委,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赂乐,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布挖滤,位于F島的核電站浅役,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惧盹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一反惕、第九天 我趴在偏房一處隱蔽的房頂上張望演侯。 院中可真熱鬧背亥,春花似錦、人聲如沸娄徊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橄仆。三九已至衅斩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間畏梆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工宪巨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溜畅,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓天吓,卻偏偏與公主長得像峦椰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子物邑,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 上周色解,公司要實現(xiàn)推送通知的功能,并決定在項目中集成友盟推送的 SDK來代替之前集成的云巴推送科阎。 云巴推送是什么鬼?...
    4VZhang閱讀 13,070評論 35 15
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評論 25 707
  • 極光推送: 1.JPush當前版本是1.8.2,其SDK的開發(fā)除了正常的功能完善和擴展外也緊隨蘋果官方的步伐错英,SD...
    Isspace閱讀 6,719評論 10 16
  • 貓喜歡吃魚椭岩,可貓不會游泳,魚喜歡吃蚯蚓判哥,可魚不能上岸 ; 一個整宿睡的很好的人惩琉,會嫉妒一個睡眠質(zhì)量不怎么好夺荒、甚至半...
    不忘初心___閱讀 200評論 0 1
  • 短暫的分身術(shù)訓(xùn)練營結(jié)束了,在這幾天里學(xué)到了不少實用性很強的知識伍玖,在以后的工作生活中會多加運用剿吻。 一次刻意訓(xùn)練 在這...
    忘卻的紀念wp閱讀 342評論 0 0