首页 > 其他分享 >Android 手记 | Android MobPush 接入小结

Android 手记 | Android MobPush 接入小结

时间:2022-11-11 22:00:25浏览次数:44  
标签:小结 keep MobPush Mob Android 推送 com class

  • 手记 | MobPush 接入总结

不瞒各位大佬,我想混个杯子,杯子被猫猫干碎了...

PS:这不仅仅是一篇简单 ​​MobPush​​ 接入总结,同时也会掺杂个人理解以及不成熟的想法。接入的本身很 easy,总要透过现象看本质,去深入了解其他的内容。文章涉及到三方统计数据截图,均已在文末提供链接地址,如有异议,请联系我删除~

手记开始,记录项目点滴,一起加油~

上来还是简单叨叨几句,不吐不快。

推送的目的是什么?在地铁上我想了很多:

  • 拉活,通过产品各种特性(活动)吸引用户点击使用,进一步验证产品思路、方向;
  • 促进用户粘性,好比今天收到通知,鸡老大直播 ing,马不停蹄的点击进去开始膜拜;
  • 重大事件通知与防范,科技的力量,在某些方面,总会统一战线,无时无刻提示风险以及加强警惕;
  • 。。。

其实推送最终的目的,个人更大的感觉还是将用户进一步留存,无论采取任何方式方法。

而相比 iOS 的推送,则 Android 要痛苦的很多。Android 的开放性使其自身逐步发展壮大,同时开放性也衍生了国内各种厂商的定制化。各种 系统 层出不穷,百花齐放的场景也给 Android 开发小伙伴带来了很多兼容性的问题。iOS 只需要发送苹果服务器,然后进行后续处理 个人理解,而 Android?这里特意搜索了下国内几大厂商的历史图:

Android 手记 | Android MobPush 接入小结_ide

瞧瞧,目前五大厂商赫然在目!!!我们再看看截止 2021 年国内手机出货量:

Android 手记 | Android MobPush 接入小结_Android_02

除了魅族暂时未上榜单,其余依旧坚挺。这里排除华为鸿蒙,这个不在这篇文章考虑范围内。

那么对于我们原生 Android 开发而言,如何处理,能达到最好的推送效果?我想那可能是依次对主流厂商进行兼容适配,但是同时也带来了成倍的接入工作。

较好的一点是,有困难,便有专业解决困难提供商。对于小公司而言,一键接入成型并且经过市场检验的三方推送服务便是上上策。而国内众多推送服务商,我们又该选择哪儿个?接着往下看~

Push 厂商对比

我一直都是小公司,小公司里面对于方案的选择,大部分是 直系领导 直接拍板决定,少部分是看 主程 更倾向于哪儿家就用哪儿家。

下面从我个人关注的几个维度进行极光、友盟、Mob、个推这四个厂商简单的对比吧。  (❌ 代表不支持,✅ 代表支持。特殊情况单独注明) (截止到 2021 年 8 月 10 日):

极光

友盟

Mob

个推

支持消息格式

通知栏通知、自定义消息(透传)、富媒体、本地通知

通知栏通知、自定义消息(透传)、本地通知

通知栏通知、自定义消息(透传)、本地通知

通知消息、自定义消息(透传)、分组对比

离线厂商通道支持

华为、小米、OPPO、vivo、魅族、华硕、FCM

华为、小米、OPPO、vivo、魅族

华为、小米、魅族、OPPO、vivo

小米、华为、OPPO、vivo、魅族、坚果、海信、索尼等

别名、标签支持





移除关联启动

需要开通 VIP




消息撤回





卸载统计

高级版支持




支持平台

Android、iOS、Windows Phone、QuickApp

Android、iOS、Flutter

Android、iOS、Flutter、Unity、JavaScript、Cocos2d-X

Android、iOS

分析对比,找瞎眼,如果不对,欢迎拍砖~

上图中只是个人简单对比,部分详细内容未考虑,当然也包括默认支持服务端 Web 调用,例如每个厂商对某个功能特性支持是否完整,这里就不一一诉说了。

方案很多,各位按照自身需求进行对应接入即可,下面开始个人习惯的 MobPush 集成啦~

MobPush 集成

从下面官网进入,准备开始接入:

  • ​​MobPush​​

登录成功后选择工作台:

Android 手记 | Android MobPush 接入小结_Android_03

0、Mob 后台创建 App 信息

创建应用:

  • 上传 Icon
  • 填写 App 名称

