Android 华为集成消息推送sdk

本来是想吐槽的,写到最好发现官网好清晰

不容易发现的官方API

image.png

集成步骤:开发准备官方链接地址

创建应用,添加签名证书
    1. 打开命令行工具(使用CMD命令),执行cd命令进入keytool.exe所在的目录
    1. 执行命令keytool -list -v -keystore <keystore-file>,按命令行提示进行操作。<keystore-file>为应用签名文件的完整路径。填写SHA256,然后等十几分钟后下载对应的agcibbetct0services.json文件。
keytool -list -v -keystore I:\yhxx\releasexxxxx.keystore
image.png
image.png

image.png
添加应用的AppGallery Connect配置文件

a. 登录 AppGallery Connect 网站,选择“我的项目”。
b. 在项目列表中找到您的项目,在项目中点击需要集成HMS SDK的应用。
c. 在“项目设置”页面中,单击“应用”栏下的agconnect-services.json下载配置文件。
d. 将agconnect-services.json文件拷贝到应用级根目录下。

image.png

配置HMS SDK的maven仓地址

a. 打开AndroidStudio项目级project下的build.gradle文件。

image.png

b. 在allprojects ->repositories里面配置HMS SDK的maven仓地址。

allprojects {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}

c. 在buildscript ->repositories里面配置HMS SDK的maven仓地址。

buildscript {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}

d. 在buildscript -> dependencies里面增加配置。

buildscript {
    dependencies {
        classpath 'com.huawei.agconnect:agcp:1.2.1.301'
    }
}
添加编译依赖

a. 打开应用级modulebuild.gradle文件。

image.png

b. 在dependencies中添加如下编译依赖。
说明:{version}替换为实际的·SDK·版本号:implementation 'com.huawei.hms:push:4.0.3.301'

根据文档来填写,版本号好像更新

dependencies {
     //其它已存在的依赖不要删除 implementation 'com.huawei.hms:push:4.0.3.301
     implementation 'com.huawei.hms:push:{version}'
}

c. 在应用级build.gradle文件尾添加配置。

apply plugin: 'com.huawei.agconnect'

配置签名(不可少,否则会获取不到token,6003错误)

android {
     signingConfigs {
         config {
             keyAlias 'yalun'
             keyPassword '123456'
             storeFile file('I:/yhxx/release1.keystore')
             storePassword '123456'
         }
     }
     buildTypes {
         debug {
             signingConfig signingConfigs.config
         }
         release {
             signingConfig signingConfigs.config
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
 }
同步工程

修改完的build.gradle文件,点击右上方出现Sync Now等待同步完成。

注册HWPushReceiverService:

配置完成后,可以通过两种方式获取token,一种是清单文件直接加入配置,可以再onNewToken方法里面直接获取,推荐。再一种是设置一下,也是在onNewToken方法中获取token。参考本项目中的类HWPushReceiverService

HWPushReceiverService类需要开发者自己定义,继承于com.huawei.hms.push.HmsMessageService类并实现其中的方法。
exported属性需要设置为false

image.png

package com.cc.pushallsdk;

import android.text.TextUtils;
import android.util.Log;

import com.huawei.hms.push.HmsMessageService;
import com.huawei.hms.push.RemoteMessage;

import java.util.Arrays;


public class HWPushReceiverService extends HmsMessageService {
    private static String TAG=HWPushReceiverService.class.getSimpleName();
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.i(TAG, "getCollapseKey: " + remoteMessage.getCollapseKey()
                + "\n getData: " + remoteMessage.getData()
                + "\n getFrom: " + remoteMessage.getFrom()
                + "\n getTo: " + remoteMessage.getTo()
                + "\n getMessageId: " + remoteMessage.getMessageId()
                + "\n getOriginalUrgency: " + remoteMessage.getOriginalUrgency()
                + "\n getUrgency: " + remoteMessage.getUrgency()
                + "\n getSendTime: " + remoteMessage.getSentTime()
                + "\n getMessageType: " + remoteMessage.getMessageType()
                + "\n getTtl: " + remoteMessage.getTtl());
        RemoteMessage.Notification notification = remoteMessage.getNotification();
        if (notification != null) {
            Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
                    + "\n getTitle: " + notification.getTitle()
                    + "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
                    + "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
                    + "\n getBody: " + notification.getBody()
                    + "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
                    + "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
                    + "\n getIcon: " + notification.getIcon()
                    + "\n getSound: " + notification.getSound()
                    + "\n getTag: " + notification.getTag()
                    + "\n getColor: " + notification.getColor()
                    + "\n getClickAction: " + notification.getClickAction()
                    + "\n getChannelId: " + notification.getChannelId()
                    + "\n getLink: " + notification.getLink()
                    + "\n getNotifyId: " + notification.getNotifyId());

        }
    }
    @Override
    public void onDeletedMessages() {
        super.onDeletedMessages();

    }
    /**
    *
    *清单文件设置了自动初始化能力的应用,不需要显式的调用getToken申请token,
    * Push SDK会自动申请token,并通过onNewToken回调方法返回。
    */
    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        if (!TextUtils.isEmpty(token)) {
//            refreshedTokenToServer(token);
        }
    }

    @Override
    public void onTokenError(Exception e) {
        super.onTokenError(e);
    }
}

