Android 辅助模式实战:自动分享微信文章给好友

承香墨影

最快捷的技术进阶之路

题图:by Pleasantblake

Hi,大家好,我是承香墨影!

前两天写了一篇文章,讲 Android 的辅助模式,今天再补充一个实际的例子,看看实际使用 Accessibility 进行开发的整个流程!

还不了解辅助模式(Accessibility)的,可以先看看之前的文章☞「Android 的辅助模式」。

Accessibility 的例子

网上很多例如抢微信红包、Apk 安装的例子,今天写个新的例子,希望大家对整个流程有一个概念。

首先,为了简化流程,提前在微信里打开某一篇待分享的文章,我们只需要处理后续模拟一直到分享完成的整个步骤。

拆分一下步骤:

  1. 微信文章页面,点击右上角“···”按钮。

  2. 弹出选择框,点击“分享给朋友”。

  3. 进入分享选择页,选择右上角“多选”按钮。

  4. 找到列表里“承香墨影”,选中。

  5. 找到右上角,点击“发送”。

  6. 在分享弹窗上的输入框中,输入“分享给你一篇好文章”。

  7. 分享弹窗上,点击“发送”。

在开始编写代码之前,我们还需要一些准备工作,拿到一些必要的信息,例如不同页面上,控件对应的 ViewID。

准备工作

分析步骤之后,我们接下来就需要找到不同页面下,我们要操作的关键节点(NodeInfo),那些按钮的 ID,通过 ID 去查找关键节点是一个比较稳妥的方法。

查找 ViewId,可以使用 Android Device Monitor,可以在 Tools → Android → Android Device Monitor 打开。

Android Device Monitor 非常好用,只需要选中我们需要查找的 View,就会自动显示它的信息。

Android Device Monitor,不太稳定,有些设备可能无法进入此页面,推荐直接换个设备或者使用模拟器。

例如这里找到的 “···” 按钮的 ID,就是 com.tencent.mm:id/hh,并且是一个 ImageButton,如果上面有文字,还可以看到它的 Text 内容,后续可以根据 Text 的内容进行简单的筛选。

根据上面的步骤,查找到不同页面的 ID:

  1. 微信文章页面,"···" 按钮:com.tencent.mm:id/hh

  2. 弹出选择框,“分享给朋友” 按钮:com.tencent.mm:id/ge

  3. 进入分享选择页,"多选"按钮:com.tencent.mm:id/hg

  4. 联系人列表每一项中 名称 的TextView:com.tencent.mm:id/lp

  5. 右上角,"发送" 按钮:com.tencent.mm:id/hg

  6. 分享弹窗上的输入框:com.tencent.mm:id/anb

  7. 分享弹窗上,“发送”按钮:com.tencent.mm:id/an3

准备工作做好之后,就开始写具体的逻辑代码了。

编写转发小工具

准备工作做好了,就开始编写转发小工具了。整个小工具的核心功能,其实就是找到 NodeInfo ,然后点击或者填入文本数据。

1. 找到NodeInfo

我们可以通过 findAccessibilityNodeInfoByViewId() 方法,找到 ViewId 对应的 NodeInfo ,前面的准备工作,已经把 ViewId 找到了。但是一般这个方法可能会找到很多个 NodeInfo,所以我们还需要根据文本去做一次筛选。

    private fun findNodeInfo(viewId: String, findText: String = "", containsText: String = ""): AccessibilityNodeInfo? {
        var mNodeInfo = rootInActiveWindow
        var items = mNodeInfo.findAccessibilityNodeInfosByViewId(viewId)
        var isEquals = !TextUtils.isEmpty(findText)
        for (item in items) {
            if (TextUtils.isEmpty(findText) && TextUtils.isEmpty(containsText)) {
                // 如果两个都不传递,就点击最先找到的 Node
                return item
            }
            if (isEquals) {
                if (item.text.toString().equals(findText)) {
                    return item
                }
            } else {
                if (item.text.toString().contains(containsText)) {
                    return item
                }
            }
        }
        return null
    }

一个通用的方法,我们根据找到的 NodeInfo 中的 Text 再做一次筛选,找到最符合我们要求的 NodeInfo 再返回。注意这里为 Text 的条件做了区分,可以使用 equals() 也可以使用 contains()

2. 模拟点击

找到关键的 NodeInfo 之后,我们就可以通过 performAction() 方法,向他传递一个 AccessibilityNodeInfo.ACTION_CLICK 事件即可。

private fun nodeClick(node: AccessibilityNodeInfo?) {
    var clickNode = node;
    while (clickNode != null) {
        if (clickNode.isClickable) {
            clickNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)
            break;
        }
        clickNode = node?.parent
    }
}

private fun findNodeClick(viewId: String, findText: String = "", containsText: String = "") {
    Thread.sleep(1000);
    var findNodeInfo = findNodeInfo(viewId, findText, containsText)
    if (findNodeInfo != null) {
        nodeClick(findNodeInfo)
    }
}

为了避免上一个事件执行之后,页面没有立刻响应,我们在所有的事件执行之前,都强行 sleep(1000)

3. 在文本框里输入内容

最后分享弹窗之上,还有一个文本框,我们需要填入内容“分享给你一篇好文章”。

private fun nodeSetText(node: AccessibilityNodeInfo?, text: String) {
    Thread.sleep(1000);
    var argument = Bundle()
    argument.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text)
    node?.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, argument)
}

到此,基础的几个主要的方法就已经实现了。

4. 将整个流程串联起来

fun startWeForwarding() {
    var wechatIntent = packageManager!!.getLaunchIntentForPackage("com.tencent.mm")
    startActivity(wechatIntent);

    var mNodeInfo = rootInActiveWindow
    if (mNodeInfo != null) {
        findNodeClick(WENZHANG_JIAHAO)
        findNodeClick(SEND_FRIEND_BTN, "发送给朋友")
        findNodeClick(SHARE_MULTI_SELECT, "多选")
        findNodeClick(SHARE_ITEM_NAME, "承香墨影")
        findNodeClick(SEND_BTN, containsText = "发送")
        var editNodeInfo = findNodeInfo(EDIT_MESSAGE)
        nodeSetText(editNodeInfo,"分享给你一篇好文章")
        findNodeClick(DIALOG_SEND_BTN,"发送")
    }
}

最后看看执行的效果:

小结

辅助模式的权限很大,至于它能实现什么功能,完全靠你的想象力。


联机圆桌」????一年 50 个优质问题,上桌联机学习。

公众号后台回复成长『成长』,将会得到我准备的学习资料,也能回复『加群』,一起学习进步;你还能回复『提问』,向我发起提问。

推荐阅读:

听说喜欢留言的人,运气都不会太差

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值