最近开发Android PDA项目,需要软件在后台运行,有一项功能需要监控用户按键,onKeyDown只能在前台监听按键,无法后台运行,所以只能采用Accessibility Sevice,其可在后台运行。在Accessibility Service中监听按键,将键值以广播形式发送出去,在MainActivity中接收该广播,并处理按键信息。方法介绍如下。
步骤一
在Android manifest.xml中加入如下信息。
<service
android:name=".keyService"
android:label="@string/app_name"
android:enabled="true"
android:exported="true"
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/keyservice_config" />
</service>
kerservice_config.xml文件如下
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:description="@string/accessibility_description"
android:notificationTimeout="100"/>
步骤二 keyService实现
继承AccessibilityService,通过onKeyEvent监听按键,并将键值和按下或弹起状态通过广播发送出去。在MainActivity中接收该广播。步骤三,
public class keyService extends AccessibilityService {
private final int KEYCODE_1=110;
private final int KEYCODE_2=111;
//
@Override
protected boolean onKeyEvent(KeyEvent event){
int key = event.getKeyCode();
switch(key){
case KEYCODE_1:
Intent f1intent = new Intent("allinkcn.broadcaster.FUNCTIONKEYDOWN");
f1intent.putExtra("keycode", KEYCODE_1);
f1intent.putExtra("keyAction",event.getAction());
sendBroadcast(f1intent);
break;
case KEYCODE_2:
Intent f2intent = new Intent("allinkcn.broadcaster.FUNCTIONKEYDOWN");
f2intent.putExtra("keycode", KEYCODE_2);
f2intent.putExtra("keyAction",event.getAction());
sendBroadcast(f2intent);
break;
default:
return super.onKeyEvent(event);
}
return false;
}
@Override
public void onInterrupt() {
}
@Override
public void onCreate() {
Log.d("key", "keyservice::onCreate");
super.onCreate();
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// TODO Auto-generated method stub
}
}
步骤三,在MainActivity中接收keyService发送的广播信息。
private BroadcastReceiver keyReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int keyCode=intent.getIntExtra("keycode",-1);
int keyAction=intent.getIntExtra("keyAction",-1);
switch(keyCode){
case KEYCODE_1:
if(keyAction==KeyEvent.ACTION_DOWN)
isL1keyDown=true;
if(keyAction==KeyEvent.ACTION_UP)
isF1keyDown=false;
break;
case KEYCODE_2:
if(keyAction==KeyEvent.ACTION_DOWN)
isL2keyDown=true;
if(keyAction==KeyEvent.ACTION_UP)
isL2keyDown=false;
break;
default:
break;
}
当然,需要先注册该广播。
IntentFilter filter=new IntentFilter();
filter.addAction("allinkcn.broadcaster.FUNCTIONKEYDOWN");
registerReceiver(keyReceiver,filter);
存在问题,在每次关机后,相应的辅助功能都会被关闭,所以需要每次开机后手动开启服务。如果在APP中开启,需要APP具有系统权限。
方法如下:
在AndroidManiferst.xml中声明权限
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
在APP启动入口处添加:
Settings.Secure.putString(getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
"com.gdvictor.victortool/com.gdvictor.victortool.IntelligentUpgrade.MyAccessibilityService");
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 1);
APP中采用以下方法判断服务是否开启。
AccessibilityManager am=(AccessibilityManager)this.getSystemService((this.ACCESSIBILITY_SERVICE));
List<AccessibilityServiceInfo>serviceinfos=am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
String id=null;
boolean isServiceOpen=false;
for(AccessibilityServiceInfo info :serviceinfos){
id=info.getId();
if(id.contains("keyService")){
isServiceOpen=true;
break;
}
}
if(!isServiceOpen) {
Toast.makeText(getApplicationContext(), "xxx辅助功能未开启!", Toast.LENGTH_SHORT).show();