最近弄一块开发板,其中使用usb打印机后,每次自动重启均会自动触发系统usb授权弹窗,在无法改变Android源码的前提下,只能另想它途。
首先想到最常见的按键精灵…于是查寻按键精灵的原理和方法。
1 我们都知道Android 自动的工具 adb shell,里面自带有一个input工具,可以实现屏幕的点击,滑动,home键等。
如在Terminal中输入:
adb shell #进入系统 input keyevent KEYCODE_BACK #模拟按返回键 input keyevent KEYCODE_HOME #模拟按Home键 input tap 100 200 #在屏幕坐标(100, 200)处点击在这里插入代码片
那么是不是可以用代码实现呢?
当然是可以的。看实践后的代码
方法一:
/**
* 执行shell命令
*
* @param cmd
*/
private void execShellCmd(String cmd) {
android.util.Log.d(TAG, "execShellCmd: " +cmd);
try {
// 申请获取root权限,这一步很重要,不然会没有作用
Process process = Runtime.getRuntime().exec("su");
// 获取输出流
OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
Log.d("wjz restart ",t);
t.printStackTrace();
}
}
但是坑来了,跑起来以后说没有权限!!
所以这种方法需要root。但我并不打算对我的设备root…于是继续找方法
方法二(没有成功,但也并贴出来,留个纪念)
//使用 ProcessBuilder
int x = 35, y = 78;
String[] order = { "input", "tap", " ", x + "", y + "" };
try {
new ProcessBuilder(order).start();
} catch (IOException e) {
android.util.Log.d("GK", e.getMessage());
e.printStackTrace();
}
方法三 (仅做记录,未尝试,不做评论)
模拟MotionEvent
通用方法如下:
private void setSimulateClick(View view, float x, float y) {
long downTime = SystemClock.uptimeMillis();
final MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,
MotionEvent.ACTION_DOWN, x, y, 0);
downTime += 1000;
final MotionEvent upEvent = MotionEvent.obtain(downTime, downTime,
MotionEvent.ACTION_UP, x, y, 0);
view.onTouchEvent(downEvent);
view.onTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
}
方法四 (Instrumentation 本人成功使用的)
Instrumentation是Android的测试框架,通过他,可以模拟很多Activity操作,可以把测试包和目标测试应用加载到同一个进程中运行。既然各个控件和测试代码都运行在同一个进程中了,测试代码当然就可以调用这些控件的方法了,同时修改和验证这些控件的一些数据 :具体可以看这位兄弟做了详细介绍javascript:void(0)
还可以参考github上的这个项目
github源码 关于instrumentation的使用本人源码
new Thread(new Runnable() {
@Override
public void run() {
//模拟点击click事件
float x = 625;
float y = 723;
Instrumentation mInst = new Instrumentation();
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN,
x, y, 0));
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
x, y, 0));
}
}).start();
这里的两个动作处理,一个是按下一个是抬起,分别在x轴625位置和y轴的723位置。这样就是完整的模拟一个点击事件。想点击屏幕什么地方就修改x和y的值。我使用的工业版不需要考虑兼容性问题,所以直接写死了。
注意:Instrumentation务必启动于子线程
这个时候,你run的时候会提示你没有INJECT_EVENTS!而这个权限大家都知道是系统权限,一般的app肯定是没有办法获得的。
那就见招拆招…将APP变成系统应用。也就是对其进行系统签名.
本人尝试过的系统签名的几种方法
最近没有时间写,未完待续…