KeyEvent 需要触发 Activity。因此,无法通过服务检测到硬件按键,因为服务没有主机活动。你可以要求一个 SystemOverlay,并创建一个透明的 Activity。但这种方法似乎不适用于 API 26+ 设备。
解决方法是通过 AccessibilityServices 设置观察者。这使您可以全局检测硬件按键。
注意:将应用程序启用为辅助功能应用程序可能会导致重大安全问题,用户会警惕启用此功能。因此,在您的应用程序对于您的应用程序将要处理的数据对用户“透明”的情况下,这将是可取的。此方法适用于所有 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());
//This allows the key pressed to function normally after it has been used by your app.
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) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/** request permission via start activity for result */
startActivity(intent);
return false;
} else {
return true;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG,"Key pressed");
//this prevents the key from performing the base function. Replace with super.onKeyDown to let it perform it's original function, after being consumed by your app.
return true;
}
}