导读:本期聚焦于叶子创作的《Android推送如何完整接入厂商通道并做好保活?》,敬请观看详情。离线推送经常收不到,很可能是厂商通道没有配置到位。Android各系统对后台限制越来越严格,普通第三方推送在进程被杀死后基本无法唤醒。而华为、小米、OPPO、vivo、荣耀等厂商通道走系统级链路,即使App不在运行也能显示通知。本文先梳理厂商通道的接入流程,包括各平台SDK依赖、权限声明、消息配置以及聚合推送方案,再重点讨论保活配置,例如关闭电池优化、申请自启动和后台弹出权限,以及WorkManager定时任务如何配合厂商通道工作。掌握这些配置后,通知到达率可以明显提升,同时减少对常驻进程的依赖。

Android的消息推送长期以来都是工程实践里的麻烦事。海外可以依赖FCM,但国内没有统一推送服务,第三方推送SDK通常需要自己维持长连接。系统一旦进入Doze模式、清理后台或者开启省电策略,进程和连接很容易被冻结或杀掉。厂商通道正好补上这个短板,它由手机系统服务维护链路,应用进程不在时也能收到消息并展示通知。因此,稳定到达的核心就从单纯保活进程,变成了厂商通道接入和系统权限配置的组合。

Android推送如何完整接入厂商通道并做好保活?

为什么厂商通道能解决到达率问题

Android从6.0开始引入Doze和App Standby机制,系统会根据应用使用频率限制后台运行。到Android 12以后,后台启动Activity和Service的限制进一步收紧。第三方推送SDK依赖的TCP长连接一旦断开,客户端进程又处于缓存状态,服务器就只能等待应用下次被用户主动打开才能恢复连接。此时如果用户清理了任务列表,或者系统因内存压力回收进程,推送就会长时间失效。

厂商通道的链路不同。以华为、小米为例,系统内部运行着厂商自己的推送服务,这些服务由系统框架管理,拥有比普通应用更高的优先级。消息从厂商服务器下发到手机系统服务后,系统服务会根据包名匹配目标应用,然后通过广播或直接拉起进程的方式触发通知展示。即使应用进程完全不存在,通知栏仍然可以显示消息。这就是厂商通道到达率明显高于普通第三方通道的根本原因。

但厂商通道不是万能的。不同厂商对通知样式、点击行为、透传消息都有各自的限制。部分通道只允许展示通知栏消息,不允许应用在后台处理数据;还有厂商要求应用签名、包名、消息类别完全匹配。因此在实际项目中,厂商通道通常作为第一优先级,第三方长连接作为回退方案,两者配合才能覆盖更多设备。

主流厂商通道接入流程

国内主流厂商通道包括华为、小米、OPPO、vivo和荣耀。接入思路基本一致:先在厂商开发者平台创建应用,填写包名和应用签名证书的SHA256指纹,获取AppID、AppKey或AppSecret等参数;然后在工程中引入对应SDK,声明权限和Service组件;最后在应用启动时初始化推送并注册Token。下面以华为HMS Push为例展示关键代码。

华为推送需要在项目根目录的build.gradle中配置华为Maven仓库地址,并添加agcp插件。如果使用较新的Android Gradle Plugin,建议检查agcp插件的兼容版本,避免构建阶段出现插件冲突。

buildscript {
    repositories {
        google()
        jcenter()
        maven { url 'https://developer.huawei.com/repo/' }
    }
    dependencies {
        classpath 'com.huawei.agconnect:agcp:1.6.0.300'
    }
}

应用模块中需要应用插件并引入HMS Push依赖。同时要把从华为AGC后台下载的agconnect-services.json文件放到app目录下,否则初始化时会读取不到配置。

apply plugin: 'com.huawei.agconnect'
android {
    ...
}
dependencies {
    implementation 'com.huawei.hms:push:6.11.0.300'
}

AndroidManifest中需要声明网络权限和唤醒锁权限,并注册华为的推送消息服务。注意组件名必须与自定义Service类保持一致,否则系统无法正确回调。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

<application>
    <service
        android:name=".HmsMessageService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.huawei.push.action.MESSAGING_EVENT"/>
        </intent-filter>
    </service>
</application>

初始化阶段开启自动初始化,并获取推送Token。拿到Token后需要上传到业务服务器,服务端后续才能根据设备Token调用厂商接口下发消息。

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        HmsMessaging.getInstance(this).setAutoInitEnabled(true);
        HmsMessaging.getInstance(this).getToken()
            .addOnSuccessListener(token -> {
                Log.i("PushToken", token);
                uploadTokenToServer(token);
            })
            .addOnFailureListener(e -> {
                Log.e("PushToken", "get token failed", e);
            });
    }
}

除了华为,小米、OPPO、vivo和荣耀的接入方式类似,但工程配置和后台要求略有差异。下面用表格归纳关键信息。

厂商SDK/服务关键配置注意事项
华为HMS Pushagconnect-services.json、AppIdDebug包和Release包证书指纹通常要分开配置
小米MiPushAppId、AppKey需要声明XMPushReceiver,部分消息类型需在后台申请
OPPOOPushAppKey、AppSecret、ChannelID通知栏消息必须指定已创建的ChannelID
vivovPushAppId、AppKey正式推送能力需要应用上架后申请,审核较严格
荣耀HonorPushAppId、AppKey与华为体系独立,荣耀设备无法使用HMS Push

保活配置与系统权限

