Android 集成华为推送

大概整理步骤4步

  • 首先须要在华为开发者联盟平台注册帐号java

    进入 “管理中心” -> “应用管理”,点击 “建立移动应用” 按钮,填写必要的信息,建立一个应用android

  • 须要为建立的应用程序申请Push权益web

    进入 “管理中心” -> “应用管理”,点击权益列的 “+” 打开 “配置权益”对话框,申请须要的Push权益api

  • 申请 Push权益时,须要提供应用签名证书的 SHA256 指纹网络

    在命令行使用 keytool -list -v -keystore < keystore-file > 命令
    < keystore-file > 是为应用签名使用的 keystore 文件,当提示输入口令时,能够选择不输入不影响得到 SHA256 指纹
    注意:keytool 命令是”%JAVA_HOME%\bin\keytool.exe”下的命令符app

  • 想要正常接收通知,若是不是华为手机,须要安装 “华为服务”才能够接收通知异步

集成华为推送有两种方式

  • HMS Push (本文使用HMS方式集成)
  • Push SDK
    注意:
    HMS Push 的接口能够全量替换老版本的 Push 接口
    APP 不能同时集成 HMS Push 和老的 Push SDK, 若是使用 HMS Push,必须删除老的 Push SDK 代码和 jar 包
    切换到 HMS Push 后,原来的 setTag/getTag/deleteTag 功能暂时不可用,若是 APP须要使用到这 3 个接口功能,那建议先不要切换,等后续 HMS 版本支持了再切换

相关文件配置

  • 配置 manifest 文件
<!-- 必需的权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- 保存富媒体消息须要,无富媒体消息则不须要 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 建立桌面快捷方式,无富媒体消息则不须要 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<!-- 根据地理位置推送消息须要事先上报地理位置信息,须要以下权限,不上报则不须要-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 访问Push APK provider须要的权限,SDK富媒体须要,无富媒体功能则不须要 -->
<uses-permission android:name="com.huawei.pushagent.permission.RICHMEDIA_PROVIDER"/>

配置APPID
<meta-data  android:name="com.huawei.hms.client.appid" android:value="appid">
</meta-data>
其中meta-data中,指定了应用ID,"appid"用实际申请的应用ID替换

<!-- 升级provider,向安装器提供 "content://<package.name>.hsf.update.provider/update/hms/HwMobileService.apk" -->
<provider  android:name="com.huawei.hms.update.provider.UpdateProvider" android:authorities="您的包名.hms.upda te.provider" android:exported="false" android:grantUriPermissions="true"/>

<!-- 第三方相关 :接收Push消息(注册、Push消息、Push链接状态)广播 -->
<receiver android:name=".receiver.HuaweiPushReceiver">
    <intent-filter>
    <!-- 必须,用于接收token -->
    <action android:name="com.huawei.android.push.intent.REGISTRATION"/>
    <!-- 必须,用于接收消息 -->
    <action android:name="com.huawei.android.push.intent.RECEIVE"/>
    <action android:name="com.huawei.android.push.intent.CLICK"/>
    <!-- 可选,查看push通道是否链接,不查看则不须要 -->
    <action android:name="com.huawei.intent.action.PUSH_STATE"/>
    </intent-filter>

    <meta-data  android:name="CS_cloud_ablitity" android:value="@string/hwpush_ability_value"/>
</receiver>

<receiver  android:name="com.huawei.hms.support.api.push.PushEventReceiver">
    <intent-filter>
    <!-- 接收通道发来的通知栏消息,兼容老版本Push -->
    <action android:name="com.huawei.intent.action.PUSH"/>
    </intent-filter>
</receiver>
  • 申请 token
    应用在调用 Push 接口前须要先链接到华为移动服务(HMS),进行接口鉴权,接口鉴
    权成功以后才能调用 push 接口

建立HuaweiApiClient实例,链接到华为移动服务ide

