前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IMSDK华为离线推送快速集成

IMSDK华为离线推送快速集成

原创
作者头像
ppchao
修改2021-01-13 18:14:31
2K0
修改2021-01-13 18:14:31
举报
文章被收录于专栏:写个呆萌写个呆萌

一、简介

即时通信 IM 的终端用户需要随时都能够得知最新的消息,而由于移动端设备的性能与电量有限,当 App 处于后台时,为了避免维持长连接而导致的过多资源消耗,即时通信 IM 推荐您使用各厂商提供的系统级推送通道来进行消息通知,系统级的推送通道相比第三方推送拥有更稳定的系统级长连接,可以做到随时接受推送消息,且资源消耗大幅降低。

本篇主要介绍:在tuikit上如何快速跑通华为离线推送,实现如下功能点,顺便记录一下,在集成过程中,容易踩到的坑点

1、退后台/杀进程,接收离线消息

2、离线消息透传ext字段

3、通知栏点击,打开应用内界面

4、app角标计数刷新

二、官网集成

所有的集成流程,在IM官网已经有介绍,细心的同学参考官网流程,即可跑通代码。

本篇直接从tuikit demo入手,快速运行集成运行华为离线推送。

准备工作:

1、下载tuikit demo

2、申请好华为离线推送账号;

3、参考IM官网,完成im控制台的一些简单配置;

4、将配置后的各个id,替换到tuikit demo中去

5、搞定

离线推送效果如下图

三、集成操作

1、下载tuikit demo,并运行起来

tuikit已经将华为离线推送必要的库都集成好了,我们只需要替换掉tuikit中的几个配置参数,就能运行起来。

需要替换的几个配置参数,下面会逐一指明。

如果您已经熟悉了tuikit,需要自行集成,可以参考华为官网集成文档

2、申请好华为离线推送账号

如下图,申请好了账号,下载agconnect-services.json文件,替换到tuikit demo中去

如果您申请的包名不是com.tencent.qcloud.tim.tuikit,而是自己的app包名,可以修改demo的包名appliationId。

华为离线推送账号,有些项目申请时需要企业资质,由华为审核,需要几个工作日,记得提前申请。

3、im控制台一些简单配置

如下图,将华为开发者控制台上,申请到的离线推送账号信息,填到IM控制台,会生成一个buzid证书。

将buzid、appid填入demo中

4、将离线推送账号配置参数,写入demo中

如上已经配置齐活了,一共3点,替换agconnect-services.json文件、写入buzid、写入appid。

5、搞定

要运行起来,必需使用release包,签名文件的sha256指纹证书,要与华为控制台配置的sha256证书一致。如果不一致,代码中运行到注册华为离线推送时,会报6003错误。

代码语言:java
复制
HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");

四、离线推送原理

如下图,“发送方”发一条消息给“接收方”,消息投递流程。

1、消息到了IM服务端,IM服务端会判断接收方userid的在线状态;

2、如果接收方是login登入状态、而且应用在前台,这种后台标记状态是Online,消息就直接发到接收端imsdk。这就是在线消息。

3、如果接收方是login登入状态、但是应用退后台、进程还活着,这种后台标记也是Online,消息会同时发给接收端imsdk、发给华为离线推送后台,华为离线推送后台,会再给手机推送这条消息。

4、如果接收方是login登入状态,但是应用退后台、进程被杀死了,这种后台标记是PushOnline,消息不会再发给接收端imsdk了,只会发送给华为离线推送后台,华为离线推送后台再转推这条消息,弹出系统通知栏。这就是离线消息。

5、如果接收方已经logout登出了,这种后台标记是Offline,消息不会向下投递了,会存在漫游服务器中,接收端在有效期内,login登入了,再通过拉漫游接口获取这些消息。

第2点与第3点,后台标记同样是Online状态,推送策略却不一样,这是受imsdk终端api触发的:终端退后台时,调用了doBackground接口,后台就会推在线消息的同时,也给推离线消息。

代码语言:java
复制
//APP 检测到应用退后台时可以调用此接口,可以用作桌面应用角标的初始化未读数量。
//从5.0.1版本开始,如果配置了离线推送,会收到厂商的离线推送通道下发的通知栏消息。
V2TIMManager.getOfflinePushManager().doBackground(param)

五、离线推送,透传ext字段

注意:

由于华为推送的兼容性问题,透传内容只能在部分 EUI10+ 的设备上收到。

步骤1:发送端设置自定义内容

在发消息前设置每条消息的通知栏自定义内容。

下面是 Android 端简单示例,也可以参考 TUIKit 中 ChatManagerKit.java 类的 sendMessage() 方法中对应的逻辑:

