android接收推送消息推送消息,在移动互联网时代,推送服务已成为移动应用开发中不可或缺的一部分。而针对Android平台的推送服务更是备受关注。本文将介绍一种仅需一行代码即可实现Android推送服务的方法,帮助开发者快速搭建推送服务,提升应用的用户体验。
Android 推送服务一行代码实现
推送消息主要用来提示用户一些重要信息,或者引导用户进入App;消息的到达率,及时性,点击后消息处理等,每一个节点,都影响着用户体验;所以,实现一个友好的推送交互,是非常有意义的。
文章目录:
目前现状实现分析功能实现总结1.目前现状目前国内推送现状,国产ROM无法使用GCM(Google Cloud Messaging,主要用于消息推送),为了提升用户体验,一些国内的厂商,第三方,不得不推出自己的推送方案,按照推送通道,大致划分为3种,系统级推送、三方推送、混合推送。
1、系统推送
2、三方推送
特征App级长连接推送,进程独立,由系统广播事件保活,链式唤醒。厂商友盟推送,腾讯信鸽推送,百度云推送等。优点通用性强,各类ROM都可通用,进程存活时,消息到达率与系统级推送相当。缺点进程被杀死,或其他App没有链式唤醒,导致消息到达率低。单独守护进程,链式唤醒,也导致耗电高。3、混合推送
特征同时包含系统级长连接通道和 App 级长连接通道。厂商小米推送,极光推送,阿里云推送等。优点成功率相对于第三方高,适用性比纯系统推送强。缺点接入成本相对比较高。推送按消息类型划分,分为通知消息和透传消息,通知消息由推送SDK来处理,消息格式较为固定,由系统公共通道完成,到达率有保证;透传消息需要App自己来实现,可以自定义消息,灵活度高,是由App通道来完成,与三方推送没有太大的区别。
2.实现分析由以上现状分析和业务需求,最终选择使用系统推送 + 通知消息方案实现消息推送。为了保证消息到达率高,大品牌,比如华为,小米,根据ROM类型使用自家的推送,其他品牌统一使用小米推送;小米推送的完成度更高,在系统推送的基础上实现了三方通道,兼容了非 MIUI 的 Android 机;在此基础上,如果其他品牌(vivo,OPPO)消息到达率低,只需要增加相应ROM的推送SDK,保证消息到达率。
通过调研几家App发现,有些点击了推送消息,不了了之,没有任何动作,比如打开App,或者跳转到相应的界面;还有一些是进入了相应的界面,后退,又回到了桌面,此种情况属于没有判断App是否运行,或者App已经在后台运行,没有启动到前台,这样的体验非常的不舒服。
从点击消息,处理消息,页面跳转,整个过程,用户体验是非常的重要,那怎么样实现一个完美的用户体验,分为以下几种情况。
画了一个XMind思维导向图,看着更清楚。
通过以上逻辑实现,包含了所有的可能情况,用户点开推送消息进入相应界面,关闭界面,依旧App在前台运行,符合用户预期操作习惯。
3.功能实现建立Push Module,为什么这样做?
每家厂商的推送SDK,都用jar或依赖来实现。又要到AndroidManifest中注册大量的清单内容,注册广播或者Service等,一大堆的内容,放到Base模块,显然不合理;推送相对于业务逻辑,是非常独立的,所以单独建立Module,与其他业务逻辑隔离,也符合组件化设计思想。
项目组件化方案实现,请看
实现组件化,接入推送业务逻辑,会变得非常简单。
在项目中接入小米,华为等推送,按照官方文档接入即可;接下来需要整合各家推送SDK,以下分别从初始化推送,规范数据来源,接收数据,消息初始化前准备,启动App,分发消息,页面跳转,7个流程,介绍消息推送方案实现。
1、初始化推送
class PushInit { companion object { // app是否已经初始化 var shouldInit = false fun with(): PushInit { return PushInit() } } /** * 初始化 */ fun init(context: Context) { shouldInit = true if (OSUtils.isEmui()) { huaweiPushInit(context) } else { xiaomiPushInit() } // 有推送消息,需要处理 val data = PushSetting.pushData if (!TextUtils.isEmpty(data)) { MessageHandler.messageHandle(context, data) PushSetting.pushData = "" } } }
根据不同的手机ROM,初始化推送SDK,如果有推送消息,则进行消息分发;shouldInit,用来标识App是否已经打开,后面会讲到。
2、规范数据来源,App端统一使用Scheme协议接收数据,服务端API指定intent参数。
自定义Scheme协议,一个应用中通常会有多个推送消息类型,只需要定义一个参数“extraData”(值用字符串JSON实现),扩展性强。
val intent = Intent(Intent.ACTION_VIEW) // Scheme协议(例如:pushscheme://com.xingzhi.android.components/deeplink/pushreceiver?)需要您自定义 intent.setData(Uri.parse("pushscheme://com.xingzhi.android.components/deeplink/pushreceiver?")) // 往intent中添加参数,根据自己的需求进行添加参数 intent.putExtra("extraData", "{"code": 0, "data":{}}") // 应用必须带上该Flag,如果不添加该选项有可能会显示重复的消息 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val intentUri = intent.toUri(Intent.URI_INTENT_SCHEME) // 打印出的intentUri值就是设置到推送消息中intent字段的值 Log.d("intentUri", intentUri)
生成的IntentUri为:
intent://com.xingzhi.android.components/deeplink/pushreceiver?#Intent;scheme=pushscheme;launchFlags=0x4000000;S.extraData={};end
extraData中的数据格式为"{"code": 0, "data":T}",code为消息类型,用来跳转不同的界面,data是泛型,可自定义每个页面不同的数据。
3、接收数据,用一个没有布局的Activity来实现,注册AndroidManifest时申明Scheme协议。
<activity android:name=".activity.PushReceiverActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="${applicationId}" android:path="/deeplink/pushreceiver" android:scheme="pushscheme" /> </intent-filter> </activity>
class PushReceiverActivity : BaseActivity() { companion object { private const val EXTRA_DATA = "extraData" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val data = intent.getStringExtra(EXTRA_DATA) MessageHandler.init(this, data) finish() } }
这样,就可以接收到服务端传递的extraData字段内容;当用户点击推送消息时,系统会发送intent,Scheme协议来接收消息,在PushReceiverActivity中就可以获取到intent内容,就可以分发消息了。
4、消息初始化前准备,根据业务逻辑,App是否启动,是否在后台运行等,上面用XMind分析过,直接上代码。
fun init(context: Context?, data: String?) { if (context == null || TextUtils.isEmpty(data)) { return } val shouldInit = PushInit.shouldInit // TODO 此处根据自身业务页面逻辑实现 "isLogin" val isLogin = true // 没有登录,没有打开app if (!isLogin || !shouldInit) { PushSetting.pushData = data!! launcherApp(context, shouldInit) return } // app是否在后台运行 val isBackground = AppUtils.isAppBackground(context) if (isBackground) { launcherApp(context, shouldInit) } // 分发消息 messageHandle(context, data!!) }
此处用到了val shouldInit = PushInit.shouldInit,为什么这样实现?当你点击推送消息时,PushReceiverActivity收到消息。系统进程中就有了App的进程,无法再根据进程判断是否真正打开了App,所以在PushInit中申明了shouldInit变量,来标示,用户是否真正打开了App。
5、启动App
private fun launcherApp(context: Context, shouldInit: Boolean) { if (shouldInit) { val intent =AppUtils.getAppOpenIntentByPackageName(context, "com.xingzhi.android.components") context.startActivity(intent) } else { val intent = Intent(context, SplashActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(intent) } }
如果在后台运行,需要启动App到前台,再分发消息;如果App没有打开过,启动App,到Main页面后,再分发消息;如果在前台运行,直接分发消息。
6、分发消息
fun messageHandle(context: Context, data: String) { try { when (JSONObject(data).get("code") as Int) { PushType.SETTINGS_TYPE -> { toSettings(context) } PushType.TODAY_DETAILS_TYPE -> { val type = object : TypeToken<ResponsePush<TodayDetails>>() {}.type val response = ConvertUtils.fromJson<ResponsePush<TodayDetails>>(data, type) toTodayDetails(context, response.data.id) } } } catch (e: Exception) { e.printStackTrace() } }
解析消息JSON内容,根据Code分别解析数据类型,再跳转界面。
7、页面跳转,只需要 Push Module 依赖业务组件Api层,即可访问业务页面路由,推送模块与业务组件没有任何关系,非常便捷。
dependencies { implementation project(':module-biz-today-api') implementation project(':module-biz-mine-api') }
/** * 我的组件 - 设置页面 */ private fun toSettings(context: Context) { Launcher.navigation(SettingsLauncher::class.java).startActivity( context, Intent.FLAG_ACTIVITY_NEW_TASK ) } /** * 今日组件 - 今日详情页面 */ private fun toTodayDetails(context: Context, id: Int) { Launcher.navigation(TodayDetailsLauncher::class.java).startActivity( context, Intent.FLAG_ACTIVITY_NEW_TASK, id ) }
最后,只需要在app Module中,加入 Push Module 依赖和初始化代码,即可加入推送模块。
dependencies { implementation project(':module-biz-push') }
app build.gradle中加入推送模块依赖,即可编译推送模块代码;删除依赖,则去除整个推送模块的代码;业务层代码不会因为加入依赖或者删除依赖,做任何修改。
// push init PushInit.with().init(this)
MainActivity中加入PushInit,完成初始化推送模块任务;注释这行代码,则不初始化推送模块,也不接收推送消息。
真正意义上实现,android接收推送消息推送消息推送功能,与项目现有业务逻辑没有任何牵扯。
4.总结小米推送,业界口碑很好,接入简单,覆盖大部分安卓手机。第三方推送使用进程保活和链式唤醒,也是国内ROM优化严打的对象。混合推送方案,适用性比纯系统推送强,极光,阿里云推送是不错的选择。多平台推送方案,和文章中使用一样,高幅度提升消息到达率,需自行整合各厂商推送SDK。推送功能要实现的完美,需要组件化支撑,组件化也是每个App必然发展趋势。说在最后,Demo包含组件化 + 推送功能实现,项目地址:https://github.com/ixingzhi/Components
Apk下载二维码:
http://d.firim.pro/xm6k?utm_source=fir&utm_medium=qr (二维码自动识别)
总的来说,Android 推送服务的一行代码实现帮助开发者轻松接入推送消息,实现即时通讯和消息推送等功能。在当今竞争激烈的移动应用市场中,及时有效的消息推送可以帮助应用不断增加用户和活跃度,提高用户黏度和留存率,因此 Android 推送服务是每个开发者都应该学习和掌握的技能。
电脑教程推荐
win10系统推荐
Copyright © 2012-2024 win10系统家园 版权声明