Android 手记 | Android MobPush 接入小结_Android_04

随后选择「立即接入」:

Android 手记 | Android MobPush 接入小结_ide_05

这里选择 MobPush:

Android 手记 | Android MobPush 接入小结_android_06

添加应用包名以及选择接入厂商通道:

Android 手记 | Android MobPush 接入小结_推送_07

接入指南:

Android 手记 | Android MobPush 接入小结_推送_08

1、合规处理

由于目前针对用户个人信息/数据进一步管控加强,首要保证 App 符合合规。这里根据 Mob 官方进行部分整理:

  • 确保App有《隐私政策》,并且在用户首次启动App时就弹出《隐私政策》取得用户同意;
  • 务必告知用户选择 MobSDK 服务,并在《隐私政策》中增加参考条款;
  • 务必确保用户同意《隐私政策》之后,调用 MobSDK 提交隐私协议接口。

2、项目根目录 build 中添加 MobPush 依赖:

buildscript {
repositories {
// 配置 Mob Maven 库
maven {
url "https://mvn.mob.com/android"
}
}
dependencies {
// 集成 MobPush
classpath "com.mob.sdk:MobSDK:2018.0319.1724"
}
}

3、app 下 build 中新增 Mob 插件和扩展:

这里建议单独提出一个 Mob gradle,避免后续维护混乱.

// 调用MobTech SDK
apply plugin: 'com.mob.sdk'

// 在 MobSDK 的扩展中注册 MobPush 的相关信息
MobSDK {
appKey "appKey"
appSecret "appSecret"
MobPush {
// 集成其他推送通道(可选)
devInfo {
// 华为推送配置信息
HUAWEI {
appId "华为的appid"
}

// 魅族推送配置信息
MEIZU {
appId "魅族的appid"
appKey "魅族的appkey"
}

// 小米推送配置信息
XIAOMI {
appId "小米的appid"
appKey "小米的appkey"
}

// FCM 推送通道配置
FCM {
// 设置默认推送通知显示图标
iconRes "@mipmap/ic_launcher"
}

// OPPO 推送配置信息
OPPO {
appKey "OPPO的appKey"
appSecret "OPPO的appSecret"
}

// VIVO 推送配置信息
VIVO {
appId "应用对应的vivo appID"
appKey "应用对应的vivo appKey"
}
}
}
}

随后在主 app 下 build 文件中进行引用:

// 引入 Mob 配置
apply from: 'MobSettings.gradle'

4、gradle.properties 中配置隐私协议适配版本

# 设定 MobSDK 为隐私协议适配版本
MobSDK.spEdition=FP

5、添加混淆代码

这块可以按照实际需求进行对应 CV 即可~

# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

# Mob 混淆代码
-keep class com.mob.**{*;}
-dontwarn com.mob.**

#厂商的混淆规则
-keep class android.os.SystemProperties
-dontwarn android.os.SystemProperties
-keep class com.huawei.**{*;}
-keep class com.meizu.**{*;}
-keep class com.xiaomi.**{*;}

-dontwarn com.huawei.**
-dontwarn com.meizu.**
-dontwarn com.xiaomi.**

