在Android使用到am和进行一些操作是非常方便的,比如一个重复自动的操作,具体用来实现一些什么是看个人需求了,接下来说对于am和input的使用。

 

    本文适用于已经大概去了解了am和input的朋友,如果暂时不了解,这里推荐两篇文章大家可以去看看,我就不说了,说了也多是抄,当然如果您是大牛,请忽略本文,本文主要是一些使用中的经验,和一些小技巧

am:

http://blog.csdn.net/u010164190/article/details/51384099

input:

http://blog.csdn.net/soslinken/article/details/49587497

 

 

首先是am:

    am命令主要用于让手机去做一些指定的命令,比如打开指定应用或activity

   而input命令则是模拟用户的点击。

先对这两个东西有个模糊的概念,这两个命令经常搭配在一起使用,

(暂时可以这样去理解它们两个,当然不是很恰当的例子:input是一步一步的去做某个事情,慢慢的去做,和人手去操作手机一样,一步接一步的,比如拨打10010查话费就是先点拨号然后点10010这5个数字,而am也可以暂时把它当成是input,但它是一个大的input,指哪打哪的那种,一步到位,比如我要打10010,adb shell am start -a android.intent.action.CALL -d tel:10086   这样一句就可以了,因为am命令能做到的事情“并不是很多”,而input可以实现完全像人手一样操作,所以这两个经常搭配使用。当然不完全是因为这个。)

 

接下来详细的说明这两个命令:

使用am和input有这样两种方式:

一种是在Android的命令行中,打开cmd或android studio中自带的命令行,cd到sdk的platform-tools文件夹下,在输入am或input命令之前记得加上adb shell

另一种就是实际应用到你的android代码中,在代码中是不需要加入adb shell的,只需要写命令就可以了。

 

事实上我们使用am和input大多是做一下比较投机的事情,比如一个游戏老是会有重复的点击事件,那我就可以通过命令去实现,还有时,我有很多机器,我要进行一个同样的操作,那也可以通过am和input去实现,am和input还可以结合Accessibility去做更多更方便的事情,很多人说这些按键精灵一样的还算是编程吗,我的看法是这样的,只要是通过你的代码带来了便利,起到了作用的东西,都应该是编程。

 

好了,不说废话了

我们假设现在有这么一个情况,我有一千台机器,每个机器上我都安装了一个软件,我要这一千个机器都需要更改个性签名,我们就可以用input和am写小脚本

 

我们捋一捋思路。

首先需要使用am跳转离个性签名Activity尽量近的地方

怎么才能知道APP的哪个界面是叫什么呢,有这样一个方法!

在命令行的platfrom-tools目录下输入:

 

adb shell "dumpsys window | grep mCurrentFocus
查看当前app的当前activity

 

 在代码中获取当前activity有点繁琐,实在需要可以私聊我发源码

 

我们在跳转到某个activity时需要注意一点重要

有的APP不要一步到位跳转到指定Activity

比如微信,频繁的am指定跳转可能会被封号,因为系统会认为你是机器人在点,而不是人为,如果条件允许,甚至可以是一步一步去input,但是比较麻烦,且要一些时间,因为每次input后是需要线程休眠的,通常是两秒,因为activity的跳转加载跟不上程序的运行速度,不进行线程休眠会导致你的脚步啪啪啪一套运行完了,但都是乱点,没有达到需要的效果

 

但是在我们假定的情况中是没有这个限制的,因为不是每个软件都像微信这样去判定

这时我们要考虑的就是去跳转到哪一个activity才最方便。

 

又有一点需要注意

不是所有am都可以简单的运行的,大多时候我们的需求都是需要root权限的,比如要跳转到安装的app的某个指定Activity,否则,会提示权限不够

获取root的方法如下:

  主要是通过操作Process来进行

Process process = Runtime.getRuntime().exec("su");
在执行am命令时还需要使用到输出流
完整的am执行方法如下:
public static void exeCmd(String cmd) {
try {
      Process process = Runtime.getRuntime().exec("su");
      OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
dataOutputStream.writeBytes(cmd + "\n");
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
t.printStackTrace();
}
}

参数cmd就是我们的am命令

这时就可以通过adb shell "dumpsys window | grep mCurrentFocus获取到activity,跳转到指定activity

但是我们在跳转时很多时候不只是跳转这么简单,我们会往am中传值提交到指定Activity中(通过Intent),但是要怎么知道指定的activity是接收的什么名字的值呢。

这就需要用到反编译.


反编译不会混淆四大组件的名字,因为混淆后会在AndroidManifest找不到,这时我们可以去看反编译出的代码进行传值,这样就轻易很多,怎么反编译我也不说了,大家应该都会。

 

到了指定activity通常还不能直接做完需求,需要搭配使用input。input在代码中怎么使用呢

也是通过我们的exeCmd方法,但是传值不再是一个单词的String 而是按键行为其实也是使用的String,只是我的意思是,它不只是简单的全一个String进去,因为我们要有面向对象的思想,如果可以面向对象,就去面,多少也是程序员,input和am不同,常用又有够多的共性,如果不进行这样一个封装,真的很乱,尤其是input一多,那么到底是这样去实现呢,如下:

会使用到String的Format方法格式化,format和C语言中的print很相似

 

举个点击的例子:

  

private static String TAP = "input tap %d %d";
public static String getTap(int x, int y) {
return String.format(TAP, x,y);
}

使用时:exeCmd(getTap(100,100))
长按,滑动...都是这么个事。
am和input结合起来就可以实现我们需要的了。

input如何输入中文?
public static void execShell(String cmd) {
try {
Process process = Runtime.getRuntime().exec("su");

OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
byte[] t_utf8 = (cmd + "\n").getBytes("UTF-8");
dataOutputStream.write(t_utf8);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
Log.e("test","execCommonShell[ "+cmd+" ] error.",t);
}
}

private static String TEXT_ALL = "am broadcast -a ADB_INPUT_TEXT --es msg \"%s\"";
public static String getTextAll(String content) {
return String.format(TEXT_ALL, content);
}


就是这样了,没有讲什么复杂的东西原理什么的,很拙劣,是自己使用中学到的经验,都是一些实际使用中的可能会用的到的,在记录下来的同时也希望可以帮到大家。

 

posted on 2017-04-03 11:49  霞辉  阅读(3590)  评论(0编辑  收藏  举报