谈Android模拟点击的价值和实现

“Action!”,欢迎收看这期大型扯淡实用类技术节目,《小明讲故事》,大家好我是小明!今天的主题是如果孙膑、诸葛亮和曾国藩是程序员,会怎么实现Android模拟自动点击。此处可以有Android手机广告,没有赞助商提供,我们继续。很难想象那三位历史大佬是程序员吧?且不说他们,我们撸清下Android模拟点击对我们产生的价值,“唯利是图”一下下!

内容思维导图

一.模拟点击的价值

  1. 有这么种情况,手机邮件每天都有很多邮件,邮件里也有一些不想去看或者是过期了的未读邮件,莫名的强迫症都想去掉那些罪恶的小红点,我都懒得的点击全选设置成已读,如果有个自动点击该多好;
  2. 又有这么种情况,有个手游我很喜欢玩,但是升级有很慢,刷怪有很单调,如果有个小外挂帮我点击,自己玩其他的事去该多好?这时,你是不是想回答“嗯,是的,最好有个帮忙点击微信红包什么的就真真是极好极好的了”。
  3. 最后这样的情况,尽管我们懒,尽管我们考试想带小抄作弊,但我们也是能站在宇宙中心呼唤爱的嘛。对于有些身体不便的手机使用人群确实要需要使用某些手机功能,模拟点击是不是特别有爱。爱,又是多方面的,在你们的TA手机上一旦是接受自己的信息就自动点击打开,然后播放一句“亲爱的,我来了,你在哪?”,又是多浪漫的事情。

好,模拟点击的价值就显而易见了,基本是以下3点:

1. 无障碍爱心服务。[爱还是排在第一位比较合适]
2. 更自动完成特定日常使用。
3. 作弊外挂。[难免有些小兴奋吧?]

二.MotionEvent实现模拟点击

1. 实现原理

1)获取被点击的View。
2)模拟点击事件MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP。

2. 实现过程

哦,冷落了历史三位大佬挺久了。有请鬼谷先生得意弟子孙膑!
1)孙膑瞒天过海

自从孙膑被同窗庞涓嫉妒猜忌而被陷害落得一个膑刑(他从轻只被挑了膝盖骨),庞涓为了掩盖他的罪恶和野性,把孙膑供养起来一心想套出孙膑从鬼谷先生得到的《孙子兵法》,后来孙膑从外人得知这一切的受罪都是庞涓所为,除了绝望和无奈外,还是想尽快逃离庞涓的魔爪。
就这样情况下,孙膑来了一招孙子兵法的瞒天过海,装疯卖傻骗过了庞涓不再逼他默写孙子兵法同时也减去对自己提防,最后在一个夜黑风高的夜晚被齐国使臣淳于髡救走。

①.孙膑逃离就是犹如一次MotionEvent事件。
②.装疯卖傻就犹如假装点击触动MotionEvent.ACTION_DOWNMotionEvent.ACTION_UP事件

2)Show Code

//孙膑瞒天过海
private void manTianGuoHai(View view, float x, float y) {

    long downTime = SystemClock.uptimeMillis();
    
    //装疯
    MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,
            MotionEvent.ACTION_DOWN, x, y, 0);
    downTime += 1000;
    
    //卖傻
    MotionEvent upEvent = MotionEvent.obtain(downTime, downTime,
            MotionEvent.ACTION_UP, x, y, 0);
            
    view.onTouchEvent(downEvent);
    view.onTouchEvent(upEvent);
    downEvent.recycle();
    upEvent.recycle();
}

2)查看效果

Motionevent模拟点击

哎哟喂,这也行。我也装一个傻卖个萌什么的!现在都流行语音支付,如果小明捡到志玲姐姐的手机,我一定要试试她手机语音支付,对着志玲姐姐的手机娇滴滴的喊“萌萌站起来,加油,萌萌站起来”。那为人兄,嘿嘿嘿,呕吐袋已准备了在座椅右边!!

