AlarmManager理解

本文深入探讨了在Android开发中使用AlarmManager进行一秒重复任务设置时遇到的问题及解决方案。通过源码分析,揭示了为何在Android 4.4(KitKat)之后版本无法实现精确一秒重复,并介绍了如何利用setExact方法实现精确时间提醒。
摘要由CSDN通过智能技术生成

哎,最近刚刚开始做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去实现精确的时间提醒。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值