文档开发者中心
我的

华为推送服务(HMS)接入文档

       怀着谦卑和感恩的心情写下本文,希望对大家能有所帮助,没有什么技术含量,只是记录下自己踩过的坑,有问题请指教。
       写作的原因有二:
       1.        华为推送sdk的文档写得不好并且分散是不争的事实,值得吐槽的是这不是大厂作风,同样是push sdk,这点需要向小米和魅族学习。我也是东拼西凑看了好多个地方的文档,包括sdk中的指导书以及开发者联盟,然后自己和同事不断地尝试以及踩坑才最终较为完美的接入了华为HMS。我自己身在华为开发者群中,看到群主MM每天由于文档不完善这个大坑各种给大家解答,十分无奈,希望下次再有人在群里问一些常见问题的时候,群主只需将这篇文章贴出来即可。
       2.       无论如何还是要感激华为免费(至少目前)为我们在华为手机上提供了类似APNs在iOS的推送服务。感激我在接入各家推送服务过程中社区给予我的帮助,这篇文章算是一种回馈。
       废话到此,进入正题。

       一、背景
       公司的push系统采用的是N+1的方式,即N家厂商通道+1家第三方推送的方式。华为、小米和魅族手机使用它们的系统通道,其他手机使用一家第三方推送。所以对于华为推送,我们只在华为手机上使用。

       二、目的
       期望在我们的用户中,使用华为推送的手机不论app是否存活都能收到通知栏消息,并且不需要引导用户开启自启动权限就能捕获点击通知栏的事件进行自定义处理。 这也是接入华为推送服务的意义所在。

       三、选型
        1.        我接入的HMS版本为2.4.0.300,选择HMS而不是push sdk的原因是老版的push sdk官方已经不再维护,以及hms的体积只有200K出头。
        2.        只使用通知栏消息,而不使用透传。在华为手机上使用华为的透传消息与第三方推送一样需要app存活,因此使用透传消息没有意义。所以劝打算使用透传消息的朋友打消这个念头。华为推送的通知栏消息在EMUI上就如同APNs在iOS的效果,因为通知直接由系统弹出,所以不论app是否存活消息都可达。然而通过官方的说明以及经过我和同事的一系列测试发现通知栏消息并不是所有的华为手机都能到达,需要满足一定的条件:1. emuiApiLevel > 9;2. 华为移动服务版本>=2.4.1.300。不满足这个条件的华为手机我们仍然使用第三方推送。
        3.        服务端调用接口发送通知栏消息,参数设置为app自定义打开方式。
   
      四、客户端接入参照开发指导书即可

      五、服务端接入
      前面提到,我们采用通知栏消息以及自定义打开方式,直接上代码:
  1. OAuth2Client oauth2Client = new OAuth2Client();
  2.         oauth2Client.initKeyStoreStream(HuaweiPushService.class.getResource("/mykeystorebj.jks").openStream(), "123456"); // jks文件直接使用sdk里的即可,密码固定为123456
  3.         AccessToken accessToken = oauth2Client.getAccessToken("client_credentials", "appId", "appSecret");
  4.         System.out.println("access token: " + accessToken.getAccess_token() + " expires in " + accessToken.getExpires_in());
  5.         NSPClient client = new NSPClient(accessToken.getAccess_token());
  6.         client.initHttpConnections(30, 50);
  7.         client.initKeyStoreStream(HuaweiPushService.class.getResource("/mykeystorebj.jks").openStream(), "123456");
  8.         client.setTimeout(10000, 15000);
  9.         Map<String, Object> params = new HashMap<>();
  10.         String[] tokens = {"token"};
  11.         params.put("cacheMode", 1);
  12.         params.put("msgType", -1);
  13.         params.put("deviceTokenList", tokens);
  14.         params.put("android", "{"notification_title":"title","intent":"intent:#Intent;launchFlags=0x10000000;component=com.xxx.xxx/.MainActivity;i.age=18;S.name=zhang;end","notification_content":"content","doings":2}"); // intent由代码生成,具体请参考Q&A第3条
  15.         params.put("expire_time", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(System.currentTimeMillis() + 3600 * 1000)));
  16.         PushRet rsp = client.call("openpush.message.psBatchSend", params, PushRet.class);
  17.         System.out.println("通知栏消息接口响应:" + rsp);
复制代码

六、客户端处理自定义事件
        由于app杀死以后点击push不会回调onEvent(因为广播被系统限制了),所以自定义动作的处理我们统一用intent来实现。参数传递依赖android结构体中的intent参数。intent中处理消息的组件只能是activity,不能是service或receiver。于是这时处理自定义事件的方式变为在指定activity的onCreate方法中调用getIntent()来获取服务端要传的参数进行处理。有的朋友说,我kill掉app后点击通知还能回调onEvent,那是因为你给app开了自启动权限。

