phonegap推送实现(android)

需求

必备知识

这篇文章至少需要有过一个中等层次的PhoneGap的开发经验

必须产品

PhoneGap Build


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

用户级

全部适用


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

上一篇文章是通过PhoneGap能够在苹果设备上推送通知。在这篇文章中,我将会讲解如何在Android平台上使用PhoneGap去推送通知。通过对比,我发下我的通知在Android设备上的推送速度更快。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

Google Cloud Messaging


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

Android的通知推送可以通过 GoogleCloud MessagingGCM的服务,这个和苹果的通知推送服务相似。以前它们都是对C2DM支持(用于云与设备之间消息传递的框架),但是现在那些API已经放弃使用了,还有就是GoogleCloud Message提供了更多增强实现,这些都是C2DM所提供不到的。通过 Cordova/PhoneGap 插件能够帮组你利用到GoogleCloud Messaging的服务。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

消息的大小分配给GCM的净负荷是4kb(只是字符串数据),明显地比苹果推送所要求的256个位要大很多。这里有一篇文章关于这些消息发送到底支持那些数据类型。还有我建议你在你构建你的应用程序之前先在这里阅读一下应该怎样去使用这样服务,因为我在这篇文章中很多关于这方面的细节都没有讨论到。某些点我需要在这篇文章中着重强调一下是:

<!--[if !supportLists]-->·         <!--[endif]-->GCM并不保证消息的分发或者它的顺序。

<!--[if !supportLists]-->·         <!--[endif]--> 并不需要在一个Android设备上运行一个Android应用才能接受到消息。其实它是通过网络的广播,当一个消息到达的时候,系统就会唤醒Android应用,当然这需要你为你的应用程序设置好正确的广播接受者和权限。

<!--[if !supportLists]-->·         <!--[endif]-->GCM并不提供任何内建的用户接口或者消息的处理。GCM只是简单的传递没处理过的消息数据然后直接送到对应的Android应用上,这样你就拥有全部对数据处理的权利。例如应用可以发送一个通知、显示一个自定义的用户接口或者悄悄地同步数据。

设置如何去推送通知

通过这些步骤就能在你的Android 应用程序去推送通知:

1.      通过命令行工具或者Eclipse去创建一个AndroidCordova 项目(我们推荐使用命令行)

2.      下载GCM Cordova 插件

3.      跟着插件说明的以下步骤:

<!--[if !supportLists]-->·         <!--[endif]-->  要跟着说明文档所写地去设置你的Google Cloud Messaging 帐号和注意记下位于URL中的项目ID。举个例子,下面加粗的数字就是你需要发送给register()方法:

 




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]--><?xml:namespace prefix = "o" />

<!--[if !supportLists]-->2.   <!--[endif]--> 

<!--[if !supportLists]-->3.   <!--[endif]-->https://code.google.com/apis/console/?pli=1#project:824841663942

复制代码



<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->·         <!--[endif]-->  不要忘记将以下代码换成你的GCM项目的ID

 




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->window.GCM.register("[your_sender_id]", "GCM_Event", GCM_Success, GCM_Fail );

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->·         <!--[endif]-->  包含你的发送器的ID

 




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->window.GCM.register("824841663942", "GCM_Event", GCM_Success, GCM_Fail );

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

4. 当一个应用接受到一个消息的时候要为它添加处理函数决定它是否打开。例如你可能会显示一个弹出警告或者一个状态栏通知。

Note:这个插件将会处理GCM的登记,并有对应的方法去接收一个消息,但它实际上并不为这些通知做出响应,这些就是你需要添加的东西。你也可以去更深入阅读关于如何了解怎么添加原生代码去产生一个状态栏通知。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

如果你需要更多有关于创建GCM项目的资料,某些特定的步骤你可以在这里找到。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

PhoneGap插件包含一个简单的项目,并已经为通知推送设置寄存器,包括改变了AndroidManifest.xml和插件的配置。而你所要做的事就是修改CORDOVA_GCM_script.js文件,这样你就能够在你的register()函数里面使用GCM发送者/项目的ID,这有你立马运行它或者将这个项目作为参考并根据自己的需求做修改。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

