长按检测电源按钮

时间:2016-08-21 13:06:37

标签: android events

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

我试过这个:

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

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

修改

这就是我放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
            }
        }

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

另外,我试图找出当用户点击电源按钮时如何删除对话框我试过这个:

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

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

11 个答案:

答案 0 :(得分:16)

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

基本上,它的作用是

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

    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));
                }
            }
        }
    }
    
  2. 启动服务并为WindowManager添加特殊视图

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

    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
            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;
        }
    }
    
  4. <强>清单:

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

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

答案 1 :(得分:6)

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

只需将Broadcastreceiver注册到以下this one

"_id" : ObjectId("57c47c86ef20310d0ebdd2af"),
    "full_count" : 12643,
    "version" : 4,
    "ad5913d" : [
        "800B67",
        37.7181,
        47.4987,
        143,
        45000,
        459,
        "3665",
        "F-UBBL1",
        "",
        "",
        1472494567,
        "TZX",
        "",
        "",
        0,
        -64,
        "VTJUI",
        0
    ],
    "ad55d85" : [
        "",
        37.9425,
        43.5465,
        104,
        45000,
        504,
        "5532",
        "F-UBBN1",
        "GLEX",
        "",
        1472494551,
        "",
        "",
        "",
        0,
        -64,
        "GLEX",
        0
    ]
}

不要忘记添加以下权限:

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

答案 2 :(得分: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);
}

如果您想停止系统弹出,请使用下面其中一个答案中指定的onWindowFocusChanged方法。

输出将显示带有“Clicked:26”的吐司,如下所示。enter image description here

答案 3 :(得分:4)

使用此

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

当你想要捕获那个事件时,请执行此操作

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

可以使用广播接收器完成。见this answer

答案 4 :(得分:3)

试试这个:

<tr>
                    <td><label>  Product : </label></td>
                    <td>
                        <select id="proID" name="proID" >
                           <option>Select Product</option>
                                     <?php
                                       $getProId = $pi->getAllProd();
                                        foreach($getProId as $pi){
                                        ?>          
                            <option value="<?php echo $pi['proID'] ;?>" id="<?php echo $pi['proUPrice'];?>"><?php echo $pi['proName'] ;?></option>
                                        <?php } ?>
                        </select> 
                             <input type="text" size="30" name="display" id="display" />
                             <p>
                            <input type="button" id="showVal" value="Value Property" />     
                            </p>    
                     </td>              
                    </tr>
<script>(function() {

    // get references to select list and display text box
    var sel = document.getElementById('proID');
    var el = document.getElementById('display');


    function getSelectedOption(sel) {
        var opt;
        for ( var i = 0, len = sel.options.length; i < len; i++ ) {
            opt = sel.options[i];
            if ( opt.selected === true ) {
                break;
            }
        }
        return opt;
    }

    // assign onclick handlers to the buttons
    document.getElementById('showVal').onclick = function () {
        el.value = sel.value;    
    }   

}());</script>

答案 5 :(得分:3)

  

长按....请试试这个......

rails12factor

长按按钮功能显示吐司测试...

enter image description here

答案 6 :(得分:3)

R。Zagórski上面使用的方法很长时间以来一直对我有效,但是从Android 9的某些版本开始, onCloseSystemDialogs 方法停止接收“ globalactions”。

作为一种解决方法,我的应用程序已在使用辅助功能。在AccessibilityService内部,您可以在onAccessibilityEvent中添加此代码

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    Log.i(TAG,"Accessibilityevent");
    if (event == null || event.getPackageName()==null||event.getClassName()==null)
        return;


    if (event.getClassName().toString().contains("globalactions")){
        //TRIGGER YOUR CODE HERE

    }
        ....

请注意,如果我在注释中输入“ TRIGGER YOUR CODE HERE”,我实际上只是在调用 onCloseSystemDialogs 中相同的代码。

请注意,到目前为止,该功能仅在运行最新Android的Pixel 2上进行了测试。我没有任何其他手机运行的是最新版本,因此无法测试该解决方案是否在手机上具有足够的通用性。

答案 7 :(得分:2)

从Skizo-ozᴉʞS问题,我明白,你实际上想要防止电源按钮的行为,这是无法做到的。就像按下主页按钮一样,无法阻止Android中的某些事件,以避免人们拥有无法退出的应用程序。

答案 8 :(得分:1)

您可以通过覆盖onKeyDown方法来捕获电源按钮事件

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
            Log.e("key","long");
            /*//disable the system dialog
            Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);*/
            Toast.makeText(getApplicationContext(),"Power",Toast.LENGTH_SHORT).show();
        }
        return super.onKeyDown(keyCode, event);
    }

据我所知,我们不能在户外活动(例如后台服务)

答案 9 :(得分:1)

试试这个:

 @Override
   public boolean onKeyLongPress( int keyCode, KeyEvent event ) {
     if( keyCode == KeyEvent.KEYCODE_POWER ) {
       //Handle what you want in long press.

       return true;
     }
     return super.onKeyLongPress( keyCode, event );
   }

在Manifest中添加:

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

答案 10 :(得分:1)

公认的答案可以在Android Oreo之前完美运行,但不能在Android P中使用。 要使其在android P中工作,您需要使用辅助功能服务

服务等级

import android.accessibilityservice.AccessibilityService;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;

import com.bm.yucasa.Utils.LocationSetup;

import static com.bm.yucasa.controller.AppController.TAG;

public class PowerServiceTwo extends AccessibilityService {
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.i(TAG,"Accessibilityevent");
        if (event == null || event.getPackageName()==null||event.getClassName()==null)
            return;


        if (event.getClassName().toString().contains("globalactions")){
            LocationSetup locationSetup = 
LocationSetup.getInstance(PowerServiceTwo.this);
            if (locationSetup.isConnected) {
                locationSetup.startOnDemandLocationUpdates(false, "0");
            } else {

                //Toast.makeText(getApplicationContext(), "please check gps", Toast.LENGTH_SHORT).show();
            }

        }
    }

    @Override
    public void onInterrupt() {

    }
}

由于您无法使用startService()方法启动辅助功能,因此

这就是启用它的方法。

Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openSettings);