1.android的推送一直飽受詬病,最近項目中需要用到推送劣摇。本來用的是極光推送,但是應用一旦被殺死推送便收不到。我跟boss說這是android的問題,不能做到ios那樣百分百推送,但是boss說你看人家誰誰的應用我清理掉后臺推送怎么還可以收到的畴。最后經(jīng)過網(wǎng)上的一通搜,查到了輔助通道推送。
2.什么是輔助通道推送,即集成品牌機的官方推送(華為尝胆、小米丧裁、OPPO)這樣如果你的應用在這些手機上即使殺死APP照樣可以收到通知,但是如果沒有集成輔助通道推送那收到通知只能隨緣了。
3.我集成了阿里的移動推送這里記錄一下含衔。畢竟不是專業(yè)做推送的就在我集成的當天,阿里的移動推送居然出問題了,IOS的通知延時高達3小時上新聞了煎娇。不管了android沒受影響,關(guān)鍵是boss的手機是華為手機必須保證boss是手機能收到推送哈哈。
4.貼上阿里移動推送的官方鏈接:https://help.aliyun.com/document_detail/51056.html?spm=a2c4g.11174283.3.4.52eb6d16SpqQmM
5.建議使用maven快速集成簡單方便贪染。
(1).在Project根目錄下build.gradle文件中配置maven庫URL:
allprojects {
repositories {
jcenter()
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}
(2).在對應的module下的build.gradle文件中添加對應依賴缓呛。
android {
......
defaultConfig {
applicationId "com.xxx.xxx" //包名
......
ndk {
//選擇要添加的對應cpu類型的.so庫。
abiFilters 'armeabi', 'x86'
}
......
}
......
}
dependencies {
......
implementation 'com.aliyun.ams:alicloud-android-push:3.1.4'
......
}
注 : 如果在添加以上 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).在AndroidManifest文件中設置appKey杭隙,appSecret(注:這里有個坑在粘貼appsecret的時候多個空格注意要刪掉!!!!):
<application android:name="*****">
<meta-data android:name="com.alibaba.app.appkey" android:value="*****"/>
<meta-data android:name="com.alibaba.app.appsecret" android:value="****"/>
</application>
(4).創(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中
<receiver
android:name=".MyMessageReceiver"
android:exported="false">
<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>
(4).混淆配置
-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.**
(5).初始化阿里推送
首先通過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)絡通暢的情況下進行相關(guān)的初始化調(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關(guān)鍵字:
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
沖突池磁,可參考:阿里云-移動云產(chǎn)品SDK UTDID沖突解決方案
(6).Android8.0及以上NotificationChannel機制
在客戶端創(chuàng)建自己的NotificationChannel
奔害,可參考下面代碼
具體調(diào)用位置為:Application的onCreate,云推初始化前后都可以地熄,可參考 Demo
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);
}
(7).集成輔助通道推送华临。
(1).目前阿里只有華為、小米端考、OPPO雅潭、谷歌上各自的開放平臺開通推送服務配置到阿里的控制臺。
(2).添加輔助通道依賴却特。
dependencies {
compile 'com.aliyun.ams:alicloud-android-third-push:3.0.6@aar'
}
(3).如果集成了谷歌商店的推送的話需要額外的配置一下
dependencies {
......
compile ('com.google.firebase:firebase-messaging:9.6.1')
}
同時在AndroidManifest文件中添加如下配置:
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.taobao.taobao" />
</intent-filter>
</receiver>
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
android:exported="false" />
<service
android:name="com.alibaba.sdk.android.push.AgooFirebaseInstanceIDService"
android:exported="true" >
<intent-filter android:priority="-500" >
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name="com.alibaba.sdk.android.push.AgooFirebaseMessagingService"
android:exported="true" >
<intent-filter android:priority="-500" >
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
(4).混淆配置扶供。
小米通道
-keep class com.xiaomi.** {;}
-dontwarn com.xiaomi.*
華為通道
-keep class com.huawei.** {;}
-dontwarn com.huawei.*
GCM/FCM通道
-keep class com.google.firebase.{;}
-dontwarn com.google.firebase.*
OPPO通道
-keep public class * extends android.app.Service
(5).初始化輔助通道。
將以下代碼加入你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ā)者平臺獲
(6).用指定的機型查看log是否集成成功尼荆。
華為通道初始化成功,可以看到以下日志:
11-11 22:21:33.671 30248-30324/com.xxx E/MPS:HuaWeiRegister: HuaWeiRegister checkDevice flag=true //確認是華為的手機
11-11 22:21:33.674 30248-30324/com.xxx E/MPS:HuaWeiRegister﹕ Register huawei push............ //開始注冊華為手機
11-11 22:21:33.714 29643-30328/com.xxx E/MPS:HuaWeiRegister﹕ huawei register success唧垦,token = 08657430243125472000000411000001
小米通道初始化成功捅儒,可以看到以下日志:
12-09 22:20:39.710 19566-19566/com.xxx E/MPS:MiPushRegister: MiPushRegister checkDevice flag=true //確認是小米的手機
12-09 22:20:39.712 19566-19566/com.xxx E/MPS:MiPushRegister: Register mipush. //開始注冊小米
12-09 22:20:40.596 19566-19733/com.xxx E/MPS:MiPushRegister: XiaoMi register success. //小米注冊成功 regid=d//igwEhgBGCI2TG6lWqlCesc0I6xE1wUhNCBXQ8uNOi/dDZioYXVysbrVrvRmyEVPn9nWz92D28IzYbA1RzoGDyTzYZwXKfBHEQkrey4G8=
GCM/FCM通道初始化成功,可以看到以下日志:
05-19 19:18:44.530 19153-19177/com.xxx D/MPS:GcmRegister: token from register: eWIXLYCNP0Q:APA91bFUAgxj6XYf5okyoCBnRPw1UwITndzXrvPDgbdI2N44PYm17hFEBiNXNQJrJ8bOG_xjw3c3UPDAhzNMTLNjlAKcjUanKyLA6E3k4wEmgZuhgUT02UMmMvH2LVA1L2Z4-l-cT_Ug
收到小米通道下行的消息:(需要將sdk日志等級設置到DEBUG)
12-09 22:24:34.065 19566-25042/com.xxx D/MPS:MiPushReceiver: onReceiveMessage,msg=[{"f":262,"b":"{"content"\ ... ... ,"i":"f__-rnje3_OH74gE|VG0g3kwMnGADAGrXZku1FFW5"}]
收到GCM/FCM通道下發(fā)的消息:
05-19 19:20:04.900 19153-20391/com.alibaba.push2 D/MPS:GcmRegister: onReceiveMessage payload msg:[.
(7).該功能的使用需要接入推送輔助通道,確保使用最新的輔助通道擴展包巧还,具體參考上文鞭莽;
輔助彈窗送達的通知展示效果,和普通通知相同麸祷;
服務端指定輔助彈窗通道推送時澎怒,一定要指定通知點擊后要打開的Activity,該Activity需繼承自抽象類AndroidPopupActivity(MiPushSystemNotificationActivity已廢棄阶牍,小米彈窗喷面、華為彈窗、OPPO彈窗統(tǒng)一繼承AndroidPopupActivity)走孽,否則無法獲取到通知的相關(guān)信息惧辈,并且會影響通知到達率的統(tǒng)計;
AndroidPopupActivity中提供抽象方法onSysNoticeOpened()磕瓷,實現(xiàn)該方法后可獲取到輔助彈窗通知的標題盒齿、內(nèi)容和額外參數(shù),在通知點擊時觸發(fā)困食,原本的通知回調(diào)onNotification()和onNotificationOpened()不適用于輔助彈窗边翁;
指定打開的托管彈窗Activity在AndroidManifest.xml中注冊時需要聲明屬性:android:exported=true
注:AndroidPopupActivity 適合作為中間件,因為它繼承自Activity擴展性差。點擊彈窗回調(diào)onSysNoticeOpened()方法!!!
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)方法硕盹,獲取通知相關(guān)信息
* @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);
}
}
另外對通知的標題長度限制是16個字符,但是我試了超過10個就不行了,不知道是不是服務端哪里設置的有問題暫時沒解決符匾。