实现定时关机的方法之一(网上还有多种方法,目前用的这个是自己实践的)
主要是使用AlarmManager,思路就是:利用AlarmManager在特定的时刻发送一个广播,在程序中写一个广播接收器用于接收这个广播,一旦接收到该广播,则执行关机的命令。一句话就介绍完了,但是个人觉得这个知识点还是蛮有用的,下面详解这次用到的知识点及遇到的问题
关于AlarmManager的官网文档介绍
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
上面说的是:当你想要在某个特定的时刻运行你的程序代码,可以使用AlarmManager,即使当前该程序并没有运行亦可。对于平时那些用到定时的操作(如ticks, timeouts),AlarmManager比Handler使用起来各更简单、有效
该APP的截图
关于界面就不介绍了。
主要实现大体是按照上面的思路来的
1.设置AlarmManager所需的参数
Intent intent = new Intent(getApplicationContext(), AlarmBroadcastReciver.class); pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
}```
这里要说一下关于AlarmManager的几个重要方法!
[这篇文章介绍的比较详细,感谢作者](http://www.runoob.com/w3cnote/android-tutorial-alarmmanager.html)
`set(int type, long triggerAtMillis, PendingIntent operation)`
这个方法是本次使用到的方法之一,用于在特定时间传递一个广播,但是只能单次提醒,它的参数说明:
**第一个参数是指AlarmManager的类型**,有5个值可以选择:`AlarmManager.ELAPSED_REALTIME` 闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始); `AlarmManager.ELAPSED_REALTIME_WAKEUP `闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间; `AlarmManager.RTC `闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间(即当前系统时间);` AlarmManager.RTC_WAKEUP` 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间; `AlarmManager.POWER_OFF_WAKEUP `表示闹钟在手机关机状态下也能正常进行提示
**第二个参数是指开启提示的时间**
**第三个参数是绑定了需要执行的操作**,比如这次采用的发送广播,也可以弹出提示框等等
`setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)`
这个方法和上一个类似,就是多了一个参数`long intervalMillis`,这个方法是可以重复执行提醒功能,而多出的这个参数就是重复提醒之间的时间间隔
`cancel(PendingIntent operation)`
这个方法从名字就可以看出来,是用来取消提醒的
2.设置广播接收器
注意1中的这一行代码 `Intent intent = new Intent(getApplicationContext(), AlarmBroadcastReciver.class); ` 这行代码就是利用Intent直接指定广播接收器,这样就不需要在清单文件中注册具体的广播标签,该广播接收器接受到广播时,会直接执行关机操作
```@Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context,"关机啦", Toast.LENGTH_SHORT).show(); try { Process process = Runtime.getRuntime().exec("su"); DataOutputStream out = new DataOutputStream( process.getOutputStream()); out.writeBytes("reboot -p\n"); out.writeBytes("exit\n"); out.flush(); } catch (IOException e) { e.printStackTrace(); }```
3.设置按钮监听器,根据点击的按钮开启循环提醒还是单次提醒,同时显示出当前设定的数据
4.重写onStop()方法,在方法中使用ShardPreference用于保存设定的数据,在进入程序时读取保存的数据,并显示出来,以方便知道之前设定的数据
遇到的问题:本来是覆写的onDestroy()方法,想的是在程序销毁时保存数据,结果总是没保存下来,之前也用过ShardPreference在onDestroy()方法中保存数据,是可以的。最后经过多次测试,又看了一下Activity的生命周期图才发现问题所在,下面结合官网给出的生命图来说明
![activity_lifecycle.png](http://upload-images.jianshu.io/upload_images/2234797-ab5649666d06b5a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
当程序进入到后台时就由运行态转换到onPause()态,当不再对用户可见时,就会进入到onStop()态,当程序被finifsh掉后,会进入onDestroy()进而被消灭,这种正常退出的情况下在onDestroy()中保存数据当然是可以的。但是考虑到图中的另一条路线,由onStop()直接转到死亡状态,这种情况就属于非正常情况退出了,比如正在运行时突然被什么清理软件给彻底杀掉了,那么这个时候是不会到onDestroy()这一步,所以此时在这个方法中保存数据就会失败,因此面对这种情况可以考虑覆写onStop()方法进行保存数据,然后在onCreate()中即活动刚创建时获取即可
按照习惯,总是以一个小APP的形式熟悉这些知识点,全代码还有之前的涉及到其他知识点的小APP的代码,都放在[GitHub](https://github.com/huangkunkun/),有些地方可能说的不是很到位,希望各位大神留言指正
一些bug的更改及遗漏问题放在[Android定时关机问题解决](http://www.jianshu.com/p/da37562f1111)