阿里云移動推送的接入和踩坑

近期由于業(yè)務需求,要換掉以前的推送,首先選擇了阿里云推送,官方介紹阿里移動推送(Alibaba Cloud Mobile Push)是基于大數(shù)據(jù)的移動智能推送服務,幫助App快速集成移動推送的功能,在實現(xiàn)高效、精確、實時的移動推送的同時,極大地降低了開發(fā)成本。讓開發(fā)者最有效地與用戶保持連接,從而提高用戶活躍度、提高應用的留存率。那么接下來我們就一起看看是如何接入的。

一. 在阿里云后臺創(chuàng)建自己的App

具體的步驟請詳看阿里云移動推送的技術文檔:阿里云移動推送快速入門

打開阿里云移動研發(fā)平臺EMAS控制臺,進行后面的操作

一、創(chuàng)建產(chǎn)品和應用

移動服務當前創(chuàng)建應用,需要兩步

  • (1)添加產(chǎn)品(產(chǎn)品是一個集合的概念,產(chǎn)品下包含iOS應用、Android應用);
  • (2)在產(chǎn)品處,點擊管理后,右上角點擊“創(chuàng)建應用”完成應用創(chuàng)建。

1、點擊頁面中的“添加產(chǎn)品”按鈕,即可創(chuàng)建一個新的產(chǎn)品

?
2、輸入產(chǎn)品的基本信息創(chuàng)建App時需要輸入產(chǎn)品的名稱,上傳產(chǎn)品圖標,選擇產(chǎn)品分類。

3、產(chǎn)品創(chuàng)建成功

App創(chuàng)建成功后,產(chǎn)品列表會多出一個產(chǎn)品,強烈建議您去配置app。


4、創(chuàng)建產(chǎn)品對應的應用

在產(chǎn)品列表頁面,點擊已經(jīng)創(chuàng)建的產(chǎn)品按鈕,進入產(chǎn)品管理頁面。

?
5、在產(chǎn)品管理頁面,點擊添加應用圖標,創(chuàng)建應用(目前需要分端創(chuàng)建)。

  • (1)創(chuàng)建Android應用,并填寫APP名稱和PackageName

創(chuàng)建完成后,應用會出現(xiàn)在應用列表中:

二. Android SDK 3.0配置

安卓sdk的配置,個人強烈建議采用Maven庫快速集成(遠程同步),本博客也將采用遠程快速集成。

1. 在Project根目錄下build.gradle文件中配置maven庫URL

    allprojects {
        repositories {
            jcenter()
            maven {
                url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
            }
        }
    }

2. 在對應的app下的build.gradle文件中添加對應依賴

    android {
        ......
        defaultConfig {
            applicationId "com.xxx.xxx" //包名
            ......
            ndk {
                //選擇要添加的對應cpu類型的.so庫。
                abiFilters 'armeabi', 'x86'
            }
            ......
        }
        ......
    }
    dependencies {
        ......
        compile 'com.aliyun.ams:alicloud-android-push:3.1.4@aar'
        // 或(二選一)
        compile 'com.aliyun.ams:alicloud-android-push:3.1.4'

        compile 'com.aliyun.ams:alicloud-android-utils:1.1.3'
        compile 'com.aliyun.ams:alicloud-android-beacon:1.0.1'
        compile 'com.aliyun.ams:alicloud-android-ut:5.4.0'

        ......
    }

特別注意 : 如果在添加以上 abiFilter 配置之后android Studio出現(xiàn)以下提示:

    NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.

則在 Project 根目錄的gradle.properties文件中添加:

android.useDeprecatedNdk=true

3. appKey, appSecret配置

在AndroidManifest文件中設置appKey,appSecret:

    <application android:name="*****">
        <meta-data android:name="com.alibaba.app.appkey" android:value="*****"/> <!-- 請?zhí)顚懩阕约旱? appKey -->
        <meta-data android:name="com.alibaba.app.appsecret" android:value="****"/> <!-- 請?zhí)顚懩阕约旱腶ppSecret -->
    </application>

**特別提示:**com.alibaba.app.appkeycom.alibaba.app.appsecret為您App的對應信息,在推送控制臺APP列表頁的應用證書中獲取。appkeyappsecret請務必寫在application標簽下,否則sdk會報找不到appkey錯誤。如果您是百川云推送用戶,不能直接使用百川平臺的appKey和appSecret,需要登錄阿里云移動推送控制臺,登錄賬號為您的百川平臺賬號,并使用阿里云平臺的appKey,appSecret。