如果你偏向于利用Eclipse去编写你的代码,那么你简单地通过导入之前所创建并包含该插件的Android项目,这样你就可以开始你的工作了。

1. Choose File | New |Project

2. 选择“Android Project from Existing Code”



 

1.选择“Android Project from Existing Code”


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

运行示例应用

当你运行插件中的示例代码时,它会尝试自动注册你的设备。如果注册成功,你会看到消息中包含一个注册ID。(看看下面截图中我圈起来的REGID字符串,这是我在我的Galaxy Tablet中运行得到的结果)



 

 

2:你会看到消息中包含一个注册的ID

当然你也应该可以在你的控制面板中看看一下的输出:



<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->10-24 18:24:20.720: V/GCMReceiver:onRegistered(21989): Registration ID arrived!

<!--[if !supportLists]-->2.   <!--[endif]-->10-24 18:24:20.730: V/GCMReceiver:onRegisterd(21989): {"regid":"APA91bFobAwM7P3Okxy2al8RI12VcJFUS-giXWTOoWXIObtSPOE1h7FuH1VPLBPgshDI_Fp7aIYVET-ssvGUErlWYA0cKPGhoXT1daqyDsEfem9ZtgZNRhQFv7kLCIVSigYlpMluToPiSHSsFSEdtCDfKoOZqNPsfg","event":"registered"}

<!--[if !supportLists]-->3.   <!--[endif]-->10-24 18:24:20.730: V/GCMPlugin:sendJavascript(21989): javascript:GCM_Event({"regid":"APA91bFobAwM7P3Okxy2al8RI12VcJFUS-giXWTOoWXIObtSPOE1h7FuH1VPLBPgshDI_Fp7aIYVET-ssvGUErlWYA0cKPGhoXT1daqyDsEfem9ZtgZNRhQFv7kLCIVSigYlpMluToPiSHSsFSEdtCDfKoOZqNPsfg","event":"registered"})

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

一旦你得到了像以上所示的注册ID,你就可以开始编写你的服务端代码。以下的部分将会讲解怎么使用Node.JS代码去发送一条消息给你的应用程序。或者,你也可以使用Urban Airship或者PushWoosh去发送一个通知。当收到这个消息时,你将会看到如下面截图所示的文本显示在屏幕上:



 

3.当收到一条消息时,你将会看到这些信息显示出来。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

这是虽然这个插件不做任何的处理。接下来的部分我们将会讲解通过添加一些代码使得但接收到一条消息的时候将会显示一个状态栏通知。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

状态栏通知


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

由于这个插件只是简单地接收消息——不管你的应用程序是否是在运行——但是即使消息到达了也没有做任何处理,你决定它应该做出怎样的响应。一个常见的需求就是把这个消息显示在一个原生的状态栏上。在IOS上,这个过程会有所不同,这个通知会被自动显示。但是在Android上你需要为它编写明确的代码。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

其中一个选择就是使用Cordova StatusBarNotification 插件去实现这样的效果。如果你想用更快的解决方案,你可以通过简单添加原生的Java代码到你的GCMIntentService.javaonMessage()方法里面,就像一下代码那样:


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->String message = extras.getString("message");

<!--[if !supportLists]-->2.   <!--[endif]-->String title = extras.getString("title");

<!--[if !supportLists]-->3.   <!--[endif]-->Notification notif = new Notification(android.R.drawable.btn_star_big_on, message, System.currentTimeMillis() );

<!--[if !supportLists]-->4.   <!--[endif]-->notif.flags = Notification.FLAG_AUTO_CANCEL;

<!--[if !supportLists]-->5.   <!--[endif]-->notif.defaults |= Notification.DEFAULT_SOUND;

<!--[if !supportLists]-->6.   <!--[endif]-->notif.defaults |= Notification.DEFAULT_VIBRATE;

<!--[if !supportLists]-->7.   <!--[endif]--> 

