在消息的获取上是选择 轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了。但如果只是一般的消息检测比如 更新检查,可能是半个小时或一个小时一次,那用轮询也是一个不错的选择,因为不需要额外搭建推送服务器,不用额外配置推送服务。另外推送现在一般以维持长 连接的方式实现,在手机客户端也会耗费一定的电量。今天就介绍一个在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, ,
intent, PendingIntent.FLAG_UPDATE_CURRENT); //触发服务的起始时间
long triggerAtTime = SystemClock.elapsedRealtime(); //使用AlarmManger的setRepeating方法设置定期执行的时间间隔(seconds秒)和需要执行的Service
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime,
seconds * , 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, ,
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, , i,
Intent.FLAG_ACTIVITY_NEW_TASK);
mNotification.setLatestEventInfo(this,
getResources().getString(R.string.app_name), "You have new message!", pendingIntent);
mManager.notify(, mNotification);
} /**
* Polling thread
* 模拟向Server轮询的异步线程
* @Author Ryan
* @Create 2013-7-13 上午10:18:34
*/
int count = ;
class PollingThread extends Thread {
@Override
public void run() {
System.out.println("Polling...");
count ++;
//当计数能被5整除时弹出通知
if (count % == ) {
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, , 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

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. nginx 配置轮询服务

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

  7. Android 轮询之 Service + AlarmManager+Thread (转)

    android中涉及到将服务器中数据变化信息通知用户一般有两种办法,推送和轮询. 消息推送是服务端主动发消息给客户端,因为第一时间知道数据发生变化的是服务器自己,所以推送的优势是实时性高.但服务器主动 ...

  8. 三周,用长轮询实现Chat并迁移到Azure测试

    公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都花在这上面了.简单地说就是用MVC4基于长 ...

  9. polling轮询和comet

    comet:(原意:彗星) Comet is a web application model in which a long-held(held:保留) HTTP request allows a w ...

随机推荐

  1. 黑白图像(DFS)

    输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数.如果两个黑格子有公共边或者公共顶点,就说它们属于同一个八连块.如图6-11所示的图形有3个八连块. 图6-11  拥有3 ...

  2. 在 Java 中高效使用锁的技巧--转载

    竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...

  3. 转载:C#中事件的由来

    原文地址 http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx 感谢博主分享! 我们继续思考转 ...

  4. css font的简写规则

    font的属性简写里面常用的有5个是可以写在一起的: font-style设定斜体 如:font-style: italic;font-weight设定文字粗细 如:font-weight: bold ...

  5. 学习CSS一些事(下)

    2.浮动(float) 浮动(float)特点:1.元素会左移.右移,直到触碰到容器为止.    2.设置浮动元素,仍旧处于标准文档流. 3.当元素没有设置宽度值,而设置了浮动属性,元素的宽度随着内容 ...

  6. 使用jq深入研究轮播图特性

    网站轮播图 太耳熟的词了  基本上做pc端的 主页绝壁会来一个轮播图的特效 轮播图他一个页面页面的切换,其实的原理是通过css的定位 ,定位到一起,第一张首先显示,其余默认隐藏. 今天我实现的这个轮播 ...

  7. Wpf ListBox数据绑定实例1--绑定字典集合

    1.使用ListBox绑定Dictionary字典数据 ListBox常用事件SelectionChanged private void bindListBox() { Dictionary<s ...

  8. 通过ip地址获取当前地理位置

    1.  使用接口的方式: 这种方式是相对稳定,而且提供的数据相对稳定,提供接口的地方很多,大家可以参照 http://www.hujuntao.com/api/the-ip-address-api-a ...

  9. linux command cp.

    Examples cp file1.txt newdir Copies the file1.txt in the current directory to the newdir subdirector ...

  10. MySQL中对varchar类型排序问题

    在数据库表中有一个对varchar类型的数值进行desc排序,很简单的要求吧.可是奇怪的现象出现了表中的数据不会根据从高到底进行排序了瞬间有点泪奔的感觉呀还好经过高手指点啊.所以想和大家分享一下希望下 ...