Permission權限配置:

    <!-- 阿里云推送相關權限 -->
    <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.RESTART_PACKAGES" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.REORDER_TASKS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

4. 消息接收Receiver配置

創(chuàng)建消息接收Receiver,繼承自com.alibaba.sdk.android.push.MessageReceiver,并在對應回調(diào)中添加業(yè)務處理邏輯,可參考以下代碼:

    public class MyMessageReceiver extends MessageReceiver {
        // 消息接收部分的LOG_TAG
        public static final String REC_TAG = "receiver";
        @Override
        public void onNotification(Context context, String title, String summary, Map<String, String> extraMap) {
            // TODO 處理推送通知
            Log.e("MyMessageReceiver", "Receive notification, title: " + title + ", summary: " + summary + ", extraMap: " + extraMap);
        }
        @Override
        public void onMessage(Context context, CPushMessage cPushMessage) {
                Log.e("MyMessageReceiver", "onMessage, messageId: " + cPushMessage.getMessageId() + ", title: " + cPushMessage.getTitle() + ", content:" + cPushMessage.getContent());
        }
        @Override
        public void onNotificationOpened(Context context, String title, String summary, String extraMap) {
            Log.e("MyMessageReceiver", "onNotificationOpened, title: " + title + ", summary: " + summary + ", extraMap:" + extraMap);
        }
        @Override
        protected void onNotificationClickedWithNoAction(Context context, String title, String summary, String extraMap) {
            Log.e("MyMessageReceiver", "onNotificationClickedWithNoAction, title: " + title + ", summary: " + summary + ", extraMap:" + extraMap);
        }
        @Override
        protected void onNotificationReceivedInApp(Context context, String title, String summary, Map<String, String> extraMap, int openType, String openActivity, String openUrl) {
            Log.e("MyMessageReceiver", "onNotificationReceivedInApp, title: " + title + ", summary: " + summary + ", extraMap:" + extraMap + ", openType:" + openType + ", openActivity:" + openActivity + ", openUrl:" + openUrl);
        }
        @Override
        protected void onNotificationRemoved(Context context, String messageId) {
            Log.e("MyMessageReceiver", "onNotificationRemoved");
        }
    }

將該receiver添加到AndroidManifest.xml中(切不要忘記了)

    <!-- 消息接收監(jiān)聽器 (用戶可自主擴展) -->
    <receiver
        android:name=".MyMessageReceiver"
        android:exported="false"> <!-- 為保證receiver安全,建議設置不可導出,如需對其他應用開放可通過android:permission進行限制 -->
        <intent-filter>
            <action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.alibaba.sdk.android.push.RECEIVE" />
        </intent-filter>
    </receiver>

如果是從V2.3.7及以下版本升級到V3.0.0及以上版本的用戶,需將<action android:name="org.agoo.android.intent.action.RECEIVE" />改為<action android:name="com.alibaba.sdk.android.push.RECEIVE" />,否則會接收不到推送。

5. Proguard配置

    -keepclasseswithmembernames class ** {
        native <methods>;
    }
    -keepattributes Signature
    -keep class sun.misc.Unsafe { *; }
    -keep class com.taobao.** {*;}
    -keep class com.alibaba.** {*;}
    -keep class com.alipay.** {*;}
    -keep class com.ut.** {*;}
    -keep class com.ta.** {*;}
    -keep class anet.**{*;}
    -keep class anetwork.**{*;}
    -keep class org.android.spdy.**{*;}
    -keep class org.android.agoo.**{*;}
    -keep class android.os.**{*;}
    -dontwarn com.taobao.**
    -dontwarn com.alibaba.**
    -dontwarn com.alipay.**
    -dontwarn anet.**
    -dontwarn org.android.spdy.**
    -dontwarn org.android.agoo.**
    -dontwarn anetwork.**
    -dontwarn com.ut.**
    -dontwarn com.ta.**

