长按检测电源按钮

Ski*_*ᴉʞS 17 events android

我一直在阅读Stackoverflow上的一些帖子,我没有找到一个好的解决方案,我想知道是否有可能检测到用户长时间按下电源按钮时试图关闭设备,我想知道你是否可以检测到该事件,并且让或者不显示出现的对话框(重启,关机等...)

我试过这个:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
        Toast.makeText(MainActivity.this, event.getKeyCode(), Toast.LENGTH_SHORT).show();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但它没有出现,它也应该作为一项服务工作,我的意思是应用程序可以打开或不打开显示吐司.

编辑

这就是我的方式 onCloseSystemDialog

//home or recent button
public void onCloseSystemDialogs(String reason) {
    if ("globalactions".equals(reason)) {
        Toast.makeText(PowerButtonService.this, "yaps", Toast.LENGTH_SHORT).show();
        Intent i= new Intent(getBaseContext(), Demo.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getApplication().startActivity(i);
    //} else if ("homekey".equals(reason)) {
        //home key pressed
    //} else if ("recentapss".equals(reason)) {
        // recent apps button clicked
    }
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,但只有当设备解锁时,设备被锁定时才会显示任何内容.

此外,我试图弄清楚如何在用户单击powerbutton时删除对话框我试过这个:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
Run Code Online (Sandbox Code Playgroud)

但如果我想再次展示它,我该怎么办呢?

R. *_*ski 17

分享我的方法来做你想要达到的目标.

基本上,它的作用是什么

  1. 要求系统允许绘制叠加层(这不是正常或易受攻击的权限).这不是用户权限,所以你应该真的知道,你在做什么,通过要求它.

    public class MainActivity extends AppCompatActivity {
    
        public final static int REQUEST_CODE = 10101;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (checkDrawOverlayPermission()) {
                startService(new Intent(this, PowerButtonService.class));
            }
        }
    
        public boolean checkDrawOverlayPermission() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                return true;
            }
            if (!Settings.canDrawOverlays(this)) {
                /** if not construct intent to request permission */
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            /** request permission via start activity for result */
                startActivityForResult(intent, REQUEST_CODE);
                return false;
            } else {
                return true;
            }
        }
    
        @Override
        @TargetApi(Build.VERSION_CODES.M)
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == REQUEST_CODE) {
                if (Settings.canDrawOverlays(this)) {
                    startService(new Intent(this, PowerButtonService.class));
                }
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 启动服务并添加特殊视图 WindowManager

  3. 等待中的作用ViewonCloseSystemDialogs方法.

    public class PowerButtonService extends Service {
    
        public PowerButtonService() {
    
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            LinearLayout mLinear = new LinearLayout(getApplicationContext()) {
    
                //home or recent button
                public void onCloseSystemDialogs(String reason) {
                    if ("globalactions".equals(reason)) {
                        Log.i("Key", "Long press on power button");
                    } else if ("homekey".equals(reason)) {
                        //home key pressed
                    } else if ("recentapps".equals(reason)) {
                        // recent apps button clicked
                    }
                }
    
                @Override
                public boolean dispatchKeyEvent(KeyEvent event) {
                    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                        || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
                        || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
                        || event.getKeyCode() == KeyEvent.KEYCODE_CAMERA
                        || event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
                        Log.i("Key", "keycode " + event.getKeyCode());
                    }
                    return super.dispatchKeyEvent(event);
                }
            };
    
            mLinear.setFocusable(true);
    
            View mView = LayoutInflater.from(this).inflate(R.layout.service_layout, mLinear);
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    
            //params
           final WindowManager.LayoutParams params;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    
        params = new WindowManager.LayoutParams(
                100,
                100,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
    } else {
        params = new WindowManager.LayoutParams(
                100,
                100,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_FULLSCREEN
                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                PixelFormat.TRANSLUCENT);
    }
            params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
            wm.addView(mView, params);
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

表现:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="powerbuttonpress">

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
            android:name=".PowerButtonService"
            android:enabled="true"
            android:exported="true">
        </service>

    </application>

</manifest>
Run Code Online (Sandbox Code Playgroud)

service_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

  • 我在 Pixel 2 上找到了 Android P 最新版本的解决方法,见下文。不确定它是否超级通用 (2认同)

Rob*_*hof 6

我看到许多答案试图挂钩到电源按钮.但是,监听关闭事件会不会更容易?我不确定这是否符合您的需求,但似乎就是这样.

只需将Broadcastreceiver注册到以下操作:

<receiver android:name=".ShutdownReceiver">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_SHUTDOWN" />
        <action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
    </intent-filter>
</receiver>
Run Code Online (Sandbox Code Playgroud)

不要忘记添加以下权限:

<uses-permission android:name="android.permission.DEVICE_POWER" />


Arj*_*ini 5

对于长按......请试试这个......

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class demo extends Activity {


    private final List<Integer> blockedKeys = new ArrayList<>(Arrays.asList(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_POWER));


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        setContentView(R.layout.demo);


    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (!hasFocus) {
            // Close every kind of system dialog
            Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);
            Toast.makeText(demo.this, "Your LongPress Power Button", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onBackPressed() {
        // nothing to do here
        // … really
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (blockedKeys.contains(event.getKeyCode())) {


            return true;
        } else {

            return super.dispatchKeyEvent(event);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Long Press Button of power show toast for test...

在此处输入图片说明


DsD*_*DsD 5

这个简单的解决方案有效:

    @Override
public boolean dispatchKeyEvent(KeyEvent event) {
    int keyPressed = event.getKeyCode();
    if(keyPressed==KeyEvent.KEYCODE_POWER){
        Log.d("###","Power button long click");
        Toast.makeText(MainActivity.this, "Clicked: "+keyPressed, Toast.LENGTH_SHORT).show();
        return true;}
    else
        return super.dispatchKeyEvent(event);
}
Run Code Online (Sandbox Code Playgroud)

如果要停止系统弹出窗口,请使用onWindowFocusChanged以下答案之一中指定的方法。

输出将显示带有“ Clicked:26”的吐司,如下所示。在此处输入图片说明


Tap*_*nHP 5

一起去

<uses-permission android:name="android.permission.PREVENT_POWER_KEY" />
Run Code Online (Sandbox Code Playgroud)

当您想捕获该事件时,请执行此操作

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_POWER) {
        // this is method which detect press even of button
        event.startTracking(); // Needed to track long presses
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_POWER) {
        // Here we can detect long press of power button
        return true;
    }
    return super.onKeyLongPress(keyCode, event);
}
Run Code Online (Sandbox Code Playgroud)

可以用广播接收器完成。看到这个答案

  • 没有检测到电源按钮 (2认同)