web-dev-qa-db-ja.com

ホームボタンと同じように電源ボタンをオーバーライドする

さて、私はデバイスのすべてのハードボタンを無効にしたいことをしています。

電源、ホーム、音量アップ、音量ダウン、検索、戻るなどのハードボタン。

ほとんどすべてのボタンを上書きしました ここ Powerを除きます。

ですから、皆さんに見てもらい、アイデアを共有してほしいです。

私は長押しonDispatchKeyEvent()のパワーキーイベントを取得しています。同じ方法で同じクリックをキャッチしたいのと同じです。さらに、電源を押すと、SCREEN_OFFBroadcastを取得して停止Screen offを試みましたが、受信に成功しましたが、処理できませんでした。

ありがとう。

次に、スクリーンのオン/オフのブロードキャストを受信するReceiverScreenを作成しました

ReceiverScreen.Java

public class ReceiverScreen extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // do whatever you need to do here
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // and do whatever you need to do here
            wasScreenOn = true;
        }
    }
}

DisableHardButton.Java

public class DisableHardButton extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ReceiverScreen();
    registerReceiver(mReceiver, filter);
    }

@Override
    protected void onPause() {
        // when the screen is about to turn off
        if (ScreenReceiver.wasScreenOn) {
            // this is the case when onPause() is called by the system due to a screen state change
            System.out.println("SCREEN TURNED OFF");

    } else {
        // this is when onPause() is called when the screen state has not changed
    }
    super.onPause();
}

@Override
protected void onResume() {
    // only when screen turns on
    if (!ScreenReceiver.wasScreenOn) {
        // this is when onResume() is called due to a screen state change
        System.out.println("SCREEN TURNED ON");
    } else {
        // this is when onResume() is called when the screen state has not changed
    }
    super.onResume();
}
}
34
Azhar Shaikh

ふう。これは非常に議論の多い質問であり、その背後には多くの解説があります。

あなたの質問を少し言い換えることから始めましょう。私が明確に理解している場合、あなたはあなたの活動の間、デバイス上のすべての物理的なボタンを無効にしたいと思います。これには、ACTION_SCREEN_OFFインテントを処理することで検出する電源ボタンが含まれます。このシナリオの現在の(成功した)回避策は、ホストがこれを正しく実装していれば、ACTION_SCREEN_ONをブロードキャストし、画面がオフになったときに画面を元に戻すことです。

システムに送信される前にACTION_SCREEN_OFFをキャッチして処理できる場合にのみ(この場合にのみ)このアクションを不要にすることで、さらに一歩前進したいと思います。これは可能ですか?

これにはいくつかの議論があります。ただし、短いバージョンはシンプルです:これは不可能です。ファームウェアをカスタマイズしたり、Androidオペレーティングシステムのコアをカスタマイズしたり、デバイスの数

Androidシステムは、文書化されている限り、これを broadcast action メッセージ伝播の publish-subscribeパターン に従って、このメッセージはすべての関係者にこのアクションを通知します。このメッセージはシステムによって送信されるため、メッセージスタックはシステムによって管理され、メッセージもシステムによって received されるため、このメッセージの受信をブロックする適切な場所にコードが挿入されることはありません。

さらに、一部のデバイスでは、これは physical スイッチであり、プログラムによる割り込みは一切ありません。せいぜい、Androidシステムは、イベントが発生したときにイベントを処理することを期待できます。これがまさに、このブロードキャストメッセージがサービススタックの特殊なケースである理由です。このシナリオに関するスパースドキュメントに基づいて、悪用の可能性のあるベクトルのいずれかを検討する前に、すぐに使用できるサポートされた機能ではないのはこのためです。

問題のデバイスの物理ハードウェアを変更する能力がある場合、物理電源ボタンへのアクセスを制限したり、マングルしたり、無効にしたりすることができれば、最良の手段は実際にははるかに簡単です。多くのシナリオではこれは望ましくありませんが、AndroidデバイスがPOSまたは公共サービスマシンとして使用されている場合に機能します。これが機能しない場合、 ACTION_SCREEN_ONを送信することにより、電源ボタンへのアクセスに物理的な制限を設定するだけで、残りのケース(たとえば、画面の切り替えを試行するスポット)を処理できます。

ただ、この戦略は万全ではないことを覚えておいてください。次の 2600exposé の飼料にならないように、これを有能に行い、手順を文書化します。

アプリケーションの幸運を祈ります。

51
MrGomez

すべての答えに反して..これをチェックしてください:


@Override
public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
                Log.i("", "Dispath event power");
                Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                sendBroadcast(closeDialog);
                return true;
        }

        return super.dispatchKeyEvent(event);
}

それが何をする:

ユーザーが電源ボタンを押すたびに。ダイアログが表示される前にキャンセルします!! :)。これは私のために働きます..(note2でテスト済み)

8
amalBit

ここに私がやったことがあります:

(1)レシーバークラスを作成します。

public class ScreenReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        switch (action) {
            case Intent.ACTION_SCREEN_OFF:
                BaseActivity.unlockScreen();
                break;

            case Intent.ACTION_SCREEN_ON:
                // and do whatever you need to do here
                BaseActivity.clearScreen();
        }
    }
}

(2)上記で呼び出される2つのメソッドは次のようになりました。

public static void unlockScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Turning on screen ... " );

    Window window = current.getWindow();
    window.addFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.addFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.addFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

public static void clearScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Clearing screen flag when on ... " );

    Window window = current.getWindow();
    window.clearFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.clearFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.clearFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

private static BaseActivity current;

@Override
protected void onResume () {
    current = this;
}

(3)メインアクティビティクラスのonCreate()メソッドで、レシーバーを登録します。

    IntentFilter filter = new IntentFilter( Intent.ACTION_SCREEN_ON );
    filter.addAction( Intent.ACTION_SCREEN_OFF );
    registerReceiver(new ScreenReceiver(), filter);
5
Sileria

電源ボタンの押下について知ることはできますが、それを無効にすることはできませんし、電源オフのダイアログを閉じて他の何かを表示することもできます。

これが私が試したものです、

package com.easylogs.app;

import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.util.Log;
import Android.widget.Toast;

public class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
    public void onReceive(final Context context, final Intent intent) {
        Log.i("HERE", "------------------------------------HERE");
        Toast.makeText(context, "OFFFFFFFFFFFFFFFF",Toast.LENGTH_LONG).show();
    }
}

マニフェストの宣言として、

    <receiver Android:name="CloseSystemDialogsIntentReceiver">
    <intent-filter>
            <action Android:name="Android.intent.action.CLOSE_SYSTEM_DIALOGS" />
            <category Android:name="Android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
2
MKJParekh
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

電源キーイベントを処理できる上記のコードを試してみましたか。また、これを見てください [〜#〜] link [〜#〜] これは、電源ボタンが押されたイベントを処理しました。

2
Shankar Agarwal

私はそれが遅すぎることを知っていますが、将来的に他の開発者に役立つかもしれません。テスト済みAndroid Nhttps://stackoverflow.com/a/15828592/1065357 からの参照

 @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(!hasFocus) {
           Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);
        }
    }
1
Radhey

アプリをキオスクモード/ COSU(Corporate Owned Single Use application)に開発するためのソリューションを探している場合、さまざまなハードウェアボタンを無効にする必要があります以下のリンクに従ってください-

https://www.andreasschrade.com/2015/02/16/Android-tutorial-how-to-create-a-kiosk-mode-in-Android/

0
B.shruti