构建Android Push Notification Service服务端及客户端
文章来源:http://www.360doc.com/content/12/0324/19/2472295_197330481.shtml
终于又开始上班了,只有在值班的时候,才是我比较清闲的时候,可以静下来做自己喜欢的事情,看自己喜欢的文章,写自己喜欢的博客。在Android架构部分,几个比较难啃的骨头里面,Android Push Notification Service算一个。我想今天来解释一下她的实现以及使用。
1 这个服务的必要性问题
在手机的使用过程中,我们知道,正睡觉呢,突然响起了短信声,打开一看,原来是移动/电信在提醒我们该上厕所了,或者天边冷了,多穿点衣服吧之类的话语。而在使用Android手机的时候,我们发现,如果有Gmail端,收到邮件的时候,会弹出一个提示,你有一条新邮件,并包含邮件的标题和相关信息。不知道你会不会好奇,这是如何实现的呢?我很好奇,所以便有了此文的写作动机。而对于QQ、安卓市场之类的软件,时不时的也弹出来这类信息,相信大家可以明白,这东西应该是有点用处的。比如我们开发一款应用,需要实时的提醒我们的安装用户一些事情,相信,你就会明白,这个服务是很有必要的,相信,在未来移动互联网、物联网占据大片江山的时候,也是很有必要的。
2 几个问题
好了,我们提出了这个东西的必要性,但是在做的时候,我们必须要考虑几个问题。
2.1 俺的电池不怎么抗用,可千万别太耗我的电量啊,这是哥最在意的啊。
2.2 除了花点流量,这玩意不要花我另外的钱,我可是月光族啊。
2.3 我着急要收到这个消息,别半小时后才把消息发给我,那样的话,会损失我的订单的。
2.4 必须要可靠哦,别用着用着,不好使了。
秉着以上的几个关键问题,我们开始了下一部分的探讨了。
3 几种可能的方案
我们来思考一下,要实现实时得到信息,有哪几种方法呢?
1 通过http/https或者其他协议,客户端以服务的方式,每隔10分钟或者10秒钟,向服务器请求一次,服务器判断这段时间是否有新消息,需要发给客户端,如果有就通过json或者xml方式发给客户端。
2 通过短信的方式,服务器端通过SMS的方式,将所需要的消息及时发送回来。
3 使用tcp长连接和心跳包的机制,实现数据定时推送。
4 采用的方案
从我的能力,我目前只能想到这么几种办法,下面我们来根据第二条里面的准则来分析上面提到的几种方案。
第一条通过http或者https的方式,向服务器每隔多长时间请求一次的方式,的确可以实现我们的功能,但是违反了我们的2.1和2.3原则。首先这种方式会耗电,当然你可以说时间设置长一点,但是这样又违背了2.3原则。所以这条一般是不会被采纳的。除非某些特殊应用。
第二条呢,2.1、2.3、2.4都符合,可是,违背了2.2,所以我们也不会考虑的。
第三条呢,好像全部符合,但是有一个小问题在里面,就是如果以Service的方式进行,由于Android系统的特殊性,在内存不够用的时候,会主动结束一些服务,这个服务包括了我们的定义服务,这么说,他违背了2.4。
但是,我们还是有办法的。
5 被采用方案的可实施方法
在Android 2.2以后,Google放出了C2DM【Android Cloud to Device Messaging Framework】服务,从服务的使用方法上,我们就可以明白他们采用了第三种方式。
随着他们推出这个服务后,很多公司开始基于这个服务做一些应用,如推送广告、推送定制信息等。如xtify和airpush等,国内也有一些企业加入了这种阵营,如单独提供服务的push-notification,当然QQ也有这样的服务存在。
在这种方案里面,有几个细节地方,需要来解释一下。
5.1 传输的时候使用什么协议?
5.2 传输的时候如何保证数据的安全性?
5.3 对于多平台,多用户的push如何保证惟一性?
5.4 服务器端的如何部署?
5.1的问题目前有几种方式,使用xmpp协议、IBM的MQTT、自定义协议。 目前有一些开源的项目中,大都采用第一种和第二种,当然,如果有特殊需求,可以采取自定义协议的。
5.2的问题可以对数据进行可逆加密。
5.3的问题,一般是将手机的ID传递到服务器端进行惟一性验证。
5.4的问题,服务器端可以自己使用任何语言开发,也可以使用Nginx + 脚本语言部署。
6 实例说明
本文的实例采用了mqtt的架构,完全按照tokudu兄的文章而来(https://github.com/tokudu),并成功实现了。里面采取的不是IBM的Really Small Message Broker,而是采用的开源Mosquitto实现,
准备工作:
6.1 Android真机,本文为三星I809
6.2 Apache + Php环境
6.3 tokudu兄的Android源代码
6.4 tukudu兄的php代码
6.5 mosquitto的可执行程序。
步骤1:
下载mosquitto的可执行程序,我选择的是cygwin版本的,安装后,进入目录双击mosquitto.exe执行即可。
步骤2:下载tokudu兄的php代码,官方地址为:https://github.com/tokudu/PhpMQTTClient
我这里也提供下载:androidpushservice
主要代码为如下:
<?php
require ( 'SAM/php_sam.php' );
//create a new connection object
$conn = new SAMConnection();
//start initialise the connection
$conn ->connect(SAM_MQTT, array (SAM_HOST => '202.198.21.131' ,
SAM_PORT => 1883));
//create a new MQTT message with the output of the shell command as the body
$msgCpu = new SAMMessage( $_REQUEST [ 'message' ]);
//send the message on the topic cpu
$conn ->send( 'topic://' . $_REQUEST [ 'target' ], $msgCpu );
$conn ->disconnect();
echo 'MQTT Message to ' . $_REQUEST [ 'target' ] . ' sent: ' . $_REQUEST [ 'message' ];
?>
|
将代码部署到php环境目录里面。输入地址:http://localhost/androidpushservice/
步骤三:下载tokudu兄的android代码:
地址:https://github.com/tokudu/AndroidPushNotificationsDemo
本文提供下载:
tokudu-AndroidPushNotificationsDemo-ea18b09
导入项目,编译,在真机上面使用打开即可。
这里有一个Device Target号码需要在php的界面里面输入。才可以发送成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
/*
* $Id$ */ package com.tokudu.demo; import java.io.BufferedWriter; import android.os.Environment; public class ConnectionLog private static final SimpleDateFormat TIMESTAMP_FMT = public ConnectionLog() open(logDir.getAbsolutePath() + "/push.log"); public ConnectionLog(String basePath) protected void open(String basePath) println("Opened log."); private static String getTodayString() public String getPath() public void println(String message) public void close() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package com.tokudu.demo;
import android.app.Activity; public class PushActivity extends Activity { mDeviceID = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); final Button startButton = ((Button) findViewById(R.id.start_button)); @Override SharedPreferences p = getSharedPreferences(PushService.TAG, MODE_PRIVATE); ((Button) findViewById(R.id.start_button)).setEnabled(!started); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 |
package com.tokudu.demo;
import java.io.IOException; import com.ibm.mqtt.IMqttClient; import android.app.AlarmManager; /* // the IP address, where your MQTT broker is running. // MQTT client ID, which is given the broker. In this example, I also use this for the topic header. // These are the actions for the service (name are descriptive enough) // Connection log for the push service. Good for debugging. // Connectivity manager to determining, when the phone loses connection // Whether or not the service has been started. // This the application level keep-alive interval, that is used by the AlarmManager // Retry intervals, when the connection is lost. // Preferences instance // Notification title // This is the instance of an MQTT connection. // Static method to start the service // Static method to stop the service // Static method to send a keep alive message @Override log("Creating service"); try { // Get instances of preferences, connectivity manager and notification manager /* If our process was reaped by the system for any reason we need // This method does any necessary clean-up need in case the server has been destroyed by the system // Do a clean start @Override // Stop the services, if it has been started try { @Override // Do an appropriate action based on the intent. @Override // log helper function } else { if (mLog != null) // Reads whether or not the service has been started from the preferences // Sets whether or not the services has been started in the preferences. private synchronized void start() { // Do nothing, if the service is already running. // Establish an MQTT connection // Register a connectivity listener private synchronized void stop() { // Save stopped state in the preferences // Remove the connectivity receiver // Destroy the MQTT connection if there is one // private synchronized void keepAlive() { mConnection.disconnect(); // Schedule application level keep-alives using the AlarmManager // Remove all scheduled keep alives // We schedule a reconnect based on the starttime of the service // Calculate the elapsed time since the start // Set an appropriate interval based on the elapsed time since start log("Rescheduling connection in " + interval + "ms."); // Save the new internval // Schedule a reconnect using the alarm manager. // Remove the scheduled reconnect private synchronized void reconnectIfNecessary() { // This receiver listeners for network changes and updates the MQTT connection // Is there connectivity? log("Connectivity changed: connected=" + hasConnectivity); if (hasConnectivity) { // Display the topbar notification n.flags |= Notification.FLAG_SHOW_LIGHTS; n.defaults = Notification.DEFAULT_ALL; n.icon = com.tokudu.demo.R.drawable.icon; // Simply open the parent activity // Change the name of the notification here mNotifMan.notify(NOTIF_CONNECTED, n); // Check if we are online // This inner class is a wrapper on top of MQTT client. // Creates a new connection given the broker address and initial topic // register this client app has being able to receive messages // Subscribe to an initial topic, which is combination of client ID and device ID. log("Connection established to " + brokerHostName + " on topic " + initTopic); // Save start time // Disconnect if ((mqttClient == null) || (mqttClient.isConnected() == false)) { /* /* public void sendKeepAlive() throws MqttException { |
7 代码下载
tokudu-AndroidPushNotificationsDemo-ea18b09
androidpushservice
MQTT实现:http://mosquitto.org/download/
8 尾声
我们目前已经完成了整个功能,如果要商业使用,还有一些问题摆在我们面前,如连接数的问题,大并发的问题,Apikey的问题等等。我们也会在tokudu兄的基础上,尝试完善一下,在这里对tokudu兄致以深深的敬意。
参考文章:
1 http://tokudu.com/2010/how-to-implement-push-notifications-for-android/【主参考】
2 http://sourceforge.net/projects/androidpn/
3 http://blog.mediarain.com/2011/03/simple-google-android-c2dm-tutorial-push-notifications-for-android/
4 http://mosquitto.org/download/
5 http://hi.baidu.com/zhu410289616/blog/item/b697f5328b0c405fad4b5f83.html
6 http://blog.csdn.net/joshua_yu/article/details/6563587
7 http://blog.mediarain.com/2011/03/simple-google-android-c2dm-tutorial-push-notifications-for-android/
8 http://www.codeproject.com/Articles/339162/Android-push-notification-implementation-using-ASP
9 http://www.eoeandroid.com/thread-97603-1-1.html
10 https://www14.software.ibm.com/webapp/iwm/web/reg/acceptLogin.do?source=AW-0U9&lang=en_US
11 http://mosquitto.org/
12 https://github.com/tokudu/AndroidPushNotificationsDemo
13 http://code.google.com/intl/zh-CN/android/c2dm/
14 http://stackoverflow.com/questions/1378671/push-notifications-in-android-platform
15 http://dalelane.co.uk/blog/?p=938
16 http://mqtt.org/
17 http://stackoverflow.com/questions/1243066/does-android-support-near-real-time-push-notification
18 http://www.chengyunfeng.com/2010/09/android-push-notification
19 http://www.airpush.com/
-END-
构建Android Push Notification Service服务端及客户端相关推荐
- axis idea 设置apache_利用IDEA创建Web Service服务端和客户端的详细过程
创建服务端 一.file–>new–>project 二.点击next后输入服务端名,点击finish,生成目录如下 三.在 HelloWorld.Java 文件中右击,选 WebServ ...
- Linux下用gSOAP开发Web Service服务端和客户端程序(一)
1.功能说明: 要开发的Web Service功能非常简单,就是一个add函数,将两个参数相加,返回其和. 2.C版本的程序: (1)头文件:SmsWBS.h,注释部分不可少,url部分的IP必须填写 ...
- Apple Push Notification Service(苹果推送服务)
https://developer.apple.com/library/IOS/documentation/NetworkingInternet/Conceptual/RemoteNotificati ...
- Android 学习笔记 Service服务与远程通信...(AIDL)
PS:这一章节看的我有几分迷茫,不是很容易理解...不过还好总算是明白了一大半了...基本的迷惑是解决了... 学习内容: 1.跨应用启动服务... 2.跨应用绑定服务... 3.跨应用实现通信... ...
- ssr Android简书,Vue 服务端渲染(SSR)
什么是服务端渲染,简单理解是将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序.于传统的SPA(单页应用)相比,服务端渲染 ...
- 使用axis开发web service服务端
一.axis环境搭建 1.安装环境 JDK.Tomcat或Resin.eclipse等. 2.到 http://www.apache.org/dyn/closer.cgi/ws/axis/1_4 下载 ...
- windos未能链接服务器,提示Windows没法连接到System Event Notification Service服务
是win7吗?百度来的,您试试! Windows7系统无法连接到System Event Notification Service服务的解决方法 第一步: 点击开始,在搜索栏中输入CMD,右键点击程序 ...
- w ndows无法连接到System,Windows无法连接到System Event Notification Service服务解决方法...
采用windows7操作系统的电脑在开机时提示"Windows 无法连接到 System Event Notification Service 服务"(如下图)的解决方法: 操作系 ...
- w ndows无法连接到System,电脑无法连接到System Event Notification Service服务
很多用户表示,在使用电脑的时候,电脑右下角任务栏提示"未能连接一个Windows服务,Windows无法连接到System Event Notification Service服务" ...
- Android:在同一WiFi下通讯(局域网下服务端和客户端通讯)
看了几天的Android WiFi通讯,总结一下,并附相关Demo(也是仿网上做的),建议收藏 两台设备(手机与手机,手机与硬件都一样)在同一WiFi下通讯,用的是TCP/IP协议,那我们应如 ...
最新文章
- layui与eazyui的区别_jquery easyui和layui的区别是什么?
- 数学基础学习随笔--序言
- 【软考】 2019年上半年软件设计师考试上午真题(专业解析+参考答案)
- 使用systemctl设置tomcat开机自启动
- MapReduce-Combiner规约-原理分析
- Spring 基于 Java 的配置
- 英伟达3060Ti安装GPU版本TensorFlow2.X
- win7系统cocos2dx 3.4 绑定自定义类到Lua
- 云中数据_简化云中的应用程序开发
- Docker系列(二):Docker安装
- springbank 开发日志 springbank是如何执行一个handler的requestMapping对应的方法的
- [Excel函数] 逻辑判断函数
- 微商推广引流秘笈—— 8 个高效的引流策略
- pyecharts(9)-动态可视化-树形图-思维导图
- Astah 7.2 安装
- 水星mac1300r虚拟服务器,水星(MERCURY)MAC1300R路由器用手机怎么设置?
- 【动画图解微积分笔记】 (一) -1.概述 (附B站视频)
- 可敬可悲硅谷人 科技富豪失乐园
- PDM信号与PCM信号
- mysql varchar(n) n表示字符个数
热门文章
- Gym - 101808K Another Shortest Path Problem (Damascus University Collegiate)【并查集+LCA】
- html手写笔记照片,html手写代码学习笔记
- 计算机屏幕方向变化,知识:如何切换笔记本电脑屏幕的方向_计算机的基本知识_IT /计算机_信息...
- python另存为excel_python 将数据保存为excel的xls格式(实例讲解)
- 安徽汽车网程序员删库跑路?安徽汽车官网只剩3张图片!
- 标准二维表问题 (卡特兰数)
- 数据库中的主键、超键、候选键、外键
- pcr mix试剂选购相关问题
- Android音量系统分析
- 工业镜头的主要参数与选型