6. 在應用中注冊和啟動移動推送

  • 首先通過PushServiceFactory獲取到CloudPushService,然后調(diào)用register()初始化并注冊云推送通道,并確保Application上下文中進行初始化工作。
  • 請參照以下代碼段進行初始化:
    import android.app.Application;
    import android.content.Context;
    import android.util.Log;
    import com.alibaba.sdk.android.push.CloudPushService;
    import com.alibaba.sdk.android.push.CommonCallback;
    import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
    public class MainApplication extends Application {
        private static final String TAG = "Init";
        @Override
        public void onCreate() {
            super.onCreate();
            initCloudChannel(this);
        }
        /**
         * 初始化云推送通道
         * @param applicationContext
         */
        private void initCloudChannel(Context applicationContext) {
            PushServiceFactory.init(applicationContext);
            CloudPushService pushService = PushServiceFactory.getCloudPushService();
            pushService.register(applicationContext, new CommonCallback() {
                @Override
                public void onSuccess(String response) {
                    Log.d(TAG, "init cloudchannel success");
                }
                @Override
                public void onFailed(String errorCode, String errorMessage) {
                    Log.d(TAG, "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
                }
            });
        }
    }

【注意】:

  • 移動推送的初始化必須在Application中,不能放到Activity中執(zhí)行。移動推送在初始化過程中將啟動后臺進程channel,必須保證應用進程和channel進程都執(zhí)行到推送初始化代碼。
  • 如果設備成功注冊,將回調(diào)callback.onSuccess()方法。
  • 但如果注冊服務器連接失敗,則調(diào)用callback.onFailed方法,并且自動進行重新注冊,直到onSuccess為止。(重試規(guī)則會由網(wǎng)絡切換等時間自動觸發(fā)。)
  • 請在網(wǎng)絡通暢的情況下進行相關的初始化調(diào)試,如果網(wǎng)絡不通,或者App信息配置錯誤,在onFailed方法中,會有相應的錯誤碼返回,可參考錯誤處理。

啟動正常確認方法:

  • 回調(diào)方法callback.onSuccess()被調(diào)用。以上文接入代碼為例,logcat將會打印以下日志:
11-24 12:55:51.096 15235-15535/com.alibaba.xxxx D/YourApp﹕ init cloudchannel success
  • 確認cloudchannel初始化正常,在logcat日志中:輸入awcn關鍵字:
11-24 12:53:51.036 15235-15556/com.alibaba.xxxx E/awcn﹕ |[seq:AWCN1_1] AUTH httpStatusCode: 200
11-24 12:53:51.036 15235-15556/com.alibaba.xxxx E/awcn﹕ |[seq:AWCN1_1] status:AUTH_SUCC

以上就是阿里云推送的創(chuàng)建、接入和sdk初始化的過程,做到這里我們就可以阿里云移動推送后臺發(fā)送測試推送了,但是在安卓8.0以上發(fā)現(xiàn)收不到推送,自8.0(API Level 26)起,Android 推出了NotificationChannel機制,旨在對通知進行分類管理。如果用戶App的targetSdkVersion大于等于26,且并未設置NotificaitonChannel,創(chuàng)建的通知是不會彈出的,所以我們要對8.0及其以上的設配設置NotificaitonChannel。

具體調(diào)用位置為:Application的onCreate,云推初始化前后都可以,具體代碼如下:

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                // 通知渠道的id
                String id = "1";
                // 用戶可以看到的通知渠道的名字.
                CharSequence name = "notification channel";
                // 用戶可以看到的通知渠道的描述
                String description = "notification description";
                int importance = NotificationManager.IMPORTANCE_HIGH;
                NotificationChannel mChannel = new NotificationChannel(id, name, importance);
                // 配置通知渠道的屬性
                mChannel.setDescription(description);
                // 設置通知出現(xiàn)時的閃燈(如果 android 設備支持的話)
                mChannel.enableLights(true);
                mChannel.setLightColor(Color.RED);
                // 設置通知出現(xiàn)時的震動(如果 android 設備支持的話)
                mChannel.enableVibration(true);
                mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
                //最后在notificationmanager中創(chuàng)建該通知渠道
                mNotificationManager.createNotificationChannel(mChannel);
            }

在服務端的話一定也要設置:

// 指定notificaitonchannel id
pushRequest.setAndroidNotificationChannel("1"); 

特別注意:利用阿里云控制臺推送

使用阿里云控制臺推送通知時,需要設置 “高級設置”,在最下面的 “Android8.0 特殊配置:” ,填寫 “通知通道:”,也就是上述客戶端注冊的 NotificationChannel 的 id,例如上述代碼中NotificationChannel 為1,如下圖所示:

以上就是阿里云的全部推送,那么還有一個很致命的問題在這,目前谷歌的推送通道在大陸被墻了,一般的推送只能用service接收,并且app只能在啟動或者后臺的情況下收的到。當App進程被殺死后,推送是收不到的,那么該如何解決這種問題呢?

