38

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

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

ここで、電源を除くほとんどすべてのボタンを正常にオーバーライドしました。

ですから、皆さんに見てもらい、いくつかのアイデアを共有してもらい、私がそれを回避できるようにしてください.

同じの短いクリックをキャッチしたいのと同じように、長押しのPowerキーイベントを取得しています。onDispatchKeyEvent()また、電源を押すと、私もオフの取得で画面オフを停止しようとしましたが、受信には成功しましたが、処理できませんでした。BroadcastSCREEN_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();
}
}
4

7 に答える 7

55

ふぅ。これは非常に争われた質問であり、その背後には多くの解説があります。

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

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

これには議論が必要です。ただし、短いバージョンは単純です。限られた数のデバイスに対して、ファームウェアまたは Android オペレーティング システムのコアをカスタム変更しない限り、これは不可能です。

Android システムは、文書化されている限り、これをブロードキャスト アクションとして定義しています。メッセージ伝播のパブリッシュ/サブスクライブ パターンに従って、このメッセージは関係者全員にこのアクションを通知します。このメッセージはシステムによって送信され、メッセージ スタックはシステムによって管理され、メッセージもシステムによって受信されるため、このメッセージの受信をブロックする適切な場所にコードが挿入されていません。

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

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

この戦略は絶対確実ではないことを覚えておいてください。次の2600 エクスポゼの餌食にならないように、適切にこれを行い、手順を十分に文書化してください。

あなたのアプリケーションで頑張ってください。

于 2012-04-12T05:42:30.100 に答える
5

これが私がやったことです:

(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);
于 2015-08-27T17:55:34.143 に答える
2
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

電源キーイベントを処理できる上記のコードを試しましたか。また、電源ボタンが押されたイベントを処理したこのLINKもご覧ください。

于 2012-04-15T11:20:44.703 に答える
2

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

これが私が試したことです、

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>
于 2012-04-12T09:09:17.970 に答える