我有一個報警應用程序,並被用戶聯繫,他報告說他的報警有時會延遲。我嘗試過不同的方法和理論,最後建議用戶使用默認的Android鬧鐘作爲備份。帶PARTIAL_WAKE_LOCK的WakeLock無法正常工作
通常報警延遲了大約一個小時,但是最後一次我的報警剛剛發生在Android的一個明確的建議之後,那個設備就睡着了,並且被Android的報警喚醒,從而允許我的「繼續啓動」。
編輯: 由於我修改了一些類,並且已經收到來自新版本的日誌,因此我正在更改下面的類和日誌信息。
以下是我正在使用的CountedWakeLock類 - 我創建了自己的HandlerThread來處理喚醒鎖的延遲釋放,以檢查是否會影響啓動問題。它沒有解決問題,但它在日誌(下面)中產生了有趣的信息。
public class CountedWakeLock {
private static long TIMEOUT_DEFAULT = DateUtils.MINUTE_IN_MILLIS * 3;
private static WakeLock sWakeLock = null;
private static int sLockCount;
private static class TimeoutReleaseThread extends HandlerThread {
static TimeoutReleaseThread mInstance = null;
Handler mHandler;
private Runnable mReleaseRunnable;
public static TimeoutReleaseThread instance() {
if (mInstance == null) mInstance = new TimeoutReleaseThread();
return mInstance;
}
public TimeoutReleaseThread() {
super("TimeoutReleaseThread HandlerThread");
start();
mHandler = createHandler();
mReleaseRunnable = new Runnable() {
@Override
public void run() {
Utils.log("TimeoutReleaseThread release lock");
releaseLock();
}
};
}
private synchronized Handler createHandler() {
return new Handler(getLooper());
}
public synchronized void postRelease(long timeout) {
mHandler.removeCallbacks(mReleaseRunnable);
mHandler.postDelayed(mReleaseRunnable, timeout);
}
}
public synchronized static void acquireLock(Context context) {
acquireLock(context, TIMEOUT_DEFAULT);
}
public synchronized static void acquireLock(Context context, long timeout) {
if (sWakeLock == null) {
Utils.log("WakeLock creating");
PowerManager pm = (PowerManager) context.getApplicationContext()
.getSystemService(Context.POWER_SERVICE);
sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"AlarmReceiver lock");
sWakeLock.setReferenceCounted(false);
sLockCount = 0;
} else if (sWakeLock.isHeld())
Utils.log("WakeLock held already");
else
Utils.log("WakeLock not held");
Utils.log("WakeLock acquiring for " + timeout);
sLockCount++;
sWakeLock.acquire();
TimeoutReleaseThread.instance().postRelease(timeout);
}
public synchronized static void releaseLock() {
Utils.log("WakeLock releasing");
if (sWakeLock == null) {
Utils.log("WakeLock==null");
} else if (!sWakeLock.isHeld()) {
Utils.log("WakeLock not held");
sWakeLock = null;
sLockCount = 0;
} else {
sLockCount--;
if (sLockCount <= 0) {
Utils.log("WakeLock released");
sWakeLock.release();
sWakeLock = null;
if (sLockCount != 0) Utils.log("lockcount=" + sLockCount);
}
}
}
}
AlarmReceiver廣播接收器 - 它是從AlarmManager
public void onReceive(Context context, Intent intent) {
Logger.initialize(context, "AlarmReceiver");
if (CALL_IS_ON) {
//set another alarm with AlarmManager to start after 5 seconds
//doesn't happen in this situation
} else {
Utils.log("sending START ALARM");
CountedWakeLock.acquireLock(context);
Intent i = new Intent();
i.setAction(StartAlarmReceiver.ACTION_START_ALARM);
i.putExtras(intent.getExtras());
context.sendOrderedBroadcast(i, null); //it is ordered, so eventual previous Alarm Activities etc. can be stopped
Utils.log("START ALARM send");
}
}
StartAlarmReceiver接收意圖。它實際上是啓動報警活動
public void onReceive(Context context, Intent intent) {
Logger.initialize(context, "StartAlarmReceiver");
Intent i = new Intent(context, AlarmOnScreen.class);
Bundle extras = intent.getExtras();
i.putExtras(extras);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Utils.log("AlarmActivity started");
}
更新日誌:
504. 27/3 5:0:0 - logger initialized again from AlarmReceiver
505. 27/3 5:0:0 - sending START ALARM
506. 27/3 5:0:0 - WakeLock creating
507. 27/3 5:0:0 - WakeLock acquiring for 180000
508. 27/3 5:0:0 - START ALARM send
509. 27/3 5:0:0 - logger initialized again from StartAlarmReceiver
510. 27/3 5:0:0 - AlarmActivity started
511. 27/3 5:0:0 - Main start
512. 27/3 5:0:1 - Main resume
513. 27/3 5:0:1 - Main pause
514. 27/3 5:0:5 - Main stop
515. 27/3 5:3:0 - TimeoutReleaseThread release lock
516. 27/3 5:3:0 - WakeLock releasing
517. 27/3 5:3:0 - WakeLock released
518. 27/3 6:46:18 - logger initialized again from AlarmOnScreen create //user said he unlocked phone then to check the time...
從日誌現在我相信,激活鎖定實際工作 - 畢竟CPU必須一直運行,如果TimeoutReleaseThread能完成加工。
問題是爲什麼AlarmOnScreen Activity未啓動?爲什麼主要活動(511-514行)已經開始?最近我讓AlarmOnScreen在manifest中設置了singleTask模式。這可能會導致問題嗎?但爲什麼?我需要這個單一任務的其他幾個原因...
設備是GT-S5830i與2.3.6 Android。