KeyEvents需要触发活动(Activity)。因此,硬件按键无法通过服务(Service)检测,因为服务没有托管活动。您可以请求SystemOverlay并创建一个透明的活动。但是,在API 26+设备上,这种方法似乎不起作用。
解决方法是通过AccessibilityServices设置观察者(observer)。这允许您全局检测硬件按键。
注意:将应用程序启用为辅助功能应用程序可能会导致重大安全问题,并且用户可能会警惕启用此功能。因此,在处理应用程序将处理的数据方面,建议在应用程序“透明”于用户的情况下使用此方法。此方法适用于所有API 21+设备,我尚未测试低于此版本的设备,因此可能有效也可能无效。
步骤:
- 创建一个XML文件,包括以下选项
<accessibility-service
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:packageNames="yourpackagename"
android:canRequestFilterKeyEvents="true"
/>
在清单文件中定义您的AccessibilityService
<service android:name=".Services.AccessibilityKeyDetector"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/accessibility_layout" />
</service>
创建一个AccessibilityService类
public class AccessibilityKeyDetector extends AccessibilityService {
private final String TAG = "AccessKeyDetector";
@Override
public boolean onKeyEvent(KeyEvent event) {
Log.d(TAG,"Key pressed via accessibility is: "+event.getKeyCode());
return super.onKeyEvent(event);
}
@Override
protected void onServiceConnected() {
Log.i(TAG,"Service connected");
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
}
- 创建一个MainActivity,用于处理此权限请求。
public class MainActivity extends AppCompatActivity {
private final String TAG = "Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkAccessibilityPermission();
}
public boolean checkAccessibilityPermission() {
int accessEnabled=0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled==0) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return false;
} else {
return true;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG,"Key pressed");
return true;
}
}