借着有志玲姐姐语音的高德地图导航,我们回到了三国赤壁。正好碰见孔明先生。“晚生小明,久仰诸葛先生大名!”,孔明见短发短袖短裤短腿短拖鞋的小明惊悚道:“何方妖怪?”,“噗~~

三.AccessibilityService实现模拟点击

1. 基本概念

AccessibilityService是Android提供有某些障碍手机人群使用的辅助服务,可以帮助用户实现点击屏幕等一些帮助。是一个很有爱的服务。
官方对这个功能介绍如下:

Many Android users have different abilities that require them to interact with their Android devices in different ways. These include users who have visual, physical or age-related limitations that prevent them from fully seeing or using a touchscreen, and users with hearing loss who may not be able to perceive audible information and alerts.

2. 实现原理

1)通过resource-id获取对应的View。

nodeInfo.findAccessibilityNodeInfosByViewId(resId);  

2)或者通过带text属性的View。

nodeInfo.findAccessibilityNodeInfosByText(text);

3)执行AccessibleService的指定方法实现点击。

targetNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);

3. 实现过程

1)诸葛亮草船借箭

这个大家再熟悉不过了,舌战群儒后的草船借箭啦。

周瑜说“我这里只有船和水军,我没有‘贱’,孔明兄还是你来‘贱’吧!”,孔明君子之躯何贱之有啊,“短时间要我‘贱’,可以,你我通力合作可否?”。“行,只要你拿出‘贱’来,我同意,立下下军令状吧”周瑜得意挑衅。智比天高的诸葛亮想“我又不作‘贱’,还是找个‘贱’人来借一把吧!”

这样妙极了吧,曹操这么多‘贱’,草船使过来了,抖一抖‘贱’掉了一船,拿去!

①.舌战群儒后的合作击退曹操好比AccessibleService服务。
②.周瑜提供船和水军就是具体的findAccessibilityNodeInfosByViewId(resId)findAccessibilityNodeInfosByText(text)
③.诸葛亮去敲鼓正是performAction(AccessibilityNodeInfo.ACTION_CLICK);

2)如何获取resource-id或text
①.如何你是获取自己应用的resource-id,那就是布局xml定义的@id/shuijun或者@+id/chuan
②.别人的软件,那就通过dump出view层级outline查找出resource-id或text。

dump页面分析

3)申明使用的服务要求
诸葛亮要申明我可以用兵用船。
①click_config.xml文件配置

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service    xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/click_auto"
    android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged"
    android:packageNames="com.youmi.android.addemo"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="100"
    android:accessibilityFlags=""
    android:canRetrieveWindowContent="true"/>

②AndroidManifest.xml文件配置

<service
    android:label="@string/app_name"
    android:name="com.minggo.autoclick.ClickService"
    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/click_config"/>
</service> 

4)授权使用辅助服务应用
合作达成,又要授权给诸葛亮办事才行。

授权启动辅助服务

5)Show Code
最后就约上鲁肃去借箭

//借箭(点击)
private void performClick(String resourceId) {

    Log.i("mService","点击执行");

    AccessibilityNodeInfo nodeInfo = this.getRootInActiveWindow();
    AccessibilityNodeInfo targetNode = null;
    targetNode = findNodeInfosById(nodeInfo,"com.youmi.android.addemo:id/"+resourceId);
    if (targetNode.isClickable()) {
        targetNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
}


//调用兵力(通过id查找)
public static AccessibilityNodeInfo findNodeInfosById(AccessibilityNodeInfo nodeInfo, String resId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(resId);
        if(list != null && !list.isEmpty()) {
            return list.get(0);
        }
    }
    return null;
}

//调用船只(通过文本查找)
public static AccessibilityNodeInfo findNodeInfosByText(AccessibilityNodeInfo nodeInfo, String text) {
    List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(text);
    if(list == null || list.isEmpty()) {
        return null;
    }
    return list.get(0);
}

6)查看效果图

Accessibility服务点击

‘贱’周瑜还是拿到了十万,不过那口来到喉咙边上的老血差点没有喷出来。估计周瑜恨不得借这次庆功约诸葛亮到自家澡堂,赠与他一个,能为您的家庭提供24小时全面保护的舒肤佳。

