集成 Huawei PUSH 服务开发主要包括两部分:客户端开发和服务端开发。具体的流程可参照下图
(图片来源:Huawei PUSH 官方文档)
客户端开发的主要目的是为了向PUSH服务器获取设备的PUSH Token,获取Token之后开发者可以在开发者联盟PUSH控制台或者开发者自己的服务器上根据Token向这些设备发送推送消息。
开发者联盟PUSH控制台链接:https://developer.huawei.com/consumer/cn/console#/openCard/AppService/6
说明:
①华为手机申请Token的流程:(图片来源:Huawei PUSH 官方文档)
②非华为手机申请Token的流程:(图片来源:Huawei PUSH 官方文档)
-----------------------------------------------------------------------------------------
具体步骤如下:
1.调用init,在application的onCreate方法中初始化HMS Agent套件。
说明:查找application文件的方法:在Manifest.xml中的application节点中的name属性即为application文件的路径
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HMSAgent.init(this);
}
}
2.调用connect
在应用启动后的首个Activity的OnCreate方法中调用connect接口,确保HMS SDK 和HMS APK的连接。
示例代码:
HMSAgent.connect(this, new ConnectHandler() {
@Override
public void onConnect(int rst) {
showLog("HMS connect end:" + rst);
}
});
3.申请Token
建议开发者在首个Activity的onCreate方法中调用getToken方法,同一个手机的同一个应用获取的Token不会变,但是建议每次启动更新一次PUSH token。调用getToken接口后,Token不是在本接口中直接返回的,而是通过广播的形式通知APP因此需要开发者实现自定义广播的onToken方法来接收Token。
示例代码:
private void getToken() {
showLog("get token: begin");
HMSAgent.Push.getToken(new GetTokenHandler() {
@Override
public void onResult(int rtnCode, TokenResult tokenResult) {
showLog("get token: end" + rtnCode);
}
});
}
注意:获取Token的时候经常会返回错误码6003,原因是证书指纹校验错误,此时解决该问题的方法有两个:一是使用Keystore文件将项目打包成apk,二是在子项目的gradle文件中signingConfigs修改成如下信息:
signingConfigs {
release {
keyAlias 'keystore.keystore'
keyPassword 'trechina'
storeFile file('../keystore.keystore')
storePassword 'trechina'
}
debug {
keyAlias 'keystore.keystore'
keyPassword 'trechina'
storeFile file('../keystore.keystore')
storePassword 'trechina'
}
}
-----------------------------------------------------------------------------------------
开发者需要创建子类继承com.huawei.hms.support.api.push.PushReceiver,实现onToken,onPushMsg,onEvent这几个方法,用于接收Token返回,透传消息和通知栏点击事件处理。具体步骤如下:
注意: onEvent会在后续版本中逐渐废弃,请开发者谨慎使用,建议开发者创建两个子类继承PushReceiver类,分别实现onToken,onPushMsg和onEvent的处理。
1.自定义HuaweiPushReceiver类继承PushReceiver类,用于实现对于PUSH Token和透传消息的接收
示例代码:
public class HuaweiPushReceiver extends PushReceiver {
@Override
public void onToken(Context context, String token, Bundle extras) {
}
@Override
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
}
}
onToken方法:返回Token信息
onPushMsg方法:返回透传信息
2.开发者自定义HuaweiPushRevicerEx类继承PushReceiver,实现接收通知栏或通知栏上按钮点击事件的onEvent回调
注意:后续版本逐渐废弃,请开发者谨慎使用
示例代码:
public class HuaweiPushReceiverEx extends PushReceiver {
@Override
public void onEvent(Context context, Event event, Bundle extras) {
}
}
onEvent方法:点击打开通知栏消息、点击通知栏上的按钮之后被调用
4.在application节点下增加AppUpdateActivity和PackageInstallActivity,用来是应用自升级接口所需要使用的页面
-----------------------------------------------------------------------------------------
如果开发者不调用此方法,默认是接收通知栏消息。
示例代码:
private void setReceiveNotifyMsg(boolean enable){
showLog("enableReceiveNotifyMsg:begin");
HMSAgent.Push.enableReceiveNotifyMsg(enable, new EnableReceiveNotifyMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNotifyMsg:end code=" + rst);
}
});
}
-----------------------------------------------------------------------------------------
如果开发者不调用此方法,默认是接收透传消息。
示例代码:
private void setReceiveNormalMsg(boolean enable){
showLog("enableReceiveNormalMsg:begin");
HMSAgent.Push.enableReceiveNormalMsg(enable, new EnableReceiveNormalMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNormalMsg:end code=" + rst);
}
});
}
客户端的其他方法,比如删除PUSH Token、展示角标等,可以参照:https://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush_agent.html?page=hmssdk_huaweipush_devguide_client_agent
-----------------------------------------------------------------------------------------
MainActivity.java:
import static com.example.testpush.HuaweiPushRevicer.ACTION_TOKEN;
import static com.example.testpush.HuaweiPushRevicer.ACTION_UPDATEUI;
public class MainActivity extends AppCompatActivity implements HuaweiPushRevicer.IPushCallback {
private String token;
StringBuffer sbLog = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HMSAgent.connect(this, new ConnectHandler() {
@Override
public void onConnect(int rst) {
showLog("HMS connect end:" + rst);
}
});
getToken();
HuaweiPushRevicer.registerPushCallback(this);
setReceiveNotifyMsg(true);
setReceiveNormalMsg(true);
Log.d("****Token****",token+"");
showLog(token);
Intent intent = new Intent();
intent.setClass(MainActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("ext1","helloExt1");
intent.putExtra("ext2","helloExt2");
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
Log.e("onCreate: ",intentUri );
Toast.makeText(this,getIntent().getStringExtra("ext1"),Toast.LENGTH_SHORT).show();
}
/**
* 获取token
*/
private void getToken() {
showLog("get token: begin");
HMSAgent.Push.getToken(new GetTokenHandler() {
@Override
public void onResult(int rtnCode) {
showLog("get token: end" + rtnCode);
}
});
}
/**
* 设置接收通知消息 | Set up receive notification messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNotifyMsg(boolean enable){
showLog("enableReceiveNotifyMsg:begin");
HMSAgent.Push.enableReceiveNotifyMsg(enable, new EnableReceiveNotifyMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNotifyMsg:end code=" + rst);
}
});
}
/**
* 设置是否接收普通透传消息 | Set whether to receive normal pass messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNormalMsg(boolean enable){
showLog("enableReceiveNormalMsg:begin");
HMSAgent.Push.enableReceiveNormalMsg(enable, new EnableReceiveNormalMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNormalMsg:end code=" + rst);
}
});
}
protected void showLog(String logLine) {
DateFormat format = new java.text.SimpleDateFormat("MMddhhmmssSSS");
String time = format.format(new Date());
sbLog.append(time+":"+logLine);
sbLog.append('\n');
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
View vText = findViewById(R.id.tv_log);
if (vText != null && vText instanceof TextView) {
TextView tvLog = (TextView)vText;
tvLog.setText(sbLog.toString());
}
View vScrool = findViewById(R.id.sv_log);
if (vScrool != null && vScrool instanceof ScrollView) {
ScrollView svLog = (ScrollView)vScrool;
svLog.fullScroll(View.FOCUS_DOWN);
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
HuaweiPushRevicer.unRegisterPushCallback(this);
;
}
@Override
public void onReceive(Intent intent) {
if (intent != null) {
String action = intent.getAction();
Bundle b = intent.getExtras();
if (b != null && ACTION_TOKEN.equals(action)) {
token = b.getString(ACTION_TOKEN);
Log.d("****Token****",token+"");
showLog(token);
showLog(intent.getStringExtra("aa"));
} else if (b != null && ACTION_UPDATEUI.equals(action)) {
String log = b.getString("log");
showLog(log);
Log.d("****Token****",token+"");
showLog(token);
}
}
}
}
HuaweiPushRevicer.java:
public class HuaweiPushRevicer extends PushReceiver {
public static final String TAG = "HuaweiPushRevicer";
public static final String ACTION_UPDATEUI = "action.updateUI";
public static final String ACTION_TOKEN = "action.updateToken";
private static List pushCallbacks = new ArrayList();
private static final Object CALLBACK_LOCK = new Object();
public interface IPushCallback {
void onReceive(Intent intent);
}
public static void registerPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.add(callback);
}
}
public static void unRegisterPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.remove(callback);
}
}
@Override
public void onToken(Context context, String tokenIn, Bundle extras) {
String belongId = extras.getString("belongId");
Intent intent = new Intent();
intent.setAction(ACTION_TOKEN);
intent.putExtra(ACTION_TOKEN, tokenIn);
callBack(intent);
intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "belongId is:" + belongId + " Token is:" + tokenIn);
callBack(intent);
}
@Override
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
try {
//CP可以自己解析消息内容,然后做相应的处理 | CP can parse message content on its own, and then do the appropriate processing
String content = new String(msg, "UTF-8");
Intent intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "Receive a push pass message with the message:" + content);
callBack(intent);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "Receive push pass message, exception:" + e.getMessage());
callBack(intent);
}
return false;
}
public void onEvent(Context context, Event event, Bundle extras) {
}
@Override
public void onPushState(Context context, boolean pushState) {
Intent intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "The Push connection status is:" + pushState);
callBack(intent);
}
private static void callBack(Intent intent) {
synchronized (CALLBACK_LOCK) {
for (IPushCallback callback : pushCallbacks) {
if (callback != null) {
callback.onReceive(intent);
}
}
}
}
}
-----------------------------------------------------------------------------------------
MainActivity.java:
import static com.example.testpush.HuaweiPushRevicer.ACTION_TOKEN;
import static com.example.testpush.HuaweiPushRevicer.ACTION_UPDATEUI;
public class MainActivity extends AppCompatActivity implements HuaweiPushRevicer.IPushCallback {
private String token;
StringBuffer sbLog = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HMSAgent.connect(this, new ConnectHandler() {
@Override
public void onConnect(int rst) {
showLog("HMS connect end:" + rst);
}
});
getToken();
HuaweiPushRevicer.registerPushCallback(this);
setReceiveNotifyMsg(true);
setReceiveNormalMsg(true);
Log.d("****Token****",token+"");
showLog(token);
}
/**
* 获取token
*/
private void getToken() {
showLog("get token: begin");
HMSAgent.Push.getToken(new GetTokenHandler() {
@Override
public void onResult(int rtnCode) {
showLog("get token: end" + rtnCode);
}
});
}
/**
* 设置接收通知消息 | Set up receive notification messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNotifyMsg(boolean enable){
showLog("enableReceiveNotifyMsg:begin");
HMSAgent.Push.enableReceiveNotifyMsg(enable, new EnableReceiveNotifyMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNotifyMsg:end code=" + rst);
}
});
}
/**
* 设置是否接收普通透传消息 | Set whether to receive normal pass messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNormalMsg(boolean enable){
showLog("enableReceiveNormalMsg:begin");
HMSAgent.Push.enableReceiveNormalMsg(enable, new EnableReceiveNormalMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNormalMsg:end code=" + rst);
}
});
}
protected void showLog(String logLine) {
DateFormat format = new java.text.SimpleDateFormat("MMddhhmmssSSS");
String time = format.format(new Date());
sbLog.append(time+":"+logLine);
sbLog.append('\n');
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
View vText = findViewById(R.id.tv_log);
if (vText != null && vText instanceof TextView) {
TextView tvLog = (TextView)vText;
tvLog.setText(sbLog.toString());
}
View vScrool = findViewById(R.id.sv_log);
if (vScrool != null && vScrool instanceof ScrollView) {
ScrollView svLog = (ScrollView)vScrool;
svLog.fullScroll(View.FOCUS_DOWN);
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
HuaweiPushRevicer.unRegisterPushCallback(this);
;
}
@Override
public void onReceive(Intent intent) {
if (intent != null) {
String action = intent.getAction();
Bundle b = intent.getExtras();
if (b != null && ACTION_TOKEN.equals(action)) {
token = b.getString(ACTION_TOKEN);
Log.d("****Token****",token+"");
showLog(token);
showLog(intent.getStringExtra("aa"));
} else if (b != null && ACTION_UPDATEUI.equals(action)) {
String log = b.getString("log");
showLog(log);
Log.d("****Token****",token+"");
showLog(token);
}
}
}
}
HuaweiPushRevicer.java:
public class HuaweiPushReceiver extends PushReceiver {
//HuaweiPushRevicer类继承PushReceiver,实现PUSH Token和透传消息的接收
public static final String TAG = "HuaweiPushReceiver";
public static final String ACTION_UPDATEUI = "action.updateUI";
public static final String ACTION_TOKEN = "action.updateToken";
//定义用于保存接口对象的列表
private static List pushCallbacks = new ArrayList();
private static final Object CALLBACK_LOCK = new Object();
//定义IPushCallback接口用于回传Token信息
public interface IPushCallback {
void onReceive(Intent intent);
}
public static void registerPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.add(callback);
}
}
public static void unRegisterPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.remove(callback);
}
}
@Override
public void onToken(Context context, String tokenIn, Bundle extras) {
//onToken 调用getToken方法后,获取服务端返回的token结果,返回token以及belongId
String belongId = extras.getString("belongId");
Intent intent = new Intent();
intent.setAction(ACTION_TOKEN);
intent.putExtra(ACTION_TOKEN, tokenIn);
callBack(intent); //返回Token信息
intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "belongId is:" + belongId + " Token is:" + tokenIn);
callBack(intent); //返回日志信息
}
@Override
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
return true;
}
public void onEvent(Context context, Event event, Bundle extras) {
}
@Override
public void onPushState(Context context, boolean pushState) {
//调用getPushState方法后,获取push连接状态的查询结果
Intent intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "The Push connection status is:" + pushState);
callBack(intent);
}
private static void callBack(Intent intent) {
synchronized (CALLBACK_LOCK) {
for (IPushCallback callback : pushCallbacks) {
if (callback != null) {
callback.onReceive(intent); //执行接口对象的onReceive方法
}
}
}
}
}
-----------------------------------------------------------------------------------------
自定义Intent为:intent://com.huawei.pushtest/notify_detail#Intent;scheme=customscheme;launchFlags=0x10000000;S.package=test;end
MainActivity.java:
import static com.example.estpush.HuaweiPushRevicer.ACTION_TOKEN;
import static com.example.testpush.HuaweiPushRevicer.ACTION_UPDATEUI;
public class MainActivity extends AppCompatActivity implements HuaweiPushRevicer.IPushCallback {
private String token;
StringBuffer sbLog = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HMSAgent.connect(this, new ConnectHandler() {
@Override
public void onConnect(int rst) {
showLog("HMS connect end:" + rst);
}
});
getToken();
HuaweiPushRevicer.registerPushCallback(this);
setReceiveNotifyMsg(true);
setReceiveNormalMsg(true);
if("test".equals(getIntent().getStringExtra("package"))){
//开发者自己写逻辑
}
}
/**
* 获取token
*/
private void getToken() {
showLog("get token: begin");
HMSAgent.Push.getToken(new GetTokenHandler() {
@Override
public void onResult(int rtnCode) {
showLog("get token: end" + rtnCode);
}
});
}
/**
* 设置接收通知消息 | Set up receive notification messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNotifyMsg(boolean enable){
showLog("enableReceiveNotifyMsg:begin");
HMSAgent.Push.enableReceiveNotifyMsg(enable, new EnableReceiveNotifyMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNotifyMsg:end code=" + rst);
}
});
}
/**
* 设置是否接收普通透传消息 | Set whether to receive normal pass messages
* @param enable 是否开启 | enabled or not
*/
private void setReceiveNormalMsg(boolean enable){
showLog("enableReceiveNormalMsg:begin");
HMSAgent.Push.enableReceiveNormalMsg(enable, new EnableReceiveNormalMsgHandler() {
@Override
public void onResult(int rst) {
showLog("enableReceiveNormalMsg:end code=" + rst);
}
});
}
protected void showLog(String logLine) {
DateFormat format = new java.text.SimpleDateFormat("MMddhhmmssSSS");
String time = format.format(new Date());
sbLog.append(time+":"+logLine);
sbLog.append('\n');
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
View vText = findViewById(R.id.tv_log);
if (vText != null && vText instanceof TextView) {
TextView tvLog = (TextView)vText;
tvLog.setText(sbLog.toString());
}
View vScrool = findViewById(R.id.sv_log);
if (vScrool != null && vScrool instanceof ScrollView) {
ScrollView svLog = (ScrollView)vScrool;
svLog.fullScroll(View.FOCUS_DOWN);
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
HuaweiPushRevicer.unRegisterPushCallback(this);
;
}
@Override
public void onReceive(Intent intent) {
if (intent != null) {
String action = intent.getAction();
Bundle b = intent.getExtras();
if (b != null && ACTION_TOKEN.equals(action)) {
token = b.getString(ACTION_TOKEN);
Log.d("****Token****",token+"");
showLog(token);
showLog(intent.getStringExtra("aa"));
} else if (b != null && ACTION_UPDATEUI.equals(action)) {
String log = b.getString("log");
showLog(log);
Log.d("****Token****",token+"");
showLog(token);
}
}
}
}
HuaweiPushRevicer.java:
public class HuaweiPushReceiver extends PushReceiver {
//HuaweiPushRevicer类继承PushReceiver,实现PUSH Token和透传消息的接收
public static final String TAG = "HuaweiPushReceiver";
public static final String ACTION_UPDATEUI = "action.updateUI";
public static final String ACTION_TOKEN = "action.updateToken";
//定义用于保存接口对象的列表
private static List pushCallbacks = new ArrayList();
private static final Object CALLBACK_LOCK = new Object();
//定义IPushCallback接口用于回传Token信息
public interface IPushCallback {
void onReceive(Intent intent);
}
public static void registerPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.add(callback);
}
}
public static void unRegisterPushCallback(IPushCallback callback) {
synchronized (CALLBACK_LOCK) {
pushCallbacks.remove(callback);
}
}
@Override
public void onToken(Context context, String tokenIn, Bundle extras) {
//onToken 调用getToken方法后,获取服务端返回的token结果,返回token以及belongId
String belongId = extras.getString("belongId");
Intent intent = new Intent();
intent.setAction(ACTION_TOKEN);
intent.putExtra(ACTION_TOKEN, tokenIn);
callBack(intent); //返回Token信息
intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "belongId is:" + belongId + " Token is:" + tokenIn);
callBack(intent); //返回日志信息
}
@Override
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
return true;
}
public void onEvent(Context context, Event event, Bundle extras) {
}
@Override
public void onPushState(Context context, boolean pushState) {
//调用getPushState方法后,获取push连接状态的查询结果
Intent intent = new Intent();
intent.setAction(ACTION_UPDATEUI);
intent.putExtra("log", "The Push connection status is:" + pushState);
callBack(intent);
}
private static void callBack(Intent intent) {
synchronized (CALLBACK_LOCK) {
for (IPushCallback callback : pushCallbacks) {
if (callback != null) {
callback.onReceive(intent); //执行接口对象的onReceive方法
}
}
}
}
-----------------------------------------------------------------------------------------
客户端开发过程中错误码及解决方法请参照:https://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush_agent.html?page=hmssdk_huaweipush_api_reference_errorcode