目前市面上華為、小米、oppo、vivo和魅族品牌占據(jù)大陸手機市場前五,每個品牌的手機都有自己的推送渠道,以下我簡稱輔助渠道。也就是說當app的進程被殺死的情況下,我們可以通過廠商渠道來推送,這樣即使App不啟動也可以收到推送。

接下來我們一起來看一下輔助渠道的接入,不要走開,這個是關鍵點哦?。。?!

一. 小米/華為/OPPO系統(tǒng)推送支持

  • 輔助通道:移動推送針對小米、華為設備管控較嚴的情況特意接入華為,小米推送輔助通道以提高在華為、小米設備上的到達率。移動推送優(yōu)先選擇自有通道進行推送消息下發(fā),只有在自有通道斷連時選擇輔助通道下發(fā)消息。當前輔助通道通過華為、小米推送下發(fā)透傳消息,消息到達應用后經(jīng)移動推送SDK處理后觸發(fā)onNotification,onMessage回調(diào)。小米、華為推送在下發(fā)透傳消息時并不保證會拉起被殺死進程(相關機制可參考小米、華為推送官網(wǎng)),所以輔助通道在進程被殺死情況下無法保證消息一定到達。
  • 輔助彈窗:輔助彈窗通過系統(tǒng)通道下發(fā)通知,可以在進程被殺死情況下推送成功。由于輔助彈窗通過在對應設備上推送通知實現(xiàn),因而通過輔助彈窗下發(fā)的通知不會觸發(fā)onNotification回調(diào)。當前移動推送已接入小米、華為、OPPO輔助彈窗。其中華為彈窗到達率統(tǒng)計只覆蓋用戶點擊華為彈窗推送通知的場景,未點擊部分暫未覆蓋;小米彈窗到達率統(tǒng)計覆蓋所有場景。

在對應的應用市場配置應用

  • 小米開放平臺 注冊你的App, 得到相應的小米AppID,小米AppKey,小米AppSecert。在控制臺應用配置設置你的小米AppSecert。(注意:最新的小米開放平臺是分開 push 功能的,需要在 push 功能區(qū) 開通/啟用 推送功能)。

  • 同理在 華為開發(fā)者聯(lián)盟 注冊 App,應用審核通過后,能夠得到華為的AppID和AppSecert。在控制臺應用配置中設置你的華為AppID和AppSecert。(注意:最新的華為開放平臺是分開push功能的,需要在push功能區(qū) 開通/啟用 推送功能)

  • OPPO開放平臺 注冊OPPO企業(yè)開發(fā)者賬號,添加應用并開通oppo推送服務,目前應用需滿足:1.在oppo市場上架,2.評級為A,才能使用推送服務,具體政策可咨詢oppo客服。同樣需要在控制臺應用配置設置你的OppoAppkey和OppoMasterSecret(AppServerSecret )。

二. 依賴Maven集成

1. 項目頂層build.gradle中添加Maven倉庫地址:

    allprojects {
        repositories {
            maven {
                url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
            }
        }
    }

2. gradle添加依賴:

    dependencies {
        compile 'com.aliyun.ams:alicloud-android-third-push:3.0.6@aar'
    }

需要特別注意的地方:oppo 通道 需使用 v3.0.6 版本,應用滿足:1、在 oppo 市場上架,2、評級為 A.

3. Proguard配置

如果集成推送SDK的工程開啟代碼混淆,在Proguard配置的基礎上,需要添加以下輔助通道的Proguard配置。

    # 小米通道
    -keep class com.xiaomi.** {*;}
    -dontwarn com.xiaomi.**
    # 華為通道
    -keep class com.huawei.** {*;}
    -dontwarn com.huawei.**
    # OPPO通道
    -keep public class * extends android.app.Service

4. 在應用中初始化輔助通道

將以下代碼加入你application.onCreate()方法中初始通道。注意:輔助通道注冊務必在Application中執(zhí)行且放在推送SDK初始化代碼之后,否則可能導致輔助通道注冊失敗

    // 注冊方法會自動判斷是否支持小米系統(tǒng)推送,如不支持會跳過注冊。
    MiPushRegister.register(applicationContext, "小米AppID", "小米AppKey");
    // 注冊方法會自動判斷是否支持華為系統(tǒng)推送,如不支持會跳過注冊。
    HuaWeiRegister.register(applicationContext);
    //GCM/FCM輔助通道注冊
    GcmRegister.register(this, sendId, applicationId); //sendId/applicationId為步驟獲得的參數(shù)
    // OPPO通道注冊
    OppoRegister.register(applicationContext, appKey, appSecret); // appKey/appSecret在OPPO通道開發(fā)者平臺獲取

