前言:
条件,定时关机不能关机,只能待机;要能定时“开机”(唤醒)
1.定时“关机”(待机)
众所周知android 有wakelock 在有wakelock 时不能待机,可按如下的方法进行待机;
Java:
启动force sleep 服务,只是运行force_sleep_part1.sh
SystemProperties.set("ctl.start", "force_sleep");
init.xxx.rc
定义force_sleep服务
service force_sleep /system/bin/force_sleep_part1.sh
oneshot
disabled
force_sleep_part1.sh
切换root 运行force_sleep_part2.sh
su -s /bin/sh /system/bin/force_sleep_part2.sh
force_sleep_part2.sh
强制写/sys/power/state 来进行待机
echo mem > /sys/power/state
2.定时“开机” (唤醒)
此处折磨了我两天,终于在一个朋友的指点下找到原因。
NOTE: 在有的厂商会控制通过RTC唤醒机器的程序,比如本人开发的这个平台会根据包名判断此包名内的程序是否在唤醒机器白名单内,每个厂商可能在不同的位置控制,碰到这个问题,不要一味的找自己写的代码的问题,还是要相信自己的。查下相关的流程,看下是否在哪修改掉了;比如在我使用的BSP中
frameworks/base/services/java/com/android/server/AlarmManagerService.java
608 private static final String[] sAlarmWhiteList = {
609 "com.android.providers.calendar",
610 "com.android.alarmclock",
611 "com.android.deskclock",
612 "com.android.keyguard",
614 };
616 /*
617 * Only packages above can set RTC_WAKEUP/ELAPSED_REALTIME_WAKEUP alarm.
618 */
619 private int filterType(int type, PendingIntent operation) {
620 if( type == AlarmManager.RTC_WAKEUP || type == AlarmManager.ELAPSED_REALTIME_WAKEUP ) {
621 String pakeageName = operation==null?null:operation.getTargetPackage();
622 for(String packet : <strong><span style="color:#ff0000;">sAlarmWhiteList</span></strong>) {
623 Slog.v("kevin", "packagename = "+ pakeageName);
624 if( packet.equals(pakeageName) ) {
625 return type;
626 }
627 }
628 type = (type == AlarmManager.RTC_WAKEUP ) ? AlarmManager.RTC : AlarmManager.ELAPSED_REALTIME;
629 }
630 return type;
631 }
AlarmManager 使用比较简单,但因为上面的原因,让我反复查了几十遍;
如下:
Calendar c = Calendar.getInstance();
int length = timeonArray.length;
c.set(Calendar.YEAR, timeonArray[0]);
c.set(Calendar.MONTH, timeonArray[1] -1 );
c.set(Calendar.DAY_OF_MONTH, timeonArray[2]);
c.set(Calendar.HOUR_OF_DAY, timeonArray[3]);
c.set(Calendar.MINUTE, timeonArray[4]);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Intent PowerOnIntent = new Intent();
PowerOnIntent.setAction(DataObject.ACTION_ALARM_POWER_ON_TIMER_OUT);
PowerOnIntent.setClass(mContext, BroadcastReciver.class);
mPowerOnPendingIntent = PendingIntent.getBroadcast(mContext,
0, PowerOnIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
if (isKitKatOrLater()) {
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), mPowerOnPendingIntent);
} else {
mAlarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), mPowerOnPendingIntent);
}
3.android 重启
CommonUntils.ShellCommand("reboot");
Intent rebootIntent = new Intent(Intent.ACTION_REBOOT);
rebootIntent.putExtra("nowait", 1);
rebootIntent.putExtra("interval", 1);
rebootIntent.putExtra("window", 0);
mContext.sendBroadcast(rebootIntent);
基本上,按如上的方法,定时“开关”(待机,唤醒)机是没有任何问题的。