随着谷歌开发者大会在中国的成功举行,也带来激动人心的消息,2016年12月8日Google Developers中文网站正式发布了。以后学习Android,获取Android Studio、安卓最新版SDK等最新开发资源也变得更加轻松了。直接访问Google Developers官网 https://developers.google.cn/ 即可。好了,激动之余让我们来看看今天为大家带来的关于消息推送的博文,这次还是使用Android Studio进行开发,不过Eclipse的集成开发也和下面要介绍的内容差不太多。按照惯例,还是先来看看程序的效果图:
1. 集成SDK前的准备工作
1.1 开发者身份认证
登录百度云推送官网后,点击创建应用,如果没有申请过,则会跳转到认证页面,通过填写一系列的认证信息,完成认证。
1.2 下载SDK
从官网下载最新版的SDk
1.3 创建项目
1.3.1 在编辑器中创建好项目
利用Android Studio新建好项目,并记好包名。
1.3.2 在百度云推送官网创建应用
再次点击百度云推送“创建应用”的菜单项,成功跳转后点击“创建新应用”按钮后开始创建应用,过程中需要填写项目的包名,就不再细说了。最后得到下图的API Key等信息,后面马上就要派上用场了。
2. 如何在项目中集成SDK
集成的步骤和调用SDK的方法都可以在文档中心查阅,还算是写的比较详细的了。
2.1 导入Jar包
解压好之前下载的SDK,把libs目录下的 pushservice-5.5.0.50.jar 复制到工程目录下的libs文件夹中。
2.2 导入so文件
在工程目录 src/main 下新建一个jniLibs文件夹,把libs目录下除Jar包以外的文件(so文件)复制到里面。最后工程目录的结构如下图所示:
2.3 添加依赖
① 修改项目下的 build.gradle 文件,在android节点下,定义 sourceSets 内容为 jniLibs 路径,这样才能使用so库文件;
② 同样地,修改 build.gradle 文件,添加Jar包的依赖项。
最后,添加好依赖以后文件的部分内容(其他部分暂时用省略号替代)如下所示:
apply plugin: 'com.android.application'
android {
......
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
}
dependencies {
......
compile files('libs/pushservice-5.5.0.50.jar')
}
2.4 配置AndroidManifest文件
2.4.1 添加相关权限
在 manifest 节点下添加权限:
2.4.2 注册Receiver 和 Service
在application节点中注册广播接收器和服务:
2.5 自定义Receiver
我们需要通过继承 com.baidu.android.pushservice.PushMessageReceiver 实现一个Receiver,并在 AndroidManifest 文件中注册,来接受推送的消息,处理通知的点击事件等。
2.5.1 继承实现Receiver类
由于只是简单的接收一下推送消息,所以只重写了 onBind 方法。部分代码如下:
public class MyPushMessageReceiver extends PushMessageReceiver {
@Override
public void onBind(Context context, int errorCode, String s, String s1,
String s2, String s3) {
if (errorCode == 0) {
Toast.makeText(context, "绑定成功!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "绑定失败!"+errorCode, Toast.LENGTH_SHORT).show();
}
}
......
}
2.5.2 注册自定义Receiver
在application节点中注册自定义的Receiver
2.6 启动云推送
① 在 MainActivity 中添加如下代码进行初始化,将最后一个参数替换成自己的API Key。
PushManager.startWork(getApplicationContext(), PushConstants.LOGIN_TYPE_API_KEY,
Constants.APIKEY_VALUE);
② 程序启动的时候,显示“绑定成功”则表示可以接收推送信息了(之前在自定义Receiver类中写的)。利用云推送控制台简单测试一下,在应用列表页面,点击创建推送 —> 创建通知 —> 填写相关内容后发送,能成功收到信息,我们就已经成功了一大半了。
3. 通过客户端请求推送通知
依照上两节的内容,我们已经可以推送/接收通知了,但是推送还是要使用网页控制台才能完成。接下来,就让我们来看看如何利用REST API实现客户端推送。同样地,也有相应的文档介绍了其具体的用法:http://push.baidu.com/doc/restapi/sdk_developer
3.1 请求的URL
百度提供了REST风格的htttp和https接口,如下所示:
http[s]://api.tuisong.baidu.com/rest/3.0/{class}/{method}?{query_string}
{class}是所要请求的资源类别,如我们想要推送通知,则为push;
{method}是具体的操作方法名称,如要推送给安装了我们程序的所有用户,则为all;即:
http://api.tuisong.baidu.com/rest/3.0/push/all
{query_string}是具体的请求参数,有几点要注意一下:
我们请求推送使用的是POST的方式。
3.2 请求的参数
可划分为①公共请求参数:即每次请求都需要传递的参数;②API调用参数:每种请求类型都会有相对应的请求参数。
3.2.1 公共请求参数
通过下表更进一步了解一下通用参数:
参数名 | 类型 | 必需 | 描述 |
---|---|---|---|
apikey | string | 是 | 应用的Api Key,用于标识应用。 |
timestamp | number | 是 | 用户发起请求时的unix时间戳。本次请求签名的有效时间为以该时间戳开始的10分钟。 |
sign | string | 是 | 通过签名算法生成,与apikey成对出现。用于防止请求内容被篡改。下一小节详细介绍。 |
expires | number | 否 | 用户指定本次请求签名的失效时间。格式为unix时间戳形式,用于防止 replay 型攻击。为保证防止 replay攻击算法的正确有效,需保证客户端系统时间正确。 |
device_type | number | 否 | 当一个应用同时支持多个设备平台类型(比如:Android和iOS),请务必设置该参数。其余情况可不设置。Android对应的参数值为3,IOS为4. |
3.2.2 API调用参数
① 这里主要讲一下推送广播消息的请求参数,同样的利用官网API(http://push.baidu.com/doc/restapi/restapi)的表格来熟悉一下:
参数名 | 类型 | 必需 | 限制 | 描述 |
---|---|---|---|---|
msg_type | number | 否 | 取值如下:0:消息;1:通知。默认为0 | 消息类型 |
msg | string | 是 | 消息/通知数据格式详见下方介绍 | 消息内容,json格式 |
msg_expires | number | 否 | 0~604800(86400*7),默认为5小时(18000秒) | 消息过期时间,单位为秒 |
deploy_status | number | 否 | 取值为:1:开发状态;2:生产状态; 若不指定,则默认设置为生产状态。 | 设置iOS应用的部署状态,仅iOS应用推送时使用 |
send_time | number | 否 | 指定的实际发送时间,必须在当前时间60s以外,1年以内 | 定时推送,用于指定的实际发送时间 |
{
"title" : "hello" ,
"description": "hello world" //必选
"notification_builder_id": 0, //可选
"notification_basic_style": 7, //可选
"open_type":0, //可选
"url": "http://developer.baidu.com", //可选
"pkg_content":"", //可选
"custom_content":{"key":"value"},
}
代码就比较随意了,直接贴出来:
String msg = String.format("{" + Constants.TITLE + ":\"%s\","
+ Constants.DESCRIPTION + ":\"%s\","
+ Constants.NOTIFICATION_BUILDER_ID + ":0,"
+ Constants.NOTIFICATION_BASIC_STYLE + ":7}", title, contents);
requestData.put(Constants.MSG, msg);
拼接好之后放入请求Map中,用于后面的传递。
3.3 签名算法
云推送API使用的签名算法(http://push.baidu.com/doc/restapi/sdk_developer#签名算法)如下:
① 获取请求的http method;
② 获取请求的url,包括host和sheme,但不包括query_string的部分;
③ 将所有参数(包括GET或POST的参数,但不包含签名字段)格式化为“key=value”格式,如“k1=v1”、“k2=v2”、“k3=v3”;
④ 将格式化好的参数键值对以字典序升序排列后,拼接在一起,如“k1:v1,k2 :v2,k3:v3”,并将http method和url按顺序拼接在这个字符串前面;
⑤ 在拼接好的字符串末尾追加上应用的secret_key,并进行urlencode,形成base_string;
了解签名算法的规则后,让我们来看看代码是怎么写的:
/**
* 通过签名算法得到sign值
*
* @param data
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
private StringBuilder getSign(RequestData data)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(Constants.POST);
stringBuilder.append(Constants.REQUEST_URL);
for (Map.Entry i : data.entrySet())
{
stringBuilder.append(i.getKey());
stringBuilder.append('=');
stringBuilder.append(i.getValue());
}
stringBuilder.append(Constants.SECRETKEY_VALUE);
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
Log.e("TAG", stringBuilder.toString());
messageDigest.update(urlEncode(stringBuilder.toString()).getBytes());
byte[] md5 = messageDigest.digest();
stringBuilder.setLength(0);
for (byte b : md5) {
stringBuilder.append(String.format("%02x", b & 0xff));
}
return stringBuilder;
}
/**
* url编码方式
*
* @param str
* 指定编码方式,默认为utf-8
* @return
* @throws UnsupportedEncodingException
*/
private String urlEncode(String str) throws UnsupportedEncodingException {
String rc = URLEncoder.encode(str, "utf-8");
return rc.replace("*", "%2A");
}
最后请求的时候,记得要设置请求Header中的Content-Type和User-Agent的值。大致的内容就这些,大家可以去云推送官网查看详细的API文档,完整的代码可以通过下方的链接下载。
如若文中或代码有任何写的不对或者不好的地方,欢迎大家指出。
程序源代码:
Android推送 利用REST API实现从客户端推送(百度云推送)