在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了。但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一次,那用轮询也是一个不错的选择,因为不需要额外搭建推送服务器,不用额外配置推送服务。另外推送现在一般以维持长连接的方式实现,在手机客户端也会耗费一定的电量。今天就介绍一个在Android上实现轮询机制的方法——使用AlarmManager

AlarmManager在Android中主要用来定时处理一个事件或是定期处理一个事件,比如闹钟应用就是使用AlarmManager来实现的,我们今天要使用AlarmManager的定期执行功能来实现轮询的功能。对于定期执行任务也可以用Timer和TimerTask来实现,也可以开一个Service在Thread里面以while循环来实现。但最好的方案还是选用AlarmManager,这里涉及一个Android系统锁的机制,即系统在检测到一段时间没有活跃以后,会关闭一些不必要的服务来减少资源和电量消耗。使用Timer和Service来实现的话很可能出现的情况就是屏幕熄灭后一段时间,服务就被停止了,当然轮询也就被停止了。这个大家可以实验一下,之前我写过一篇文章也介绍了一种保持后台唤醒的机制《使用WakeLock使Android应用程序保持后台唤醒》,感兴趣的可以看看。那么接下来就开始使用AlarmManager+Service+Thread来实现我们的轮询服务吧!

一、新建轮询工具类PollingUtils.java

public class PollingUtils {

	//开启轮询服务
public static void startPollingService(Context context, int seconds, Class<?> cls,String action) {
//获取AlarmManager系统服务
AlarmManager manager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE); //包装需要执行Service的Intent
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT); //触发服务的起始时间
long triggerAtTime = SystemClock.elapsedRealtime(); //使用AlarmManger的setRepeating方法设置定期执行的时间间隔(seconds秒)和需要执行的Service
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime,
seconds * 1000, pendingIntent);
} //停止轮询服务
public static void stopPollingService(Context context, Class<?> cls,String action) {
AlarmManager manager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
//取消正在执行的服务
manager.cancel(pendingIntent);
}
}

二、构建轮询任务执行PollingService.java

public class PollingService extends Service {

	public static final String ACTION = "com.ryantang.service.PollingService";

	private Notification mNotification;
private NotificationManager mManager; @Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public void onCreate() {
initNotifiManager();
} @Override
public void onStart(Intent intent, int startId) {
new PollingThread().start();
} //初始化通知栏配置
private void initNotifiManager() {
mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int icon = R.drawable.ic_launcher;
mNotification = new Notification();
mNotification.icon = icon;
mNotification.tickerText = "New Message";
mNotification.defaults |= Notification.DEFAULT_SOUND;
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
} //弹出Notification
private void showNotification() {
mNotification.when = System.currentTimeMillis();
//Navigator to the new activity when click the notification title
Intent i = new Intent(this, MessageActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i,
Intent.FLAG_ACTIVITY_NEW_TASK);
mNotification.setLatestEventInfo(this,
getResources().getString(R.string.app_name), "You have new message!", pendingIntent);
mManager.notify(0, mNotification);
} /**
* Polling thread
* 模拟向Server轮询的异步线程
* @Author Ryan
* @Create 2013-7-13 上午10:18:34
*/
int count = 0;
class PollingThread extends Thread {
@Override
public void run() {
System.out.println("Polling...");
count ++;
//当计数能被5整除时弹出通知
if (count % 5 == 0) {
showNotification();
System.out.println("New message!");
}
}
} @Override
public void onDestroy() {
super.onDestroy();
System.out.println("Service:onDestroy");
} }

三、在MainActivity.java中开启和停止PollingService

public class MainActivity extends Activity {

	@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Start polling service
System.out.println("Start polling service...");
PollingUtils.startPollingService(this, 5, PollingService.class, PollingService.ACTION);
} @Override
protected void onDestroy() {
super.onDestroy();
//Stop polling service
System.out.println("Stop polling service...");
PollingUtils.stopPollingService(this, PollingService.class, PollingService.ACTION);
} }

四、运行效果

运行工程后可以在控制台输出看到,每隔5s就发出一个通知,退出Activity时,轮询服务就停止了,达到了我们事先期望的效果,并且锁屏后很长一段时间也不会停止服务,因为AlarmManager是系统及服务。Demo效果如下图:

在手机上我们可以看到弹出的通知信息,点击通知则进到消息界面:

                            

当进入消息详情Activity时,顶部状态栏的消息通知就会取消,使用如下方式也可以取消状态栏顶部的消息通知显示:

NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();

以上就实现了使用AlarmManger实现轮询的一种方式,有不足或缺陷的地方欢迎大家留言补充,以上代码只是部分,需要工程源码的同学可以到Github上Clone:https://github.com/tangren03/RTPollingDemo

