
第javascript
97
java
次推文
android
LZ-Saysweb
咱們都曾羨慕別人,卻忘了,咱們也曾是別人羨慕的咱們。json
推薦直接拉到底閱讀原文~緩存
前言微信
最近的任務吶,真是讓人蛋碎一地,各類被錘。
app
不過比較 nice 的是,推送湊齊了,能夠整理一篇咯~maven
點滴積累吧。ide
跟着老大~
前期調研
移動端發展到如今,各類推送 SDK 真的琳琅滿目,讓人看花了眼。
這裏就挑我用過的幾個來作一個簡單對比,畢竟雞老大說了,連基本的論證對比都沒,你還玩個錘子(我瞎編的)。
下面從我我的關注的幾個維度進行簡單的對比 (❌:表明不支持,✅:表明支持。特殊狀況單獨註明):
對於小司而言,價格是一個重點,真的賊羨慕動不動就開通 VIP 或者 Pro 的小夥伴,酸了。
針對以上三種,我的以爲:
若是當前應用僅僅在線推送,極光、Mob、友盟均可以;
若是當前應用僅僅支持國內並且還要支持離線推送,那麼友盟以及 Mob 不二人選;
若是土豪級別應用,又支持國外,那麼直接極光 VIP/Pro 走起,一鍵式支持國內廠商以及 FCM 海外推送;
反之,想支持海外,老老實實接入 FCM 吧。
有點茫然,明明看着 Mob 支持 FCM,可是官網上卻沒看到寫。
對了,今天偶然看到小夥伴對極光推送的一些討論:
好壞很少說,純技術分享,不涉及其餘東西,自行選擇吧。
沒轍,一分錢,難倒英雄漢!還好,哈哈哈。
因爲項目私密性,這裏就不放置對應的效果圖了。PS:其實我仍是蠻喜歡放個效果圖的,至少一上來就能看到效果,But 涉密,阿哦~
1、友盟廠商申請對應 key
因爲我司帳號問題,沒法集入全部廠商,尷尬啊。
畢竟雞老大也說過,不對未接觸的事物發表任何意見。
因此這裏按照友盟所須要對應廠商資料進行依次註冊填入便可:
推薦幾個不錯的廠商推送指南:
友盟 - 廠商通道集成文檔
Mob - 第三方廠商推送指南
圖忒多了,並且沒啥難點,按照集成對應平臺提供資料進行對應廠商註冊吧。
2、Android 原生集成 - 友盟 v6.0.5
當初採用友盟緣由以下:
支持廠商推送
方便運營小夥伴直接友盟查看全部數據
1.1 添加友盟依賴
前期在友盟平臺建立當前應用之類的就不談了,注意推送 Android 版須要綁定包名。
關於友盟推送須要離線廠商推送,因此涉及到大部分的配置項,這裏我直接提取一個 gradle,避免主 gradle 各類雜亂不堪。
首先咱們在項目根目錄下添加友盟的遠程庫:
buildscript { repositories { google() jcenter() 這裏 maven { url 'https://dl.bintray.com/umsdk/release' } } dependencies { 。。。 }}
allprojects { repositories { flatDir { dirs 'libs' } google() jcenter() maven { url 'https://jitpack.io' } 這裏 maven { url 'https://dl.bintray.com/umsdk/release' } }}
隨後在 app 下建立友盟依賴的 gradle,這裏注意因爲我司開發者帳號緣由,並沒能集成全部廠商:
dependencies { // 友盟推送 // 基礎組件庫依賴(必須) Push 605 版本必須升級新版本 Common SDK implementation 'com.umeng.umsdk:common:2.2.2' implementation 'com.umeng.umsdk:utdid:1.5.2' // 友盟 push 相關依賴(必須) implementation 'com.umeng.umsdk:push:6.0.5' implementation 'com.umeng.umsdk:alicloud-httpdns:1.2.5' implementation 'com.umeng.umsdk:alicloud-utils:1.1.5' implementation 'com.umeng.umsdk:alicloud_beacon:1.0.1' implementation 'com.umeng.umsdk:agoo-accs:3.3.8.8-open-fix2' implementation 'com.umeng.umsdk:agoo_networksdk:3.5.5' implementation 'com.umeng.umsdk:agoo_tlog:3.0.0.17' implementation 'com.umeng.umsdk:agoo_tnet4android:3.1.14.9' // ====== 廠商集成 Start // 小米 Push 通道 implementation 'com.umeng.umsdk:xiaomi-push:3.7.0' implementation 'com.umeng.umsdk:xiaomi-umengaccs:1.1.4' // 華爲 Push 通道 implementation 'com.umeng.umsdk:huawei-basetb:2.6.3.306' implementation 'com.umeng.umsdk:huawei-pushtb:2.6.3.306' implementation 'com.umeng.umsdk:huawei-umengaccs:1.2.4' // Oppo Push 通道 implementation 'com.umeng.umsdk:oppo-push:2.0.2' implementation 'com.umeng.umsdk:oppo-umengaccs:1.0.6' // vivo Push 通道 implementation 'com.umeng.umsdk:vivo-push:2.3.5' implementation 'com.umeng.umsdk:vivo-umengaccs:1.1.0'}
最後在主 gradle 也就是 app 下的 gradle 添加對此依賴:
// 友盟推送apply from: 'UMeng_Push.gradle'
1.2 初始化友盟推送並設置通知欄點擊動做
在 Application 中進行友盟推送的初始化以及點擊通知欄後操做:
private fun initUMengSettings() { // 初始化 SDK mContext?.let { UMConfigure.init( mContext, K_RELEASE_UMENG, it.getString(R.string.code_umeng), UMConfigure.DEVICE_TYPE_PHONE, K_UMENG_SECRET ) initUMengPush(it) } } /** * 初始化友盟消息推送 */ private fun initUMengPush(context: Context) { // 獲取消息推送代理示例 val pushAgent = PushAgent.getInstance(context) // 註冊推送服務,每次調用 register 方法都會回調該接口 pushAgent.register(mIUmengRegisterCallback) // 設置點擊通知欄打開操做 pushAgent.notificationClickHandler = mNotificationClickHandler
initUMengPushSettings(pushAgent) } /** * 註冊推送服務 */ private val mIUmengRegisterCallback = object : IUmengRegisterCallback { override fun onSuccess(deviceToken: String?) { pwcLog("-------> 註冊成功:deviceToken:--------> $deviceToken") }
override fun onFailure(s: String?, s1: String?) { pwcLog("-------> 註冊失敗:s ---> $s ||| s1 ---> $s1") } }
/** * 點擊通知欄 後續操做 */ private val mNotificationClickHandler = object : UmengNotificationClickHandler() { /** * 處理用戶點擊通知欄消息 */ override fun dealWithCustomAction(context: Context?, uMessage: UMessage?) { super.dealWithCustomAction(context, uMessage) context ?: return uMessage ?: return // 後臺接口傳遞過來的參數都在 map 中 val extraMap = uMessage.extra // 這裏演示下獲取倆個值 val openType = extraMap["type"] val openID = extraMap["id"] // 。。。 }
} /** * 推送基礎信息配置 */ private fun initUMengPushSettings(pushAgent: PushAgent) { // 設置最多顯示通知條數 參數 number 能夠設置爲 0~10 之間任意整數。當參數爲 0 時,表示不合並通知; pushAgent.displayNotificationNumber = 0 // 設置客戶端容許聲音提醒 pushAgent.notificationPlaySound = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE // 設置客戶端容許呼吸燈點亮 pushAgent.notificationPlayLights = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE // 設置客戶端容許震動 pushAgent.notificationPlayVibrate = MsgConstant.NOTIFICATION_PLAY_SDK_ENABLE // 通知免打擾 SDK默認在「23:00」到「7:00」之間收到通知消息時不響鈴,不振動,不閃燈 pushAgent.setNoDisturbMode(23, 0, 7, 0) // 設置冷卻時間 避免一分鐘內出現多條通知而被替換 pushAgent.muteDurationSeconds = 600 }
1.3 離線推送支持
在 Application 中對應初始化廠商通道便可:
/** * @author:heliquan * @date:2020-05-07 * @desc:廠商推送 */class PushSDKBizImpl : AppInterface {
private var mContext: Context? = null
override fun onCreate(knowledgeCore: KnowledgeCore) { if (mContext == null) { mContext = knowledgeCore.applicationContext } registerPush(knowledgeCore) }
private fun registerPush(knowledgeCore: KnowledgeCore) { // 小米 Push register MiPushRegistar.register(mContext, K_XIAOMI_ID, K_XIAOMI_KEY) // 華爲 Push register HuaWeiRegister.register(knowledgeCore) // OPPO Push register OppoRegister.register(mContext, K_OPPO_KEY, K_OPPO_SECRET) // Vivo Push register VivoRegister.register(mContext) } // 。。。}
不少時候咱們都但願,即便用戶當前未使用 App,或者說當前的 App 處於被殺死的狀態,後臺推送消息依然想被前臺接收。
那麼若是想實現離線推送,咱們還要完善下面的一步:
import com.umeng.message.UmengNotifyClickActivityimport org.android.agoo.common.AgooConstants/** * @author HLQ_Struggle * @date 2020/5/7 * @desc * 小米、華爲等對後臺進程作了諸多限制。若使用一鍵清理,應用的channel進程被清除,將接收不到推送。經過接入托管彈窗功能,可有效防止以上狀況,增長推送消息的送達率。 */class PushActivity : UmengNotifyClickActivity() {
private val mSelfActivity = PushActivity@ this
override fun onMessage(intent: Intent?) { super.onMessage(intent) // 拿到數據 AgooConstants.MESSAGE_BODY 進行對應後續操做 val offlinePushBean = intent?.getStringExtra(AgooConstants.MESSAGE_BODY)?.let { GsonUtil.fromJson( it, // 這裏須要將獲取到的json再次進行格式化 object : TypeToken<OfflinePushBean>() { }) } // 例如我這裏直接跳轉啓動頁,而後慢慢跳轉目標頁 offlinePushBean?.extra?.let { val intent = Intent(mSelfActivity, SplashActivity::class.java) intent.putExtra(K_OFFLINE_PUSH_ID, it.id) intent.putExtra(K_OFFLINE_PUSH_TYPE, it.type) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) finish() } }
}
固然 AndroidManifest 此 Activity 內容附上:
<activity android:name=".ui.activity.push.PushActivity" android:exported="true" android:launchMode="singleTask" android:theme="@style/FullScreenTransparentTheme" />
到此,友盟 Android 集成推送已完成~
3、Android 原生集成 - FCM
Google 爸爸 GCM 集成的真的是賊貼心,業界楷模啊。
我不吹,你本身瞧~
附上 FCM 地址:
firebase.google.com/?hl=zh-cn
須要注意的幾點:
記得測試的時候,ke xue 上網,我以前就遇到這麼一個狀況,顯示發送了,結果 App 收不到,最後才反應過來,沒有 ke xue 上網。
國內的手機通常沒有 Google 全家桶,或者說 Google 服務,須要去豌豆莢中下載。
3.1 FCM 前期配置
首先不可避免的,建立項目:
這裏須要注意建立項目的一個規則:
項目名稱必須至少包含 4 個字符只能包含字母、數字、空格和如下字符:-!'"
按照要求輸入項目名稱,勾選接收條款:
添加 Google Analytics 分析:
第三步勾選對應的條款,完成項目建立:
建立期間還有個小進度,賊好看:
建立的速度很快:
3.2 FCM 集成
進入首頁後,點擊 Android 圖標,開始 Android 接入/集成相關工做:
一共有以下四步:
第一步填寫對應包名以及 SHA-1,反之我是都填了。
第二步下載配置文件並拷貝到 app 目錄下:
第三步添加對應的 SDK
第四步運行驗證,可忽略
固然 Google 也爲咱們提供了一鍵式的配置,可是尷尬的是,我嘗試失敗了,不過也算是一種方式,具體文章內容以下:
將 Firebase 添加到您的 Android 項目
這裏爲了偷個懶,直接一張圖展現了:
3.3 FCM 消息處理
在 app build 中完善下依賴:
// FCMimplementation 'com.google.firebase:firebase-analytics:17.4.4'// FCM Message 處理implementation 'com.google.firebase:firebase-messaging:20.2.2'// FCM Message 後臺處理implementation 'com.google.firebase:firebase-messaging-directboot:20.2.2'
隨後建立一個 Service 用於處理 FCM 消息,這裏我直接採用了接收到 Google FCM 消息後手動建立一個通知:
/** * @author HLQ_Struggle * @date 2020/7/8 * @desc */class MyFirebaseMessagingService : FirebaseMessagingService() { /** * 處理 FCM 消息 */ override fun onMessageReceived(remoteMessage: RemoteMessage) { Log.d(TAG, "From: ${remoteMessage.from}") // Check if message contains a data payload. if (remoteMessage.data.isNotEmpty()) { Log.e(TAG, "Message data payload: ${remoteMessage.data}") // 這裏包含後臺傳遞自定義的值 val remoteMessageMap = remoteMessage.data sendNotification( remoteMessageMap["type"].toString(), remoteMessageMap["title"].toString(), remoteMessageMap["content"].toString() ) }
remoteMessage.notification?.let { Log.e(TAG, "Message Notification Body: ${it.body}") }
} /** * 令牌更新回調 FCM 沒有設置別名這麼一說 因此須要咱們經過令牌的方式去指定推送 */ override fun onNewToken(token: String) { Log.d(TAG, "Refreshed token: $token") sendRegistrationToServer(token) } /** * 保存令牌 */ private fun sendRegistrationToServer(token: String?) { Log.d(TAG, "sendRegistrationTokenToServer($token)") } /** * Create and show a simple notification containing the received FCM message. * * @param messageBody FCM message body received. */ private fun sendNotification(type: String, title: String, content: String) { val intent = Intent(this, SplashActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity( this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT ) val channelId = getString(R.string.default_notification_channel_id) val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val notificationBuilder = NotificationCompat.Builder(this, channelId) .setSmallIcon(R.mipmap.ic_launcher_round) .setContentTitle(title) .setContentText(content) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Since android Oreo notification channel is needed. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT ) notificationManager.createNotificationChannel(channel) } notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()) }
companion object { private const val TAG = "MyFirebaseMsgService" }}
複製代碼在 AndroidManifest 中 Service:
<service android:name=".service.MyFirebaseMessagingService" android:directBootAware="true" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter></service>
3.4 FCM 其它配置
固然還有一些可修改的內容,例如:
icon
notification_color
我是直接採用默認的了。這裏官網找到的,貼出來,避免小夥伴有需求還的找。
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/appicon" /> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/styleTitleOrange" /> <meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" /> <meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />
到此,FCM 完畢~
4、Flutter Android 集成 - Mob
此模塊在廠商相關信息完善時,集成僅僅幾分鐘~
相對於 Flutter 接入推送,不得不說 Mob 作的賊優秀,直接 Flutter 插件搞起,大大的方便了 Flutter 開發者,先比個當心心~ ❤️
附上 Mob 插件地址:
pub.dev/packages/mo…
以及對應 Flutter 的集成指南:
mob.com/wiki/detail…
Mob 的文檔,真的是良心,集成賊簡單,入手超級方便,一塊兒來看。
2.1 添加 Mob 插件依賴
mobpush_plugin: ^1.1.5
2.2 配置 Android 基本環境
首先,根目錄下的 build 文件添加以下:
dependencies { // 。。。 classpath 'com.mob.sdk:MobSDK:+'}
其次,app 下 build 文件添加對應的配置項,這裏關於 Mob 的配置可單獨提取一個 gradle 文件,這裏當初爲了實現而實現,就不抽離了。
導入插件:
apply plugin: 'com.android.application' // 通常項目自帶有這個,因此這塊的這個能夠忽略apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"apply plugin: 'com.mob.sdk'
Mob 推送的相關配置:
基礎的 appKey 以及 appSecret
廠商對應的 key 以及其它信息
代碼以下:
MobSDK { appKey "Mob 提供的 App Key" appSecret "Mob 提供的 App Secret" // 配置MobPush MobPush { // 配置廠商推送(可選配置,不須要廠商推送可不配置,須要哪些廠商推送只需配置哪些廠商配置便可) devInfo { // 配置小米廠商推送 XIAOMI { appId "您的小米平臺appId" appKey "您的小米平臺appKey" } // 配置華爲廠商推送 HUAWEI { appId "您的華爲平臺appId" } // 配置魅族廠商推送 MEIZU { appId "您的魅族平臺appId" appKey "您的魅族平臺appKey" } // 配置FCM廠商推送 FCM { // 設置默認推送通知顯示圖標 iconRes "@mipmap/default_ic_launcher" } // 配置 OPPO 廠商推送 OPPO { appKey "您的OPPO平臺appKey" appSecret "您的OPPO平臺appSecret" } // 配置VIVO廠商推送 VIVO { appId "您的VIVO平臺appId" appKey "您的VIVO平臺appKey" } } }}
接着去 MainActivity 中註冊下,通常也無需操做,我這裏是以前寫過一個通道,附上部分代碼:
import io.flutter.embedding.android.FlutterActivityimport io.flutter.embedding.engine.FlutterEngineimport io.flutter.plugin.common.MethodCallimport io.flutter.plugin.common.MethodChannelimport io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) }
}
最後就是對於初始化 Mob 以及接受到 Mob 消息推送如何處理了,蠻簡單的,這裏說下幾個點吧:
因爲項目需求設置以用戶名爲別名,因此也涉及到了添加別名這個操做,而在這裏則是本地維護了一個狀態,避免屢次設置重複別名;
其次需求是接收到消息推送執行刷新操做,因此我在這裏直接接收到推送消息後經過 eventBus 發送狀態去執行數據更新操做了。
如下是部分代碼,僅供參考:
/// 目前僅支持 Android 端推送 void initMobPush() { getCacheValue(memberInfo).then((userCache) { MemberInfoBean memberInfoBean = memberInfoBeanFromJson(userCache); if (Platform.isAndroid) { // 設置隱私協議受權狀態 MobpushPlugin.updatePrivacyPermissionStatus(true);
getCacheValue(pushAliaState).then((result) { LogUtil.e(" ===> 獲取 Mob 註冊狀態"); if (result == null) { LogUtil.e(" ===> Mob 未註冊 須要註冊"); MobpushPlugin.setAlias(memberInfoBean.memberInfo.id) .then((Map<String, dynamic> map) { LogUtil.e(" ===> 設置 Mob 推送別名:-> res: ${map['res']} "); if (map['errorCode'] == '0') { // 註冊成功 本地緩存狀態 setCacheValue(bool, pushAliaState, true); } }); } }); // 添加推送回調 MobpushPlugin.addPushReceiver(_onEvent, _onError); } }); }
void _onEvent(Object event) { LogUtil.e(' 接收到消息內容:$event'); eventBus.fire(PushEvent(true)); }
void _onError(Object event) {}
End
本文內容較多,主要是整理前段時間遇到的問題,其實也不算啥問題吧,主要各類帳號前期準備不足,後期產品調整頻繁致使。
基本都附上了源碼。
菜雞一枚,歡迎各位大佬指正~
Thanks
極光推送
友盟推送
Mob 推送
歡迎各位關注
不按期發佈
見證成長路




本文分享自微信公衆號 - 賀利權(hlq_struggle)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。