前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你使用Android原生写一个订票机器人

手把手教你使用Android原生写一个订票机器人

原创
作者头像
brzhang
修改2023-12-15 07:54:29
2880
修改2023-12-15 07:54:29
举报
文章被收录于专栏:玩转全栈

前篇文章yy了一下自动化测试工具Cypress的另类玩法,引入了一个知识点,订票机器人(ps,这个本身不是什么值得炫耀的东西,实际上也没有什么太大技术难度),今天就索性在加点料,即我们要聊的是,在原生的Android上实现一个订票机器人的话,该怎么操作?

因此,学习本文,你将学会不借助任何工具,也无需依赖任何三方Android库,实现一个订票机器人,代码完全自己可控,不怕别人给你的apk里面埋雷。当然,本文是不会提供任何源码给到你,但是会给你打通所有环节的技术内幕。

要在Android上实现一个订票机器人,其实需求可以转化为,Android可以自动开打开某个App,然后,进入某个App的行程预定页面,填上你的出发地,目的地,然后点击查找,当然,为了预定到比较廉价的机票,我们是需要设定一个阈值的,当阈值达到某个点之后,我们就让手机震动或者启动闹铃,告知你该出手了,这一切都是自动发生的。整个交互的过程如下图所示:

核心的原理部分

要实现一个自动化订票机器人服务,需要借助于Android上的 无障碍服务 ,无障碍服务是一种应用,可提供界面增强功能,来协助残障用户或可能暂时无法与设备进行全面互动的用户完成操作。例如,正在开车、照顾孩子或参加喧闹聚会的用户可能需要其他或替代的界面反馈方式。但是没想到这个玩意被黑产用到了极致,如大名鼎鼎的 auto.js ,ctrl.js 就是基于这个服务开发的。

step1.我们创建一个Android工程,这个无需多讲。

step2.编写一个服务,需要继承android.accessibilityservice.AccessibilityService,并且实现onAccessibilityEvent,和onInterrupt,这两个方法,我们的主要逻辑将会放在onAccessibilityEvent里面。在下面这个框架中。

代码语言:javascript
复制
package com.example.android.apis.accessibility;

import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;

public class MyAccessibilityService extends AccessibilityService {
...
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
			Log.d(TAG, "onAccessibilityEvent: "+event.toString());
        // 拦截事件并处理
        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_VIEW_CLICKED:
                Log.i(TAG, "A view was clicked: " + event.getContentDescription());
                break;
            // 其他事件类型...
        }
    }

    @Override
    public void onInterrupt() {
			// 在服务被中断时调用(例如,当用户禁用无障碍服务时)
    }
}

step3.在AndroidManifest.xml文件中补充一下服务的描述,这个需要放在application 的下面,这一步骤的主要作用是注册我们这个服务,这样一来,在 咱们这个 App 启动的时候,这个服务就注册到了系统里面了。

代码语言:javascript
复制
<service android:name=".MyAccessibilityService"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:exported="false">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" />
        </service>

step4.新增上面Android描述文件引用的资源文件**/res/xml/accessibility_service_config.xml,注意,需要将**accessibilityEventTypes设置为 typeAllMask,这里是为了简化,表示捕捉所有的事件。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="<http://schemas.android.com/apk/res/android>"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackVisual"
    android:notificationTimeout="100"
    android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagRequestTouchExplorationMode|flagRequestEnhancedWebAccessibility|flagReportViewIds|flagRetrieveInteractiveWindows"
    android:canRetrieveWindowContent="true"
    >
</accessibility-service>

好了,所以的步骤都讲解完毕了,现在就是编译,启动我们的 App,然后,到设置里面去定位到,无障碍已下载的应用。打开如图所示的设置,开启这两个 switch,当然,我们也可以使用程序的方式在我们的 App 的 activity 中去实现一键导航到这里,引导用户打开这两个设置,这里是为了演示的方便,就不去做的一一俱全了。注意!!!,下图这个是高风险操作哦,千万不要随便给不信任的 App 开启 无障碍 这个设置

我们随便开启一个应用,比如Android 的 demo 应用,然后点击里面的按钮看看;我这里打了一个断点,点击这里,我们看到,EventType 为 TYPE_VIEW_CLICKED 的时间被我们捕捉到了,而且我们可以看到这个事件来源哪个应用,这里是包名为’com.example.myapplication’的应用,同时我们还知道点的是一个 Button,另外下面我还没截图出来的,有这个 Button上的 文字。

好了,有了以上基础,实现一个订票机器人还是难事吗?

基于我们上面的简单的demo,我们知道通过AccessibilityService 的功能,我们可以做到

  • 捕捉任何 App 的任何事件,事件的类型可以在这里看。其中包括界面的变更按钮的点击
  • 我们可以查找到当前活动的 App 页面上的各种元素,textviewbuttonoptions 等等。
  • 我们可以对 editortext 设置内容,对 option 进行选择,对按钮进行点击事件的发送。

这所有的操作,我们都可以在onAccessibilityEvent触发,只需要通过捕获我们上面提到的几种事件即可。

一些技巧

1、如何判断当前应用是否是某应用,对,就是通过包名来判断,有人可能会问,我怎么知道包名呢?很简单,你打开这个应用随便点下,通过我们 log 到的事件看看,就可以找到他的包名,当然还有其他办法。

代码语言:javascript
复制
private boolean isMainScreen(AccessibilityEvent event) {
        // 检查当前界面是否是App的主界面
        // 这通常需要检查类名或者界面的特定内容
        return event.getClassName().equals("com.example.bookingapp.MainActivity");
 }

2、如何找到某个控件,进行一些操作呢?这里拿找一个按钮来举例

代码语言:javascript
复制
List<AccessibilityNodeInfo> bookingButtons = rootNode.findAccessibilityNodeInfosByViewId("com.example.bookingapp:id/booking_button");
//do something

3、通过闹铃提醒用户有合适的票了

代码语言:javascript
复制
private void playAlarmSound() {
    Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    if (alarmUri == null) {
        alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
    }
    Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), alarmUri);
    if (ringtone != null) {
        ringtone.play();
    }
}

总结

AccessibilityService 的熟练了解于使用,可以解决我们日常工作生活中的一些问题,出了本文的订票机器人的 demo,实际上还可以用来做自动化测试,是的,你没听错,的确是可以,另外也有一些另类的玩法,比如有人使用AccessibilityService 做了一个 微信消息防止撤回的工具,你能思考出来,他是怎么实现的吗?哈哈,我想如果你已经做出了本文的订票机器人,相信在实现一个 这种让人又讨厌有喜欢的工具并不是什么难事,对的,就是监听聊天界面的变化或者监听应用通知,将消息备份一份到本地存储中,当然是你的应用的的存储了,然后就可以通过前后消息定位去检索了。然后嘿嘿,曾经火爆一时的抢红包插件,你想到应该怎么去实现了吗?

为什么我们需要自己实现一个,因为这个是一个高风险的能力,很多有这些能力的 apk 也可能存在一些后门,使用起来有极高的风险,所以也通常不建议对自己不信赖的 App 开启 无障碍 能力。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 核心的原理部分
  • 好了,有了以上基础,实现一个订票机器人还是难事吗?
    • 一些技巧
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档