Android集成HuaweiPUSH(五)——服务端开发

Android集成Huawei PUSH(五)——服务端开发

一、服务器获取Access Token

开发者在开发服务器端时,首先要调用请求Access Token接口获取接入Token,Access Token是应用服务器实现发送PUSH 消息功能的必须条件。

Access Token存在有效期,当前版本Access Token的有效期为1个小时,有效期通过响应参数消息的expires_in参数传达。Access Token在有效期内请尽量复用,如果开发者应用服务器频繁的申请Access Token,可能会被流控。Access Token过期前,业务要根据这个有效时间提前去申请新Access Token。

服务端获取Access Token的主要代码如下:

public class PushNcMsg
{ 
    private static String appSecret = "appSecret";//用户在华为开发者联盟申请Push服务获取的服务参数
    private static  String appId = "12345678";//用户在华为开发者联盟申请Push服务获取的服务参数
    private static  String tokenUrl = "https://login.cloud.huawei.com/oauth2/v2/token"; //获取认证Token的URL
    private static  String apiUrl = "https://api.push.hicloud.com/pushsend.do"; //应用级消息下发API
    private static  String accessToken;//下发通知消息的认证Token
    private static  long tokenExpiredTime;  //accessToken的过期时间

    //获取Access Token
    private static void refreshToken() throws IOException
    {
        String msgBody = MessageFormat.format(
         "grant_type=client_credentials&client_secret={0}&client_id={1}", 
         URLEncoder.encode(appSecret, "UTF-8"), appId);
        String response = httpPost(tokenUrl, msgBody, 5000, 5000);
        JSONObject obj = JSONObject.parseObject(response);
        accessToken = obj.getString("access_token");
        tokenExpiredTime = System.currentTimeMillis() + (obj.getLong("expires_in") - 5*60)*1000;
    }
} 

其中:
①appId 和appSecret 为开发者在开发者联盟为应用申请Huawei PUSH 服务时的参数;
②tokenUrl为获取认证Token的URL,参数的值是一个固定值,开发时直接复制即可
③apiUrl为应用级消息下发API的URL,参数的值是一个固定值,开发时直接复制即可

-----------------------------------------------------------------------------------------

二、服务端发送PUSH消息

具体步骤如下:

1.发送PUSH消息前判断AT是否过期,如果过期需要重新申请。
其中refreshToken()为上一章节实现的获取AT的方法。

示例代码:

 if (tokenExpiredTime <= System.currentTimeMillis()) { 
         refreshToken();        
 }  

2.封装PUSH Token
USH Token为客户端调用getToken()接口获取到保存到服务器的,开发者需要读取服务器上的token,将其放到JSONArray中。服务器接口每次只支持发送100个,如果想使用更大发送量,请参考如下链接:
https://developer.huawei.com/consumer/cn/help/60103

示例代码:

JSONArray deviceTokens = new JSONArray();//目标设备Token
deviceTokens.add("12345678901234561234567890123456");
deviceTokens.add("22345678901234561234567890123456");
deviceTokens.add("32345678901234561234567890123456"); 

设备的Token值在客户端获取之后可以通过网络请求调用后台接口获得,或者保存至数据库中,服务端通过查询数据库获得。

3.封装推送消息body,用于显示通知栏消息显示的标题和内容

示例代码:

JSONObject body = new JSONObject();//仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义
body.put("title", "Push message title");//消息标题
body.put("content", "Push message content");//消息内容体

4.封装消息点击动作的参数

示例代码:

JSONObject param = new JSONObject();
param.put("appPkgName", "com.huawei.hms.hmsdemo");//定义需要打开的appPkgName,根据实际情况修改

5.封装消息点击动作
用于定义通知栏点击行为,param为步骤4封装的点击动作参数

示例代码:

JSONObject action = new JSONObject();
action.put("type", 3);//类型3为打开APP,其他行为请参考接口文档设置
action.put("param", param);//消息点击动作参数

说明:type=1表示自定义Intent,type=2表示打开URL,type=3表示打开APP。

