google的GCM推送使用简介

pom
<!-- https://mvnrepository.com/artifact/com.google.gcm/gcm-server -->
        <dependency>
            <groupId>com.google.gcm</groupId>
            <artifactId>gcm-server</artifactId>
            <version>1.0.0</version>
        </dependency>
Demo
        Sender sender = new Sender("your_google_key");//需要去谷歌注册,然后获取你的key
        Message message = new Message.Builder().addData("标题", "消息体").build();

        MulticastResult resultMulti = null;
        try {
            Integer retries = 5;//如果失败重新发送的次数
            List<String> appKeys = new ArrayList<>();
            appKeys.add("手机的唯一标识");
            resultMulti = sender.send(message, appKeys, retries);
            Integer successCount = resultMulti.getSuccess();
            Integer failCount = resultMulti.getFailure();
            // TODO:统计成功和失败次数
            return Boolean.TRUE;
        } catch (IOException e) {
            LOGGER.error("androidMessage send fail" + title + body);
            return Boolean.FALSE;
        }

转载请注明出处:http://blog.csdn.net/newhope1106/article/details/54709916

GCM即Google Cloud Messaging,主要用于消息推送的,即使在应用没有起来的情况下,客户端也能通过GCM收到来自服务器的消息。GCM支持Android、IOS和Chrome。由于GCM需要google service支持,在国内基本不能用,经常会断线,不过最近项目要求,只在美国上线该项目,因此可以采用GCM实现推送的方式,国内相关文章较少,特意整理了一下客户端使用的官方文档。

首先来看看目前应用不启动实现推送的方式有哪些:

1.使用Google自带的GCM实现推送

2.采用监听开机广播的方式,启动后台服务,为了防止被杀死,采用多进程的方式,监听服务是否被杀,被杀之后,把它拉起来(比较流氓)

3.采用第三发方案,如友盟、极光、信鸽

国内第二种和第三种用得比较多,本文主要讲解第一种方案,也就是GCM,以下内容均来自官网

一、概述

GCM可以让开发者在客户端和服务器之间传递消息,有2种方式实现消息推送,一种是xmpp,它即可让服务器把消息推送给客户端,也可让客户端把消息推送给服务器,另一种方式是http,只能服务器将消息推送给客户端,以下是其架构图。

GCM服务器接收应用服务器的消息,然后再把消息转发给客户端,服务器端根据自己的需要实现xmpp或者http接口,和GCM服务器进行通信,客户端想要接收消息,需要使用GCM提供的API。

二.客户端使用GCM

1.使用限制:

a.最低要求Android 2.2+的设备,并且安装了Google应用商店

b.想要使用GCM新特性,要求Android 2.3+

c.低于Android 4.0.4版本,需要Google账号,Android 4.0.4+不需要

2.客户端使用GCM流程

和使用一般的sdk类似,首先需要在官网注册自己的应用,获取一个appid,出于安全要求,需要在本地使用这个appid去获取动态token,需要把token上传给服务器,每隔一段时间token可能会失效,需要去重新获取token。按照上面的过程我们来看看怎么使用的。以下针对Android Studio开发的。

(1)官网注册应用

首先我们需要到这个网址:https://console.firebase.google.com/ 去注册自己的应用,按照相关步骤操作之后,点击下载配置文件,会下载一个叫google-services.json的文件,把它放到自己的项目的app/目录下。

(2)添加配置文件解析插件依赖

上述下载的google-services.json需要插件进行解析,要在项目中按照下面步骤添加依赖

a.在项目级别(project-level)的build.gradle添加下面依赖

classpath 'com.google.gms:google-services:3.0.0' b.在自己的应用级别(app-level)的build.gradle添加下面插件

apply plugin: 'com.google.gms.google-services' (3)添加GCM依赖

代码中需要用到gcm的api,因此需要添加gcm的依赖,版本请使用最新的版本,下面只是示范

dependencies {   compile "com.google.android.gms:play-services-gcm:10.0.0" } (4)修改AndroidMenifest.xml文件

a.添加权限,因为我们不允许其他的应用接收和发送属于自己应用的消息,因此添加权限屏蔽其他应用,权限格式:<application-package-name> + ".permission.C2D_MESSAGE"