代码语言:java
复制
OfflineMessageContainerBean containerBean = new OfflineMessageContainerBean();
OfflineMessageBean entity = new OfflineMessageBean();
entity.content = message.getExtra().toString();
entity.sender = message.getFromUser();
entity.nickname = TUIKitConfigs.getConfigs().getGeneralConfig().getUserNickname();
entity.faceUrl = TUIKitConfigs.getConfigs().getGeneralConfig().getUserFaceUrl();
containerBean.entity = entity;
		
V2TIMOfflinePushInfo v2TIMOfflinePushInfo = new V2TIMOfflinePushInfo();
v2TIMOfflinePushInfo.setExt(new Gson().toJson(containerBean).getBytes());
		
V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, userID, null,
            V2TIMMessage.V2TIM_PRIORITY_DEFAULT, false, v2TIMOfflinePushInfo, V2TIMSendCallback)

步骤2:接收端获取自定义内容

  • 添加证书 时设置【点击通知后】的操作为【打开应用】或【打开应用内指定界面】,当点击通知栏的消息时,客户端可以在相应的 Activity 中获取自定义内容,可以参考 OfflineMessageDispatcher.java 类的 parseOfflineMessage(Intent intent) 方法实现。
代码语言:javascript
复制
Bundle bundle = getIntent().getExtras();
String value = bundle.getString("ext"); 
Log.i(TAG, "push custom data ext: " + ext);

//输出push custom data ext:
{
    "entity":{
        "action":1,
        "chatType":1,
        "content":"这是一条含有自定义ext字段的消息",
        "faceUrl":"",
        "nickname":"",
        "sendTime":0,
        "sender":"chaoli01",
        "version":1
    }
}

六、通知栏点击动作

参考IM官网配置

这里给出示例,演示点击打开应用内界面:

代码语言:java
复制
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.tencent.qcloud.tim.demo">
    
        ......
            <activity
            android:name="com.tencent.qcloud.tim.demo.chat.ChatActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustResize|stateHidden">

            <!-- 华为离线推送打开应用内页面 -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <data
                    android:host="com.tencent.qcloud.tim"
                    android:path="/detail"
                    android:scheme="pushscheme" />
            </intent-filter>


        </activity>
        ......
    
</manifest>

七、app角标刷新

  • 手机系统控制角标

厂商推送离线消息到手机,手机系统会触发刷新通知栏、app角标,在手机系统设置里面打开/关闭角标功能,就可以了。

一条离线消息,对应一条通知栏信息,对应一个角标数字+1

  • 代码控制角标

我们先看看华为离线推送文档,对于终端代码控制角标的描述。

当点击通知栏消息,唤起应用,才能在app内通过代码控制角标,主要是需要处理消除角标,tuikit demo中有监听消息已读上报,已读成功了就调用华为api,消除app角标,代码如下:

代码语言:java
复制
public class DemoApplication extends Application {


    @Override
    public void onCreate() {
        DemoLog.i(TAG, "onCreate:DemoApplication");
        super.onCreate();

        registerActivityLifecycleCallbacks(new StatisticActivityLifecycleCallback());

    }

    class StatisticActivityLifecycleCallback implements ActivityLifecycleCallbacks {
        private int foregroundActivities = 0;
        private boolean isChangingConfiguration;
        private IMEventListener mIMEventListener = new IMEventListener() {
            @Override
            public void onNewMessage(V2TIMMessage msg) {
                String version = TIMManager.getInstance().getVersion();
                int i = Integer.parseInt(version.substring(0,1));

                //imsdk 5.0以上的版本,当app退后台时调用doBackground,im后台就会同时推送在线消息和离线消息。
                //当sdk版本大于等于5.0时,默认退后台不触发在线消息的自定义通知栏。
                if(i<4){
                    MessageNotification notification = MessageNotification.getInstance();
                    notification.notify(msg);
                }

            }
        };

        private ConversationManagerKit.MessageUnreadWatcher mUnreadWatcher = new ConversationManagerKit.MessageUnreadWatcher() {
            @Override
            public void updateUnread(int count) {
                // 华为离线推送角标
                HUAWEIHmsMessageService.updateBadge(DemoApplication.this, count);
            }
        };

        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) {
            DemoLog.i(TAG, "onActivityCreated bundle: " + bundle);

        }

        @Override
        public void onActivityStarted(Activity activity) {
            foregroundActivities++;
            if (foregroundActivities == 1 && !isChangingConfiguration) {
                // 应用切到前台
                DemoLog.i(TAG, "application enter foreground");
                V2TIMManager.getOfflinePushManager().doForeground(new V2TIMCallback() {
                    @Override
                    public void onError(int code, String desc) {
                        DemoLog.e(TAG, "doForeground err = " + code + ", desc = " + desc);
                    }

                    @Override
                    public void onSuccess() {
                        DemoLog.i(TAG, "doForeground success");
                    }
                });
                TUIKit.removeIMEventListener(mIMEventListener);
                ConversationManagerKit.getInstance().removeUnreadWatcher(mUnreadWatcher);
                MessageNotification.getInstance().cancelTimeout();
            }
            isChangingConfiguration = false;
        }

