3

私はアラームアプリケーションを持っていて、彼のアラームが時々遅れることを報告したユーザーから連絡がありました。私はさまざまなアプローチと理論を試し、最終的にユーザーにデフォルトのAndroidのアラームをバックアップとして使用することを提案しました。

通常、アラームは約1時間遅れましたが、前回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);

        }
    }
}
}

AlarmReceiverBroadcastReceiver-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...

ログから、WakeLockが実際に機能していると思います。つまり、TimeoutReleaseThreadが機能を終了できた場合は、すべてのCPUが実行されている必要があります。

質問は、AlarmOnScreenアクティビティが開始されなかった理由ですか?そして、なぜメインアクティビティ(行511-514)が開始されたのですか?最近、AlarmOnScreenのマニフェストにsingleTaskモードを設定しました。それが問題を引き起こしている可能性がありますか?しかし、なぜ?他のいくつかの理由でこのsingleTaskが必要です...

デバイスは、2.3.6Androidを搭載したGT-S5830iです。

4

2 に答える 2

2

何が問題を引き起こしたのかはまだわかりませんが、誰かが同様の問題を経験した場合、多くのテストの後、それはたった1つの簡単な変更でした。StartAlarmReceiverのIntentにIntent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDEDを追加します。

だからそれは

i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

それは機能しますか?はい、そうです。そしてこれまでのところ、他の電話では問題は発生していません。

それは意味がありますか?いいえ、まったくありません。

于 2013-04-19T21:12:54.710 に答える
2

この方法で通知を送信することにより、サービスの問題を解決しました。

startForeground(ID, notification)
于 2020-04-24T04:20:43.097 に答える