使用AlarmManager定期执行工作
新建一个Service来模拟后台执行的程序,PollingService.java:
package com.ryantang.rtpollingdemo; import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
/**
* Polling service
* @Author Ryan
* @Create 2013-7-13 涓婂崍10:18:44
*/
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");
} }
别望了在AndroidManifest.xml中注册Service:
<service android:name="com.ryantang.rtpollingdemo.PollingService">
<intent-filter>
<action android:name="com.ryantang.service.PollingService"/>
</intent-filter>
</service>
当计数能被5整除时弹出通知,点击通知后进入MessageActivity.java:
package com.ryantang.rtpollingdemo; import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle; public class MessageActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
System.out.println("新的activity");
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.cancelAll();
}
}
使用AlarmManager封装已给PollingUtils.java来执行Service的启动和停止,PollingUtils.java:
package com.ryantang.rtpollingdemo; import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
/**
* Polling Tools
* @Author Ryan
* @Create 2013-7-13 涓婂崍10:14:43
*/
public class PollingUtils { /**开启轮询服务
* @param context
* @param seconds 定期执行的时间间隔
* @param cls
* @param action
*/
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();
//使用AlarmManager的setRepeating方法设置定期执行时间间隔(seconds秒)和需要执行的Service
manager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime,
seconds * 1000, pendingIntent);//第二个参数与第一个参数有对应的关系,ELAPSED_REALTIME对应的为SystemClock.elapsedRealTime,RTC对应的为System.currentTimeMills()
} /**
* 停止轮询服务
* @param context
* @param cls
* @param action
*/
public static void stopPollingService(Context context, Class<?> cls,String action) {
//获取AlarmManager系统服务
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, cls);
intent.setAction(action);//需要与启动的action一致,负责无法取消定时任务
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
//取消正在执行的服务
manager.cancel(pendingIntent);
}
}
最后在主程序中执行,MainActivity.java:
package com.ryantang.rtpollingdemo; import android.app.Activity;
import android.os.Bundle; 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, 30, PollingService.class,PollingService.ACTION);// PollingService.ACTION与AndroidManifest.xml一一对应
} @Override
protected void onDestroy() {
super.onDestroy();
// Stop polling service
System.out.println("Stop polling service...");
PollingUtils.stopPollingService(this, PollingService.class,PollingService.ACTION);
} }
Android之AlarmManager(全局定时器/闹钟)指定时长或以周期形式执行某项操作
(1)在指定时长后执行某项操作
//操作:发送一个广播,广播接收后Toast提示定时操作完成
Intent intent =new Intent(Main.this, alarmreceiver.class);
intent.setAction("short");
PendingIntent sender=
PendingIntent.getBroadcast(Main.this, 0, intent, 0); //设定一个五秒后的时间
Calendar calendar=Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 5); AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
//或者以下面方式简化
//alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+5*1000, sender);
//注意:receiver记得在manifest.xml注册,使用的是静态的广播消息机制
public static class alarmreceiver extends BroadcastReceiver{ @Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(intent.getAction().equals("short")){
Toast.makeText(context, "short alarm", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(context, "repeating alarm",Toast.LENGTH_LONG).show();
}
}
}
//AndroidManifest.xml中需要注册广播接收器
<receiver android:name="" >
<intent-filter >
<action android:name="short"><action />
</intent-filter>
</receiver>
AlarmManager类型如下:
AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。
AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发射时唤醒手机休眠;
AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒手机休眠;在指定的延时过后,发送广播,但不唤醒设备。
AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,当闹钟发射时唤醒手机休眠;
RTC闹钟和ELAPSED_REALTIME最大的差别就是前者可以通过修改手机时间触发闹钟事件,后者要通过真实时间的流逝,即使在休眠状态,时间也会被计算。
(2)周期性的执行某项操作
Intent intent =new Intent(Main.this, alarmreceiver.class);
intent.setAction("repeating");
PendingIntent sender=PendingIntent
.getBroadcast(Main.this, 0, intent, 0);
//开始时间
long firstime=SystemClock.elapsedRealtime();
AlarmManager am=(AlarmManager)getSystemService(ALARM_SERVICE);
//5秒一个周期,不停的发送广播
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstime, 5*1000, sender);
AlarmManager的setRepeating()相当于Timer的Schedule(task,delay,peroid);有点差异的地方时Timer这个方法是指定延迟多长时间以后开始周期性的执行task;
AlarmManager的取消:(其中需要注意的是取消的Intent必须与启动Intent保持绝对一致才能支持取消
Intent intent =new Intent(Main.this, alarmreceiver.class);
intent.setAction("repeating");
PendingIntent sender=PendingIntent
.getBroadcast(Main.this, 0, intent, 0);
AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);
alarm.cancel(sender);
当然还需要写一个静态的广播接收器。
*****************************************2015-09-07 08:21:18***************************************************
周期性执行选用的闹钟类型推荐AlarmManager.RTC_WAKEUP,经测试还是定时时间还是比较准确的,SystemClock.elapsedRealTime()指的的从计算机起始时间1970-1-1算1起,而System.currentTimeMills()指的是系统开机时间算起。
***********************************更新:2015-09-06 08:53:15*******************************************
Android的碎片化严重,定制的ROM被国内厂商修改了很多,对于定时任务MIUI作为代表,开发者遇到到很多这样的情况,定时任务偏离,多半的原因是考虑到了系统休眠、降低CUP运行效率等等以达到省电的效果,这里就介绍另一种方法解决:PowerManager.WakeLock来实现要求的功能。
PowerManager:给予控制设备电量状态的权限
PowerManager.WakeLock:让系统知道你需要设置在工作状态上
Android中通过各种Lock锁对电源进行控制,需要注意的是加锁和解锁必须成对出现
首先获取权限:
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DEVICE_POWER"/>
有时候Eclipse会提示系统应用才能需要这个权限,解决的办法是将项目Clean下即可。WakeLock的设置是Activity级别的,不是针对整个Application应用的。
package com.eyu.wake_lock; import android.app.Activity;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock; public class Wake_lockActivity extends Activity { private boolean iswakeLock = true;// 是否常亮
private WakeLock wakeLock; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); } @Override
protected void onResume() {
// TODO Auto-generated method stub
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, "DPA"); if (iswakeLock) {
wakeLock.acquire();
}
super.onResume(); } @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onDestroy();
if (wakeLock != null) {
wakeLock.release();
}
android.os.Process.killProcess(android.os.Process.myPid());
} }
通常在onRusume方法中将获得到的锁使用acquire()方法来保持唤醒,在onPause方法中使用release()方法来释放掉该锁,利用Activity的生命周期来巧妙的使这两种方法成对的出现。
- PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);通过
Context.getSystemService()
.方法获取PowerManager实例。 - 然后通过PowerManager的newWakeLock((int flags, String tag)来生成WakeLock实例。int Flags指示要获取哪种WakeLock,不同的Lock对cpu 、屏幕、键盘灯有不同影响。
- 获取WakeLock实例后通过acquire()获取相应的锁,然后进行其他业务逻辑的操作,最后使用release()释放(释放是必须的)。
关于int flags
PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
ACQUIRE_CAUSES_WAKEUP:正常唤醒锁实际上并不打开屏幕,但是,一旦打开就会一直保持。当获得wakelock,这个标志会使屏幕或/和键盘立即打开。一个典型的使用就是可以立即看到那些对用户重要的通知。
ON_AFTER_RELEASE:设置了这个标志,当wakelock释放时用户activity计时器会被重置,导致照明持续一段时间。
***********************************更新:2015-09-15 20:24:29*******************************************
使用AlarmManager就不需要设备锁了,测试过有时候还会导致程序报错,测试手机小米2S,先后试过MIUI、Lewa等第三方Rom,后来刷入Android4.0.3启动定时任务,毫秒不差 。
使用AlarmManager定期执行工作的更多相关文章
- crontab 设置服务器定期执行备份工作
基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示0点) 第3列表示日期1-31 第4列表示 ...
- Linux下设置定期执行脚本
下面针对的是非ubuntu环境,会在文章末尾介绍ubuntu的一些区别. 在Linux下,经常需要定期的执行一些脚本从而来实现一些功能. 在Linux下我们用crontab来实现定期的执行脚本这个功能 ...
- 如何利用Cron让django应用定期执行
最近用Django写了一个项目,但是有一个地方需要应用在后台自动定期执行检查,并存入数据库,如果单纯的写Python程序的话不能很好的跟django的结合在一起,写起来也和麻烦,查找资料的时候发现了d ...
- LINUX 命令定期执行可执行文件
linux命令将nodejs文件变成可执行文件 在linux中一般我们在运行node文件时用的命令为: node example.js 首先.删除文件后缀,在linux命令下添加可执行权限 mv ex ...
- 如何让django方法自动地定期执行
实现思路:1.首先把需要自动执行的django method写成django command2.将自己定义的django command添加到cron中使用cron服务实现定期执行 Part1 在dj ...
- C#制作Windows service服务系列二:演示一个定期执行的windows服务及调试(windows service)
系列一: 制作一个可安装.可启动.可停止.可卸载的Windows service(downmoon原创) 系列二:演示一个定期执行的windows服务及调试(windows service)(down ...
- django定期执行任务
要在django项目中定期执行任务,比如每天一定的时间点抓取数据,刷新数据库等,可以参考stackoverflow的方法,先编写一个manage.py命令,然后使用crontab来定时执行这个命令. ...
- mac corntab定期执行任务
mac corntab定期执行任务 crontab中的每一行代表一个定期执行的任务,分为6个部分.前5个部分表示何时执行命令,最后一个部分表示执行的命令.每个部分以空格分隔,除了最后一个部分(命令)可 ...
- Linux crontab定时器设置(定期执行java程序)(转)
Crontab 语法 Crontab语法一个crontab文件用五个段来定义:天,日期和时间,和一个要定期执行的命令代码. * * * * * command to be execut ...
随机推荐
- shell入门-sed-1
sed这个工具比grep复杂一点,功能比grep复杂一点 功能也能指定匹配的行,不能颜色显示 sed 基础功能 [root@wangshaojun ~]# sed -n '10'p 1.txtuucp ...
- C笔试题(二)
/* 现在有一个数组 我们可以定义数组的子数组 如 数组 1 3 4 2 5 8 7 它的子数组可以是 1 3 4 3 4 2 5 等等 请写一个算法 找一个子数组 这个子数组递增不减少 并且是满足递 ...
- CSS之边距合并
外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距.合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. 情况1:当一个元素出现在另一个元素上面时,第一个元素的下外边距与第二个元 ...
- 同名项目复制,发布新项目,提示已存在该项目于webapp
来自为知笔记(Wiz)
- 树莓派 Learning 002 装机后的必要操作 --- 06 共用键鼠 之 windows和树莓派
树莓派 装机后的必要操作 - 使用Synergy软件 共用键鼠 之 windows和树莓派 我的树莓派型号:Raspberry Pi 2 Model B V1.1 装机系统:NOOBS v1.9.2 ...
- ARC097E Sorted and Sorted
传送门 题目 There are 2N balls, N white and N black, arranged in a row. The integers from 1 through N are ...
- The project was not built since its build path is incomplete. Cannot find the class file for java.lang.Object
The project was not built since its build path is incomplete. Cannot find the class file for java.la ...
- C# 中介者模式
中介者模式 中介者模式,定义了一个中介对象来封装一系列对象之间的交互关系.中介者使各个对象之间不需要显式地相互引用,从而使耦合性降低,而且可以独立地改变它们之间的交互行为. 结构: 中介者模式设计两个 ...
- php5.6安装window7安装memcache.dll库所遇到的误区
问题: window7 64位,下载的库 memcache.dll 为64位的,且对应php的版本.但是重启后phpstudy查看phpinfo依然没有memcache: 根源: 发现是下载的 mem ...
- 【转】C# 使用正则表达式去掉字符串中的数字,或者去掉字符串中的非数字
源地址:http://www.cnblogs.com/94cool/p/4332957.html