<!--[if !supportLists]-->8.   <!--[endif]-->Intent notificationIntent = new Intent(context, TestSampleApp.class);

<!--[if !supportLists]-->9.   <!--[endif]-->notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

<!--[if !supportLists]-->10.  <!--[endif]-->PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

<!--[if !supportLists]-->11.  <!--[endif]--> 

<!--[if !supportLists]-->12.  <!--[endif]-->notif.setLatestEventInfo(context, title, message, contentIntent);

<!--[if !supportLists]-->13.  <!--[endif]-->String ns = Context.NOTIFICATION_SERVICE;

<!--[if !supportLists]-->14.  <!--[endif]-->NotificationManager mNotificationManager = (NotificationManager)

<!--[if !supportLists]-->15.  <!--[endif]-->context.getSystemService(ns);

<!--[if !supportLists]-->16.  <!--[endif]-->mNotificationManager.notify(1, notif);

复制代码




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

还有要记得要添加以下的导入,这样上面的代码才能实现:




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->import android.app.Notification;

<!--[if !supportLists]-->2.   <!--[endif]-->import android.app.NotificationManager;

<!--[if !supportLists]-->3.   <!--[endif]-->import android.app.PendingIntent;

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

要确定你已经使用YourActivityClassName.class替换继承至DroidGap的子类的名字。例如,在示例项目中我们叫它MainActivity


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

以上的代码将会设置一个带有一个星星图片的通知,并伴随震动和默认声音。这个例子已经在我的Android Galaxy Tablet上运行了,图如下所示(红色圈圈标记)


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->



 

4.状态栏通知(包含星型图片和震动、默认声音)


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

当你点击这个通知后,那么应用程序将会打开并显示它说真实收到的消息。



 

5.点击那个通知将会触发应用程序打开并显示它所收到的消息。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

状态栏的显示因不同的设备而有所不同。在一般的Android手机上,是会显示在最上面而不是像我的截图那样显示在底端。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

通过node-gcm去发送一条消息


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

这里是通过Node.js 库使得Google Cloud Messaging去发送通知。它被称为称为node-gcm。下面的这些代码是为了让我的设备能发送一条消息。

相信你们注意到我改变了那些键。在发送的参数中,用你在申请Google Cloud Messaging 服务时Google给你的ID去指定你自己的API键。你会收到两个API键,一个浏览器键和服务器键,这里两个可能都会用到。如果其中一个不能用,试一下另外一个。还有就是当你注册使用到以上插件的时候,也要指定返回给你的应用程序的值。当你运行你的应用程序并调用GCM register函数的时候,注册的ID将会在你的屏幕和控制台上显示。




<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->var gcm = require('node-gcm');

<!--[if !supportLists]-->2.   <!--[endif]--> 

<!--[if !supportLists]-->3.   <!--[endif]-->var message = new gcm.Message();

<!--[if !supportLists]-->4.   <!--[endif]-->var sender = new gcm.Sender('AIzaSyCDx8v9R0fMsAsjoAffF-P3FCFWXlvwKgL');

<!--[if !supportLists]-->5.   <!--[endif]-->var registrationIds = [];

<!--[if !supportLists]-->6.   <!--[endif]--> 

<!--[if !supportLists]-->7.   <!--[endif]-->message.addData('title','My Game');

<!--[if !supportLists]-->8.   <!--[endif]-->message.addData('message','Your turn!!!!');

<!--[if !supportLists]-->9.   <!--[endif]-->message.addData('msgcnt','1');

<!--[if !supportLists]-->10.  <!--[endif]-->message.collapseKey = 'demo';

<!--[if !supportLists]-->11.  <!--[endif]-->message.delayWhileIdle = true;

<!--[if !supportLists]-->12.  <!--[endif]-->message.timeToLive = 3;

<!--[if !supportLists]-->13.  <!--[endif]--> 

<!--[if !supportLists]-->14.  <!--[endif]-->// At least one token is required - each app registers a different token

