定时循环执行某些任务,在开发中是很常见的一种方式,Android中有两种定时器可以实现,一种是Alarm,另一种是AlarmManager,Alarm在Android4.4以后,这种方式的定时器不太准确,Android官方为了优化手机电池使用时间,将多个差不多时间差的Alarm定时器放在一起执行,导致部分计时器先执行或者或执行。相比于Alarm,AlarmManager是准确执行的。所以这里我们不考虑Alarm定时器,以AlarmManager作为示例。
1. 创建一个定时循环任务(定时循环后台任务创建挺简单的,主要是多个定时循环会有些麻烦),按照惯例,先直接上代码。
- 首先创建一个界面TimeTask.java,直观地显示出后台的运行信息。
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.example.mrc.csdndemo.R;
public class TimeTask extends AppCompatActivity implements View.OnClickListener {
Button mOpenBtn ,mCloseBtn ,mOpenMoreBtn ,mCloseMoreBtn;
Intent mOneIntent = null ;
Intent mMoreIntent =null;
TimeTaskService timeTaskService ;
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time_task);
/*sharedPreferences =getApplicationContext().getSharedPreferences("com.example.mrc.csdnDemo" , 0);
editor=sharedPreferences.edit();
editor.putInt("count",0);
editor.commit();*/
findView();
Init();
}
void findView(){
mOpenBtn = (Button)findViewById(R.id.open_time_task);
mCloseBtn = (Button)findViewById(R.id.close_time_task);
mOpenMoreBtn = (Button)findViewById(R.id.open_more_time_task);
mCloseMoreBtn = (Button)findViewById(R.id.close_more_time_task);
mOpenBtn.setOnClickListener(this);
mCloseBtn.setOnClickListener(this);
mOpenMoreBtn.setOnClickListener(this);
mCloseMoreBtn.setOnClickListener(this);
}
void Init(){
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.open_time_task :
mOneIntent =new Intent(this ,TimeTaskService.class) ;
/*mOneIntent.setAction("ITOP.MOBILE.SIMPLE.SERVICE.SENSORSERVICE");*/
startService(mOneIntent);
break;
case R.id.close_time_task :
Intent intentOneStop = new Intent(this, TimeTaskService.class);
/*Intent intent =new Intent();*/
/* intent.setAction("ITOP.MOBILE.SIMPLE.SERVICE.SENSORSERVICE");*/ //android5.0以下才适合使用
stopService(intentOneStop);
break;
case R.id.open_more_time_task :
mMoreIntent =new Intent(this ,MoreTimeTaskService.class) ;
/*mOneIntent.setAction("ITOP.MOBILE.SIMPLE.SERVICE.SENSORSERVICE");*/
startService(mMoreIntent);
break;
case R.id.close_more_time_task :
Intent intentMoreStop = new Intent(this, MoreTimeTaskService.class);
/*Intent intentMoreStop =new Intent();*/
/* intent.setAction("ITOP.MOBILE.SIMPLE.SERVICE.SENSORSERVICE");*/ //android5.0以下才适合使用
stopService(intentMoreStop);
break;
default:break;
}
}
}
- 相对应的activity_time_task.xml布局
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mrc.csdndemo.BackgroundTimeTask.TimeTask">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center">
<Button
android:id="@+id/open_time_task"
android:layout_gravity="center_horizontal"
android:layout_width="240dp"
android:layout_height="48dp"
android:text="打开一个定时任务"
android:background="@drawable/button_style"
android:textSize="17sp"
android:textColor="@color/text_white"
android:layout_marginTop="16dp"/>
<Button
android:id="@+id/close_time_task"
android:layout_gravity="center_horizontal"
android:layout_width="240dp"
android:layout_height="48dp"
android:text="关闭一个定时任务"
android:background="@drawable/button_style"
android:textSize="17sp"
android:textColor="@color/text_white"
android:layout_marginTop="16dp"/>
<Button
android:id="@+id/open_more_time_task"
android:layout_gravity="center_horizontal"
android:layout_width="240dp"
android:layout_height="48dp"
android:text="打开多个定时任务"
android:background="@drawable/button_style"
android:textSize="17sp"
android:textColor="@color/text_white"
android:layout_marginTop="16dp"/>
<Button
android:id="@+id/close_more_time_task"
android:layout_gravity="center_horizontal"
android:layout_width="240dp"
android:layout_height="48dp"
android:text="关闭多个定时任务"
android:background="@drawable/button_style"
android:textSize="17sp"
android:textColor="@color/text_white"
android:layout_marginTop="16dp"/>
</LinearLayout>
</ScrollView>
界面效果如下:
- 以上都不用解释,相信都能看懂,接下来创建后台服务的事情
创建一个后台服务:TimeTaskService.java ,这个服务在没有特殊情况下是不会关闭的
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.util.Calendar;
public class TimeTaskService extends Service {
private static final int INTERVAL_TIME = 10 ;
AlarmManager alarmManager ;
PendingIntent pIntent ;
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
Calendar mCalendar ;
public TimeTaskService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sharedPreferences =getApplicationContext().getSharedPreferences("com.example.mrc.csdnDemo" , 0);
sharedPreferences.edit();
//这里模拟后台操作
Handler handler=new Handler(Looper.getMainLooper());
handler.post(new Runnable(){
public void run(){
int count =sharedPreferences.getInt("count" ,0);
count ++ ;
Log.e("messages","循环执行了"+ count +"次定时任务,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"循环执行了"+ count +"次定时任务,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("count" ,count);
editor.commit();
}
});
mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(System.currentTimeMillis());
mCalendar.add(Calendar.SECOND, INTERVAL_TIME);
//通过AlarmManager定时启动广播
alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntent=new Intent(this, AlarmReceiver.class);
pIntent=PendingIntent.getBroadcast(this,0,timeTaskIntent ,PendingIntent.FLAG_CANCEL_CURRENT);
int apiLevel = getApiLevel();
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME, pIntent);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntent);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntent);
Log.d("api>23", "setExactAlarmCompat ");
}
return super.onStartCommand(intent, flags, startId);
}
public static int getApiLevel() {
try {
Field f = Build.VERSION.class.getField("SDK_INT");
f.setAccessible(true);
return f.getInt(null);
} catch (Throwable e) {
return 3;
}
}
@Override
public void onDestroy(){
alarmManager.cancel(pIntent);
Handler handler=new Handler(Looper.getMainLooper());
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext() ,"停止后台循环任务,停止执行时间为:"
+ System.currentTimeMillis() , Toast.LENGTH_LONG ).show();
}
});
Log.e("messages","停止后台循环任务,停止执行时间为:"+ System.currentTimeMillis());
}
}
这是创建一个定时后台服务的主要代码:
mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(System.currentTimeMillis());
mCalendar.add(Calendar.SECOND, INTERVAL_TIME);
//通过AlarmManager定时启动广播
alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntent=new Intent(this, AlarmReceiver.class);
pIntent=PendingIntent.getBroadcast(this,0,timeTaskIntent ,PendingIntent.FLAG_CANCEL_CURRENT);
int apiLevel = getApiLevel();
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME, pIntent);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntent);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntent);
Log.d("api>23", "setExactAlarmCompat ");
}
AlarmManager是一个定时器,在不同的Android版本里AlarmManager的执行方法也不同,具体看代码。 PendingIntent是一个即将执行的意图,和Intent的最主要的区别是PendingIntent是即将执行的,Intent是立即执行的,怎么解释呢,就是PendingIntent是等待某些信号才执行一般配合AlarmManager或者Alarm等一起使用。PendingIntent的使用方法和Intent也有很大差异。在PendingIntent里还嵌入一个Intent,这才是真正的意图。
- 执行TimeTaskService服务后,会跳转到一个广播类,广播类会定时回调TimeTaskService服务,这样就做到定时循环执行的效果。其实挺简单的。下面是AlarmReceiver.java广播类的代码:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
public class AlarmReceiver extends BroadcastReceiver {
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, TimeTaskService.class);
context.startService(i);
}
}
仔细看代码,感觉也不是很难,这种定时后台任务其实很常用,学一学没什么弊端。
2.定时循环执行多个任务(这里指的是在一个后台服务里执行定时间隔都不一样的任务,这要解决如何知道执行了哪一个定时任务,又不影响其他定时任务的问题,当然,创建多个服务和广播类也可以实现,但是博主比较死心眼,就想在一个服务Service里把所有需求实现。后来通过不断摸索,最终实现了),按照惯例,先献上代码:
- 界面的实现和上面一致,这里就不多说了,直接说后台服务。创建MoreTimeTaskService.java服务,代码如下:
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.Service;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.util.Calendar;
public class MoreTimeTaskService extends Service {
private static final int INTERVAL_TIME_ONE = 10 ;
private static final int INTERVAL_TIME_TWO = 15 ;
private static final int INTERVAL_TIME_THREE = 20 ;
AlarmManager mAlarmManagerOne;
AlarmManager mAlarmManagerTwo;
AlarmManager mAlarmManagerThree;
PendingIntent pIntentOne ;
PendingIntent pIntentTwo ;
PendingIntent pIntentThree ;
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
Calendar mCalendar ;
public MoreTimeTaskService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sharedPreferences =getApplicationContext().getSharedPreferences("com.example.mrc.csdnDemo" , 0);
sharedPreferences.edit();
int type = sharedPreferences.getInt("type" ,0);
//1表示执行第一个定时任务 2,3同理 ;0表示未执行,则三个一起执行
mCalendar = Calendar.getInstance();
mCalendar.setTimeInMillis(System.currentTimeMillis());
int apiLevel = getApiLevel();
//这里模拟后台操作
if(type ==0){
Handler handlerOne=new Handler(Looper.getMainLooper());
handlerOne.post(new Runnable(){
public void run(){
int countOne =sharedPreferences.getInt("countOne" ,0);
countOne ++ ;
Log.e("messages","第1个定时任务循环执行了"+ countOne +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第1个定时任务循环执行了"+ countOne +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countOne" ,countOne);
editor.commit();
}
});
Handler handlerTwo=new Handler(Looper.getMainLooper());
handlerTwo.post(new Runnable(){
public void run(){
int countTwo =sharedPreferences.getInt("countTwo" ,0);
countTwo ++ ;
Log.e("messages","第2个定时任务循环执行了"+ countTwo +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第2个定时任务循环执行了"+ countTwo +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countTwo" ,countTwo);
editor.commit();
}
});
Handler handlerThree=new Handler(Looper.getMainLooper());
handlerThree.post(new Runnable(){
public void run(){
int countThree =sharedPreferences.getInt("countThree" ,0);
countThree ++ ;
Log.e("messages","第3个定时任务循环执行了"+ countThree +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第3个定时任务循环执行了"+ countThree +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countThree" ,countThree);
editor.commit();
}
});
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_ONE);
//通过AlarmManager定时启动广播
mAlarmManagerOne= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentOne=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentOne.putExtra("type" ,1);
pIntentOne=PendingIntent.getBroadcast(this,1,timeTaskIntentOne ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerOne.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_ONE, pIntentOne);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerOne.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentOne);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerOne.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentOne);
Log.d("api>23", "setExactAlarmCompat ");
}
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_TWO);
//通过AlarmManager定时启动广播
mAlarmManagerTwo= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentTwo=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentTwo.putExtra("type" ,2) ;
pIntentTwo=PendingIntent.getBroadcast(this,2,timeTaskIntentTwo ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerTwo.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_TWO, pIntentTwo);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerTwo.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentTwo);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerTwo.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentTwo);
Log.d("api>23", "setExactAlarmCompat ");
}
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_THREE);
//通过AlarmManager定时启动广播
mAlarmManagerThree= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentThree=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentThree.putExtra("type" ,3) ;
pIntentThree=PendingIntent.getBroadcast(this,3,timeTaskIntentThree ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerThree.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_THREE, pIntentThree);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerThree.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentThree);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerThree.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentThree);
Log.d("api>23", "setExactAlarmCompat ");
}
} else if(type ==1){
Handler handlerOne=new Handler(Looper.getMainLooper());
handlerOne.post(new Runnable(){
public void run(){
int countOne =sharedPreferences.getInt("countOne" ,0);
countOne ++ ;
Log.e("messages","第1个定时任务循环执行了"+ countOne +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第1个定时任务循环执行了"+ countOne +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countOne" ,countOne);
editor.commit();
}
});
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_ONE);
//通过AlarmManager定时启动广播
mAlarmManagerOne= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentOne=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentOne.putExtra("type" ,1);
pIntentOne=PendingIntent.getBroadcast(this,1,timeTaskIntentOne ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerOne.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_ONE, pIntentOne);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerOne.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentOne);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerOne.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentOne);
Log.d("api>23", "setExactAlarmCompat ");
}
}else if(type ==2){
Handler handlerTwo=new Handler(Looper.getMainLooper());
handlerTwo.post(new Runnable(){
public void run(){
int countTwo =sharedPreferences.getInt("countTwo" ,0);
countTwo ++ ;
Log.e("messages","第2个定时任务循环执行了"+ countTwo +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第2个定时任务循环执行了"+ countTwo +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countTwo" ,countTwo);
editor.commit();
}
});
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_TWO);
//通过AlarmManager定时启动广播
mAlarmManagerTwo= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentTwo=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentTwo.putExtra("type" ,2);
pIntentTwo=PendingIntent.getBroadcast(this,2,timeTaskIntentTwo ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerTwo.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_TWO, pIntentTwo);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerTwo.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentTwo);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerTwo.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentTwo);
Log.d("api>23", "setExactAlarmCompat ");
}
}else if(type ==3){
Handler handlerThree=new Handler(Looper.getMainLooper());
handlerThree.post(new Runnable(){
public void run(){
int countThree =sharedPreferences.getInt("countThree" ,0);
countThree ++ ;
Log.e("messages","第3个定时任务循环执行了"+ countThree +"次,执行时间为:"+ System.currentTimeMillis());
Toast.makeText(getApplicationContext() ,"第3个定时任务循环执行了"+ countThree +"次,执行时间为:"+ System.currentTimeMillis() ,Toast.LENGTH_LONG).show();
editor = sharedPreferences.edit();
editor.putInt("countThree" ,countThree);
editor.commit();
}
});
mCalendar.add(Calendar.SECOND, INTERVAL_TIME_THREE);
//通过AlarmManager定时启动广播
mAlarmManagerThree= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent timeTaskIntentThree=new Intent(this, MoreAlarmReceiver.class);
timeTaskIntentThree.putExtra("type" ,3);
pIntentThree=PendingIntent.getBroadcast(this,3,timeTaskIntentThree ,PendingIntent.FLAG_CANCEL_CURRENT);
if (apiLevel < Build.VERSION_CODES.KITKAT) {
Log.d("api<19", "setExactAlarmCompat ");
mAlarmManagerThree.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), INTERVAL_TIME_THREE, pIntentThree);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManagerThree.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentThree);
}
Log.d("19<api<23", "setExactAlarmCompat ");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManagerThree.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pIntentThree);
Log.d("api>23", "setExactAlarmCompat ");
}
}
return super.onStartCommand(intent, flags, startId);
}
public static int getApiLevel() {
try {
Field f = Build.VERSION.class.getField("SDK_INT");
f.setAccessible(true);
return f.getInt(null);
} catch (Throwable e) {
return 3;
}
}
@Override
public void onDestroy(){
Handler handler=new Handler(Looper.getMainLooper());
handler.post(new Runnable(){
public void run() {
mAlarmManagerOne.cancel(pIntentOne);
Toast.makeText(getApplicationContext() ,"停止了第1个后台循环任务,停止执行时间为:"
+ System.currentTimeMillis() , Toast.LENGTH_LONG ).show();
mAlarmManagerTwo.cancel(pIntentTwo);
Toast.makeText(getApplicationContext() ,"停止了第2个后台循环任务,停止执行时间为:"
+ System.currentTimeMillis() , Toast.LENGTH_LONG ).show();
mAlarmManagerThree.cancel(pIntentThree);
Toast.makeText(getApplicationContext() ,"停止了第3个后台循环任务,停止执行时间为:"
+ System.currentTimeMillis() , Toast.LENGTH_LONG ).show();
}
});
editor.putInt("type" ,0) ;
editor.commit();
Log.e("messages","停止后台循环任务,停止执行时间为:"+ System.currentTimeMillis());
}
}
- 同样的,也创建一个广播类MoreAlarmReceiver.java ,代码如下:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
public class MoreAlarmReceiver extends BroadcastReceiver {
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
@Override
public void onReceive(Context context, Intent intent) {
int type =intent.getIntExtra("type" ,0) ;
Log.e("cqx" ,type+"");
sharedPreferences =context.getSharedPreferences("com.example.mrc.csdnDemo" , 0);
editor =sharedPreferences.edit();
sharedPreferences.edit();
if(type ==1){
editor.putInt("type" ,1);
editor.commit();
}else if(type ==2){
editor.putInt("type" ,2);
editor.commit();
}else if(type ==3){
editor.putInt("type" ,3);
editor.commit();
}else {
editor.putInt("type" ,0);
editor.commit();
}
Intent i = new Intent(context, MoreTimeTaskService.class);
context.startService(i);
}
}
博主是通过SharedPreferences和Intent之间的传值告诉服务那个定时任务到点了,应该执行与之相关的代码,并且再一次设置这个任务的定时器AlarmManager,从而实现不同定时任务之间的互不干扰。一开始对PendingIntent不熟悉,导致不同的定时任务出现混乱,后来发现对PendingIntent.getBroadcast(context,requestCode,Intent,FLAG)这个方法理解不够深入,创建多个PendingIntent时 ,requestCode需要设置不同的值,才能区分它们,一开始博主把每一个PendingIntent的requestCode都设置为0,发现只是执行了定时时间最短的那个任务,其他的定时任务都被覆盖掉,这个问题花了一天多的时间才找到,挺折磨人的小问题,有容易被忽视,这里指出来希望其他人不要犯同样的错误。
注释:代码中可能存在一些bug,但是不影响整体实现的思路,如发现有误,欢迎指出来,如果其他大神还有一些比较好的方法,期待一起交流进步。