Override Power button just like Home button

柔情痞子 提交于 2019-11-26 11:40:47

Phew. This is quite a contended question, with a great deal of commentary behind it.

Let me begin by rephrasing your question a bit. If I understand clearly, you'd like to disable all physical buttons on the device for the duration of your activity. This is inclusive of the power button, which you detect by handling the ACTION_SCREEN_OFF intent. Your current (successful) workaround for this scenario is to broadcast an ACTION_SCREEN_ON, kicking the screen back to life when it's turned off, provided the host implements this correctly.

You'd now like to go the extra mile, by rendering this action unnecessary, if (and only if) you are able to catch and handle ACTION_SCREEN_OFF before it gets sent to the system. Is this possible, and if so, how?

This bears some discussion. The short version, however, is simple: this is not possible, without custom modification to your firmware or the core of the Android operating system, for a limited number of devices.

The Android system, as far as is documented, defines this as a broadcast action. Following the publish-subscribe pattern of message propagation, this message will notify all concerned parties of this action. Because this message is sent by the system, because the message stack is managed by the system, and because the message is also received by the system, your code simply isn't injected in the right place to block the reception of this message.

Furthermore, for some devices, this will be a physical switch that has no programmatic interrupt whatsoever. At best, the Android system can hope to handle for the event when it happens, which is precisely why this broadcast message is something of a special case in the service stack. To the best of my knowledge and based upon the sparse documentation on this scenario, this is why it's not an out-of-the-box, supported feature, before we consider any of the possible vectors for abuse.

Your best recourse is actually a much simpler one, if you have the ability to modify the physical hardware for the device in question: restrict access to, mangle, or otherwise disable the physical power button. In many scenarios this is undesirable, but this works in situations where your Android device is being used, for example, as a point-of-sale or a public service machine. If this is unworkable, placing physical restrictions on access to the power button may be all that's required, handling for the remainder of cases (for example, spot attempts to toggle the screen) by sending ACTION_SCREEN_ON.

Just remember, this strategy isn't foolproof. Do this competently and document the procedure well, lest you become fodder for the next 2600 exposé.

Best of luck with your application.

On the contrary to all the answers .. Check this out:


@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);
}

What it does:

Whenever the user presses the power button. We cancel the Dialog before its even seen!! :) . This works for me.. (Tested on note2)

Here is what I have done:

(1) Create a receiver class:

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) The two methods that are called above looked like this:

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) In the main activity class onCreate() method register the receiver:

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

You can get to know about the Power Button press, but I dont think you will get to override it and you will be able to dismiss the dialog for power off and show something else.

Here is what I have tried,

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();
    }
}

and declaration in Manifest as,

    <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>
Shankar Agarwal
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

have you tried the above code where we can handle power key event. Also have a look at this LINK which has handled power button pressed event.

Radhey

I know its too late ,but may be helpful for other developers in future. Tested over Android N . Reference from https://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);
        }
    }

If someone is looking for a solution to develop your app into kiosk mode/COSU(Corporate Owned Single Use application) where you need to disable various hardware buttons then please follow the below link -

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!