<!--[if !supportLists]-->15.  <!--[endif]-->registrationIds.push('APA91bFobAwN7P3Okxy2al8RI12VcJFUS-giXWTOoWXIObtSPOE1h7FuH1VPLBPgshDI_Fp7aIYVET-ssvGUErlWYA0cKPGhoXT1daqyDsEfem9ZtgZNRhQFv7kLCIVSigYlpMluToPiSHSsFSEdtCDfKoOZqNPgfs');

<!--[if !supportLists]-->16.  <!--[endif]--> 

<!--[if !supportLists]-->17.  <!--[endif]-->/**

<!--[if !supportLists]-->18.  <!--[endif]-->* Parameters: message-literal, registrationIds-array, No. of retries, callback-function

<!--[if !supportLists]-->19.  <!--[endif]-->*/

<!--[if !supportLists]-->20.  <!--[endif]-->sender.send(message, registrationIds, 4, function (result) {

<!--[if !supportLists]-->21.  <!--[endif]-->    console.log(result);

<!--[if !supportLists]-->22.  <!--[endif]-->});

<!--[if !supportLists]-->23.  <!--[endif]-->/** Use the following line if you want to send the message without retries

<!--[if !supportLists]-->24.  <!--[endif]-->sender.sendNoRetry(message, registrationIds, function (result) {

<!--[if !supportLists]-->25.  <!--[endif]-->console.log(result); });

<!--[if !supportLists]-->26.  <!--[endif]-->**/

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

要为title键和message键明确地指定titlemessage,因为程序的插件将会在GCMIntentService.java中查找它:


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->1.   <!--[endif]-->Bundle extras = intent.getExtras();

<!--[if !supportLists]-->2.   <!--[endif]-->    if (extras != null) {

<!--[if !supportLists]-->3.   <!--[endif]-->        try {

<!--[if !supportLists]-->4.   <!--[endif]-->          String title = extras.getString("title");

<!--[if !supportLists]-->5.   <!--[endif]-->          String message = extras.getString("message");

<!--[if !supportLists]-->6.   <!--[endif]-->          ....

<!--[if !supportLists]-->7.   <!--[endif]-->        }

<!--[if !supportLists]-->8.   <!--[endif]-->     }

复制代码





<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

折叠键

根据Android的开发文档,当你定义一个折叠键时,它只会分发给你最后收到的通知和一个给定的折叠键,为了不让用户被过多的通知烦扰例如像体育比赛中的分数。



 

6.title键和message键指定明确的titlemessage。注意在弹出列表中所出现的状态栏通知(如果被受理),像图7所示



 

7.状态栏通知在弹出框中显示


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

其它可供选择的插件

迟点我将会解释那些你在Android上使用Cordova去推送通知时要用到的资料,你可能会想到在GitHub那里的另外一个插件。这个插件是为了能够让捏充分利用PushWoosh去推送通知而设计出来的,这个我在我的博文中发布过,使用Pushwoosh让你能够简单通过PhoneGap去推送通知。这个插件的APIIOS上的Cordova 通知推送插件类似,有趣的是,当我测试它的时候,即使不在PushWoosh服务器的环境下,我的Node.js服务仍然能够接收到所推送的消息。此外,我并不需要添加任何原生的Java代码,能够让上面的状态栏通知显示。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

下一步

以下的这些连接你可能需要点击进去看一下

<!--[if !supportLists]-->·         <!--[endif]-->  通过Pushwoosh去利用PhoneGap去推送通知

<!--[if !supportLists]-->·         <!--[endif]-->  Cordovapush项目——依据node-apnnode-gcm的跨平台的推送服务。

<!--[if !supportLists]-->·         <!--[endif]-->  Urban Airship 通知推送服务器——融合了PhoneGap

 


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

这些只能在CreativeCommons Attribution-Noncommercial-Share Alike 3.0 Unported License的许可下被运用到。权限只能在许可范围内,关于这个例子的代码(包括项目中用到的)都可以在Adobe上找到。

原文链接:http://www.adobe.com/devnet/phonegap/articles/android-push-notifications-with-phonegap.html

猜你喜欢

转载自firepix.iteye.com/blog/1927061