这样共享半边天的日子估计是不长久的,很快就会瓦解合作闹得翻天覆地,天翻了我们回到地上吧!人生多变啊,不久将又开始仰望“蓝蓝的天空~哎呀!”,顿悟不要逆天,上天还是可以的,心情大好,去剃个头重新开始吧。

四.借助反射实现模拟点击

1. 基本概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

注意:反射本身是违背面向对象的封装原则的,所以它有破坏性;反射被使用也是很广泛的Gson,Afinal框架,Spring依赖注入注解等等。两面性看待这个机制,切勿死板。

2.基本操作

1)获取实体类型

Class clazz = spotManager.getClass();

2)获取类的变量

Field f = clazz.getDeclaredField("F");
f.setAccessible(true);//加上这个才能读取private属性

3)获取变量值

o oInstance = f.get(spotManager);

3. 实现过程

1)曾国藩反间计
《曾剃头发廊》眼前一亮啊,进去剃个头。“客官,老生看您天堂饱满,眉清目秀...”,“哎哟~您老应该就是曾国藩,曾大人吧,晚生小明,失敬失敬啊?辣椒来一根不咯,要不我请您吃臭豆腐好不咯?”。曾大人舔舔舌头,“好,我们先去吃臭豆腐,到此处不吃臭豆腐等于白来。”,“曾大人,可否讲讲您如何策反韦俊呢?”,“小明,我们边走边聊”...

“天京事变”,韦俊受到二个韦昌辉牵连,随时会被叫回去问斩。
韦俊好猎和下棋,我叫康福去山上等他与之相遇,再跟他下棋并且要赢他。棋下了一头半个月了,终于逮到机会,天国来旨要求韦俊回京(南京),康福游说他,并且挑明自己的身份,表达我对他的赏识和恳邀之意。
这样的事态,他选择了我,并告知他们打战之术,我记录为“长毛战术”。池州就算是我涤生的了。

"曾大人,您让晚生佩服不已,康福他着~么厉害!晚生寻他千百度,那人却不在灯火阑珊处撒!"。曾大人沉思一下,“这,,,你得问问唐浩明咯!”。。。

①韦俊潜在背叛的可能性就是反射机制破坏性。
②韦俊好猎好下棋就是侧面暴漏让人接近的spotManager.getClass()f.setAccessible(true);
③韦俊对康福暴漏自己身份也只能是放下手中的剑被明目张胆策反o oInstance = f.get(spotManager);

2)如何找到要反射的那个实体
要测策反韦俊,不能跑错山头了,要不然只能演一出“皇上,你还记得当年大明湖畔的夏雨荷吗?”。这可是重头戏啊,我们好好找找山头先。

五.分析有米插屏广告

整一块天都不是自家打下来的,我们来顺应天意吧。找找策反大道,看能不能得道成仙。

1. dump一下有米插屏广告页面

有米插屏广告.png

我们从图中只能发现横屏广告的webview(得到这个已经可以用之前两种方法实现点击这个地方,干你想干的事),但没有插屏广告view的层级信息。天无绝人之路,好戏都在后头。

2反编译查找位置

1)确定启动广告类入手

btnShowSpot.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            // 展示插屏广告,可以不调用预加载方法独立使用
            //从这里入手,分析插屏广告代码,找到对应的广告view
            SpotManager.getInstance(mContext)
                    .showSpotAds(mContext, new SpotDialogListener() {
...

确定是在SpotManager类里边折腾。
2)反编译SpotManager
①看看大概有什么属性:

private o F;
protected SplashView n;

这两个属性最为可能,其他是String,int,boolean属性。Splash顾名思义是闪屏这个是开屏广告,先留着,分析o F这个地。

反编译找到调用了b方法

②接着我们进入a方法中

a方法中的重要信息

果然有o F这个实例新增和使用k方法。
3)反编译o类中查看属性

反编译o类

韦俊放下剑跟康福去见曾大人吧,一切都结束了。放下屠剑立地成仁吧。

3. 瞄准目标反射带出

