likes
comments
collection
share

【玩转Android自动化】小试牛刀

作者站长头像
站长
· 阅读数 19

是骡子是马拉出来遛遛呗

目标:自动获取当前登录的微信昵称和微信号

  • 先来分析一下微信昵称和微信号在哪里,寻找他的路径是什么,首先需要打开微信首页,点击底部导航【我】tab,就可以看到我的页面的信息了,里边就包含有你的微信号和微信昵称。

大概步操作流程是:微信首页 → 点击【我】→ 获取页面节点信息 → 解析出微信昵称和微信号

具体实现

1、打开微信首页
//直接通过启动微信首页Activity就可以打开微信了
fun Context.goToWx() = Intent(Intent.ACTION_MAIN)
    .apply {
        addCategory(Intent.CATEGORY_LAUNCHER)
        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        component = ComponentName(
            "com.tencent.mm",
            "com.tencent.mm.ui.LauncherUI",
        )
    }
    .apply(::startActivity)
2、点击【我】
  • 要想点击【我】这个节点就需要找到他的节点信息,使用节点速查工具,在微信首页打印一下所有节点信息,删除了一些无关的节点数据,底导节点内容如下
|       \--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/fj3 → description =  → isClickable = false → isScrollable = false → isEditable = false
|        \--- className = android.widget.LinearLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|          +--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/kd_ → description =  → isClickable = true → isScrollable = false → isEditable = false
|          |  \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/f1f → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    +--- className = android.widget.RelativeLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    |  +--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/f2a → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    |  \--- className = android.widget.TextView → text = 1 → id = com.tencent.mm:id/l0c → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    \--- className = android.widget.TextView → text = 微信 → id = com.tencent.mm:id/f2s → description =  → isClickable = false → isScrollable = false → isEditable = false
|          +--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/kd_ → description =  → isClickable = true → isScrollable = false → isEditable = false
|          |  \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/f1f → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    +--- className = android.widget.RelativeLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    |  \--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/f2a → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    \--- className = android.widget.TextView → text = 通讯录 → id = com.tencent.mm:id/f2s → description =  → isClickable = false → isScrollable = false → isEditable = false
|          +--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/kd_ → description =  → isClickable = true → isScrollable = false → isEditable = false
|          |  \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/f1f → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    +--- className = android.widget.RelativeLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    |  \--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/f2a → description =  → isClickable = false → isScrollable = false → isEditable = false
|          |    \--- className = android.widget.TextView → text = 发现 → id = com.tencent.mm:id/f2s → description =  → isClickable = false → isScrollable = false → isEditable = false
|          \--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/kd_ → description =  → isClickable = true → isScrollable = false → isEditable = false
|            \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/f1f → description =  → isClickable = false → isScrollable = false → isEditable = false
|              +--- className = android.widget.RelativeLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|              |  \--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/f2a → description =  → isClickable = false → isScrollable = false → isEditable = false
|              \--- className = android.widget.TextView → text = 我 → id = com.tencent.mm:id/f2s → description =  → isClickable = false → isScrollable = false → isEditable = false

  • 可以看到底部导航tab有四个,这四个tab的节点ID(com.tencent.mm:id/f2s)都是一样的,说明是复用的,没有唯一ID我们就不能准确查找到当前节点,继续往上查找发现他们有一个公共的父布局,而且父布局的节点ID(com.tencent.mm:id/fj3)是唯一的,那么我们就可以先获取唯一的父布局,在父布局中查找匹配到对应的text就可以了。

温馨提示:如果在当前窗口获取到了底导的父布局节点,是不是就间接说明当前是在微信首页了呐,可以用这种方法判断当前页面是否在微信首页。

    //获取【我】的节点
    val bottomNavId = "com.tencent.mm:id/fj3"
    val findMineTabNode = wxAccessibilityService?.rootInActiveWindow?.findNodesById(bottomNavId)?.firstOrNull { it.text == "我" }
    //点击【我】的tab
    findMineTabNode.click()

    //click()是封装好的点击扩展方法,如果当前节点是不可点击的,就会往上查找父节点,让父节点调用click()方法,依次递归一般都能找到一个可以点击的父节点的

    fun AccessibilityNodeInfo?.click(): Boolean {
        this ?: return false
        return if (isClickable) {
            performAction(AccessibilityNodeInfo.ACTION_CLICK)
        } else {
            parent?.click() == true
        }
    }