b.定义一个GcmReceiver接收器,用来接收发送给应用的消息,需要添加com.google.android.c2dm.permission.SEND权限

c.定义GcmListenerService服务器,用来处理各种不同的下发信息,上发状态,自动显示通知等

d.定义一个集成InstanceIDListenerService的服务,用来获取、刷新token

e.额外的,可以添加android.permission.WAKE_LOCK权限,保证消息到达的时候,可以得到及时处理

以下是一个demo

<manifest package="com.example.gcm" ...>

    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>     <uses-permission android:name="android.permission.WAKE_LOCK" />

    <permission android:name="<your-package-name>.permission.C2D_MESSAGE"         android:protectionLevel="signature" />     <uses-permission android:name="<your-package-name>.permission.C2D_MESSAGE" />

    <application ...>         <receiver             android:name="com.google.android.gms.gcm.GcmReceiver"             android:exported="true"             android:permission="com.google.android.c2dm.permission.SEND" >             <intent-filter>                 <action android:name="com.google.android.c2dm.intent.RECEIVE" />                 <category android:name="com.example.gcm" />             </intent-filter>         </receiver>         <service             android:name="com.example.MyGcmListenerService"             android:exported="false" >             <intent-filter>                 <action android:name="com.google.android.c2dm.intent.RECEIVE" />             </intent-filter>         </service>         <service             android:name="com.example.MyInstanceIDListenerService"             android:exported="false">             <intent-filter>                 <action android:name="com.google.android.gms.iid.InstanceID" />             </intent-filter>         </service>         <service             android:name="gcm.play.android.samples.com.gcmquickstart.RegistrationIntentService"             android:exported="false">         </service>     </application>

</manifest> 如果是android 4.4之前的版本,需要在receiver中添加的intent-filter中添加下面的action

<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

3.客户端获取、刷新token

(1)先来看看获取token的接口

String authorizedEntity = PROJECT_ID; // Project id from Google Developer Console String scope = "GCM"; // e.g. communicating using GCM, but you can use any                       // URL-safe characters up to a maximum of 1000, or                       // you can also leave it blank. String token = InstanceID.getInstance(context).getToken(authorizedEntity,scope); 上述的PROJECT_ID是在https://console.developers.google.com/project中注册得到的,scope,可以自定义

(2)token的更新

在前面有提到AndroidMenifest.xml中注册一个继承InstanceIDListenerService的服务,看看具体的实现

public class MyInstanceIDService extends InstanceIDListenerService {   public void onTokenRefresh() {     refreshAllTokens();   }

