在Android设备上,只有按钮是音量按钮和电源按钮,我想让应用程序按下电源按钮(长和短)。这是怎么做到的?
答案 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+权限:
向[{3}} 询问系统权限(这不是正常或易受攻击的权限)。这不是用户权限,所以你应该真的知道,你在做什么,通过要求它。
var url = "http://google.com";
window.open(url, '_system');
启动服务并为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));
}
}
}
}
添加特殊视图
等待WindowManager
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 ("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);
} }