update 显示系统版本;兼容获取我的信息;兼容获取内部群群名;兼容聊天列表查询;兼容群拉人;兼容手势滚动;兼容修改内部群群名;兼容修改内部群群公告
This commit is contained in:
@@ -65,7 +65,8 @@ class ListenActivity : AppCompatActivity() {
|
||||
SPUtils.getInstance().put("autoReply", Constant.autoReply)
|
||||
})
|
||||
tv_host.text = WebConfig.HOST
|
||||
tv_version.text = AppUtils.getAppVersionName()
|
||||
val version = "${AppUtils.getAppVersionName()} Android ${DeviceUtils.getSDKVersionName()} ${DeviceUtils.getManufacturer()} ${DeviceUtils.getModel()}"
|
||||
tv_version.text = version
|
||||
val workVersionName = AppUtils.getAppInfo(Constant.PACKAGE_NAMES)?.versionName
|
||||
when (workVersionName) {
|
||||
null -> {
|
||||
@@ -83,7 +84,7 @@ class ListenActivity : AppCompatActivity() {
|
||||
tv_work_version.text = tip
|
||||
}
|
||||
}
|
||||
SPUtils.getInstance().put("appVersion", AppUtils.getAppVersionName())
|
||||
SPUtils.getInstance().put("appVersion", version)
|
||||
SPUtils.getInstance().put("workVersion", workVersionName)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ object WeworkGetImpl {
|
||||
fun getMyInfo(): Boolean {
|
||||
if (!goHomeTab("我")) {
|
||||
LogUtils.d("未找到我的信息")
|
||||
log("未找到我的信息")
|
||||
goHomeTab("消息")
|
||||
val firstTv = AccessibilityUtil.findAllByClazz(getRoot(), Views.TextView)
|
||||
.firstOrNull { it.text == null }
|
||||
@@ -57,13 +58,14 @@ object WeworkGetImpl {
|
||||
val newFirstTv = AccessibilityUtil.findOneByClazz(getRoot(), Views.TextView)
|
||||
val nickname = newFirstTv?.text?.toString()
|
||||
if (nickname != null) {
|
||||
log("找到我的昵称")
|
||||
var corp: String? = null
|
||||
val info = StringBuilder()
|
||||
if (AccessibilityUtil.performClick(newFirstTv)) {
|
||||
sleep(Constant.CHANGE_PAGE_INTERVAL)
|
||||
val rv = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView)
|
||||
if (rv != null && rv.childCount > 0) {
|
||||
val myInfoLayout = rv.getChild(0)
|
||||
val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView, Views.ViewGroup, minChildCount = 2)
|
||||
if (list != null) {
|
||||
val myInfoLayout = list.getChild(0)
|
||||
val tvList = AccessibilityUtil.findAllByClazz(myInfoLayout, Views.TextView)
|
||||
.filter { it.text != null }
|
||||
if (tvList.isNotEmpty()) {
|
||||
@@ -88,6 +90,7 @@ object WeworkGetImpl {
|
||||
return true
|
||||
} else {
|
||||
LogUtils.d("未找到我的昵称")
|
||||
log("未找到我的昵称")
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -141,15 +144,16 @@ object WeworkGetImpl {
|
||||
fun getGroupInfoDetail(): WeworkMessageBean {
|
||||
val weworkMessageBean = WeworkMessageBean()
|
||||
weworkMessageBean.type = WeworkMessageBean.GET_GROUP_INFO
|
||||
val tvManagerFlag = AccessibilityUtil.findOneByText(getRoot(), "微信用户创建", timeout = 2000)
|
||||
//不是管理员的群可能没有微信用户创建 todo
|
||||
// AccessibilityUtil.findOneByText(getRoot(), "全部群成员", timeout = 2000)
|
||||
val button = AccessibilityUtil.findFrontNode(tvManagerFlag)
|
||||
val tvGroupName = AccessibilityUtil.findOnceByClazz(button, Views.TextView)
|
||||
if (tvGroupName != null && tvGroupName.text != null) {
|
||||
LogUtils.d("群名: " + tvGroupName.text)
|
||||
weworkMessageBean.groupName = tvGroupName.text.toString()
|
||||
} else {
|
||||
val tvManagerFlag = AccessibilityUtil.findOneByText(getRoot(), "全部群成员", "微信用户创建", timeout = 2000)
|
||||
if (tvManagerFlag != null && tvManagerFlag.text.contains("微信用户创建")) {
|
||||
val button = AccessibilityUtil.findFrontNode(tvManagerFlag)
|
||||
val tvGroupName = AccessibilityUtil.findOnceByClazz(button, Views.TextView)
|
||||
if (tvGroupName != null && tvGroupName.text != null) {
|
||||
LogUtils.d("群名: " + tvGroupName.text)
|
||||
weworkMessageBean.groupName = tvGroupName.text.toString()
|
||||
}
|
||||
}
|
||||
if (weworkMessageBean.groupName.isNullOrEmpty()) {
|
||||
val groupNameTv = AccessibilityUtil.findOnceByText(getRoot(), "群聊名称")
|
||||
if (groupNameTv != null) {
|
||||
val tvList = AccessibilityUtil.findAllOnceByClazz(
|
||||
|
||||
@@ -227,11 +227,11 @@ object WeworkLoopImpl {
|
||||
}
|
||||
}
|
||||
if (!isAtHome()) return true
|
||||
if (logIndex++ % 15 == 0) {
|
||||
if (logIndex++ % 30 == 0) {
|
||||
LogUtils.i("读取首页聊天列表")
|
||||
log("读取首页聊天列表")
|
||||
if (logIndex % 120 == 0) log("读取首页聊天列表")
|
||||
}
|
||||
val listview = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView)
|
||||
val listview = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView, Views.ViewGroup)
|
||||
if (listview != null) {
|
||||
if (listview.childCount >= 2) {
|
||||
if (checkUnreadChatRoom(listview)) {
|
||||
|
||||
@@ -273,11 +273,14 @@ object WeworkOperationImpl {
|
||||
extraText: String? = null
|
||||
): Boolean {
|
||||
goHomeTab("工作台")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(getRoot(), "微盘")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(WeworkController.weworkService, getRoot(), "微盘")
|
||||
if (node != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
AccessibilityUtil.performClick(node)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
AccessibilityUtil.clickByNode(WeworkController.weworkService, node)
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "微盘") != null) {
|
||||
AccessibilityUtil.clickByNode(WeworkController.weworkService, node)
|
||||
}
|
||||
} else {
|
||||
AccessibilityUtil.performClick(node)
|
||||
}
|
||||
@@ -320,11 +323,14 @@ object WeworkOperationImpl {
|
||||
extraText: String? = null
|
||||
): Boolean {
|
||||
goHomeTab("工作台")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(getRoot(), "微盘")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(WeworkController.weworkService, getRoot(), "微盘")
|
||||
if (node != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
AccessibilityUtil.performClick(node)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
AccessibilityUtil.clickByNode(WeworkController.weworkService, node)
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "微盘") != null) {
|
||||
AccessibilityUtil.clickByNode(WeworkController.weworkService, node)
|
||||
}
|
||||
} else {
|
||||
AccessibilityUtil.performClick(node)
|
||||
}
|
||||
@@ -363,7 +369,7 @@ object WeworkOperationImpl {
|
||||
extraText: String? = null
|
||||
): Boolean {
|
||||
goHomeTab("工作台")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(getRoot(), "用过的小程序")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(WeworkController.weworkService, getRoot(), "用过的小程序")
|
||||
if (node != null) {
|
||||
AccessibilityUtil.performClick(node)
|
||||
sleep(Constant.CHANGE_PAGE_INTERVAL)
|
||||
@@ -591,7 +597,7 @@ object WeworkOperationImpl {
|
||||
for (select in selectList) {
|
||||
AccessibilityUtil.findTextInput(getRoot(), select.replace("…", "").replace("-.*$".toRegex(), ""))
|
||||
sleep(Constant.CHANGE_PAGE_INTERVAL * 2)
|
||||
val selectListView = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView)
|
||||
val selectListView = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView, Views.RecyclerView, Views.ViewGroup, minChildCount = 2)
|
||||
val imageView = AccessibilityUtil.findOneByClazz(selectListView, Views.ImageView)
|
||||
if (imageView != null) {
|
||||
AccessibilityUtil.performClick(imageView)
|
||||
@@ -634,21 +640,31 @@ object WeworkOperationImpl {
|
||||
*/
|
||||
private fun createGroup(): Boolean {
|
||||
goHomeTab("工作台")
|
||||
val node = AccessibilityUtil.scrollAndFindByText(getRoot(), "客户群", "居民群")
|
||||
?: return false
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
if (AccessibilityUtil.clickByNode(WeworkController.weworkService, node)) {
|
||||
val node = AccessibilityUtil.scrollAndFindByText(WeworkController.weworkService, getRoot(), "客户群", "居民群")
|
||||
if (node != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
AccessibilityUtil.performClick(node)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "客户群", "居民群") != null) {
|
||||
if (AccessibilityUtil.clickByNode(WeworkController.weworkService, node)) {
|
||||
LogUtils.d("进入客户群应用")
|
||||
val textView =
|
||||
AccessibilityUtil.findOneByText(getRoot(), "创建一个客户群", "创建一个居民群")
|
||||
return AccessibilityUtil.performClick(textView)
|
||||
}
|
||||
} else {
|
||||
LogUtils.d("进入客户群应用")
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "创建一个客户群", "创建一个居民群")
|
||||
return AccessibilityUtil.performClick(textView)
|
||||
}
|
||||
} else if (AccessibilityUtil.performClick(node)) {
|
||||
LogUtils.d("进入客户群应用")
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "创建一个客户群", "创建一个居民群")
|
||||
return AccessibilityUtil.performClick(textView)
|
||||
}
|
||||
} else if (AccessibilityUtil.performClick(node)) {
|
||||
LogUtils.d("进入客户群应用")
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "创建一个客户群", "创建一个居民群")
|
||||
return AccessibilityUtil.performClick(textView)
|
||||
}
|
||||
LogUtils.d("未找到客户群应用")
|
||||
LogUtils.e("未找到客户群应用")
|
||||
log("未找到客户群应用")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -657,19 +673,32 @@ object WeworkOperationImpl {
|
||||
*/
|
||||
private fun groupRename(groupName: String): Boolean {
|
||||
if (WeworkRoomUtil.intoGroupManager()) {
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "微信用户创建")
|
||||
//todo 微信用户创建可能找不到
|
||||
val button = AccessibilityUtil.findFrontNode(textView)
|
||||
if (button != null) {
|
||||
AccessibilityUtil.performClick(button)
|
||||
AccessibilityUtil.findTextInput(getRoot(), groupName)
|
||||
val confirmButton = AccessibilityUtil.findOneByText(getRoot(), "确定")
|
||||
AccessibilityUtil.performClick(confirmButton)
|
||||
sleep(2000)
|
||||
return true
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "全部群成员", "微信用户创建")
|
||||
?: return false
|
||||
if (textView.text.contains("微信用户创建")) {
|
||||
val button = AccessibilityUtil.findFrontNode(textView)
|
||||
if (button != null) {
|
||||
AccessibilityUtil.performClick(button)
|
||||
AccessibilityUtil.findTextInput(getRoot(), groupName)
|
||||
val confirmButton = AccessibilityUtil.findOneByText(getRoot(), "确定")
|
||||
AccessibilityUtil.performClick(confirmButton)
|
||||
sleep(2000)
|
||||
return true
|
||||
} else {
|
||||
LogUtils.e("未找到填写群名按钮")
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
LogUtils.e("未找到填写群名按钮")
|
||||
return false
|
||||
val result = AccessibilityUtil.findTextAndClick(getRoot(), "群聊名称")
|
||||
if (result) {
|
||||
AccessibilityUtil.findTextInput(getRoot(), groupName)
|
||||
val confirmButton = AccessibilityUtil.findOneByText(getRoot(), "确定")
|
||||
AccessibilityUtil.performClick(confirmButton)
|
||||
sleep(2000)
|
||||
return true
|
||||
} else {
|
||||
LogUtils.e("未找到群聊名称按钮")
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
@@ -687,9 +716,14 @@ object WeworkOperationImpl {
|
||||
if (WeworkRoomUtil.intoGroupManager()) {
|
||||
val gridView = AccessibilityUtil.findOneByClazz(getRoot(), Views.GridView)
|
||||
if (gridView != null && gridView.childCount >= 2) {
|
||||
if (gridView.childCount == 2) {
|
||||
val tvEmptySize = AccessibilityUtil.findAllOnceByClazz(gridView, Views.TextView)
|
||||
.filter { it.text == null }.size
|
||||
LogUtils.v("tvEmptySize: $tvEmptySize")
|
||||
if (tvEmptySize == 0) {
|
||||
return true
|
||||
} else if (tvEmptySize == 1) {
|
||||
AccessibilityUtil.performClick(gridView.getChild(gridView.childCount - 1))
|
||||
} else {
|
||||
} else if (tvEmptySize == 2) {
|
||||
AccessibilityUtil.performClick(gridView.getChild(gridView.childCount - 2))
|
||||
}
|
||||
} else {
|
||||
@@ -706,16 +740,18 @@ object WeworkOperationImpl {
|
||||
AccessibilityUtil.performClick(multiButton)
|
||||
AccessibilityUtil.findTextInput(getRoot(), select)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
val selectListViewTemp =
|
||||
AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView)
|
||||
val selectListView =
|
||||
AccessibilityUtil.findOnceByClazz(getRoot(), Views.RecyclerView) ?: selectListViewTemp
|
||||
val imageView =
|
||||
AccessibilityUtil.findOneByClazz(selectListView, Views.ImageView, root = false)
|
||||
AccessibilityUtil.performClick(imageView)
|
||||
val textView = AccessibilityUtil.findOnceByClazz(getRoot(), Views.TextView)
|
||||
if (textView != null && textView.text.isNullOrBlank()) {
|
||||
AccessibilityUtil.performClick(textView)
|
||||
AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView, Views.RecyclerView, Views.ViewGroup, minChildCount = 2)
|
||||
if (selectListView != null) {
|
||||
val imageView =
|
||||
AccessibilityUtil.findOneByClazz(selectListView, Views.ImageView, root = false)
|
||||
AccessibilityUtil.performClick(imageView)
|
||||
val textView = AccessibilityUtil.findOnceByClazz(getRoot(), Views.TextView)
|
||||
if (textView != null && textView.text.isNullOrBlank()) {
|
||||
AccessibilityUtil.performClick(textView)
|
||||
}
|
||||
} else {
|
||||
LogUtils.e("未查到列表结果")
|
||||
}
|
||||
}
|
||||
if (showMessageHistory) {
|
||||
@@ -749,9 +785,12 @@ object WeworkOperationImpl {
|
||||
if (WeworkRoomUtil.intoGroupManager()) {
|
||||
val gridView = AccessibilityUtil.findOneByClazz(getRoot(), Views.GridView)
|
||||
if (gridView != null && gridView.childCount >= 2) {
|
||||
if (gridView.childCount == 2) {
|
||||
val tvEmptySize = AccessibilityUtil.findAllOnceByClazz(gridView, Views.TextView)
|
||||
.filter { it.text == null }.size
|
||||
LogUtils.v("tvEmptySize: $tvEmptySize")
|
||||
if (tvEmptySize <= 1) {
|
||||
return true
|
||||
} else {
|
||||
} else if (tvEmptySize == 2) {
|
||||
AccessibilityUtil.performClick(gridView.getChild(gridView.childCount - 1))
|
||||
}
|
||||
} else {
|
||||
@@ -767,8 +806,9 @@ object WeworkOperationImpl {
|
||||
for (select in removeList) {
|
||||
AccessibilityUtil.performClick(multiButton)
|
||||
AccessibilityUtil.findTextInput(getRoot(), select)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
val selectListView =
|
||||
AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView)
|
||||
AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView, Views.RecyclerView, Views.ViewGroup, minChildCount = 2)
|
||||
val imageView =
|
||||
AccessibilityUtil.findOneByClazz(selectListView, Views.ImageView, root = false)
|
||||
AccessibilityUtil.performClick(imageView)
|
||||
@@ -808,11 +848,16 @@ object WeworkOperationImpl {
|
||||
val textView = AccessibilityUtil.findOneByText(getRoot(), "群公告")
|
||||
if (textView != null) {
|
||||
AccessibilityUtil.performClick(textView)
|
||||
val editButton = AccessibilityUtil.findOneByText(getRoot(), "编辑", timeout = 2000)
|
||||
val editButton = AccessibilityUtil.findOneByText(getRoot(), "编辑", timeout = 2000, exact = true)
|
||||
if (editButton != null) {
|
||||
LogUtils.d("群公告编辑中: $groupAnnouncement")
|
||||
AccessibilityUtil.performClick(editButton)
|
||||
sleep(1000)
|
||||
var retry = 0
|
||||
while (retry++ < 10) {
|
||||
AccessibilityUtil.performClick(editButton)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "编辑", exact = true) == null)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (AccessibilityUtil.findTextInput(getRoot(), groupAnnouncement)) {
|
||||
LogUtils.d("群公告发布中: $groupAnnouncement")
|
||||
@@ -849,16 +894,35 @@ object WeworkOperationImpl {
|
||||
val atFlag = AccessibilityUtil.findOneByText(getRoot(), "选择提醒的人", timeout = 2000)
|
||||
if (atFlag != null) {
|
||||
val rv = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView)
|
||||
AccessibilityUtil.findTextInput(getRoot(), at)
|
||||
val atNode = AccessibilityUtil.findOneByText(rv, at, root = false, timeout = 2000)
|
||||
if (atNode != null) {
|
||||
AccessibilityUtil.performClick(atNode)
|
||||
if (rv != null) {
|
||||
AccessibilityUtil.findTextInput(getRoot(), at)
|
||||
val atNode =
|
||||
AccessibilityUtil.findOneByText(rv, at, root = false, timeout = 2000)
|
||||
if (atNode != null) {
|
||||
AccessibilityUtil.performClick(atNode)
|
||||
} else {
|
||||
LogUtils.e("未找到at人: $at")
|
||||
atFailed = true
|
||||
backPress()
|
||||
}
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
} else {
|
||||
LogUtils.e("未找到at人: $at")
|
||||
atFailed = true
|
||||
backPress()
|
||||
val searchFlag = AccessibilityUtil.findOnceByText(getRoot(), "搜索", exact = true)
|
||||
val list = AccessibilityUtil.findBackNode(searchFlag, minChildCount = 2)
|
||||
if (list != null) {
|
||||
AccessibilityUtil.findTextInput(getRoot(), at)
|
||||
val atNode =
|
||||
AccessibilityUtil.findOneByText(list, at, root = false, timeout = 2000)
|
||||
if (atNode != null) {
|
||||
AccessibilityUtil.performClick(atNode)
|
||||
} else {
|
||||
LogUtils.e("未找到at人: $at")
|
||||
atFailed = true
|
||||
backPress()
|
||||
}
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
}
|
||||
}
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
}
|
||||
}
|
||||
val content = if (atFailed) "@$at $prefix$text" else "$prefix$text"
|
||||
@@ -866,8 +930,8 @@ object WeworkOperationImpl {
|
||||
val sendButton = AccessibilityUtil.findAllByClazz(getRoot(), Views.Button)
|
||||
.firstOrNull { it.text == "发送" }
|
||||
if (sendButton != null) {
|
||||
LogUtils.d("发送消息: \n$text")
|
||||
log("发送消息: \n$text")
|
||||
LogUtils.d("发送消息: \n$content")
|
||||
log("发送消息: \n$content")
|
||||
AccessibilityUtil.performClick(sendButton)
|
||||
} else {
|
||||
LogUtils.e("未找到发送按钮")
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.yameida.worktool.service.getRoot
|
||||
import java.lang.Exception
|
||||
import java.lang.Thread.sleep
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.blankj.utilcode.util.ScreenUtils
|
||||
import org.yameida.worktool.service.WeworkController
|
||||
|
||||
/**
|
||||
* 1.查询类
|
||||
@@ -96,33 +98,53 @@ object AccessibilityUtil {
|
||||
|
||||
//寻找第一个列表并点击指定条目(默认点击第一个条目)
|
||||
fun findListOneAndClick(nodeInfo: AccessibilityNodeInfo, index: Int = 0): Boolean {
|
||||
val rv = findOnceByClazz(nodeInfo, "androidx.recyclerview.widget.RecyclerView")
|
||||
val lv = findOnceByClazz(nodeInfo, "android.widget.ListView")
|
||||
if (rv == null && lv == null) return false
|
||||
if (rv != null && rv.childCount > index) {
|
||||
performClick(rv.getChild(index))
|
||||
} else if (lv != null && lv.childCount > index) {
|
||||
performClick(lv.getChild(index))
|
||||
val list = findOnceByClazz(nodeInfo, "androidx.recyclerview.widget.RecyclerView", "android.widget.ListView")
|
||||
if (list != null && list.childCount > index) {
|
||||
return performClick(list.getChild(index))
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
//滚动并按文本寻找第一个控件
|
||||
fun scrollAndFindByText(
|
||||
service: AccessibilityService,
|
||||
nodeInfo: AccessibilityNodeInfo,
|
||||
vararg textList: String,
|
||||
maxRetry: Int = 3
|
||||
): AccessibilityNodeInfo? {
|
||||
var index = 0
|
||||
while (index++ < maxRetry) {
|
||||
performScrollDown(nodeInfo, 0)
|
||||
val node = findOnceByText(nodeInfo, *textList)
|
||||
if (node != null) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
index = 0
|
||||
while (index++ < maxRetry * 2) {
|
||||
performScrollUp(nodeInfo, 0)
|
||||
val node = findOnceByText(nodeInfo, *textList)
|
||||
if (node != null) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.d("未找到可滚动列表 使用手势滚动")
|
||||
val width = ScreenUtils.getScreenWidth()
|
||||
val height = ScreenUtils.getScreenHeight()
|
||||
index = 0
|
||||
while (index++ < maxRetry * 2) {
|
||||
performScrollDown(nodeInfo, 0)
|
||||
scrollByXY(service, width / 2, height / 2, 0, -height / 2)
|
||||
sleep(SCROLL_INTERVAL)
|
||||
val node = findOnceByText(nodeInfo, *textList)
|
||||
if (node != null) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
index = 0
|
||||
while (index++ < maxRetry * 3) {
|
||||
scrollByXY(service, width / 2, height / 2, 0, height / 2)
|
||||
sleep(SCROLL_INTERVAL)
|
||||
val node = findOnceByText(nodeInfo, *textList)
|
||||
if (node != null) {
|
||||
return node
|
||||
@@ -141,11 +163,11 @@ object AccessibilityUtil {
|
||||
val gesture = builder.build()
|
||||
return service.dispatchGesture(gesture, object : GestureResultCallback() {
|
||||
override fun onCompleted(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click okk onCompleted")
|
||||
LogUtils.v("click ok onCompleted")
|
||||
}
|
||||
|
||||
override fun onCancelled(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click okk onCancelled")
|
||||
LogUtils.v("click ok onCancelled")
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
@@ -397,7 +419,7 @@ object AccessibilityUtil {
|
||||
if (node == null) return null
|
||||
val textNodeList = findAllOnceByText(node, *textList, exact = exact)
|
||||
LogUtils.v("text: ${textList.joinToString()} count: " + textNodeList.size)
|
||||
if (exact) return textNodeList[0]
|
||||
if (exact && textNodeList.size > 0) return textNodeList[0]
|
||||
else if (textNodeList.size > 0) {
|
||||
for (textNode in textNodeList) {
|
||||
for (text in textList) {
|
||||
@@ -486,13 +508,14 @@ object AccessibilityUtil {
|
||||
limitDepth: Int? = null,
|
||||
depth: Int = 0,
|
||||
timeout: Long = 5000,
|
||||
root: Boolean = true
|
||||
root: Boolean = true,
|
||||
minChildCount: Int = 0
|
||||
): AccessibilityNodeInfo? {
|
||||
var node = node ?: return null
|
||||
val startTime = System.currentTimeMillis()
|
||||
var currentTime = startTime
|
||||
while (currentTime - startTime <= timeout) {
|
||||
val result = findOnceByClazz(node, *clazzList, limitDepth = limitDepth, depth = depth)
|
||||
val result = findOnceByClazz(node, *clazzList, limitDepth = limitDepth, depth = depth, minChildCount = minChildCount)
|
||||
LogUtils.v("clazz: ${clazzList.joinToString()} result == null: ${result == null}")
|
||||
if (result != null) return result
|
||||
sleep(SHORT_INTERVAL)
|
||||
@@ -503,7 +526,7 @@ object AccessibilityUtil {
|
||||
}
|
||||
currentTime = System.currentTimeMillis()
|
||||
}
|
||||
LogUtils.e("findOneByClazz Exception()")
|
||||
LogUtils.e("findOneByClazz Exception(): ${clazzList.joinToString()}")
|
||||
Exception().printStackTrace()
|
||||
return null
|
||||
}
|
||||
@@ -518,15 +541,16 @@ object AccessibilityUtil {
|
||||
node: AccessibilityNodeInfo?,
|
||||
vararg clazzList: String,
|
||||
limitDepth: Int? = null,
|
||||
depth: Int = 0
|
||||
depth: Int = 0,
|
||||
minChildCount: Int = 0
|
||||
): AccessibilityNodeInfo? {
|
||||
if (node == null) return null
|
||||
if (node.className in clazzList) {
|
||||
if (limitDepth == null || limitDepth == depth)
|
||||
if ((limitDepth == null || limitDepth == depth) && node.childCount >= minChildCount)
|
||||
return node
|
||||
}
|
||||
for (i in 0 until node.childCount) {
|
||||
val result = findOnceByClazz(node.getChild(i), *clazzList, limitDepth = limitDepth, depth = depth + 1)
|
||||
val result = findOnceByClazz(node.getChild(i), *clazzList, limitDepth = limitDepth, depth = depth + 1, minChildCount = minChildCount)
|
||||
if (result != null) return result
|
||||
}
|
||||
return null
|
||||
@@ -560,7 +584,7 @@ object AccessibilityUtil {
|
||||
}
|
||||
currentTime = System.currentTimeMillis()
|
||||
}
|
||||
LogUtils.e("findAllByClazz Exception()")
|
||||
LogUtils.e("findAllByClazz Exception(): ${clazzList.joinToString()}")
|
||||
Exception().printStackTrace()
|
||||
return arrayListOf()
|
||||
}
|
||||
@@ -705,12 +729,115 @@ object AccessibilityUtil {
|
||||
val gesture = builder.build()
|
||||
return service.dispatchGesture(gesture, object : GestureResultCallback() {
|
||||
override fun onCompleted(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click okk onCompleted")
|
||||
LogUtils.v("click ok onCompleted")
|
||||
}
|
||||
|
||||
override fun onCancelled(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click okk onCancelled")
|
||||
LogUtils.v("click ok onCancelled")
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* 向下滚动
|
||||
* Gesture手势实现滚动(Android7+)
|
||||
* 解决 scrollable=false 无法滚动问题
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
fun scrollDownByNode(
|
||||
service: AccessibilityService,
|
||||
nodeInfo: AccessibilityNodeInfo
|
||||
): Boolean {
|
||||
val rect = Rect()
|
||||
nodeInfo.getBoundsInScreen(rect)
|
||||
val x: Int = (rect.left + rect.right) / 2
|
||||
val y: Int = (rect.top + rect.bottom) / 2
|
||||
val point = Point(x, y)
|
||||
val builder = GestureDescription.Builder()
|
||||
val path = Path()
|
||||
path.moveTo(point.x.toFloat(), point.y.toFloat())
|
||||
builder.addStroke(StrokeDescription(path, 0L, 300L))
|
||||
val gesture = builder.build()
|
||||
return service.dispatchGesture(gesture, object : GestureResultCallback() {
|
||||
override fun onCompleted(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click ok onCompleted")
|
||||
}
|
||||
|
||||
override fun onCancelled(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("click ok onCancelled")
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gesture手势实现滚动(Android7+)
|
||||
* 解决滚动距离不可控制问题
|
||||
* @param distanceX 向右滚动为负值 向左滚动为正值
|
||||
* @param distanceY 向下滚动为负值 向上滚动为正值
|
||||
*/
|
||||
fun scrollByNode(
|
||||
service: AccessibilityService,
|
||||
nodeInfo: AccessibilityNodeInfo,
|
||||
distanceX: Int = 0,
|
||||
distanceY: Int = 0
|
||||
): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val rect = Rect()
|
||||
nodeInfo.getBoundsInScreen(rect)
|
||||
val point = Point((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2)
|
||||
val builder = GestureDescription.Builder()
|
||||
val path = Path()
|
||||
path.moveTo(point.x.toFloat(), point.y.toFloat())
|
||||
path.lineTo(point.x.toFloat() + distanceX, point.y.toFloat() + distanceY)
|
||||
builder.addStroke(StrokeDescription(path, 0L, 300L))
|
||||
val gesture = builder.build()
|
||||
return service.dispatchGesture(gesture, object : GestureResultCallback() {
|
||||
override fun onCompleted(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("scroll ok onCompleted")
|
||||
}
|
||||
|
||||
override fun onCancelled(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("scroll ok onCancelled")
|
||||
}
|
||||
}, null)
|
||||
} else {
|
||||
LogUtils.e("系统版本<7.0 不支持手势操作")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gesture手势实现滚动(Android7+)
|
||||
* 解决滚动距离不可控制问题
|
||||
* @param distanceX 向右滚动为负值 向左滚动为正值
|
||||
* @param distanceY 向下滚动为负值 向上滚动为正值
|
||||
*/
|
||||
fun scrollByXY(
|
||||
service: AccessibilityService,
|
||||
x: Int = 0,
|
||||
y: Int = 0,
|
||||
distanceX: Int = 0,
|
||||
distanceY: Int = 0
|
||||
): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val builder = GestureDescription.Builder()
|
||||
val path = Path()
|
||||
path.moveTo(x.toFloat(), y.toFloat())
|
||||
path.lineTo(x.toFloat() + distanceX, y.toFloat() + distanceY)
|
||||
builder.addStroke(StrokeDescription(path, 0L, 300L))
|
||||
val gesture = builder.build()
|
||||
return service.dispatchGesture(gesture, object : GestureResultCallback() {
|
||||
override fun onCompleted(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("scroll ok onCompleted")
|
||||
}
|
||||
|
||||
override fun onCancelled(gestureDescription: GestureDescription) {
|
||||
LogUtils.v("scroll ok onCancelled")
|
||||
}
|
||||
}, null)
|
||||
} else {
|
||||
LogUtils.e("系统版本<7.0 不支持手势操作")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ object WeworkRoomUtil {
|
||||
return true
|
||||
}
|
||||
goHome()
|
||||
val list = findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView)
|
||||
val list = findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView, Views.ViewGroup)
|
||||
if (list != null) {
|
||||
val frontNode = findFrontNode(list)
|
||||
val textViewList = findAllOnceByClazz(frontNode, Views.TextView)
|
||||
@@ -106,6 +106,7 @@ object WeworkRoomUtil {
|
||||
val imageView = AccessibilityUtil.findOnceByClazz(selectListView, Views.ImageView)
|
||||
if (imageView != null) {
|
||||
AccessibilityUtil.performClick(imageView)
|
||||
LogUtils.d("进入房间: $title")
|
||||
sleep(Constant.CHANGE_PAGE_INTERVAL)
|
||||
return true
|
||||
} else {
|
||||
@@ -125,8 +126,7 @@ object WeworkRoomUtil {
|
||||
* @return true 成功进入群管理页
|
||||
*/
|
||||
fun intoGroupManager(): Boolean {
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "全部群成员") != null
|
||||
|| AccessibilityUtil.findOnceByText(getRoot(), "微信用户创建") != null) {
|
||||
if (AccessibilityUtil.findOnceByText(getRoot(), "全部群成员", "微信用户创建") != null) {
|
||||
return true
|
||||
}
|
||||
val list = findOneByClazz(getRoot(), Views.ListView)
|
||||
|
||||
@@ -2,8 +2,10 @@ package org.yameida.worktool.utils
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import org.yameida.worktool.Constant
|
||||
import org.yameida.worktool.model.WeworkMessageBean
|
||||
import org.yameida.worktool.service.getRoot
|
||||
import org.yameida.worktool.service.sleep
|
||||
import org.yameida.worktool.utils.AccessibilityUtil.findAllByClazz
|
||||
import org.yameida.worktool.utils.AccessibilityUtil.findAllOnceByClazz
|
||||
import java.util.*
|
||||
@@ -319,14 +321,13 @@ object WeworkTextUtil {
|
||||
private fun longClickMessageItem(item: AccessibilityNodeInfo, roomType: Int, key: String): Boolean {
|
||||
val backNode = getMessageListNode(item, roomType)
|
||||
AccessibilityUtil.performLongClickWithSon(backNode)
|
||||
val optionRvList = findAllByClazz(getRoot(), Views.RecyclerView)
|
||||
sleep(Constant.POP_WINDOW_INTERVAL)
|
||||
val optionRvList = findAllByClazz(getRoot(), Views.RecyclerView, Views.ViewGroup)
|
||||
for (optionRv in optionRvList) {
|
||||
val optionTvList = findAllOnceByClazz(optionRv, Views.TextView)
|
||||
for (optionTv in optionTvList) {
|
||||
if (optionTv.text == key) {
|
||||
AccessibilityUtil.performClick(optionTv)
|
||||
return true
|
||||
}
|
||||
val keyTv = AccessibilityUtil.findOnceByText(optionRv, key, exact = true)
|
||||
if (keyTv != null) {
|
||||
AccessibilityUtil.performClick(keyTv)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user