3、获取我的页面的节点信息
  • 点击了【我】的tab之后就看到了我的页面,然后继续用我们的节点速查工具查看我的页面的节点信息
|  |  +--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/eu7 → description =  → isClickable = true → isScrollable = false → isEditable = false
|  |  \--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/gv6 → description =  → isClickable = false → isScrollable = false → isEditable = false
|  |    +--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/a27 → description =  → isClickable = true → isScrollable = false → isEditable = false
|  |    \--- className = android.widget.LinearLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|  |      +--- className = android.widget.LinearLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|  |      |  \--- className = android.view.View → text = 百里守约 → id = com.tencent.mm:id/hfq → description =  → isClickable = false → isScrollable = false → isEditable = false
|  |      \--- className = android.widget.LinearLayout → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|  |        +--- className = android.widget.TextView → text = 微信号:wxid_xxxxxxx → id = com.tencent.mm:id/l29 → description =  → isClickable = true → isScrollable = false → isEditable = false
|  |        \--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/i_e → description =  → isClickable = true → isScrollable = false → isEditable = false
|  |          +--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/i_f → description = 我的二维码 → isClickable = false → isScrollable = false → isEditable = false
|  |          \--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/yj → description =  → isClickable = false → isScrollable = false → isEditable = false
|  +--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/eu4 → description =  → isClickable = false → isScrollable = false → isEditable = false
|  \--- className = android.widget.RelativeLayout → text =  → id = com.tencent.mm:id/kin → description =  → isClickable = true → isScrollable = false → isEditable = false
|    \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/fkv → description =  → isClickable = false → isScrollable = false → isEditable = false
|      +--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/fjy → description = 添加状态 → isClickable = true → isScrollable = false → isEditable = false
|      |  +--- className = android.widget.ImageView → text =  → id = com.tencent.mm:id/m2f → description =  → isClickable = false → isScrollable = false → isEditable = false
|      |  \--- className = android.widget.TextView → text = 状态 → id = com.tencent.mm:id/kvd → description =  → isClickable = false → isScrollable = false → isEditable = false
|      \--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/fld → description = 状态 → isClickable = true → isScrollable = false → isEditable = false
|        +--- className = android.widget.LinearLayout → text =  → id = com.tencent.mm:id/fl4 → description =  → isClickable = false → isScrollable = false → isEditable = false
|        |  \--- className = android.widget.ImageView → text =  → id =  → description =  → isClickable = false → isScrollable = false → isEditable = false
|        +--- className = android.widget.TextView → text = 1个朋友 → id = com.tencent.mm:id/kyq → description =  → isClickable = false → isScrollable = false → isEditable = false
|        \--- className = android.view.View → text =  → id = com.tencent.mm:id/p7n → description =  → isClickable = false → isScrollable = false → isEditable = false

  • 通过检索发现微信昵称ID(com.tencent.mm:id/hfq)和微信号ID(com.tencent.mm:id/l29)都是有唯一的,这样就可以找到对应的节点了,然后获取节点内容就可以了
4、解析出微信昵称和微信号
val nickName = wxAccessibilityService
    ?.findById(“com.tencent.mm:id/hfq”)
    ?.text
    .default()
val wxCode = wxAccessibilityService
    ?.findById(“com.tencent.mm:id/l29”)
    ?.text
    ?.split("微信号:")
    ?.getOrNull(1)
    .default()
    .trim()
//输出内容是:我的微信昵称: 百里守约   我的微信号:wxid_xxxxxxx

通过以上简单的代码就可以获取到微信昵称和微信号码了

意犹未尽

  • 啥?还没开始就结束了?是的,你没看错,只要知道目标节点唯一标识,就能获取到节点,都拿到节点了就可以为所欲为了,虽然这只是一个简单的实例,但是却是我们后续开发复杂功能的一个缩影,任何功能的开发都离不开类似的步骤

路径分析 → 节点定位 → 操作节点 → 业务逻辑

预告