  private void refreshAllTokens() {     // assuming you have defined TokenList as     // some generalized store for your tokens     ArrayList<TokenList> tokenList = TokensList.get();     InstanceID iid = InstanceID.getInstance(this);     for(tokenItem : tokenList) {       tokenItem.token =         iid.getToken(tokenItem.authorizedEntity,tokenItem.scope,tokenItem.options);       // send this tokenItem.token to your server     }   } } 第一次获取token,虽然没有获取过token,但本质还是刷新,都是调用onTokenRefresh接口,并且把获取的token发送给服务器。

上面的处理可以最好用一个IntentService来异步处理,不要放在主线程中,上述给一个使用范例而已。

(3)InstanceID

上面我们看到,获取token的时候,首先需要InstanceID,当设备上线的时候,Instance ID Service会分配一个InstanceID, InstanceID是由一对公钥和私钥共同维护的,私钥保存在本地,公钥由Instance ID Service注册产生。可以通过调用geId()方法,随时更新InstanceId,因为生成的token都是依赖这个InstanceID的。

String iid = InstanceID.getInstance(context).getId(); 你也可以删除一个InstanceID,那么对应的所有token都会失效,用新的InstanceID生成新的token

InstanceID.getInstance(context).deleteInstanceID(); String newIID = InstanceID.getInstance(context).getId(); (4)Instance ID 的生命周期图

4.客户端接收服务器下发信息

a.服务器可以通过HTTP(单向)和XMPP(双向)发送信息,看看下面的demo

HTTP POST Request https://gcm-http.googleapis.com/gcm/send Content-Type:application/json Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{ "data": {     "score": "5x1",     "time": "15:10"   },   "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..." } XMPP Message <message id="">   <gcm xmlns="google:mobile:data">     { "data": {       "score": "5x1",       "time": "15:10"     },     "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."   }   </gcm> </message> b.客户端处理下发消息

服务器发送的消息,GCM会将接收到的消息转发给客户端,在前面的AndroidManifest.xml中,我们定义了一个GcmListenerService来处理消息,可以自己继承GcmListenerService并且覆盖onMessageReceived方法。

@Override public void onMessageReceived(String from, Bundle data) {     String message = data.getString("message");     Log.d(TAG, "From: " + from);     Log.d(TAG, "Message: " + message);

    if (from.startsWith("/topics/")) {         // message received from some topic.     } else {         // normal downstream message.     }

    // ... } 5.客户端上发消息

public void onClick(final View view) {     if (view == findViewById(R.id.send)) {         new AsyncTask<void, void,="" string="" style="box-sizing: inherit;">() {             @Override             protected String doInBackground(Void... params) {                 String msg = "";                 try {                     Bundle data = new Bundle();                     data.putString("my_message", "Hello World");                     data.putString("my_action","SAY_HELLO");                     String id = Integer.toString(msgId.incrementAndGet());                     gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);                     msg = "Sent message";                 } catch (IOException ex) {                     msg = "Error :" + ex.getMessage();                 }                 return msg;             }

            @Override             protected void onPostExecute(String msg) {                 mDisplay.append(msg + "\n");             }         }.execute(null, null, null);     } else if (view == findViewById(R.id.clear)) {         mDisplay.setText("");     } }</void,> 主要是利用了gcm的send接口,上述需要服务器支持xmpp

6.服务器端的实现

可以参考:https://developers.google.com/cloud-messaging/的GCM Connection Server部分

有兴趣的可以参考google的代码demo

https://github.com/google/gcm/

https://github.com/googlesamples/google-services/

--------------------- 作者:newhope1106 来源:CSDN 原文:https://blog.csdn.net/newhope1106/article/details/54709916 版权声明:本文为博主原创文章,转载请附上博文链接!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维记录点滴

SQL Server 2008修改数据库为多用户模式

ALTER DATABASE dataBaseName SET MULTI_USER;

25120
来自专栏大白技术控的技术自留地

Google搜索命令“site:”运算符高级使用技巧:

*号技巧: 搜索“maps.*.com”可得到所有以maps.xxx.com作为域的网站内容,不过可惜的是Google不会给你全部匹配的结果,只有一部分 你可以...

18130
来自专栏黑光技术

golang的struct和interface

struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套;go中的struct类型理解为类,可以定义方法,和函数定义有些许区别;struct类型...

29240
来自专栏黑光技术

Golang UnitTest单元测试

单元测试是程序开发者适用一段代码来验证另外一段代码写的是否符合预期的一种相对高效的自我测试方法。

1.8K20
来自专栏黑光技术

golang调度机制

go语言非常重要的一个特性就是gorountine,有了这个东东,就可以很简单的做并发处理程序,比起c++和java的方式来说可以说简单了很多很多。那么goro...

47330
来自专栏大白技术控的技术自留地

谷歌浏览器chrome插件、扩展程序无法下载的解决方法

chrome网上应用店的插件下载服务在国内已经无法访问了。那么我们如何安装谷歌浏览器插件呢?

24850
来自专栏黑光技术

Goroutine+Channel+WaitGroup使用

golang语言中最有特色之一的东东就是这个goroutine了,很多时候问起别人为什么golang的好用,golang的网络性能可以那么好,一般都会多多少少想...

11550
来自专栏Java编程技术

Go并发编程之美-CAS操作

go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于...

7910
来自专栏学无止境

Go:学习笔记兼吐槽(3)

长度是数组类型的一部分,就是说数组不可以脱离长度而存在。听起来不太明白,我们来看下面的一个示例就明白了,这真的是一个大坑。

9120
来自专栏Fundebug

我们应该如何给需求排序?

开发产品的时候,我们每天都会面对各种各样、没完没了的需求,有的来自外部用户的反馈,有的来自内部团队的idea,有的是产品的BUG,有的是新的功能...

11250

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励