Android推送 利用REST API实现从客户端推送(百度云推送)

来源:互联网 发布:淘宝童装店取名 编辑:程序博客网 时间:2024/05/16 05:08

随着谷歌开发者大会在中国的成功举行,也带来激动人心的消息,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 节点下添加权限:

<!-- Push service 运行需要的权限 --><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><uses-permission android:name="android.permission.WRITE_SETTINGS" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.DISABLE_KEYGUARD" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><!-- 富媒体需要声明的权限 --><uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/><uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /><uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /><!-- 适配Android N系统必需的ContentProvider写权限声明,写权限包含*自己的应用包名*--><uses-permission    android:name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.project.baidupushtest" /><permission    android:name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.project.baidupushtest"    android:protectionLevel="normal"></permission>

2.4.2 注册Receiver 和 Service

在application节点中注册广播接收器和服务:

<!-- push service start --><!-- 用于接收系统消息以保证PushService正常运行 --><receiver android:name="com.baidu.android.pushservice.PushServiceReceiver"    android:process=":bdservice_v1" >    <intent-filter>        <action android:name="android.intent.action.BOOT_COMPLETED" />        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />        <action android:name="com.baidu.android.pushservice.action.notification.SHOW" />        <action android:name="com.baidu.android.pushservice.action.media.CLICK" />        <!-- 以下四项为可选的action声明,可大大提高service存活率和消息到达速度 -->        <action android:name="android.intent.action.MEDIA_MOUNTED" />        <action android:name="android.intent.action.USER_PRESENT" />        <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />    </intent-filter></receiver><!-- Push服务接收客户端发送的各种请求--><receiver android:name="com.baidu.android.pushservice.RegistrationReceiver"    android:process=":bdservice_v1" >    <intent-filter>        <action android:name="com.baidu.android.pushservice.action.METHOD" />        <action android:name="com.baidu.android.pushservice.action.BIND_SYNC" />    </intent-filter>    <intent-filter>        <action android:name="android.intent.action.PACKAGE_REMOVED" />        <data android:scheme="package" />    </intent-filter></receiver><service android:name="com.baidu.android.pushservice.PushService"     android:exported="true"    android:process=":bdservice_v1" >    <intent-filter >        <action android:name="com.baidu.android.pushservice.action.PUSH_SERVICE" />    </intent-filter></service><!-- 4.4版本新增的CommandService声明,提升小米和魅族手机上的实际推送到达率 --><service android:name="com.baidu.android.pushservice.CommandService"    android:exported="true" /><!-- 适配Android N系统必需的ContentProvider声明,写权限包含应用包名--><provider    android:name="com.baidu.android.pushservice.PushInfoProvider"    android:authorities="com.baidu.push.example.bdpush"    android:writePermission="baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.baidu.push.example"    android:protectionLevel = "signature"    android:exported="true" /><!-- push结束 -->

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

<!-- 此处Receiver名字修改为当前包名路径 --><receiver android:name=".MyPushMessageReceiver">    <intent-filter>        <!-- 接收push消息 -->        <action android:name="com.baidu.android.pushservice.action.MESSAGE" />        <!-- 接收bind、setTags等method的返回结果-->        <action android:name="com.baidu.android.pushservice.action.RECEIVE" />        <!-- 接收通知点击事件,和通知自定义内容 -->        <action android:name="com.baidu.android.pushservice.action.notification.CLICK" />    </intent-filter></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}是具体的请求参数,有几点要注意一下:
① 对于GET请求,{query_string}放在“?”后面传递;
② 对于POST请求,{query_string}放在POST参数中传递
③ {query_string}由通用参数和具体API调用参数2个部分组成;
④ {query_string}中的key/value对都必须经过urlencode处理,且必须是UTF-8编码;
⑤ 目前查询接口同时支持POST和GET方式,非查询接口仅支持POST方式。

我们请求推送使用的是POST的方式。

3.2 请求的参数
可划分为①公共请求参数:即每次请求都需要传递的参数;②API调用参数:每种请求类型都会有相对应的请求参数。
3.2.1 公共请求参数

通过下表更进一步了解一下通用参数:

参数名类型必需描述 apikey string 是 应用的Api Key,用于标识应用。 timestamp            number       是 用户发起请求时的unix时间戳。本次请求签名的有效时间为以该时间戳开始的10分钟。 sign string 是 通过签名算法生成,与apikey成对出现。用于防止请求内容被篡改。下一小节详细介绍。 expires number 否 用户指定本次请求签名的失效时间。格式为unix时间戳形式,用于防止 replay 型攻击。为保证防止 replay攻击算法的正确有效,需保证客户端系统时间正确。 device_typenumber 否 当一个应用同时支持多个设备平台类型(比如: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年以内 定时推送,用于指定的实际发送时间② Android平台的消息无格式要求,开发者可以自定义。详情可见:http://push.baidu.com/doc/restapi/msg_struct

{      "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<String, String> 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实现从客户端推送(百度云推送)

0 0
原创粉丝点击