定时AlarmManager循环执行后台任务和多个定时循环后台任务写在一起

定时循环执行某些任务,在开发中是很常见的一种方式,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表示执行第一个定时任务 23同理 ;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,但是不影响整体实现的思路,如发现有误,欢迎指出来,如果其他大神还有一些比较好的方法,期待一起交流进步。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值