如何挂钩Android中的电源按钮?

时间:2010-09-13 17:58:50

标签: android

在Android设备上,只有按钮是音量按钮和电源按钮,我想让应用程序按下电源按钮(长和短)。这是怎么做到的?

9 个答案:

答案 0 :(得分:39)

现有的答案并没有完全回答这个问题,并且遗漏了足够的细节,如果没有更多的调查它们将无法运作。我会分享我学到的解决这个问题的方法。

首先,您需要将以下权限添加到清单文件中:

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

要处理短按和长按,请在活动类中添加以下覆盖:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_POWER) {
        // Do something here...
        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) {
        // Do something here...
        return true;
    }
    return super.onKeyLongPress(keyCode, event);
}

注意:值得注意的是onKeyDown()会在onKeyLongPress执行之前多次触发,因此您可能希望触发onKeyUp()而不是其他逻辑,以防止在用户真正执行时对一系列onKeyDown()调用进行操作坚持下去。

我认为下一部分仅针对Cyanogenmod。 如果未定义 PREVENT_POWER_KEY 常量,那么您不应该需要它。

要开始拦截电源键,您需要在活动中设置以下标志:

getWindow().addFlags(WindowManager.LayoutParams.PREVENT_POWER_KEY);

停止拦截电源键(允许标准功能):

getWindow().clearFlags(WindowManager.LayoutParams.PREVENT_POWER_KEY);

如果您愿意,可以在程序中反复在两种模式之间来回切换。

答案 1 :(得分:7)

解决方案:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
        Intent i = new Intent(this, ActivitySetupMenu.class);
        startActivity(i);
        return true;
    }

    return super.dispatchKeyEvent(event);
}

答案 2 :(得分:4)

在您的活动上添加:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
        // do what you want with the power button
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

虽然......这种钥匙有点特别......不确定它是否会给你带来麻烦。

答案 3 :(得分:4)

共享方法以长按电源按钮。使用API​​ 23+权限:

  1. 向[{3}} 询问系统权限(这不是正常或易受攻击的权限)。这不是用户权限,所以你应该真的知道,你在做什么,通过要求它。

     var url = "http://google.com";
     window.open(url, '_system');
    
  2. 启动服务并为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)); } } } } 添加特殊视图

  3. 等待WindowManager View方法中的操作。

    onCloseSystemDialogs
  4. <强>清单:

    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 ("recentapss".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
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                100,
                100,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                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;
        }
    }
    

    <强> service_layout:

    <?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>
    

答案 4 :(得分:3)

如此处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);
    }
}

答案 5 :(得分:1)

您可以覆盖Activity类中的public boolean onKeyDown(int keyCode, KeyEvent event)public boolean onKeyUp(int keyCode, KeyEvent event)函数,并测试keyCode是否等于KeyEvent.KEYCODE_POWER

我没有对此进行测试,但我认为系统会像处理Home键一样对待它,因为你无法阻止系统接收键事件,你只能观察到它发生了。要对此进行测试,请尝试从上述函数返回True,看看是否捕获了键事件。

答案 6 :(得分:0)

你必须使用它:

BroadcastReceiver screenoff = new BroadcastReceiver() {

public static final String Screenoff = "android.intent.action.SCREEN_OFF";

@Override
public void onReceive(Context context, Intent intent) {
        if (!intent.getAction().equals(Screenoff)) return;
        //put code to handle power press here
        return;

}};

答案 7 :(得分:0)

对于所有android版本,请使用此代码。

我尝试了R. Zagórski的答案,但是无法在Pie上运行此代码。但是,我已经在答案中更新了他们的代码。

PowerButtonService:

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");
                    Intent intent = new Intent(Intent.ACTION_CALL);
                    intent.setData(Uri.parse("tel:" + "9690008019"));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
                    startActivity(intent);
                } else if ("homekey".equals(reason)) {
                    //home key pressed
                } else if ("recentapss".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);

      **// here I done with EDIT** 

        int LAYOUT_FLAG;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
        }
        View mView = LayoutInflater.from(this).inflate(R.layout.service_layout, mLinear);
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

        //params
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                LAYOUT_FLAG,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
        wm.addView(mView, params);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

和service_layout:

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


</LinearLayout>

答案 8 :(得分:0)

使用广播接收器进行电源按钮(屏幕开/关)事件

这是解决方案:创建广播接收器类

public class CallBroadCastReciever extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            //The screen off position
            Toast.makeText(context,"Screen is off",Toast.LENGTH_LONG).show();
        }
        else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            //The screen on position
     Toast.makeText(context,"Screen is on",Toast.LENGTH_LONG).show();
        }
    }}

然后执行以下步骤:          1。在活动中初始化接收器

CallBroadCastReciever broadcastReceiver = new CallBroadCastReciever();

2。在清单文件的清单文件中声明接收方

 <receiver android:name="com.android.CallBroadCastReciever">
<intent-filter>
    <action android:name="android.intent.action.SCREEN_OFF"/>
    <action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>

3。对于将动作和数据从活动发送到接收者,将其放在onCreate()或onStrat()方法下面的代码中

IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_OFF);

if (broadcastReceiver != null) {
    registerReceiver(broadcastReceiver, intentFilter);
}}

4。别忘了用onDestory()方法注销接收器

 protected void onDestroy() {
        super.onDestroy();
 if (broadcastReceiver != null) {
                unregisterReceiver(broadcastReceiver);
             } }