/**
 * 1.通过反编译[studio自带有]查看分析o F(o混淆后的类名称,F是o的实例)是广告实例。
 * 2.o类中的变量w是Imageview类型。
 * 3.就以上足够可以获取插屏广告图片实体,逐一反射获取对应的属性值。
 * 4.扩展,如果反编译出现很多属性,那样编写一个反射遍历其中属性,逐一暴力破解。
 */
private void getO(){
    SpotManager spotManager = SpotManager.getInstance(mContext);
    Class clazz = spotManager.getClass();
    Field f;
    try {
        f = clazz.getDeclaredField("F");
        f.setAccessible(true);
        Class deClazz = f.getType();
        Log.i("mService","F类型-->"+deClazz.getSimpleName());
        if(f.get(spotManager)==null){
            Log.i("mService","广告类为空");
        }else if(f.get(spotManager) instanceof o){
            Log.i("mService","是统一类型");
            o adO = (o) f.get(spotManager);
            Class oClazz = adO.getClass();
            Field imgField = oClazz.getDeclaredField("w");
            imgField.setAccessible(true);

            if (imgField.get(adO) instanceof ImageView){
                Log.i("mService","属性m是Imageview");
                final ImageView adImageView = (ImageView) imgField.get(adO);
                Log.i("mService","广告image-->"+adImageView.getId());
                if (adImageView==null){
                    Log.i("mService","广告image 为null");
                }else {
                    if(adImageView.isClickable()){
                        Log.i("mService","广告image可以点击");
                    }else{
                        Log.i("mService","广告image不可以点击");
                    }
                    Log.i("mService","广告宽高-->"+adImageView.getLayoutParams().width+","+adImageView.getLayoutParams().height);

                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {

                            setSimulateClick(adImageView,adImageView.getWidth()/2,adImageView.getHeight()/2);
                        }
                    },3000);
                }
            }
            //adImageView.setDrawingCacheEnabled(true);
            //adImageView.getDrawable();

            //ImageView imageViewxml = (ImageView) findViewById(R.id.imageView);
            //imageViewxml.setImageDrawable(adImageView.getDrawable());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4. 查看效果

反射有米插屏广告自动点击效果图

“曾大人,难怪你的一生就像开挂似的,你咋不上天啊!!”话音未落,曾大人胸口中央一团紫光一闪一闪,“叮咚,叮咚,叮咚...”哇还会作响,“嚓~”的一声曾大人不留一丝青烟冲进云中。

六.总结和扩展

1. 如果天是你们家的就直接瞒天过海。
2. 如果天一半是你们家的就草船借箭。
3. 如果天跟你没半毛钱关系的就反间计。
记住了,我从来也没有提倡大学生特别是计算机专业的特别是有班长一职的同学,组织班上同学以这种方式挣得班会费哈。因为我大学的做班长期间就没做。
节目到了尾声了,此处应该有掌声。噼里啪啦...谢谢,谢大家,让我们再次以热烈的掌声感谢今天重量级嘉宾孙膑,诸葛亮和曾国藩老师,各位老师慢走~~!

七.源码地址

https://github.com/minggo620/AndroidAutoClick
谢谢收看这期大型扯淡实用技术类节目,《小明讲故事》。哦,忘了~~曾大人,您还在吗?您还没有给我剃头呢!!!

【原创出品 未经授权 禁止转载】
【欢迎微友分享转发 禁止公号等未经授权的转载】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,078评论 25 707
  • 今天很早就醒了,主要是帮妹妹设了六点半闹钟,然后把自己吵醒后躺一会就起来了。起床后堂弟就来叫我去逛街,昨天晚...
    天空蓝上阅读 184评论 0 0
  • 李白只是一只修炼了上千年的狐妖。一天,淘气的李白乔装打扮了一下。去京城玩玩。他刚进京城,就看见化做凡人的龙族少主韩...
    信白爱恋阅读 3,958评论 0 5
  • 前言 在日常开发的过程中,我会经常用到Git来管理我的代码,它的优势是非常明显的,这里就不赘述了。那既然这个工具是...
    flemingchen阅读 433评论 0 1