七、其他Q&A
        1.        Q: 如何切换测试环境和正式环境?
                   A: 每次修改华为后台的sha256的指纹后执行如下步骤:1. 删除app;2. 清空华为移动服务的数据;3. 重装新指纹对应的app。不生效的话重复重新保存指纹,重复上述步骤。
        2.        Q: 如何生成intent参数?
                   A: 代码如下
  1. Intent intent = new Intent();
  2. intent.setClass(MainActivity.this,MainActivity.class);
  3. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  4. intent.putExtra("name", “zhangsan");
  5. intent.putExtra("age", 18);
  6. String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
复制代码
        3.        Q: 客户端连接时返回6003?
                   A: 后台配置的指纹与app对不上
        4.        Q:客户端连接是返回907135702?
                   A: 没有在后台配置指纹
        5.        Q: 配置了指纹还是返回907135702?
                   A: 参照2的步骤
        6.        Q: 客户端返回错误码2
                   A: 华为移动服务版本太低,升级一下即可
        7.        Q: app能否感知消息到达?
                   A: 不行。通知栏消息直接由系统弹出。
        8.        Q: 如何判断获取emuiApiLevel?
                   A: 代码如下:
  1. int emuiApiLevel = 0;
  2.         try {
  3.             Class cls = Class.forName("android.os.SystemProperties");
  4.             Method method = cls.getDeclaredMethod("get", new Class[]{String.class});
  5.             emuiApiLevel = Integer.parseInt((String) method.invoke(cls, new Object[]{"ro.build.hw_emui_api_level"}));
  6.         } catch (Exception e) {
  7.             e.printStackTrace();
  8.         }
复制代码
                判断emuiApiLevel>9即可。
        9.     Q: 如何判断华为移动服务版本>=2.4.1.300?
                  A: 代码如下:
  1. PackageInfo pi = null;
  2.         PackageManager pm = context.getPackageManager();
  3.         int hwid = 0;
  4.         try {
  5.             pi = pm.getPackageInfo("com.huawei.hwid", 0);
  6.             if (pi != null) {
  7.                 result = pi.versionCode;
  8.             }
  9.         } catch (PackageManager.NameNotFoundException e) {
  10.             e.printStackTrace();
  11.         }
复制代码
                 判断hwid>=20401300即可。
        10.     Q: 华为通知栏消息的声音、样式以及app在前台是否展示这些点是否可以自定义?
                  A: 通通不行,华为通知栏消息的样式只能是系统默认。

点赞
1
收藏
4
回复
29
分享
举报
浏览47422 编辑于2017-07-27 02:24未知归属地
全部评论
最多点赞
最新发布
最早发布
一年过去了,加了不少的东西,现在更乱了
29楼回复于2018-05-22 15:00 未知归属地
huafans0113816794 发表于 2017-5-22 09:13
赞一个,这几天我也在折腾这玩意,闹心。
前几天我发过一个帖子,但官方没有任何回应,傲娇!!!

请问服务器端开发文档是在哪里看的,我好像没有找到详细的资料,
28楼回复于2018-05-17 01:49 未知归属地
请问有相关文档看吗?感觉在线的文档不是很详细
27楼回复于2018-05-17 01:48 未知归属地
请问华为服务端推送能按照标签推送吗? 设置tag的接口地址参数子类的是什么
26楼回复于2017-11-23 10:06 未知归属地
请问华为服务端推送能按照标签推送吗?
25楼回复于2017-10-20 01:07 未知归属地
jiaotuo135671 发表于 2017-7-26 09:40
您的的版本是能给个下载地址么?我只能找到

我这个是旧版本的,现在官方下掉了,都建议用新接口
24楼回复于2017-07-26 09:22 未知归属地
chinacharis 发表于 2017-7-21 17:19
用系统级通道的时候,通知栏消息是一条条列出的,有办法合并吗?

还真没了解过额
23楼回复于2017-07-26 09:21 未知归属地
您的的版本是能给个下载地址么?我只能找到
22楼回复于2017-07-26 01:40 未知归属地
透传消息在APP杀死的情况下到达不了,只有使用系统级通道,系统级通道的消息在通知栏展示的时候无法控制又是很郁闷
21楼回复于2017-07-21 09:22 未知归属地
用系统级通道的时候,通知栏消息是一条条列出的,有办法合并吗?
20楼回复于2017-07-21 09:19 未知归属地
共3页
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

了解社区公约,与您携手共创和谐专业的开发者社区。