6. 封装消息类型,用于定义消息类型
区分是通知栏消息还是透传消息,其中action和body分别是步骤5和步骤3封装的消息

示例代码:

JSONObject msg = new JSONObject();
msg.put("type", 3);//3: 通知栏消息,异步透传消息请根据接口文档设置
msg.put("action", action);//消息点击动作
msg.put("body", body);//通知栏消息body内容示例代码

说明:type=1表示透传消息,type=3表示通知栏消息,type=2和4为预留。

7. 封装扩展消息
扩展消息中可以设置biTag用于消息打点,也可以携带customize参数用于触发通知栏点击事件的onEvent回调

示例代码:

JSONObject ext = new JSONObject();//扩展信息,含BI消息统计,特定展示风格,消息折叠。
ext.put("biTag", "Trump");//设置消息标签,如果带了这个标签,会在回执中推送给CP用于检测某种类型消息的到达率和状态
JSONObject temp= new JSONObject();
temp.put("season","Spring");
temp.put("weather","raining");
JSONArray customize = new JSONArray();  
customize.add(temp);
ext.put("customize",customize);

8. 封装整个消息体,可自定义实现单击消息后的跳转动作
扩展消息中可以设置biTag用于消息打点,也可以携带customize参数用于触发通知栏点击事件的onEvent回调

示例代码:

JSONObject hps = new JSONObject();//华为PUSH消息总结构体
hps.put("msg", msg);
hps.put("ext", ext);
JSONObject payload = new JSONObject();
payload.put("hps", hps);

9. 定义httpPost()方法,用于消息发送

示例代码:

public static String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException
    {
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        try
        {
            URL url = new URL(httpUrl);
            urlConnection = (HttpURLConnection)url.openConnection();          
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            urlConnection.setConnectTimeout(connectTimeout);
            urlConnection.setReadTimeout(readTimeout);
            urlConnection.connect();
            // POST data
            outPut = urlConnection.getOutputStream();
            outPut.write(data.getBytes("UTF-8"));
            outPut.flush(); 
            // read response
            if (urlConnection.getResponseCode() < 400)
            {
                in = urlConnection.getInputStream();
            }
            else
            {
                in = urlConnection.getErrorStream();
            }
            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines)
            {
                strBuf.append(line);
            }
            System.out.println(strBuf.toString());
            return strBuf.toString();
        }
        finally
        {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null)
            {
                urlConnection.disconnect();
            }
        }
    }

10. 封装整个http消息并发送

示例代码:

String postBody = MessageFormat.format(
         "access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
         URLEncoder.encode(accessToken,"UTF-8"),
         URLEncoder.encode("openpush.message.api.send","UTF-8"),
         URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000),"UTF-8"),
         URLEncoder.encode(deviceTokens.toString(),"UTF-8"),
         URLEncoder.encode(payload.toString(),"UTF-8"));
        String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
        httpPost(postUrl, postBody, 5000, 5000);    //发送PUSH消息

-----------------------------------------------------------------------------------------

三、实例代码

private static String appID = "xxxxxxxx";  //用户在华为开发者联盟申请Push服务获取的APPID
private static String appSecret ="xxxxxxxx";  //用户在华为开发者联盟申请Push服务获取的APPSECRET
private static  String tokenUrl = "https://login.cloud.huawei.com/oauth2/v2/token"; //获取认证Token的URL
private static  String apiUrl = "https://api.push.hicloud.com/pushsend.do"; //应用级消息下发API
private static String accessToken;//下发通知消息的认证Token
private static long tokenExpiredTime;  //accessToken的过期时间 

//获取Access Token
private void refreshToken() throws Exception {
    String msgBody = MessageFormat.format("grant_type=client_credentials&client_secret={0}&client_id={1}", 
    URLEncoder.encode(appSecret, "UTF-8"), appID);  //拼接信息
    String response = httpPost(tokenUrl,msgBody,5000,5000);
    JSONObject object = JSONObject.parseObject(response);
    accessToken = object.getString("access_token");
    tokenExpiredTime = System.currentTimeMillis() + (object.getLong("expires_in") - 5 * 60) * 1000;
}

