あなたの問題は、WakeLocksを適切に使用せずにAlarmManagerを使用することであると思います。デバイスが画面をオフにして「スリープ」すると、レシーバーが正しく機能しなくなります。
レシーバーがAlarmManagerからonReceive()を取得したと思います。これは、おそらく_WAKEUP
次のようなフラグで開始されています。
mAlarmManager.set(AlarmManager.RTC_WAKEUP, .......);
この_WAKEUPフラグは、デバイスがスリープモードであっても、デバイスが「オン」になることを意味します。ただし、ここのドキュメント(http://developer.android.com/reference/android/app/AlarmManager.html)で説明されているように:
アラームマネージャは、アラームレシーバのonReceive()メソッドが実行されている限り、CPUウェイクロックを保持します。これにより、ブロードキャストの処理が終了するまで電話がスリープしないことが保証されます。onReceive()が戻ると、AlarmManagerはこのウェイクロックを解除します。これは、onReceive()メソッドが完了するとすぐに電話がスリープする場合があることを意味します。アラームレシーバーがContext.startService()を呼び出した場合、要求されたサービスが起動される前に電話がスリープする可能性があります。これを防ぐために、BroadcastReceiverとServiceは、サービスが利用可能になるまで電話が実行され続けることを保証するために、個別のウェイクロックポリシーを実装する必要があります。
onReceive()
あなたのコードでは、システムが終了するとすぐにスリープ状態に戻り、startActivity(i)
同期して動作しないため、上記の問題に直接つながりますが、はるかに後で、ユーザーが向きを変えるときに起動されます画面上の。
それを解決するには、次のようなことをお勧めします。
//BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
Logger.initialize(context);
Logger.log("StartAlarm received");
Intent i = new Intent(context, AlarmOnScreen.class);
i.putExtras(intent.getExtras());
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
AlarmOnScreen.acquireLock(context);
//Before, system could sleep right after this line(not exactly, however) and activity actually would be started much later
}
//AlarmOnScreen (activity)
private static WakeLock sWakeLock;
public static void acquireLock(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "providersLock");
//Limit 10 sec, if something wrong will happen - we'll not drain the battery to much.
sWakeLock.acquire(10000);
//As we are acquiring and releasing only once - we don't need a counter.
sWakeLock.setReferenceCounted(false);
}
private static void releaseLock(Context context) {
try {
sWakeLock.release();
} catch (Exception e) {
//In case it's already auto-released
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm_on_screen);
Logger.log("AlarmOnScreen create");
//Time value of alarm is logged below
(...)
@Override
protected void onResume() {
releaseLock(this);
}
このソリューションは初めて機能し、問題をより深く理解できるようになります。テストするには-画面がオフになっていて、おそらくケーブルが接続されていないときにアラームの使用を開始しますが、デバイスをスリープモードにするために最後のものが本当に必要かどうかはわかりません。
ただし、現在の静的参照の設計は、競合状態では完全に機能しないため、かなり貧弱であるため、プロジェクトに適した、より洗練されたソリューションを実装することを強くお勧めします。
お役に立てば幸いです。ご不明な点がありましたらお知らせください。幸運を。
UPD:
PARTIAL_WAKE_LOCKだけでなく、FULLも使用することをお勧めします。好き:
pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "providersLock");
これにより、新しいアクティビティの作成に対する以前の状態やプラットフォームの反応に依存せずに、とにかく画面が強制的にオンになります。