-keepclasseswithmembernames class * {
native <methods>;
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

-keep class com.huawei.hms.**{*;}
-keep class com.meizu.cloud.**{*;}
-keep class com.xiaomi.mipush.sdk.**{*;}
-keep class org.apache.thrift.**{*;}
-keep class com.google.** {*;}
-keep class com.coloros.** {*;}
-keep class com.mob.tools.* {*;}
-keep class com.mob.wrappers.* {*;}

-dontwarn com.mob.commons.**
-dontwarn com.mob.wrappers.**
-dontwarn com.huawei.hms.**
-dontwarn com.meizu.cloud.**
-dontwarn com.xiaomi.mipush.sdk.**
-dontwarn org.apache.thrift.**
-dontwarn com.google.**
-dontwarn com.coloros.**

-dontwarn com.vivo.push.**
-keep class com.vivo.push.**{*; }
-keep class com.vivo.vms.**{*; }
-keep class com.mob.pushsdk.plugins.vivo.PushVivoReceiver{*;}

-keep class com.meizu.cloud.pushsdk.MzPushMessageReceiver{
public *;
}

-keep class com.mob.pushsdk.plugins.xiaomi.PushXiaoMiRevicer {*;}
-dontwarn com.xiaomi.push.**

#这是oppo的混淆规则
-keep public class * extends android.app.Service
-keep class com.heytap.msp.** { *;}
-keep class com.mob.pushsdk.plugins.oppo.** { *;}

6、番外

当然,也可以选择在 AndroidManifest 中选择开启 Debug 功能:

<!-- 开启日志调试功能 -->
<meta-data
android:name="com.mob.mobpush.debugLevel"
android:value="4" />

7、Test 一波,发个通知

在 Mob 后台选择发送一条通知测试下~

Android 手记 | Android MobPush 接入小结_ide_09

结果如下:

Android 手记 | Android MobPush 接入小结_ide_10

再 Test 一波,这次我们将应用回到后台,再来测试下。

Android 手记 | Android MobPush 接入小结_ide_11

那如果我们现在应用被杀了呢?再来测试下?

Android 手记 | Android MobPush 接入小结_Android_12

在这里明显可以观察到,当应用被杀(模拟用户非在线时刻),Mob 后台推送并没有及时下发客户端。而当用户再次打开 App 时,才能收到之前的推送。那么,如果我时隔几天后打开呢?消息的及时性又如何保证呢?当然,什么事情也不是绝对的。

那我们现在配置下华为厂商推送再试试?

8、华为厂商推送

这块较为简单,MobPush 写的也狠明确,按照要求进行操作就可以了。

  • ​​华为Push注册流程​​

MobSettings 中填写对应的 appId:

// 调用MobTech SDK
apply plugin: 'com.mob.sdk'

// 在 MobSDK 的扩展中注册 MobPush 的相关信息
MobSDK {
appKey "appKey"
appSecret "appSecret"
MobPush {
// 集成其他推送通道(可选)
devInfo {
// 华为推送配置信息
HUAWEI {
appId "appId"
}
}
}
}

随后我们在 Mob 后台进行测试离线推送测试:

经过如上几个测试小 case,我想大家对于接入离线厂商的必要性不言而喻了吧。

其实对于这块,个人理解是:当 Mob 自有通道开启状态,也就是 App 在线时,Mob 后台通过 Mob 自有通道进行消息通知下发。而如果 Mob 通道被关闭,也就是 App 被杀死,这块我猜测可能是心跳包检测?说实话还真没去了解过。关闭时通过设备对应不同厂商通道进行消息下发。从而保证了消息下发并不依赖 App 是否存活,比较厂商(系统)通道,肯定不会被干死,从而进一步的保证了 App 的消息接受性。

其它厂商这里就不一一进行对接测试了,大家前提记得注册好相关厂商帐号,随后按照 MobPush 进行配置即可。

9、再来个指定用户推送并传递对应 key

首先在 App 获取注册 ID:

MobPush.getRegistrationId {
Log.e("HLQ", "------> getRegistrationId $it")
}

随后获取到注册 ID 并设置 Mob 后台,接着选择自定义消息,并设置如下几个内容:

  • content:This is content.
  • hlqType:1
  • hlqCode:666

Android 手记 | Android MobPush 接入小结_推送_13

Android 手记 | Android MobPush 接入小结_Android_14

Android 手记 | Android MobPush 接入小结_推送_15

对应的消息监听如下:

MobPush.addPushReceiver(object : MobPushReceiver {

/**
* 接收到自定义消息(透传消息)
*/
override fun onCustomMessageReceive(
p0: Context?,
p1: MobPushCustomMessage?
) {
Log.e(TAG, "----> onCustomMessageReceive $p1")
}

/**
* 接收到通知消息
*/
override fun onNotifyMessageReceive(
p0: Context?,
p1: MobPushNotifyMessage?
) {
Log.e(TAG, "----> onNotifyMessageReceive $p1")
}

/**
* 通知被点击事件
*/
override fun onNotifyMessageOpenedReceive(
p0: Context?,
p1: MobPushNotifyMessage?
) {
Log.e(TAG, "----> onNotifyMessageOpenedReceive $p1")
}

/**
* 标签操作回调
*/
override fun onTagsCallback(
p0: Context?,
p1: Array<out String>?,
p2: Int,
p3: Int
) {
Log.e(TAG, "----> onTagsCallback $p1")
}

/**
* 别名操作回调
*/
override fun onAliasCallback(
p0: Context?,
p1: String?,
p2: Int,
p3: Int
) {
Log.e(TAG, "----> onAliasCallback $p1")
}
})

当在 Mob 后台点击发送时,App 是没有显式通知的,而在回调接口中,则输出我们刚刚设置的内容:

onCustomMessageReceive
messageId={4bp6i0t0m5xnyia9ds},
content={This is content.},
offlineFlag={0},
extrasMap={{hlqCode=666, hlqType=1,
pushData={"hlqCode":"666","hlqType":"1"},
channel=mobpush,
id=4bp6i0t0m5xnyia9ds}},
timestamp={1629216359101}

好咧,针对 MobPush 推送呢,代码部分到此结束了。大部分官方都有,就不充斥太多的重复性的代码段了。

MobPush 小结

从个人角度而言,每一次都需要有些收获,或者来说,把自己遇到的问题暴露出来,万一官方不好意思调整了呢?

O(∩_∩)O哈哈~

那就从以下几点,简单说说吧。

1、技术保障

周末的时候,出现 MobSDK 拉取不下来的情况,梯子、切换网络、热点,均无效。大周末本来不好意思打扰,结果直接拉群解决,虽然最后还是按照自己降低 gradle 版本处理,但是态度上让人觉得很不错。

周三的时候,中午特意给我反馈,说他们的技术测试正常,并提供了对应的测试 Demo。虽然因为工作原因没能认真看看,但是这个认真负责的态度,赞一波~

一句话,免费的东西,这就不错了。莫抬杠~

2、文档友好度

从 MobPush 的集成来看,如果前期准备工作都已完成(这里指的账号,我从来没遇到过账号准备齐全的,都是自己折腾去),在线推送集成很 Easy,似乎就是分分钟,Mob 后台创建应用,拷贝依赖到根 build,然后跟着官方继续拷贝,剩下就是根据产品进行必要的授权。

而后期厂商集成,相对折腾的点,个人感觉更多的是各个厂商折腾相关信息,开通相关服务。比如华为乱七八糟一大堆,还要下载文件。这块其实对于 Mob 后台配置较为简单,那个 key 之类的就好了,本地项目同理。

这里简单小总结下个人感观:

“文档简洁”.apply{
便于接入
不便于获取详细日志情况,例如华为集成是否成功?
针对某些失败情况,未能提供更多的解决示例
}

关于第二点,这里我拿接入华为离线厂商推送举个例子:

  • ​​MobPush后台配置​​
  • ​​华为Push注册流程​​

以上两个链接是 MobPush 官方提供,但是我怎么能再接入的同时就了解到我华为渠道接入成功了呢?相关的说明请原谅我没找到。这里我随便找个正面示例:

Android 手记 | Android MobPush 接入小结_推送_16

其实针对文档友好度,个人觉得,最简单的方式就是让开发者能否最快速的接入所需要的功能?并且能对于接入内容,官方给出详细说明文档,好比怎么算成功失败了?我怎么能第一时间了解到这些?而不是需要个人实际发送通知测试,才能得出结论。(Mob 小哥哥别打我~ -_-)

关于这个文档更新这块,其实还是会导致人产生误区,简单举几个例子:

  • 官方针对 MobSDK 依赖地址,集成文档是 https 打头,下载 SDK 却写着 http。虽然后续咨询官方,官方说都支持,但是还是上来给人产生误区的感觉。
  • 目前个人测试看是根据配置的厂商渠道自动配置对应的厂商,有个疑问是,假设某天 MobPush 未能主动更新厂商或者开发者想自己替换呢?挺好奇这块的。

还是希望官方能认真统一对待,毕竟一个疏忽会造成集成者的无奈。

人呐,总想得到更多,O(∩_∩)O哈哈~

深入 SDK 稍微看看

整套集成下来,不知道大家注意到我们从始至终都没有调用过 init 方法,那么它在哪儿完成的初始化呢?

会不会是 ContentProvider?印象中此物调用时机介于 Application 的 attachBaseContext 和 onCreate 之间。

盲猜还是不如直接进入 SDK 瞅瞅~

深入 SDK,发现目前 Mob 提供了两种方式:

  • MobApplication:onCreate() init
  • ContentProvider:onCreate() init

反编译生成的 Apk,发生 Mob 将 application name 替换为 MobApplication,如下所示:

<application
android:name="com.mob.MobApplication" >

这里我不仅微笑一下,那如果我要是 application 继承 MobApplication 呢?还会给我替换么?

class BaseApplication : MobApplication() {

override fun onCreate() {
super.onCreate()
}

}

再次反编译 apk 查看下:

<application
android:name="com.hlq.mob.BaseApplication" >

也是,都继承了 MobApplication 还替换个锤锤?

还别说,这块动态替换还是蛮有意思的,比如说,我集成的过程并没有添加权限,那这些权限什么时候被注入的呢?

奇怪的是在 AndroidManifest 中也看到了上文说到的 ContentProvider:

<provider
android:name="com.mob.MobProvider"
android:exported="false"
android:multiprocess="true"
android:authorities="com.pwccn.klcore.com.mob.MobProvider" />

这到底是什么逻辑?有点茫然了,先拿个小本本记上吧,后续再说。

期间还发现个比较 6 的操作:

  • 当我配置文件中未配置渠道时,SDK 自动拉取 Mob 相关依赖;
  • 而当我配置文件中只有华为时,SDK 自动拉取华为相关依赖。

这个操作很神奇啊,有没有老哥指导的点拨一下下那~

各种混淆,看的茫然,下次有机会再说吧~

Error

  • 如果当前 AS 版本最新,并且 gradle 版本为 7.0 时,出现 MobSDK 拉取失败的情况,直接降低 gradle 版本即可。当然官方最后提供了同样 gradle 7.0 的 Demo,因为个人懒得原因就没有细细研究了。
  • 针对厂商推送失败的情况,认真检查相关包名等是否按照官方要求配置。我这就坑了自己一把。再不行给官方丢个 Demo,让官方帮忙处理下。O(∩_∩)O哈哈~

THK

  • ​​2021 Q2中国手机市场出货量/份额排名:前五厂商详细数据报告​​
  • ​​2021年中国手机操作系统行业研究报告​​
  • ​​友盟推送​​ 、​​极光推送​​、​​MobPush​​、​​个推推送​​、​​统一推送联盟​​

标签:小结,keep,MobPush,Mob,Android,推送,com,class
From: https://blog.51cto.com/u_13346181/5845456

相关文章

  • Android 通过Service给Activity添加背景音乐
    现在木鱼已经能发出声音了,而且还能表现出动态画面了,下一步就是给整个敲木鱼的页面添加个BGM。新建一个Service,取名为MyFirstBgmService好了packagecom.example.cyberwo......
  • Android 点击触发音效
    还是以那个木鱼举例吧点击木鱼(ImageButton),发出敲击声首先准备一段音频,muyu.mp3,在res文件夹下新建一个资源文件夹raw,将muyu.mp3扔进去  然后新建一个类用来播放音......
  • Android传感器 - 光强度传感器
    Android手机内部添加了光照强度传感器,可以实时监测手机周边环境的亮度,根据周边环境的亮度可以自动调节屏幕的亮度。下面通过一个实例看一下如何监测周边环境的亮度值。主布......
  • Android - 使用SpannableString设置复合文本
    TextView通常用来显示普通文本,但是有时候需要对其中某些文本进行样式、事件方面的设置。Android系统通过SpannableString类来对指定文本进行相关处理,具体有以下功能:1、Backg......
  • android属性之clearTaskOnLaunch
    clearTaskOnLaunch有没有这样的需求,每次从桌面进入都启动根Activity?可以使用这个属性实现哦,下面通过一个实例来看一下效果:1.MainActivity.java(根Activity):packagecom.examp......
  • Android实战简易教程-第二十枪(GridView长按显示删除)
    用过UC浏览器的都使用过如下功能:长按图标会弹出删除的图标,我们下面研究一下如何实现类似效果。1.配置main.xml文件:<RelativeLayoutxmlns:android="http://schemas.android.......
  • Android开发技巧四--圆角化控件,让它看起来更美
    当需要为应用程序UI控件选择背景的时候,开发者会添加自定义的颜色和形状来代替系统的默认样式,圆角边框看起来是很不错的效果,开发者只需要添加几行代码,就可以在应用程序中使用......
  • Android clean后出现很多错误解决办法
    当我们从别的项目中拷入一个布局文件进我们的项目时,可能出现在activity中无法找到控件的情况,这时如果你clean了一下项目,就会出现很多报错,这是由于在项目有错误的情况下clean......
  • Android实战简易教程-第二十一枪(GridView动态添加Item)
    本例子实现在GridView的最后显示一个增加图片,点击图片动态增加内容item。1.main.xml:<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xml......
  • Android实战简易教程-第二十五枪(基于Baas的数据表查询下拉刷新和上拉加载实现!)
    上一节我们实现了数据表的加载,但是,当数据表数据很多时,我们就要考虑数据的分页,这里我们选用了PullToRefreshListView控件,先看一下该控件的说明:效果图:        ......