private void sendPushMessage() throws Exception{
	try{
		JSONArray deviceTokens = new JSONArray();//目标设备Token 
		deviceTokens.add("12345678901234561234567890123456");
		//封装推送消息Body用于显示通知栏消息显示的标题和内容
		JSONObject bodyObject = new JSONObject();  //仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义
		bodyObject.put("title", "haha");  //消息标题
		bodyObject.put("content", "test");  //消息内容体
		//封装消息点击动作参数
		JSONObject paramObject = new JSONObject();
		 paramObject.put("appPkgName", "com.xxx.xxx");
		//封装消息点击动作用于定义通知栏点击行为
		JSONObject actionObject = new JSONObject();
		actionObject.put("type", 1);  //type=1表示自定义intent
		//封装intent信息
		JSONObject intentObject = new JSONObject();
		intentObject.put("intent", "intent://com.huawei.pushtest/notify_detail#Intent;scheme=customscheme;launchFlags=0x10000000;S.package=test;end");
		actionObject.put("param", intentObject);
		//封装消息类型用于定义消息类型,区分是通知栏消息还是透传消息
		JSONObject msgObject = new JSONObject();
		msgObject.put("type", 3);  //type=3表示通知栏消息
		msgObject.put("action", actionObject);  //消息点击动作
		msgObject.put("body", bodyObject);  //通知栏消息body内容
		//封装扩展消息
		JSONObject extObject = new JSONObject();
		extObject.put("biTag", "Trump");  //设置消息标签,如果带了这个标签,会在回执中推送给CP用于检测某种类型消息的到达率和状态
		//封装整个消息体
		JSONObject huaweiPushObject = new JSONObject();  //华为PUSH消息总结构体
		huaweiPushObject.put("msg", msgObject);
		huaweiPushObject.put("ext", extObject);
		JSONObject payLoadObject = new JSONObject();
		payLoadObject.put("hps", huaweiPushObject);
		//封装整个HTTP消息并发送
		String postBody = MessageFormat.format(
			"access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
			URLEncoder.encode(accessToken,"UTF-8"),
			URLEncoder.encode("openpush.message.api.send","UTF-8"),
			URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000),"UTF-8"),
			URLEncoder.encode(deviceTokens.toString(),"UTF-8"),
			URLEncoder.encode(payLoadObject.toString(),"UTF-8"));
			String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appID + "\"}", "UTF-8");
			httpPost(postUrl, postBody, 5000, 5000);
		}catch(Exception e){
			e.printStackTrace();
		}
}

public String httpPost(String httpUrl, String data, int connectTimeOut, int readTimeOut) throws Exception{
    	OutputStream outputStream = null;
    	HttpURLConnection urlConnection = null;
    	InputStream inputStream = null;
    	try{
            URL url = new URL(httpUrl);
            urlConnection = (HttpURLConnection)url.openConnection();          
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            urlConnection.setConnectTimeout(connectTimeOut);
            urlConnection.setReadTimeout(readTimeOut);
            urlConnection.connect();
            // POST data
            outputStream = urlConnection.getOutputStream();
            outputStream.write(data.getBytes("UTF-8"));
            outputStream.flush();
            // read response
            if (urlConnection.getResponseCode() < 400){
                inputStream = urlConnection.getInputStream();
            }else{
            	inputStream = urlConnection.getErrorStream();
            }
            List<String> lines = IOUtils.readLines(inputStream, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines){
                strBuf.append(line);
            }
            return strBuf.toString();
        }finally{
            IOUtils.closeQuietly(outputStream);
            IOUtils.closeQuietly(inputStream);
            if (urlConnection != null){
                urlConnection.disconnect();
            }
        }
    }

-----------------------------------------------------------------------------------------

四、附录

开发发送PUSH接口时可参照API:https://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush_agent.html?page=hmssdk_huaweipush_api_reference_agent_s2
接口回执API:https://developer.huawei.com/consumer/cn/service/hms/catalog/huaweipush_agent.html?page=hmssdk_huaweipush_api_reference_agent_s3

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值