注意:1. 本方法會自動判斷是否支持小米系統(tǒng)推送,如不支持會跳過注冊。

      2\. 如果控制臺配置了`小米/華為`的信息,app需要加對應的jar包依賴,不然會有crash的風險。

      3\. OPPO通道是否注冊成功, 可以通過過濾`MPS:oppo`關鍵字查看, 注冊成功會打印`onRegister regid=****`相關日志, 否則檢 查參數(shù)是否正確填入;

      4\. 客戶端接入完畢,服務端推送時如果設備無法收到推送,可先查看 [移動推送Android SDK:Android輔助通道和彈窗排查步驟](https://help.aliyun.com/knowledge_detail/57105.html)

接入輔助通道后,需要結合輔助彈窗來接收推送

1. 當前輔助彈窗已接入小米、華為、OPPO(小米輔助彈窗:v2.3.0及以上支持;華為輔助彈窗:v3.0.8及以上支持;OPPO輔助彈窗:v3.1.4及以上支持);

2. 當前華為輔助彈窗僅支持Emotion UI(華為定制ROM)4.1級以上版本的設備;

輔助彈窗在客戶端設置:

  • 輔助彈窗送達的通知展示效果,和普通通知相同;

  • 服務端指定輔助彈窗通道推送時,一定要指定通知點擊后要打開的Activity,該Activity需繼承自抽象類AndroidPopupActivityMiPushSystemNotificationActivity已廢棄,小米彈窗、華為彈窗、OPPO彈窗統(tǒng)一繼承AndroidPopupActivity),否則無法獲取到通知的相關信息,并且會影響通知到達率的統(tǒng)計;

  • AndroidPopupActivity中提供抽象方法onSysNoticeOpened(),實現(xiàn)該方法后可獲取到輔助彈窗通知的標題、內(nèi)容額外參數(shù),在通知點擊時觸發(fā),原本的通知回調(diào)onNotification()onNotificationOpened()不適用于輔助彈窗;

  • 指定打開的托管彈窗Activity在AndroidManifest.xml中注冊時需要聲明屬性:android:exported=true

  • 接入如下所示:

    import com.alibaba.sdk.android.push.AndroidPopupActivity;
    public class PopupPushActivity extends AndroidPopupActivity {
        static final String TAG = "PopupPushActivity";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
        /**
         * 實現(xiàn)通知打開回調(diào)方法,獲取通知相關信息
         * @param title     標題
         * @param summary   內(nèi)容
         * @param extMap    額外參數(shù)
         */
        @Override
        protected void onSysNoticeOpened(String title, String summary, Map<String, String> extMap) {
            Log.d("OnMiPushSysNoticeOpened, title: " + title + ", content: " + summary + ", extMap: " + extMap);
        }
    }

以上就是輔助通道和輔助彈窗的接入的全過程,需要特別的注意的是華為的開發(fā)者聯(lián)盟里push需要設置sha2和回調(diào)地址,這一條需要特別的注意。以上有不明白的小伙伴,可以評論留言咨詢。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 前言:由于項目需要消息推送功能,由于 Android 谷歌官方的服務C2DM(Android Cloud to D...
    呼呼哥閱讀 8,153評論 8 16
  • 由于谷歌服務在國內(nèi)不能用,Android 的推送真是一大痛點,但也推動了國內(nèi)一批做第三方服務的廠商。第三方推送...
    U卡技術閱讀 6,790評論 1 10
  • Android集成友盟集成推送方案調(diào)研 鑒于項目apk瘦身的需求,經(jīng)過調(diào)研,發(fā)現(xiàn)現(xiàn)有的推送集成方案可以優(yōu)化。現(xiàn)有的...
    tinyvampirepudg閱讀 3,201評論 0 1
  • 凌晨三點鐘 發(fā)白的燈光 冷清的廊道里 匆匆的衣袍者 重重地腳步聲 擊碎寧靜的夜空 發(fā)亮的長椅 孤單的身影 滿地的煙...
    鄧虢閱讀 312評論 1 2
  • 【R:閱讀原文】 一階段 片段 一:選自《非暴力溝通》 非暴力溝通強調(diào),感受的根源在于我們自身。我們的需要和期待,...
    雪妖妖2017閱讀 136評論 3 0

友情鏈接更多精彩內(nèi)容