AlarmManager理解

来源:互联网 发布:剑网三苍爹捏脸数据 编辑:程序博客网 时间:2024/05/16 09:11

哎,最近刚刚开始做framework开发。主要做些BUG修改之类的。刚进公司。进项目组,由于之前不是做framework开发,所以很生疏。我接到的第一个任务就是移植工厂测试工具MMI.

好不容易移植到系统中去了以后呢。在各个测试项复查的过程中发现有几个case测试通不过。AlarmManager.setRepeating就是让我很头疼。我是想在一秒钟重复一次。但是始终不行,所以分析了一些源码,记录一下,以后好复习。

AlarmManager.setRepeating(int type, long triggerAtMillis, long intervalMillis,PendingIntent operation)这几个参数我就不对说了,可以参考http://blog.csdn.net/ricks_wu/article/details/22494015。比较详细。

 我们使用的AlarmManager类其实是很简单的一个包装类。他在android.app下。

AlarmManager的成员函数有:

AlarmManager(IAlarmManager service)publicvoid set(int type,long triggerAtTime, PendingIntent operation)publicvoid setRepeating(int type,long triggerAtTime,long interval,PendingIntent operation)publicvoid setInexactRepeating(int type,long triggerAtTime,long interval,PendingIntent operation)publicvoid cancel(PendingIntent operation)publicvoid setTime(long millis)publicvoid setTimeZone(String timeZone)

然而调用的却是诸如:
 try {            mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation,                    workSource, alarmClock);        } catch (RemoteException ex) {        }
对就是调用的<span style="font-family: consolas, 'Courier New', courier, monospace;">mService,那它是什么呢?</span><pre name="code" class="java">private final IAlarmManager mService;
继续跟踪会发现,它其实就是AlarmManagerService里面的IBind一个对象。熟悉IPC的就不会很生疏了,
class AlarmManagerService extends SystemService{、
<span style="white-space:pre"></span>....
<span style="white-space:pre"></span><pre name="code" class="java"><span style="white-space:pre"></span>private final IBinder mService = new IAlarmManager.Stub() {        @Override        public void set(int type, long triggerAtTime, long windowLength, long interval,                PendingIntent operation, WorkSource workSource,                AlarmManager.AlarmClockInfo alarmClock) {            if (workSource != null) {                getContext().enforceCallingPermission(                        android.Manifest.permission.UPDATE_DEVICE_STATS,                        "AlarmManager.set");            }            setImpl(type, triggerAtTime, windowLength, interval, operation,                    windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);        }        @Override        public boolean setTime(long millis) {        }        @Override        public void setTimeZone(String tz) {        }        @Override        public void remove(PendingIntent operation) {        }        @Override        public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {        }        @Override        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {        }        @Override        public void updateBlockedUids(int uid, boolean isBlocked) {        }    };
<span style="white-space:pre"></span>....
}
我们使用

alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(), 1 * 1000,pendingIntent);
就会调用到这里的
AlarmManager:
   public void setRepeating(int type, long triggerAtMillis,            long intervalMillis, PendingIntent operation) {        setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation, null, null);    }


注意这里legacyExactLength(); 看看它:

<span style="white-space:pre"></span>AlarmManager(IAlarmManager service, Context ctx) {        mService = service;        final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;        mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT);//<span style="font-family: Arial, Helvetica, sans-serif;">Build.VERSION_CODES.KITKAT=19</span>    }    private long legacyExactLength() {        return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC);//<span style="font-family: Arial, Helvetica, sans-serif;">WINDOW_EXACT=0;</span><span style="font-family: Arial, Helvetica, sans-serif;">WINDOW_HEURISTIC = -1;</span>    }

mAlwaysExact?是什么? 在AlarmManager 构造函数里面可以看到他。

这里是在比较版本。如果是在19以后则不能精确发生,在19之前可以做到时间精确提醒,说是为了节约使用电量,所以害得我在5.1手机上始终无法得到1秒钟唤醒一次。

接下来去到了

AlarmManagerService的<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 13px; line-height: 23px;">IBinder mService了。


 setImpl(type, triggerAtTime, windowLength, interval, operation,                    windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock); //<span style="font-family: Arial, Helvetica, sans-serif;">AlarmManager.WINDOW_EXACT =0</span>

注意这里第6个参数

windowLength == AlarmManager.WINDOW_EXACT 

windowLength在19以后是-1 在19之前是0.

所以第六个参数是false.调用AlarmManagerService的setImpl方法如下:

 void setImpl(int type, long triggerAtTime, long windowLength, long interval,            PendingIntent operation, boolean isStandalone, WorkSource workSource,            AlarmManager.AlarmClockInfo alarmClock) {<pre name="code" class="java"><span style="white-space:pre"></span>..........
// Sanity check the recurrence interval. This will catch people who supply // seconds when the API expects milliseconds. if (interval > 0 && interval < MIN_INTERVAL) {

<span style="white-space:pre"></span>Slog.w(TAG, "Suspiciously short interval " + interval                    + " millis; expanding to " + (int)(MIN_INTERVAL/1000)                    + " seconds");            interval = MIN_INTERVAL;        }<span style="white-space:pre"></span>..........    }
    // Minimum alarm recurrence interval    private static final long MIN_INTERVAL = 60 * 1000;  // one minute, in millis

哇。就在这里处理了我的时间,如果重复的时间小于1一分钟。则设置为一分钟,难怪我始终1秒钟始终不行啊。。。。晕哦。

哎。搞里半天是这里的问题。如果我就是要在1S后执行呢,放心Google提供了一个新方法:setExact去实现精确的时间提醒。













0 0
原创粉丝点击