使用Accessibility Service监听按键

最近开发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();

 

 

 

 

 

 

上一篇:关于C#获取微信小程序openId


下一篇:#贪心#CF605A Sorting Railway Cars