KeyEvent系统事件模拟(Home键,Back键等)

问题介绍

前言:Remote Controller中手机通过蓝牙连接手柄,接受手柄发送的各种
数据消息,最终模拟出android标准的系统事件,即KeyEvent事件

简单的实现代码如下:

public static void simulateKeyEvent(final int KeyCode) {
    new Thread(new Runnable() {
        public void run() {
            // 开线程调用方法
            try {
                Instrumentation inst=new Instrumentation();
                inst.sendKeyDownUpSync(KeyCode);
            } catch (Exception e) {
                // 异常catch
            }
        }
    }).start();
}

注:keyCode查看KeyEvent.java中的各种系统事件
系统事件的详细介绍

上面介绍的简单方法以Service的形式开启,在单个进程和单个应用中使用是没有问题的,但是当按Home键或者其他方式退出当前应用之后,虽然service还在,但是上述的方法无法执行:Injecting to another application requires INJECT_EVENTS permission
提示没有权限,但是在AndroidManifest.xml中加上权限之后,仍然无法解决问题。

解决方法

解决该问题的关键是为当前应用的id变成系统级别的,可以理解成获取系统权限,解决方法围绕这点展开

  1. 在应用程序的AndroidManifest.xml中的manifest节点中加入
    android:sharedUserId=”android.uid.system”这个属性。
  2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
  3. 源码下使用mm命令来编译,生成的apk就有系统的权限。

具体的代码实现(没有本质区别,只是详细些)

package com.bingka.demo1;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.app.Instrumentation;

public class myService extends Service {

    private static final String TAG = "[bingka]";
    private static final int TIME = 5*1000;

    public static final int SYSTEM_EVENT_BACK_ID = 0;
    public static final int SYSTEM_EVENT_ENTER_ID = 1;
    public static final int SYSTEM_EVENT_UP_ID = 2;
    public static final int SYSTEM_EVENT_DOWN_ID = 3;
    public static final int SYSTEM_EVENT_LEFT_ID = 4;
    public static final int SYSTEM_EVENT_RIGHT_ID = 5;

    Handler handler = new Handler(); 

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"onBind...");
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        handler.postDelayed(runnable, TIME);
        Log.d(TAG,"onStartCommand...");
        return super.onStartCommand(intent, flags, startId);
    }

    //timer
    Runnable runnable = new Runnable() {  
        @Override  
        public void run() {  
            // handler to implement the timer 
            try {  
                handler.postDelayed(this, TIME);
                sendSelfEvent(SYSTEM_EVENT_UP_ID);
                android.util.Log.d(TAG,"KeyEvent done..."); 
            } catch (Exception e) {   
                e.printStackTrace();  
                android.util.Log.d(TAG,"KeyEvent exception..."); 
            }
        }  
    };


    /*simulation key event of system
        KeyEvent: 1.KEYCODE_BACK
                  2.KEYCODE_ENTER || KEYCODE_DPAD_CENTER
                  3.KEYCODE_DPAD_UP,KEYCODE_DPAD_DOWN,
                    KEYCODE_DPAD_LEFT,KEYCODE_DPAD_RIGHT                          
    */
    private synchronized void sendSelfEvent(final int systemEventId){
        Thread th = new Thread(){
            //can not run in UI thread
            public void run() {
                Instrumentation inst = new Instrumentation();
                String logInfo = "";
                try {
                    switch (systemEventId){
                        case SYSTEM_EVENT_BACK_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
                            logInfo = "KeyEvent.KEYCODE_BACK";
                            break;
                        case SYSTEM_EVENT_ENTER_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
                            logInfo = "KeyEvent.KEYCODE_ENTER";
                            break;
                        case SYSTEM_EVENT_UP_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
                            logInfo = "KeyEvent.KEYCODE_DPAD_UP";
                            break;
                        case SYSTEM_EVENT_DOWN_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
                            logInfo = "KeyEvent.KEYCODE_DPAD_DOWN";
                            break;
                        case SYSTEM_EVENT_LEFT_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_LEFT);
                            logInfo = "KeyEvent.KEYCODE_DPAD_LEFT";
                            break;
                        case SYSTEM_EVENT_RIGHT_ID:
                            inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_RIGHT);
                            logInfo = "KeyEvent.KEYCODE_DPAD_RIGHT";
                            break;
                        default:
                            logInfo = "This behavior does not match system event ! ";
                            break;
                    }
                    android.util.Log.d(TAG, logInfo);
                } catch (Exception e) {
                    android.util.Log.d(TAG," Instrumentation Exception = "+e);
                }
            };
        };
        th.start();
    }
}

注:上述代码实现了返回键,确认键,上,下,左,右键的系统事件模拟,其他事件可自行扩展。

你可能感兴趣的:(android基础)