HuaweiApiClient client = new HuaweiApiClient.Builder(this) //
.addApi(HuaweiPush.PUSH_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
//获取token示例代码--同步调用方式
private void getToken() {
 if (!isConnected()) {
  Log.e("TAG","get token failed, HMS is disconnect");
  return;
 }
 new Thread() {
 @Override
 public void run() {
  PendingResult<TokenResult> tokenResult =
  HuaweiPush.HuaweiPushApi.getToken(huaweiApiClient);
  //token结果经过广播返回,不经过pendingResult返回,调用await()方法发起请求根据对象能够获取接口调用是否成功,可是不直接返回token结果
  tokenResult.await();
  }
 }.start();
}
//获取token--异步调用方式
private void getToken(){
    final PendingResult<TokenResult> tokenResult = HuaweiPush.HuaweiPushApi.getToken(huaweiApiClient);

tokenResult.setResultCallback(new ResultCallback<TokenResult>() {
    @Override
    public void onResult(TokenResult result) {
    Log.e(TAG,"tokenResult.setResultCallback() thread:" +Thread.currentThread().getName());
    new Thread() {
      @Override
      public void run() {
      tokenResult.await();
       }
     }.start();
   }
  });
}
【注意事项】
调用申请token前,HuaweiApiClient必须是链接成功的。
采用同步调用方式时,await()方法不能在主线程里调用。
Token结果经过广播返回,详见PushReceiver 的onToken()实现

申请不到 token?
申请不到 token的缘由有多种,最多见的是接口鉴权失败或应用证书指纹校验错误
(1)接口鉴权失败,返回 6XXX 错误先检查网络是否正常链接,检查应用是否已经在开发者联盟上面开通Push权益
(2)接口鉴权失败,返回 9071357XX 错误不容许使用Push能力联盟上的证书指纹与应用的证书指纹不匹配
(3)华为服务须要有自启动权限
(4)若是集成正确,则须要在客户端抓取日志,查看具体的失败缘由,先使用该设备(申请不到 token 的设备)安装运行下载文档中提供的demo,调用申请token 接口,确认是否能够获取到 token。若是能够获取到说明设备没问题,极可能是app集成HMS SDK时出错.若是设备能够链接adb环境,请使用工具抓取日志并将日志发送给华为接口人,工具能够咨询华为接口人并获取svg

ok,到此就能够经过华为开发者联盟平台进行推送消息了

集成 PushReceiver 接收 token,Push 链接状态等

应用须要建立一个子类继承com.huawei.hms.support.api.push.PushReceiver,实现onToken(),onPushState(),onPushMsg(),onEvent()这几个抽象方法,用来接收 token返回,push链接状态,透传消息和通知栏点击事件处理工具

public void onToken(Context context, String token, Bundle extras) {
 String belongId = extras.getString("belongId");
 String content = "获取token和belongId成功,token = " + token + ",belongId = " +
belongId;
 Log.d(PushMainActivity.TAG, content);
 // TODO
}

public void onPushState(Context context, boolean pushState) {
 try {
 String content = "查询push通道状态: " + (pushState ? "已链接" : "未链接");
 Log.d("PushLog", content);
 showPushMessage(PushMainActivity.RECEIVE_STATUS_MSG, content);
 } catch (Exception e) {
 e.printStackTrace();
 }
}

public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
 try {
 String content = "收到一条Push消息: " + new String(msg, "UTF-8");
 Log.d(PushMainActivity.TAG, content);
 showPushMessage(PushMainActivity.RECEIVE_PUSH_MSG, content);
 } catch (Exception e) {
 e.printStackTrace();
 }
 return false;
}

public void onEvent(Context context, Event event, Bundle extras) {
//NOTIFICATION_OPENED,通知栏中的通知被点击打开
//NOTIFICATION_CLICK_BTN,通知栏中通知上的按钮被点击
 if (Event.NOTIFICATION_OPENED.equals(event) ||
     Event.NOTIFICATION_CLICK_BTN.equals(event)) {
 int notifyId = extras.getInt(BOUND_KEY.pushNotifyId, 0);
 if (0 != notifyId) {
 NotificationManager manager = (NotificationManager)context
 .getSystemService(Context.NOTIFICATION_SERVICE);
 manager.cancel(notifyId);
 }
 String content = "收到通知附加消息:"+extras.getString(BOUND_KEY.pushMsgKey);
 Log.d(PushMainActivity.TAG, content);
 showPushMessage(PushMainActivity.RECEIVE_NOTIFY_CLICK_MSG, content);
 }
 super.onEvent(context, event, extras);
}

透传消息和通知栏消息有什么区别?

透传消息是华为 Push 将消息送达手机后不作呈现,直接转给开发者的应用,由应用本 身去解析消息和呈现内容。 通知栏消息是华为 Push 将消息送达手机后,会在通知栏显示一条消息,点击后触发指 定动做,应用不须要去解析消息和控制呈现,减小了应用的开发工做量。