清单文件AndroidManifest.xml集成的所有的可能用得到的
<application>
        <!--华为-->
        <provider
            android:name="com.huawei.agconnect.core.provider.AGConnectInitializeProvider"
            android:authorities="${applicationId}.AGCInitializeProvider"
            android:exported="false" />

        <service
            android:name="com.huawei.agconnect.core.ServiceDiscovery"
            android:exported="false" />

        <service
            android:name="com.huawei.hms.support.api.push.service.HmsMsgService"
            android:enabled="true"
            android:exported="true"
            android:process=":pushservice">
            <intent-filter>
                <action android:name="com.huawei.push.msg.NOTIFY_MSG" />
                <action android:name="com.huawei.push.msg.PASSBY_MSG" />
            </intent-filter>
        </service>
        <!-- 自定义的HWPushReceiverService extends HmsMessageService-->
        <service
            android:name="com.cc.pushallsdk.HWPushReceiverService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.huawei.push.action.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <!-- 通知消息:点击不需要程序内容做处理,需要自定义跳转就要定义协议-->
        <!-- 透传消息:继承HmsMessageService里面复写onMessageReceived该方法,接收透传参数-->
        <activity android:name="com.cc.pushallsdk.TargetActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:host="com.cc.pushallsdk"
                    android:path="/wandanotify"
                    android:scheme="wandapushscheme" />
            </intent-filter>
        </activity>

</application>

配置工程project.properties文件(不知是否必要,官方写了反正我添加了)

打开您的工程的project.properties文件,添加如下代码,用于合并子工程中的Manifest文件。

manifestmerger.enabled=true

集成步骤:[基础能力官方链接地址]

https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/push-basic-capability

基础能力概览

image.png
  • Step1与Step2,开发者的App集成HMS SDK,再调用HmsInstanceId.getToken接口获取到Push Token,请参考申请Push Token章节。

  • Step3,开发者的App将获取到的Push Token上报到开发者服务器App Provider Server上。

  • Step4,开发者使用服务器保存的Push Token调用Push服务端提供的API推送Push消息,请参考服务端开发指导章节。

  • Step5,Push服务器将开发者推送的Push消息发送给Push Token对应的用户设备,设备接收Push消息,请参考接收透传消息章节。

  • Step6与Step7,Push服务器检测到设备回复消息响应时,将响应状态回执给开发者,开发者需实现消息回执接收能力,请参考服务端开发指导章节。

2. 客户端开发指导

