android创建定时任务

时代会为你做出选择,不管你是否愿意。

最近的移动端的工作似乎也是到了瓶颈,工作并没有像15-16年那么火爆,貌似市场上出现供过于求的状态,但是没有必要感觉不安,你有着逻辑基础,有着基础能力,闭关几月在去精通一门技术又何妨?

如果你想要飞,就拼力让自己的羽翼丰满,翅膀坚硬,而不只是拥有梦想?

实际上,在开发的过程中,我们经常遇到的情景接收短信验证码?

这时候你可以开启一个线程自己书写逻辑,也可以使用android的创建定时任务功能。

android定时任务有两种:

1:Timer类。

2:Alarm机制。

现在具体说说:

Timer:Timer的使用必须和TimerTask结合在一起,如果不太明白可以百度搜索一下使用方法。

CountDownTimer:表示倒计时任务类,很适合实际开发中的接收验证码倒计时使用。下面就是这个类的使用:因为你CountDownTimer是抽象类,所以必须实现里面的抽象方法

class MyTimer extends CountDownTimer{

/**
* millisInFuture:总时长
* countDownInterval:间隔时长
*/
        public MyTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

/**
* millisUntilFinished 每次执行倒计时一次该方法就会被触发,并返回剩余时长
*/
        @Override
        public void onTick(long millisUntilFinished) {

        }

/**
* 倒计时执行完成的时候触发的动作
*/
        @Override
        public void onFinish() {

        }
    }

Alarm机制:

在网上搜索最多的还是Timer的使用,对于Alarm机制的讲解并不多,但是这里整理一下:

先看一段代码:创建一个10s的定时任务

AlarmManager manager = ((AlarmManager) getSystemService(ALARM_SERVICE));

        int time = 10*1000;

        long triggerAtTime = SystemClock.elapsedRealtime()+time;

        Intent i = new Intent(this,AlarmService.class);

        PendingIntent pendingIntent = PendingIntent.getService(this,0,i,0);

        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);

上面的代码就是 创建定时任务,但是看着有些蒙,下面说说:

1.创建Alarm定时任务,首先需要AlarmManager对象:

AlarmManager manager = ((AlarmManager) getSystemService(ALARM_SERVICE));

2.调用AlarmManager.set()的方法就可以设置定时任务。

set(int type, long triggerAtMillis, PendingIntent operation)

看看set()方法中的三个参数的意义:

type:指定AlarmManager的工作类型,有一下4中可选:

选择类型

解释:

ELAPSED_REALTIME_WAKEUP:定时任务的触发时间从系统开机的时刻开始算起,同时唤醒CPU。

ELAPSED_REALTIME:也是触发时间从系统开机的时刻算起,但是不会唤醒CPU

RTC_WAKEUP:定时任务触发时间从1970年1月1日0点开始算起,同时唤醒CPU

RTC:定时任务触发时间从1970年1月1日0点开始算起,但是不会唤醒CPU

所以对于指定方式的不同,会直接影响第二个参数的计算方式:

triggerAtMillis:如果type的取值为ELAPSED_REALTIME_WAKEUP或者ELAPSED_REALTIME的时候,那么时间使用

 SystemClock.elapsedRealtime()

获取开机至今所经历的毫秒数

如果type的取值为RTC_WAKEUP或者RTC_WAKEU的时候,那么时间使用

 System.currentTimeMillis()

获取1970年1月1日0时至今的时间

operation:是一个PendingIntent广播中有提到的,当到达触发时间时,会自动执行PendingIntenet中的逻辑内容。

那我们现在看看上述的代码,是否能明白写呢?上述代码的意义是 以开机时间为参考,10s之后执行AlarmService的内容。


实践操作:

需求:每隔10s开启一个service的服务操作

创建AlarmService如下:

public class AlarmService extends Service {


    int i = 0;

    AlarmManager manager;

    PendingIntent pendingIntent;

    private static final String TAG = "AlarmService";

    public AlarmService() {

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this,"启动服务",Toast.LENGTH_SHORT).show();
        Log.i(TAG, "onStartCommand: i------>"+i++);

        manager = ((AlarmManager) getSystemService(ALARM_SERVICE));

        int time = 10*1000;

        long triggerAtTime = SystemClock.elapsedRealtime()+time;

        Intent i = new Intent(this,AlarmService.class);

        pendingIntent = PendingIntent.getService(this,0,i,0);

        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);

        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.i(TAG, "onDestroy: AlarmManager is cancle");

        manager.cancel(pendingIntent);
    }
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

}

然后创建Actvity中的按钮来启动服务和结束服务就好了,但是结束服务之后一定要将alarm进行取消,不然时间一到,Alarm还是会执行服务的启动的。

public class AlarmActivity extends AppCompatActivity {

    Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm);
        intent = new Intent(AlarmActivity.this,AlarmService.class);
        findViewById(R.id.btn_Alarm).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                startService(intent);
            }
        });


        findViewById(R.id.btn_Alarm_stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
            }
        });
    }
}

我们看一下结果

执行

每隔10s都会尽心一次提示以及输出。

点击取消按钮:

取消服务以及将Alarm进行关闭

再看,关闭服务之后在不会进行输出,所以成功了。

当然目前的功能还是比较单一,在实际的开发中你可能要用服务进行网络请求,进行返回数据的判断等等。


注意:从android4.4开始,Alarm任务的触发时间将会变得不精准,有可能会拖延一段时间后任务才回得到执行,但这并不是bug。

而是系统在耗电性方面做得优化,系统会自动检测目前有多少Alarm任务存在,然后将触发时间相近的的几个任务放在一起进行执行,这样可以大幅度的减少CPU被唤醒的次数,从而延长电池的使用寿命。

当然,如果要求是时间准确无误,就使用setExact()方法代替set()方法就好。

Doze模式

在android6.0的系统中,google加入Doze模式,目的是延长电池的寿命,如果设备未插电源且屏幕关闭了一段时间后就会进入Doze模式。在Doze模式下系统会对CPU。网络,以及Alarm等活动进行限制,从而延长电池寿命。

具体看看Doze模式下受限的功能:

网络访问被禁止
系统忽略唤醒CPU或者屏幕操作
系统不再执行wifi扫描
系统不再提供同步服务‘
Alarm任务将会在下次退出Doze模式的时候执行

对于Alarm来讲,在Doze模式下,我们的Alarm任务将会变得不准时。当然,大多数情况这是可以理解的,因为只有长时间不适用手机的时候才会进入Doze模式,但是关于这个长时间是多长没有具体的说明。

当然如果你有特殊的要求,要求Alarm在Doze模式下也可以正常执行,调用AlarmMananger的setAndAllowWhileIdle()setExactAndAllowWhileIdle()方法就可以让程序在Doze模式下也可以正常的执行,区别和set()setExact()方法一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值