接入厂商通道后,通知到达率会大幅提升,但仍然有一些系统级开关会限制应用接收通知或响应点击。最常见的三个配置是电池优化白名单、自启动权限和后台弹出界面权限。这些配置不能通过普通代码强制开启,但可以检测状态并引导用户跳转到对应设置页。

电池优化白名单主要用于保护第三方通道和后台任务。如果应用被加入电池优化白名单,系统在待机和省电模式下不会轻易冻结应用的任务。使用PowerManager可以检测是否在白名单中,并引导用户关闭限制。代码示例如下。

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(getPackageName())) {
    Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivity(intent);
}

自启动权限在国产ROM上尤其重要。华为、小米、OPPO、vivo等系统默认会拦截应用开机自启动和后台拉起,如果不允许自启动,即使用户点击通知也可能无法启动应用。不同厂商的设置页面不一样,可以通过包名和组件名直接跳转。下面是一段兼容多个厂商的跳转逻辑。

private void openAutoStartSetting() {
    String manufacturer = Build.MANUFACTURER.toLowerCase();
    Intent intent = new Intent();
    if (manufacturer.contains("huawei")) {
        intent.setClassName("com.huawei.systemmanager",
                "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
    } else if (manufacturer.contains("xiaomi")) {
        intent.setComponent(new ComponentName("com.miui.securitycenter",
                "com.miui.permcenter.autostart.AutoStartManagementActivity"));
    } else if (manufacturer.contains("oppo")) {
        intent.setClassName("com.coloros.safecenter",
                "com.coloros.safecenter.permission.startup.StartupAppListActivity");
    } else if (manufacturer.contains("vivo")) {
        intent.setClassName("com.vivo.permissionmanager",
                "com.vivo.permissionmanager.activity.BgStartUpManagerActivity");
    } else if (manufacturer.contains("honor")) {
        intent.setClassName("com.hihonor.systemmanager",
                "com.hihonor.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
    }
    try {
        startActivity(intent);
    } catch (Exception e) {
        startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                Uri.parse("package:" + getPackageName())));
    }
}

后台弹出界面权限在OPPO和vivo上比较容易被忽略。如果该权限未开启,点击通知后Activity不会弹出,页面像没有响应一样。这个权限没有公开的API可以检测,只能跳转到应用详情页,让用户手动打开。

除了系统设置,代码层还可以使用WorkManager完成周期性Token同步。厂商Token可能因为卸载重装、清除数据或系统升级而变化,如果服务器一直保存旧token,推送就会丢失。通过WorkManager每12小时检查一次token并上报,可以降低这种风险。实现如下。

PeriodicWorkRequest tokenSyncRequest =
    new PeriodicWorkRequest.Builder(TokenSyncWorker.class, 12, TimeUnit.HOURS)
        .setConstraints(new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build())
        .build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "push_token_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    tokenSyncRequest
);

还有一类做法是使用前台服务保活。但Android 14以后前台服务类型管理更严格,推送用途需要声明specialUse,应用市场审核时也需要提供详细说明。除非确实需要长时间实时连接,否则不建议把前台服务作为主要保活手段。

聚合推送方案与多级回退

如果应用需要覆盖华为、小米、OPPO、vivo、荣耀等多个渠道,分别集成原生SDK会让工程配置变得复杂,还要维护多个厂商后台的应用信息。聚合推送平台如个推、极光、友盟等封装了各厂商通道,开发者只需接入一个SDK,平台服务端会自动选择目标设备对应的厂商通道下发消息。

聚合推送的典型初始化流程如下,完成注册后拿到平台客户端ID,再由服务端通过该ID进行厂商通道推送。

PushAgent pushAgent = PushAgent.getInstance(context);
pushAgent.register(new IRegisterCallback() {
    @Override
    public void onRegisterResult(int code, String message) {
        if (code == 0) {
            String clientId = pushAgent.getClientId();
            uploadClientId(clientId);
        }
    }
});

但聚合方案也有代价。数据需要经过第三方平台,免费版可能有限制,部分实时性要求高的场景可能不如直连厂商服务。因此架构上最好设计多级回退。服务端给每条设备记录多个通道信息,下发时先选择厂商token;如果厂商通道返回无效或未注册,再回退到平台长连接;如果用户关闭通知权限,则降级为应用内弹窗或站内信。这样可以兼顾到达率和可控性。

回退逻辑还需要处理海外设备。没有厂商服务的设备自然无法注册厂商token,此时必须保留第三方通道,否则用户完全收不到消息。token注册时可以把手机品牌、Android版本、厂商通道状态一并上报,服务端根据这些信息决定走哪条链路。

测试方法与常见问题

推送功能上线前必须在真机上验证。重点场景包括:锁屏后等待十分钟、清理最近任务、重启手机、开启省电模式。如果这些场景下通知都能正常展示,说明厂商通道配置基本生效。各厂商开发者平台一般提供调试工具,例如华为的Push Debugger和小米的推送测试页面,可以模拟不同消息类型。

排查问题时,优先确认三个点:一是Token是否成功获取,日志里的token长度是否符合厂商规范;二是通知权限是否被用户关闭;三是自启动和后台弹出界面是否开启。很多时候推送不到不是代码问题,而是系统设置被拦截。可以把这些状态做成内置的调试页面,方便测试和客服排查。

另外还要注意厂商通道对消息分类的要求。例如OPPO和vivo对公信消息和私信消息有不同渠道限制,华为对通知栏点击动作有额外配置。接入时不要只看官方快速开始文档,还要仔细阅读消息分类和模板限制,避免上线后才发现某些消息类型被厂商静默丢弃。

Android推送厂商通道保活修改时间:2026-10-01 09:53:22

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/1001/64192.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。