web-dev-qa-db-ja.com

Android-デバイスのウェイクアップとロック解除

アプリケーションの説明:アプリケーションは、特定のクライアントの安全プログラムとして意図されています(公開されません)。アプリケーションが一定期間動きを検出しなかった場合、アプリケーションがアラームを鳴らし、バックグラウンドにあるかデバイスがスリープ状態にある場合、フォアグラウンドになります。

問題:デバイスがスリープ状態でロックされている場合は、デバイスを起動してロック解除する必要があります。 SOおよび他の場所にあるさまざまなテクニックを使用して、デバイスを(部分的に)ウェイクアップおよびロック解除できましたが、デバイスが物理的にコンピュータに接続されている場合のみ適切に動作します) 。デバイスがそれ自体でプラグを抜いて座っており、ウェイクアンロックをテストした場合、何も起こりません;デバイスはスリープ状態のままであり、アプリケーションは何もしません(アラームなし)。

PowerManagerとKeyguardManagerの使用に関するこの投稿 、および ウィンドウフラグを使用するこの投稿 を使用しました。

以下は、デバイスをウェイクアップするために現在使用されているコードです。

public void wakeDevice() {
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
    wakeLock.acquire();

    KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
    runOnUiThread(new Runnable(){
        public void run(){
            getWindow().addFlags(
                      WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);                
        }
    });
}

他のいくつかのSO私が見た/使用した質問に関するコメントと投稿から、PowerManager/KeyguardManagerコードがトリックを行ったはずだと思われます。デバイスがUSBを介してdevマシンに接続されている間は技術的に機能しますが、デバイスが分離されている間はまったく機能しません。

また、これは最初のAndroidアプリケーションであるため、私たちがやろうとしていることは完全にオフになっている可能性があることを十分に認識しています。提案は歓迎します。

つまり、上記のコードを考えると、デバイスがプラグインされているかどうかに基づいてデバイスの動作が異なるのはなぜですか?また、デバイスをウェイクアップしてロックを解除するには、何を変更する必要がありますか?よろしくお願いします!

45
Paul Richter

問題を解決しました。デバイスをUSB経由で接続したときに異なる動作を観察した理由は、デバイスのCPUがスリープ状態にならないためです。これは、デバッグモード設定の結果、またはCPUスリープの省電力機能は無関係であるため、コンピューターに接続したときの単純な動作のいずれかであると考えられます。明らかに、デバイスが接続されていない場合、CPUは喜んで仮眠を取り、アプリケーションがランダムに実行されているのを観察している間(ランダムに起動する)、タイミングは一貫していません。さらに、これは、発生した数個のCPUサイクルが控えめに割り当てられており、「ランダム」な時間にアプリケーションに非常に少ないサイクルが割り当てられるためだと思います。

そのため、デバイスがバックグラウンドになったときに部分的なウェイクロックを取得し(onPauseメソッドで行われます)、onResumeメソッドでロックを解除しました。これにより、CPUがスリープするのを防ぐようです。必要に応じて、完全なウェイクロックとキーガードの無効化を使用してデバイスをウェイクします。部分的なウェイクロックを使用すると、CPUがスリープ状態にならないように思われ、デバイスは予想どおりに適切にウェイクアップするように見えます。誰かがこの問題に遭遇した場合に備えて、更新されたコードは次のとおりです。

// Called from onCreate
protected void createWakeLocks(){
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
    partialWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Loneworker - PARTIAL WAKE LOCK");
}

// Called implicitly when device is about to sleep or application is backgrounded
protected void onPause(){
    super.onPause();
    partialWakeLock.acquire();
}

// Called implicitly when device is about to wake up or foregrounded
protected void onResume(){
    super.onResume();
    if(fullWakeLock.isHeld()){
        fullWakeLock.release();
    }
    if(partialWakeLock.isHeld()){
        partialWakeLock.release();
    }
}

// Called whenever we need to wake up the device
public void wakeDevice() {
    fullWakeLock.acquire();

    KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
}
58
Paul Richter