Android Service Alarm 定时广播

Service 最常见的还是执行定时任务,比如轮询,就是每间隔一段时间就请求一次服务器,确认客户端状态或者进行信息更新

Android 提供了两种定时方式 Timer 类与 Alarm 机制

前者不适合于需要长期在后台运行的定时任务,CPU 一旦休眠,Timer 中的定时任务 就无法运行

Alarm 则不存在这种情况,它具有唤醒 CPU 的功能,另外,也要区分 CPU 唤醒与屏幕唤醒

Alarm

Alarm 有一个方法很重要,就是 set()

set(int type,long startTime,PendingIntent pi)
  1. type 参数有五个可选值

    说明
    AlarmManager.ELAPSED_REALTIME 闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为 3
    AlarmManager.ELAPSED_REALTIME_WAKEUP 闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2
    AlarmManager.RTC_WAKEUP 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0
    AlarmManager.POWER_OFF_WAKEUP 表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4
    不过本状态好像受SDK版本影响,某些版本并不支持;

    第一个参数决定第二个参数的类型

    1. 如果是 REALTIME 的话就用 SystemClock.elapsedRealtime() 方法可以获得系统开机到现在经历的毫秒数

    2. 如果是 RTC 的就用 System.currentTimeMillis() 可获得从 1970-1-1 00:00:00 点到现在做经历的毫秒数

  2. startTime

    闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间

    需要注意的是,本属性与第一个属性(type)密切相关

  3. PendingIntent pi

    绑定了闹钟的执行动作,比如发送一个广播、给出提示等等

    PendingIntent 是 Intent 的封装类

    1. 如果是通过启动服务来实现闹钟提示的话, PendingIntent 对象的获取就应该采用

      Pending.getService(Context c,int i,Intent intent,int j)方法;
      
    2. 如果是通过广播来实现闹钟提示的话,PendingIntent 对象的获取就应该采用

      PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;
      
    3. 如果是采用 Activity 的方式来实现闹钟提示的话,PendingIntent 对象的获取就应该采用

      PendingIntent.getActivity(Context c,int i,Intent intent,int j)
      

    如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。

Alarm 使用流程

Alarm 使用方式一般如下

  1. 获得 Service

    AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
    
  2. 通过 set 方法设置定时任务

    int durtime = 2 * 1000; //单位毫秒
    long triggerAtTime = SystemClock.elapsedRealtime() + durtime;
    manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
    
  3. 定义一个 Service,在 onStartCommand() 中开辟一条事务线程,用于处理一些定时逻辑

  4. 定义一个 广播 (Broadcast),用于启动 Service

  5. AndroidManifest.xml 注册 ServiceBoradcast

Android 4.4+(API 19),Alarm 任务的触发时间可能变得不准确,有可能会延时,是系统 对于耗电性的优化,如果需要准确无误可以调用 setExtra() 方法

范例

先来看看最后的效果图

  1. 创建一个 空的 Android 项目 cn.twle.android.ServiceAlarm

  2. MainActivity.java 同一目录下新建文件 LongRunningService.java

    package cn.twle.android.servicealarm;
    
    import android.app.AlarmManager;
    import android.app.Service;
    import android.app.PendingIntent;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.SystemClock;
    import android.util.Log;
    
    import java.util.Date;
    
    public class LongRunningService extends Service {
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
    
            //这里开辟一条线程,用来执行具体的逻辑操作:
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.d("BackService", new Date().toString());
                }
            }).start();
            AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
    
            //这里是定时的,这里设置的是每隔两秒打印一次时间
            int durtime = 2 * 1000;
            long triggerAtTime = SystemClock.elapsedRealtime() + durtime;
    
            Intent i = new Intent(this,MsAlarmReceiver.class);
            PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
            manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
            return super.onStartCommand(intent, flags, startId);
        }
    }
    
  3. MainActivity.java 同一目录下新建文件 MsAlarmReceiver.java

    package cn.twle.android.servicealarm;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    
    public class MsAlarmReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Intent i = new Intent(context,LongRunningService.class);
            context.startService(i);
        }
    }
    
  4. 修改 MainActivity.java

    package cn.twle.android.servicealarm;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
    
        MsAlarmReceiver receiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //创建启动 Service  Intent
            final Intent it = new Intent(this,LongRunningService.class);
            startService(it);
        }
    
    }
    
  5. 修改 AndroidManifest.xml 注册 ServiceBroadcast

    <!-- 配置 Service 组件,同时配置一个 action -->
    <service android:name=".LongRunningService">
        <intent-filter>
            <action android:name="cn.twle.android.servicealarm.LongRunningService"/>
        </intent-filter>
    </service>
    <receiver android:name=".MsAlarmReceiver">
        <intent-filter>
            <action android:name="cn.twle.android.servicealarm.MsAlarmReceiver"/>
    
        </intent-filter>
    </receiver>
    

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.