近期由於業務需求,要換掉以前的推送,首先選擇了阿里雲推送,官方介紹阿里移動推送(Alibaba Cloud Mobile Push)是基於大數據的移動智能推送服務,幫助App快速集成移動推送的功能,在實現高效、精確、實時的移動推送的同時,極大地降低了開發成本。讓開發者最有效地與用戶保持連接,從而提高用戶活躍度、提高應用的留存率。那麼接下來我們就一起看看是如何接入的。
一. 在阿里雲後臺創建自己的App
具體的步驟請詳看阿里雲移動推送的技術文檔:阿里雲移動推送快速入門
打開阿里雲移動研發平臺EMAS控制檯,進行後面的操作
一、創建產品和應用
移動服務當前創建應用,需要兩步
- (1)添加產品(產品是一個集合的概念,產品下包含iOS應用、Android應用);
- (2)在產品處,點擊管理後,右上角點擊“創建應用”完成應用創建。
1、點擊頁面中的“添加產品”按鈕,即可創建一個新的產品
2、輸入產品的基本信息創建App時需要輸入產品的名稱,上傳產品圖標,選擇產品分類。
3、產品創建成功
App創建成功後,產品列表會多出一個產品,強烈建議您去配置app。
4、創建產品對應的應用
在產品列表頁面,點擊已經創建的產品按鈕,進入產品管理頁面。
5、在產品管理頁面,點擊添加應用圖標,創建應用(目前需要分端創建)。
- (1)創建Android應用,並填寫APP名稱和PackageName
創建完成後,應用會出現在應用列表中:
二. 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出現以下提示:
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="*****"/> <!-- 請填寫你自己的- appKey -->
<meta-data android:name="com.alibaba.app.appsecret" android:value="****"/> <!-- 請填寫你自己的appSecret -->
</application>
特別提示:com.alibaba.app.appkey
和com.alibaba.app.appsecret
爲您App的對應信息,在推送控制檯APP列表頁的應用證書中獲取。appkey
和appsecret
請務必寫在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配置
創建消息接收Receiver,繼承自com.alibaba.sdk.android.push.MessageReceiver,並在對應回調中添加業務處理邏輯,可參考以下代碼:
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中(切不要忘記了)
<!-- 消息接收監聽器 (用戶可自主擴展) -->
<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
,然後調用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中執行。移動推送在初始化過程中將啓動後臺進程channel,必須保證應用進程和channel進程都執行到推送初始化代碼。
- 如果設備成功註冊,將回調callback.onSuccess()方法。
- 但如果註冊服務器連接失敗,則調用callback.onFailed方法,並且自動進行重新註冊,直到onSuccess爲止。(重試規則會由網絡切換等時間自動觸發。)
- 請在網絡通暢的情況下進行相關的初始化調試,如果網絡不通,或者App信息配置錯誤,在onFailed方法中,會有相應的錯誤碼返回,可參考錯誤處理。
啓動正常確認方法:
- 回調方法callback.onSuccess()被調用。以上文接入代碼爲例,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
-
確認DeviceId獲取正常:在初始化成功後使用
cloudPushService.getDeviceId()
獲取deviceId,應該能夠成功獲取。 -
如果集成移動推送的過程中遇到了
utdid
衝突,可參考:阿里雲-移動雲產品SDK UTDID衝突解決方案
以上就是阿里雲推送的創建、接入和sdk初始化的過程,做到這裏我們就可以阿里雲移動推送後臺發送測試推送了,但是在安卓8.0以上發現收不到推送,自8.0(API Level 26)起,Android 推出了NotificationChannel機制,旨在對通知進行分類管理。如果用戶App的targetSdkVersion
大於等於26,且並未設置NotificaitonChannel
,創建的通知是不會彈出的,所以我們要對8.0及其以上的設配設置NotificaitonChannel。
具體調用位置爲: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);
// 設置通知出現時的閃燈(如果 android 設備支持的話)
mChannel.enableLights(true);
mChannel.setLightColor(Color.RED);
// 設置通知出現時的震動(如果 android 設備支持的話)
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
//最後在notificationmanager中創建該通知渠道
mNotificationManager.createNotificationChannel(mChannel);
}
在服務端的話一定也要設置:
// 指定notificaitonchannel id
pushRequest.setAndroidNotificationChannel("1");
特別注意:利用阿里雲控制檯推送
使用阿里雲控制檯推送通知時,需要設置 “高級設置”,在最下面的 “Android8.0 特殊配置:” ,填寫 “通知通道:”,也就是上述客戶端註冊的 NotificationChannel 的 id,例如上述代碼中NotificationChannel 爲1,如下圖所示:
以上就是阿里雲的全部推送,那麼還有一個很致命的問題在這,目前谷歌的推送通道在大陸被牆了,一般的推送只能用service接收,並且app只能在啓動或者後臺的情況下收的到。當App進程被殺死後,推送是收不到的,那麼該如何解決這種問題呢?
目前市面上華爲、小米、oppo、vivo和魅族品牌佔據大陸手機市場前五,每個品牌的手機都有自己的推送渠道,以下我簡稱輔助渠道。也就是說當app的進程被殺死的情況下,我們可以通過廠商渠道來推送,這樣即使App不啓動也可以收到推送。
接下來我們一起來看一下輔助渠道的接入,不要走開,這個是關鍵點哦!!!!
一. 小米/華爲/OPPO系統推送支持
- 輔助通道:移動推送針對小米、華爲設備管控較嚴的情況特意接入華爲,小米推送輔助通道以提高在華爲、小米設備上的到達率。移動推送優先選擇自有通道進行推送消息下發,只有在自有通道斷連時選擇輔助通道下發消息。當前輔助通道通過華爲、小米推送下發透傳消息,消息到達應用後經移動推送SDK處理後觸發
onNotification
,onMessage
回調。小米、華爲推送在下發透傳消息時並不保證會拉起被殺死進程(相關機制可參考小米、華爲推送官網),所以輔助通道在進程被殺死情況下無法保證消息一定到達。 - 輔助彈窗:輔助彈窗通過系統通道下發通知,可以在進程被殺死情況下推送成功。由於輔助彈窗通過在對應設備上推送通知實現,因而通過輔助彈窗下發的通知不會觸發
onNotification
回調。當前移動推送已接入小米、華爲、OPPO輔助彈窗。其中華爲彈窗到達率統計只覆蓋用戶點擊華爲彈窗推送通知的場景,未點擊部分暫未覆蓋;小米彈窗到達率統計覆蓋所有場景。
在對應的應用市場配置應用
- 在 小米開放平臺 註冊你的App, 得到相應的小米AppID,小米AppKey,小米AppSecert。在控制檯
應用配置
設置你的小米AppSecert。(注意:最新的小米開放平臺是分開 push 功能的,需要在 push 功能區 開通/啓用 推送功能
)。 -
同理在 華爲開發者聯盟 註冊 App,應用審覈通過後,能夠得到華爲的AppID和AppSecert。在控制檯
應用配置
中設置你的華爲AppID和AppSecert。(注意:最新的華爲開放平臺是分開push功能的,需要在push功能區 開通/啓用 推送功能) -
在OPPO開放平臺 註冊OPPO企業開發者賬號,添加應用並開通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中執行且放在推送SDK初始化代碼之後,否則可能導致輔助通道註冊失敗
// 註冊方法會自動判斷是否支持小米系統推送,如不支持會跳過註冊。
MiPushRegister.register(applicationContext, "小米AppID", "小米AppKey");
// 註冊方法會自動判斷是否支持華爲系統推送,如不支持會跳過註冊。
HuaWeiRegister.register(applicationContext);
//GCM/FCM輔助通道註冊
GcmRegister.register(this, sendId, applicationId); //sendId/applicationId爲步驟獲得的參數
// OPPO通道註冊
OppoRegister.register(applicationContext, appKey, appSecret); // appKey/appSecret在OPPO通道開發者平臺獲取
注意:1. 本方法會自動判斷是否支持小米系統推送,如不支持會跳過註冊。
2. 如果控制檯配置了小米/華爲
的信息,app需要加對應的jar包依賴,不然會有crash的風險。
3. OPPO通道是否註冊成功, 可以通過過濾MPS:oppo
關鍵字查看, 註冊成功會打印onRegister regid=****
相關日誌, 否則檢 查參數是否正確填入;
4. 客戶端接入完畢,服務端推送時如果設備無法收到推送,可先查看 移動推送Android SDK:Android輔助通道和彈窗排查步驟
接入輔助通道後,需要結合輔助彈窗來接收推送
1. 當前輔助彈窗已接入小米、華爲、OPPO(小米輔助彈窗:v2.3.0及以上支持
;華爲輔助彈窗:v3.0.8及以上支持
;OPPO輔助彈窗:v3.1.4及以上支持
);
2. 當前華爲輔助彈窗僅支持Emotion UI(華爲定製ROM)4.1級以上版本的設備;
輔助彈窗在客戶端設置:
- 輔助彈窗送達的通知展示效果,和普通通知相同;
- 服務端指定輔助彈窗通道推送時,一定要指定通知點擊後要打開的Activity,該Activity需繼承自抽象類
AndroidPopupActivity
(MiPushSystemNotificationActivity
已廢棄,小米彈窗、華爲彈窗、OPPO彈窗統一繼承AndroidPopupActivity
),否則無法獲取到通知的相關信息,並且會影響通知到達率的統計; AndroidPopupActivity
中提供抽象方法onSysNoticeOpened()
,實現該方法後可獲取到輔助彈窗通知的標題
、內容
和額外參數
,在通知點擊時觸發,原本的通知回調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);
}
/**
* 實現通知打開回調方法,獲取通知相關信息
* @param title 標題
* @param summary 內容
* @param extMap 額外參數
*/
@Override
protected void onSysNoticeOpened(String title, String summary, Map<String, String> extMap) {
Log.d("OnMiPushSysNoticeOpened, title: " + title + ", content: " + summary + ", extMap: " + extMap);
}
}
以上就是輔助通道和輔助彈窗的接入的全過程,需要特別的注意的是華爲的開發者聯盟裏push需要設置sha2和回調地址,這一條需要特別的注意。以上有不明白的小夥伴,可以評論留言諮詢。