本章节指导开发者完成Push基础能力开发中的客户端开发,通过本开发指导的学习能够帮助开发者快速掌握客户端开发所需的知识技能,快速体验华为Push服务。基础能力客户端开发主要包括如下4个功能点:

1、开发者集成Push SDK后申请Push Token,请参考申请Push Token章节,同时Push SDK 4.0版本我们提供了自动初始化获取token的能力,请参考自动初始化章节

2、开发者App客户端接收服务端推送的Push透传消息,请参考接收透传消息章节

3、是否允许NC(Notification Center)显示通知栏消息,请参考设置是否显示通知栏消息章节

4、自定义点击消息的动作以及向App传递数据可以参考点击通知消息章节

1、调用getToken方法获取Token
private void getToken() {
    new Thread() {
        @Override
        public void run() {
            try {
                // read from agconnect-services.json
                String appId = AGConnectServicesConfig.fromContext(this).getString("client/app_id");
                String token = HmsInstanceId.getInstance(this).getToken(appId, "HCM");
                Log.i(TAG, "get token:" + token);
                if(!TextUtils.isEmpty(token)) {
                    sendRegTokenToServer(token);
                }
            } catch (ApiException e) {
                Log.e(TAG, "get token failed, " + e);
            }
        }
    }.start();
}
private void sendRegTokenToServer(String token) {
    Log.i(TAG, "sending token to server. token:" + token);
}

2.3 接收透传消息

2.3.1 场景介绍

App如果订阅了主题消息或者服务器主动推送的透传消息(包括通知消息前台展示功能中设置通知消息由应用自己处理,区别于NC (Notification Center)通知栏消息),都需要App通过实现onMessageReceived回调方法来接收消息,收到消息的后续行为由应用自己处理
重写onMessageReceived 继承于HmsMessageService所复写的方法获取透传消息数据。

@Override
public void onMessageReceived(RemoteMessage message) {
    Log.i(TAG, "onMessageReceived is called");
    if (message == null) {
        Log.e(TAG, "Received message entity is null!");
        return;
    }
    Log.i(TAG, "getCollapseKey: " + message.getCollapseKey()
            + "\n getData: " + message.getData()
            + "\n getFrom: " + message.getFrom()
            + "\n getTo: " + message.getTo()
            + "\n getMessageId: " + message.getMessageId()
            + "\n getOriginalUrgency: " + message.getOriginalUrgency()
            + "\n getUrgency: " + message.getUrgency()
            + "\n getSendTime: " + message.getSentTime()
            + "\n getMessageType: " + message.getMessageType()
            + "\n getTtl: " + message.getTtl());
    RemoteMessage.Notification notification = message.getNotification();
    if (notification != null) {
        Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
                + "\n getTitle: " + notification.getTitle()
                + "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
                + "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
                + "\n getBody: " + notification.getBody()
                + "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
                + "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
                + "\n getIcon: " + notification.getIcon()
                + "\n getSound: " + notification.getSound()
                + "\n getTag: " + notification.getTag()
                + "\n getColor: " + notification.getColor()
                + "\n getClickAction: " + notification.getClickAction()
                + "\n getChannelId: " + notification.getChannelId()
                + "\n getLink: " + notification.getLink()
                + "\n getNotifyId: " + notification.getNotifyId());
    }
    Boolean judgeWhetherIn10s = false;
    // If the messages are not processed in 10 seconds, the app needs to use WorkManager for processing.
    if (judgeWhetherIn10s) {
        startWorkManagerJob(message);
    } else {
        // Process message within 10s
        processWithin10s(message);
    }
}
private void startWorkManagerJob(RemoteMessage message) {
    Log.d(TAG, "Start new job processing.");
}
private void processWithin10s(RemoteMessage message) {
    Log.d(TAG, "Processing now.");
}

2.4 设置是否显示通知栏消息

2.4.1 场景介绍