        @Override
        public void onActivityResumed(Activity activity) {

        }

        @Override
        public void onActivityPaused(Activity activity) {

        }

        @Override
        public void onActivityStopped(Activity activity) {
            foregroundActivities--;
            if (foregroundActivities == 0) {
                // 应用切到后台
                DemoLog.i(TAG, "application enter background");
                int unReadCount = ConversationManagerKit.getInstance().getUnreadTotal();
                V2TIMManager.getOfflinePushManager().doBackground(unReadCount, new V2TIMCallback() {
                    @Override
                    public void onError(int code, String desc) {
                        DemoLog.e(TAG, "doBackground err = " + code + ", desc = " + desc);
                    }

                    @Override
                    public void onSuccess() {
                        DemoLog.i(TAG, "doBackground success");
                    }
                });
                // 应用退到后台,消息转化为系统通知
                TUIKit.addIMEventListener(mIMEventListener);
                ConversationManagerKit.getInstance().addUnreadWatcher(mUnreadWatcher);
            }
            isChangingConfiguration = activity.isChangingConfigurations();
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

        }

        @Override
        public void onActivityDestroyed(Activity activity) {

        }
    }
}


public class HUAWEIHmsMessageService extends HmsMessageService {


    public static void updateBadge(final Context context, final int number) {
        if (!BrandUtil.isBrandHuawei()) {
            return;
        }
        DemoLog.i(TAG, "huawei badge = " + number);
        try {
            Bundle extra = new Bundle();
            extra.putString("package", "com.tencent.qcloud.tim.tuikit");
            extra.putString("class", "com.tencent.qcloud.tim.demo.SplashActivity");
            extra.putInt("badgenumber", number);
            context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, extra);
        } catch (Exception e) {
            DemoLog.w(TAG, "huawei badge exception: " + e.getLocalizedMessage());
        }
    }
}

角标刷新效果如下:

八、总结&常见问题:

1、tuikit已经集成好了华为离线推送,参考上文3步配置,就可以快速运行起来华为推送。

2、注册华为离线推送账户,需要企业资质,需要几个工作日审批,请提前申请。

3、华为离线推送,必需要release包,签名文件的sha256指纹证书,要添加到华为控制台。

4、指纹证书不对,运行到申请token时,会报错6003

5、imsdk在5.0以上的版本,退后台调用doBackground接口,im后台会推送在线消给app内imsdk,推离线消息给厂商,厂商再推离线消息给手机系统。tuikit当前版本监听了应用前后台状态ActivityLifecycleCallbacks,请注意修改sdk版本判断逻辑,避免退后台同时收到在线、离线消息。

6、由于华为推送的兼容性问题,自定义ext字段,只能在部分 EUI10+ 的设备上收到

7、进程被杀,厂商推送离线消息到来,弹出的通知栏行为、通知栏样式、震动、提示音、角标增加,都是系统行为,控制开关在手机系统设置里面。

8、imsdk4.8以上的版本,才支持刷新角标,这是在im控制台配置的,配置app首个页面activity的全名称。

9、部分华为机型,杀进程后收到离线消息15+,角标增加会偶现少1个,不太准。线上开发如果遇到,建议咨询华为离线推送支持人员。

10、角标数置0:tuikit目前逻辑是,监听消息已读,调用华为刷新角标api,将角标数置0。目前上报已读的逻辑是:当上报了最新一条消息为已读,那么这条消息之前所有的消息,都置为已读。

11、通知栏点击动作:启动应用、打开网页、跳转到应用内界面,只需要在im控制台修改配置即可,几分钟就能生效。

12、配置打开应用内界面,参考文档配置正确即可。如果是调试tuikit,注意tuikit默认是启动应用,需要修改两处代码:①、DemoApplication里面默认打开SplashActivity滑动界面,②、ChatActivity里面默认判断intent.getExtras,如果是空就跳转到SplashActivity滑动界面,可以在EUI10+ 的设备上调试,使能收到自定义ext字段,就能正常打开停留在ChatActivity界面。

13、写作日期:2021/1/13日,以上部分功能升级,会同步更新。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简介
  • 二、官网集成
  • 三、集成操作
    • 1、下载tuikit demo,并运行起来
      • 2、申请好华为离线推送账号
        • 3、im控制台一些简单配置
          • 4、将离线推送账号配置参数,写入demo中
            • 5、搞定
            • 四、离线推送原理
            • 五、离线推送,透传ext字段
            • 六、通知栏点击动作
            • 七、app角标刷新
            • 八、总结&常见问题:
            相关产品与服务
            访问管理
            访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档