• Android定时器AlarmManager


    AlarmManager是Android的全局定时器。就是在指定时间做一个事情(封装在PendingIntent)。通过PendingIntent的getActivity()、getService()或getBroadcast()来执行。
    听起来AlarmManager和Timer很类似,但是Timer有可能因为手机休眠而被杀掉服务,但是AlarmManager可以做到唤醒手机。

    创建方式

    AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
    

    注:ALARM_SERVIC是context的一个常量。

    闹钟类型

    • RTC_WAKEUP
      表示闹钟在睡眠状态下唤醒系统并执行提示功能,绝对时间。
    • RTC
      睡眠状态下不可用,绝对时间。
    • ELAPSED_REALTIME_WAKEUP
      睡眠状态下可用,相对时间。
    • ELAPSED_REALTIME
      睡眠状态下不可用,相对时间。

    以上绝对时间就是手机的时间,相对时间是相对于当前开机时间来说。例如如果是绝对时间,那么你测试可以通过修改系统时间来提前触发。而相对时间的使用场景是强调多久之后触发,例如2小时后,这个时候把时间修改到2小时后也是没用的。
    注:以前还有一个POWER_OFF_WAKEUP,即使在关机后还能提醒,但是Android4.0以后就没有了。

    常用方法

    set(int type, long triggerAtMillis, PendingIntent operation)
    

    该方法用于设置一次性闹钟。第一个参数是闹钟类型,第二个参数是触发时间,第三个参数是动作。

    setExact(int type, long triggerAtMillis, PendingIntent operation)
    

    和set一样,但是时间更精准。

    setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
    

    重复闹钟,第1、2、4个参数同上,第3个参数是两次闹钟的时间间隔。

    setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)
    

    和setInexactRepeating一样,但是时间更精准。

    以上四个方法时间精不精准的原因还没有深入研究,大概是是否允许系统同时发出多个提醒,意义在于系统唤醒cpu后会把时间接近的alarm同时发出,避免重复唤醒cpu,减少电量。

    cancel(PendingIntent operation)
    

    取消闹钟。

    写个小程序实验一下

    目的:在指定时间从一个发送个广播,收到广播后打印log。界面如下面这样。


     
     

    布局:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.xuhongchuan.alarmclocktest.MainActivity">
    
        <LinearLayout
            android:id="@+id/view_group1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
            <TimePicker
                android:id="@+id/time_picker"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </TimePicker>
    
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/view_group2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal"
            android:layout_below="@id/view_group1">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="是否重复"/>
    
            <CheckBox
                android:id="@+id/checkbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
    
        </LinearLayout>
    
        <Button
            android:id="@+id/confirm"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_group2"
            android:text="确定" />
    </RelativeLayout>
    
    

    广播接收器:

    public class AlarmReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == MainActivity.INTENT_ALARM_LOG) {
                Log.d("AlarmReceiver", "log log log");
            }
    
        }
    }
    

    MainActivity

    public class MainActivity extends AppCompatActivity {
    
        public static final String INTENT_ALARM_LOG = "intent_alarm_log";
    
        private TimePicker timePicker;
        private CheckBox checkBox;
        private Button btnConfirm;
    
        private int hour;
        private int minute;
    
        AlarmManager am;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            init();
        }
    
        private void init() {
            timePicker = (TimePicker) findViewById(R.id.time_picker);
            timePicker.setIs24HourView(true);
            checkBox = (CheckBox) findViewById(R.id.checkbox);
            btnConfirm = (Button) findViewById(R.id.confirm);
    
            am = (AlarmManager) getSystemService(ALARM_SERVICE);
    
            btnConfirm.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (Build.VERSION.SDK_INT >= 23) {
                        hour = timePicker.getHour();
                        minute = timePicker.getMinute();
                    } else {
                        hour = timePicker.getCurrentHour();
                        minute = timePicker.getCurrentMinute();
                    }
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.HOUR_OF_DAY, hour);
                    calendar.set(Calendar.MINUTE, minute);
                    calendar.set(Calendar.SECOND, 0);
    
                    Intent intent = new Intent(INTENT_ALARM_LOG);
                    PendingIntent pi = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
    
                    if (!checkBox.isChecked()) {
                        am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi);
                    } else {
                        long intervalMillis  = 60 * 1000; // 60秒
                        am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), intervalMillis, pi);
                    }
                }
            });
        }
    }
    

    AndroidManifest要注册一下receiver

    <receiver android:name=".AlarmReceiver">
        <intent-filter>
            <action android:name="intent_alarm_log"/>
        </intent-filter>
    </receiver>
    

    经过测试,以上的时间间隔intervalMillis即使设置5秒也是没用的,因为误差(几十秒呢)无法避免,即使是setRepeating。所以精确是相对的。


     
  • 相关阅读:
    sql 内连接外链接
    深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
    mysql关闭以及重启密码
    学习---书籍
    volatile修饰符
    System.out.println和System.err.println的区别
    懒加载和急加载(lazy/eager)
    load与get在hiberate中的区别
    html
    js
  • 原文地址:https://www.cnblogs.com/endv/p/13394856.html
Copyright © 2020-2023  润新知