通知消息是由系统直接在通知中心下拉列表呈现的即时消息。开发者如果想控制应用是否允许显示通知栏消息,可以调用HmsMessaging.turnOnPush或者HmsMessaging.turnOffPush接口。如果开发者不调用此接口,系统默认是允许显示通知栏消息。

HmsMessaging.getInstance(context).turnOnPush().addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(Task<Void> task) {
        if (task.isSuccessful()) {
            Log.i(TAG, "turnOnPush Complete");
        } else {
            Log.e(TAG, "turnOnPush failed: ret=" + task.getException().getMessage());
        }
    }
});

2.5 点击通知消息

关于通知消息,开发者可以自定义点击消息的动作,包括:打开App首页、打开特定URL、打开自定义富媒体消息、打开自定义App页面。其中打开App首页与自定义App页面需要开发者端云协同开发来完成,下面我们讲下如何实现这两种动作并从服务端接收数据。

注意:
1、点击动作触发打开应用首页或者自定义App页面,都是通过跨应用启动Activity的方式来实现,需要保证要拉起的目标Activity的exported属性为true,即目标Activity要对外界公开,并且无权限保护,这样才能启动成功。
2、通过通知消息传递数据给应用需要推送服务App版本为10.0.0及以上。

2.5.1 打开自定义App页面

打开自定义App页面有两种方式,一种是通过服务端REST API指定intent参数,另一种是指定action参数。如果同时指定了两个参数,会优先选取使用intent参数。

指定intent参数

跨应用启动Activity必须使用显式intent方式,通过intent可以携带额外的数据给客户端App
1、intent参数生成
在AndroidStudio工程中参照如下代码生成intent。

Intent intent = new Intent(Intent.ACTION_VIEW);
// Scheme协议(pushscheme://com.huawei.codelabpush/deeplink?)需要开发者自定义比如:`"wandapushscheme://com.cc.pushallsdk/wandanotify?`content=thisistest")
intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
// 往intent中添加参数,用户可以根据自己的需求进行添加参数
intent.putExtra("name", "abc");
intent.putExtra("age", 180);
// 必须带上该Flag
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
// 打印出的intentUri值就是设置到推送消息中intent字段的值
Log.d("intentUri", intentUri);

intentUri

开发者传参有两种方法:这些通过本地写获取得到intentUri给到服务端或者网页端进行传输
方法1:参数之间用“&”相连,其中参数name=abc与age=180两个参数之间用“&”相连。例如:

intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?name=abc&age=180"));

方法2:intent直接添加参数:

intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
intent.putExtra("name", "abc");
intent.putExtra("age", 180);

2、App服务端消息体中指定intent值

服务端如何发送消息请参考服务端开发指导。消息体样例:

{
    "message": {
        "data": "{'score':'7','time': '16:42'}",
        "notification": {
            "title": "message title",
            "body": "message body"
        },
        "android": {
            "data":"{'androidData':'7','time':'16:42'}",
            "notification": {
                "click_action": {
                    "type": 1,
                    "intent": "intent://com.huawei.codelabpush/deeplink?#Intent;scheme=pushscheme;launchFlags=0x4000000;i.age=180;S.name=abc;end"
                }
            }
        },
        "token": [
            "pushtoken1"
        ]
    }
}

3、客户端AndroidManifest.xml文件注册待启动的Activity类
参照如下配置注册自定义的Activity,其中host、path、scheme需与步骤1中协议的配置相对应,否则不能跳转到指定的界面。

<activity android:name=".DeeplinkActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.huawei.codelabpush"
            android:path="/deeplink"
            android:scheme="pushscheme" />
    </intent-filter>
</activity>

自动初始化1

<application    
    <meta-data       
        android:name="push_kit_auto_init_enabled"        
        android:value="true" />
</application>

自动初始化2

方式2
应用显式调用HmsMessaging.setAutoInitEnabled(boolean enable)方法,设置为true即为启用了自动初始化,反之为未启用。设置后值会保存在应用本地的shared_prefs目录下的文件中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348