新建一个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和WakeLock的操作步骤
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);通过 Context.getSystemService().方法获取PowerManager实例。
  2. 然后通过PowerManager的newWakeLock((int flags, String tag)来生成WakeLock实例。int Flags指示要获取哪种WakeLock,不同的Lock对cpu 、屏幕、键盘灯有不同影响。
  3. 获取WakeLock实例后通过acquire()获取相应的锁,然后进行其他业务逻辑的操作,最后使用release()释放(释放是必须的)。

关于int flags

  各种锁的类型对CPU 、屏幕、键盘的影响:

  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定期执行工作的更多相关文章

  1. crontab 设置服务器定期执行备份工作

    基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示0点) 第3列表示日期1-31 第4列表示 ...

  2. Linux下设置定期执行脚本

    下面针对的是非ubuntu环境,会在文章末尾介绍ubuntu的一些区别. 在Linux下,经常需要定期的执行一些脚本从而来实现一些功能. 在Linux下我们用crontab来实现定期的执行脚本这个功能 ...

  3. 如何利用Cron让django应用定期执行

    最近用Django写了一个项目,但是有一个地方需要应用在后台自动定期执行检查,并存入数据库,如果单纯的写Python程序的话不能很好的跟django的结合在一起,写起来也和麻烦,查找资料的时候发现了d ...

  4. LINUX 命令定期执行可执行文件

    linux命令将nodejs文件变成可执行文件 在linux中一般我们在运行node文件时用的命令为: node example.js 首先.删除文件后缀,在linux命令下添加可执行权限 mv ex ...

  5. 如何让django方法自动地定期执行

    实现思路:1.首先把需要自动执行的django method写成django command2.将自己定义的django command添加到cron中使用cron服务实现定期执行 Part1 在dj ...

  6. C#制作Windows service服务系列二:演示一个定期执行的windows服务及调试(windows service)

    系列一: 制作一个可安装.可启动.可停止.可卸载的Windows service(downmoon原创) 系列二:演示一个定期执行的windows服务及调试(windows service)(down ...

  7. django定期执行任务

    要在django项目中定期执行任务,比如每天一定的时间点抓取数据,刷新数据库等,可以参考stackoverflow的方法,先编写一个manage.py命令,然后使用crontab来定时执行这个命令. ...

  8. mac corntab定期执行任务

    mac corntab定期执行任务 crontab中的每一行代表一个定期执行的任务,分为6个部分.前5个部分表示何时执行命令,最后一个部分表示执行的命令.每个部分以空格分隔,除了最后一个部分(命令)可 ...

  9. Linux crontab定时器设置(定期执行java程序)(转)

    Crontab 语法 Crontab语法一个crontab文件用五个段来定义:天,日期和时间,和一个要定期执行的命令代码. *    *  *  *   *  command to be execut ...

随机推荐

  1. C语言学习笔记--单引号和双引号

    (1)C 语言中单引号用来表示字符字面量(是个数值)被编译为对应的 ASCII 码 (2)C 语言中双引号用来表示字符串字面量(是个指针)被编译为对应的内存地址 例如:'a'表示字符字面量(97),在 ...

  2. 微信小程序--录制音频,播放音频

    1.在pages创建一个main文件夹2.在main文件夹下创建一个miain.js文件.添加代码: const constant = require('../../utils/constant.js ...

  3. 由hibernate配置cascade而导致的软件错误,并分析解决此问题的过程

    本文与上一篇文章的软件背景相同,是一个安装部署的工具,这个工具会生成整套系统部署用的xml文件. 这个工具中有一个“克隆”功能,当安装包有新版本后,可以克隆之前的xml版本,并在其基础上做少许修改来适 ...

  4. p3627&bzoj1179 抢掠计划(ATM)

    传送门(洛谷) 传送门(bzoj) 题目 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruser i 银行的 ATM 取款机.令人奇怪的 ...

  5. 【机器学习】关联规则挖掘(二):频繁模式树FP-growth

    Apriori算法的一个主要瓶颈在于,为了获得较长的频繁模式,需要生成大量的候选短频繁模式.FP-Growth算法是针对这个瓶颈提出来的全新的一种算法模式.目前,在数据挖掘领域,Apriori和FP- ...

  6. JsonParse类

    using System.Data; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using Syst ...

  7. linux下编译Boost库

    下载源码 boost_1_66_0.tar.gz 生成编译工具 # tar axf boost_1_66_0.tar.gz # cd boost_1_66_0 # yum install gcc gc ...

  8. shell脚本知识点汇总

    sed中在对内容进行修改时,有时候需要引用外部变量的值或者获取一个shell命令执行的结果,以便达到更加可观的输出结果 1.sed中使用变量替换1)sed命令使用双引号的情况下,使用$var直接引用[ ...

  9. C++的STL总结(1)

    没有很系统的学过算法,c++也只是学些基础,虽然经常会用一些STL里面的函数,但是并没有对STL模板库有一个清晰的了解,趁着寒假有时间就自己在网上百度浏览别人的总结的内容,自己汇集并总结了一下,希望对 ...

  10. eros --- Windows Android真机调试

    1.下载并安装JDK 2.下载并安装Android Studio 上面两项不管用weex还是eros都是前置条件,度娘有大量教程. 开始eros 手脚架安装: $ npm i -g eros-cli ...