加入我们的QQ群或微信公众账号请查看:Ryan's zone公众账号及QQ群

同时欢迎关注我的新浪微博和我交流:@唐韧_Ryan

觉得这篇文章对你有用就顶我一下或者点击右下角分享按钮分享给更多的人!

[置顶] Android AlarmManager实现不间断轮询服务的更多相关文章

  1. Android AlarmManager实现不间断轮询服务

    在消息的获取上是选择 轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如 更新检查,可能是半个小时或一个小 ...

  2. Android学习系列(7)--App轮询服务器消息

    这篇文章是android开发人员的必备知识. 1.轮询服务器     一般的应用,定时通知消息可以采用轮询的方法从服务器拿取消息,当然实时消息通知的话,建议采用推送服务.    其中需要注意轮询的频率 ...

  3. 背水一战 Windows 10 (112) - 通知(Badge): application 的 badge 通知, secondary 的 badge 通知, 轮询服务端以更新 badge 通知

    [源码下载] 背水一战 Windows 10 (112) - 通知(Badge): application 的 badge 通知, secondary 的 badge 通知, 轮询服务端以更新 bad ...

  4. 背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知

    [源码下载] 背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知 作者:webabcd 介绍背水一战 Windows 1 ...

  5. 日夕如是寒暑不间,基于Python3+Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_220 定时任务的典型落地场景在各行业中都很普遍,比如支付系统中,支付过程中因为网络或者其他因素导致出现掉单.卡单的情况,账单变成了 ...

  6. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

  7. nginx 配置轮询服务

    通常我们应用nginx做代理时,用到它的轮训服务 #设置轮询名称 upstream zyy{ server 127.0.0.1:8080  #本机的apache服务 } server { listen ...

  8. [置顶] [Android源码分析]inquiry result引起的上层变化分析

    在上一篇文章中,我们详细分析了android是如何解析蓝牙反馈上来的搜索到的设备信息,本文将会继续分析这些信息到了上层之后是如何处理. 8.inquiry result引起的上层变化 我们知道inqu ...

  9. [置顶] Android四大组件之BroadcastReceiver

    Android四大组件之BroadcastReceiver Broadcast Receiver 广播接收器,是一种负责接收广播消息并对消息做出响应的组件,和Service一样并不提供与用户交互的UI ...

随机推荐

  1. ubuntu切换root

    sudo passwd root这个命令是给root用户设定密码.然后su root切换到root用户.

  2. lookupedit清空选择 z

    lookupedit绑定数据,选择以后.怎么点击按钮使lookupedit回到初始位置,即nulltext的值.注意,是点击按钮,不是按默认的CTRL+DELETE. txtKHXX.EditValu ...

  3. 将cocos2dx项目从Visual Studio 迁移到 xcode

    因为Visual Studio和XCode的巨大差异性,一开始选择任何一个IDE,都会有一个迁移的过程,XCode的迁移到Visual Studio相对非常简单,不用再介绍.将项目从Visual St ...

  4. java 多线程同步

    一.synchronized关键字 同步方法 每个对象都包含一把锁(也叫做监视器),它自动称为对象的一部分(不必为此写任何特殊的代码).调用任何synchronized方法时,对象就会被锁定,不可再调 ...

  5. wijmo

    wijmo-5官网 Samples Forums Demos 1.当FlexGrid的单元格中文本过长时显示Tooltip 参考1:angular flexGrid tooltip on every ...

  6. Tachyon框架的Worker心跳及Master高可用性分析

    0 概述 分布式框架中的Master-Slave类型,Slave节点负责工作的具体执行,Master负责任务的分发或者相关元数据的存储等.一般情况下,一个Master节点都会对应多个Slave节点,M ...

  7. sprite常用操作

    ,锚点 锚点就是所有旋转,移动,缩放的参考点.cocos2-x中默认的锚点是中心点.锚点用比例来表示范围为0-,(,)点代表左下点,(,)代表右上点.设置的函数为setAnchorPoint(ccp( ...

  8. 事件委托(event delegation)

    事件委托给我带来的第一印象是,如果可以的话请尝试得经常使用它,性能好! 通过字符串拼接后,并进行DOM插入,不会复制事件,此时需要进行事件委托了!!! 优点 事件委托对于web应用程序的性能有如下几个 ...

  9. 第一百九十三天 how can I 坚持

    我以为我是谁. 你可以记录你今天看了电影 也可以记录你最近在听什么歌 但这都会成为回忆 .  ---oncelife 快受不了了啊.咋办. 今天看了<滚蛋吧,肿瘤君>,还看了<那山那 ...

  10. 【多线程】Java并发编程:并发容器之CopyOnWriteArrayList(转载)

    原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容 ...