update 图片截图

This commit is contained in:
gallonyin
2023-03-13 17:58:25 +08:00
parent ae3863babf
commit 432188fd0d
6 changed files with 212 additions and 61 deletions

View File

@@ -243,6 +243,9 @@ public class WeworkMessageBean {
public Integer textType; public Integer textType;
public List<ItemMessageBean> itemMessageList; public List<ItemMessageBean> itemMessageList;
public List<String> nameList; public List<String> nameList;
public Boolean imageRepeat;
public Integer imageSize;
public byte[] image;
public SubMessageBean(Integer sender, Integer textType, List<ItemMessageBean> itemMessageList, List<String> nameList) { public SubMessageBean(Integer sender, Integer textType, List<ItemMessageBean> itemMessageList, List<String> nameList) {
this.sender = sender; this.sender = sender;

View File

@@ -55,6 +55,7 @@ object MyLooper {
SPUtils.getInstance("noSyncMessage").clear() SPUtils.getInstance("noSyncMessage").clear()
SPUtils.getInstance("limit").clear() SPUtils.getInstance("limit").clear()
SPUtils.getInstance("groupInvite").clear() SPUtils.getInstance("groupInvite").clear()
SPUtils.getInstance("lastImage").clear()
} }
fun getInstance(): Handler { fun getInstance(): Handler {

View File

@@ -1,10 +1,12 @@
package org.yameida.worktool.service package org.yameida.worktool.service
import android.os.Message
import android.view.accessibility.AccessibilityNodeInfo import android.view.accessibility.AccessibilityNodeInfo
import androidx.core.text.isDigitsOnly import androidx.core.text.isDigitsOnly
import com.blankj.utilcode.util.* import com.blankj.utilcode.util.*
import org.yameida.worktool.Constant import org.yameida.worktool.Constant
import org.yameida.worktool.Demo import org.yameida.worktool.Demo
import org.yameida.worktool.activity.GetScreenShotActivity
import org.yameida.worktool.model.WeworkMessageBean import org.yameida.worktool.model.WeworkMessageBean
import org.yameida.worktool.observer.MultiFileObserver import org.yameida.worktool.observer.MultiFileObserver
import org.yameida.worktool.service.WeworkController.mainLoopRunning import org.yameida.worktool.service.WeworkController.mainLoopRunning
@@ -15,6 +17,7 @@ import java.lang.StringBuilder
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashSet
/** /**
* 获取数据类型 201 202 主循环 * 获取数据类型 201 202 主循环
@@ -46,7 +49,13 @@ object WeworkLoopImpl {
} }
} catch (e: Exception) { } catch (e: Exception) {
mainLoopRunning = false mainLoopRunning = false
error("ERROR mainLoop: " + e.message) LogUtils.e("ERROR mainLoop: " + e.message, e)
error("ERROR mainLoop: $e")
sleep(Constant.LONG_INTERVAL)
MyLooper.getInstance().sendMessage(Message.obtain().apply {
what = WeworkMessageBean.LOOP_RECEIVE_NEW_MESSAGE
obj = WeworkMessageBean().apply { type = WeworkMessageBean.LOOP_RECEIVE_NEW_MESSAGE }
})
} }
} }
@@ -127,15 +136,18 @@ object WeworkLoopImpl {
log("聊天: $title") log("聊天: $title")
val messageList = arrayListOf<WeworkMessageBean.SubMessageBean>() val messageList = arrayListOf<WeworkMessageBean.SubMessageBean>()
val messageList2 = arrayListOf<WeworkMessageBean.SubMessageBean>() val messageList2 = arrayListOf<WeworkMessageBean.SubMessageBean>()
val imageSet = LinkedHashSet<ByteArray>()
do { do {
messageList.clear() messageList.clear()
messageList2.clear() messageList2.clear()
imageSet.clear()
//聊天消息列表 1ListView 0RecycleView xViewGroup //聊天消息列表 1ListView 0RecycleView xViewGroup
val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView)
if (list != null) { if (list != null) {
LogUtils.v("消息条数: " + list.childCount) val childCount = list.childCount
LogUtils.v("消息条数: $childCount")
for (i in 0 until list.childCount) { for (i in 0 until list.childCount) {
val item = list.getChild(i) val item = list.getChild(childCount - 1 - i)
if (item != null && item.childCount > 0) { if (item != null && item.childCount > 0) {
messageList.add(parseChatMessageItem(item, titleList, roomType, false)) messageList.add(parseChatMessageItem(item, titleList, roomType, false))
} }
@@ -145,10 +157,29 @@ object WeworkLoopImpl {
LogUtils.v("双重校验聊天列表") LogUtils.v("双重校验聊天列表")
val list2 = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) val list2 = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView)
if (list2 != null) { if (list2 != null) {
LogUtils.v("list2消息条数: " + list2.childCount) val childCount = list2.childCount
LogUtils.v("list2消息条数: $childCount")
var imageCheck = true var imageCheck = true
if (Constant.enableMediaProject) {
for (i in 0 until childCount) {
val item = list2.getChild(childCount - 1 - i)
if (item != null && item.childCount > 0) {
val chatMessageItem = parseChatMessageItem(item, titleList, roomType, imageCheck)
if (chatMessageItem.imageRepeat == true) {
chatMessageItem.imageRepeat = null
imageCheck = false
}
if (chatMessageItem.image != null) {
imageSet.add(chatMessageItem.image)
chatMessageItem.image = null
chatMessageItem.imageSize = null
}
messageList2.add(chatMessageItem)
}
}
} else {
for (i in 0 until list2.childCount) { for (i in 0 until list2.childCount) {
val item = list2.getChild(i) val item = list2.getChild(childCount - 1 - i)
if (item != null && item.childCount > 0) { if (item != null && item.childCount > 0) {
val chatMessageItem = parseChatMessageItem(item, titleList, roomType, imageCheck) val chatMessageItem = parseChatMessageItem(item, titleList, roomType, imageCheck)
if (chatMessageItem.sender == 0 && chatMessageItem.textType == WeworkMessageBean.TEXT_TYPE_IMAGE) { if (chatMessageItem.sender == 0 && chatMessageItem.textType == WeworkMessageBean.TEXT_TYPE_IMAGE) {
@@ -158,11 +189,13 @@ object WeworkLoopImpl {
} }
} }
} }
}
if (messageList != messageList2) { if (messageList != messageList2) {
LogUtils.e("双重校验聊天列表失败") LogUtils.e("双重校验聊天列表失败")
} }
} while (messageList != messageList2) } while (messageList != messageList2)
if (messageList.isNotEmpty()) { if (messageList.isNotEmpty()) {
messageList.reverse()
val lastMessage = messageList.last() val lastMessage = messageList.last()
val prefix = (lastMessage.nameList.firstOrNull()?.replace("\\(.*\\)$".toRegex(), "") + ": ").replace("null:", "") val prefix = (lastMessage.nameList.firstOrNull()?.replace("\\(.*\\)$".toRegex(), "") + ": ").replace("null:", "")
val lastSyncMessage = prefix + if (lastMessage.textType == WeworkMessageBean.TEXT_TYPE_IMAGE) { val lastSyncMessage = prefix + if (lastMessage.textType == WeworkMessageBean.TEXT_TYPE_IMAGE) {
@@ -172,7 +205,24 @@ object WeworkLoopImpl {
} }
SPUtils.getInstance("lastSyncMessage").put(title, lastSyncMessage) SPUtils.getInstance("lastSyncMessage").put(title, lastSyncMessage)
LogUtils.v("lastSyncMessage: $lastSyncMessage") LogUtils.v("lastSyncMessage: $lastSyncMessage")
if (Constant.pushImage) { if (Constant.enableMediaProject && Constant.pushImage) {
log("image: ${imageSet.size}")
if (imageSet.isNotEmpty()) {
val imageMessageList = messageList.filter { it.textType == WeworkMessageBean.TEXT_TYPE_IMAGE }.reversed()
LogUtils.v("lastImage: ${imageSet.first().size}")
SPUtils.getInstance("lastImage").put(titleList.joinToString(), imageSet.first().size)
imageSet.reversed().forEachIndexed { index, bytes ->
if (imageMessageList.size > index) {
val message = imageMessageList[index]
}
}
}
for (subMessageBean in messageList) {
subMessageBean.image = null
subMessageBean.imageSize = null
subMessageBean.imageRepeat = null
}
} else if (!Constant.enableMediaProject && Constant.pushImage) {
log("createSet: ${MultiFileObserver.createSet.joinToString()}\nsaveSet: ${MultiFileObserver.saveSet.joinToString()}") log("createSet: ${MultiFileObserver.createSet.joinToString()}\nsaveSet: ${MultiFileObserver.saveSet.joinToString()}")
if (MultiFileObserver.saveSet.isNotEmpty()) { if (MultiFileObserver.saveSet.isNotEmpty()) {
val imageMessageList = messageList.filter { it.textType == WeworkMessageBean.TEXT_TYPE_IMAGE }.reversed() val imageMessageList = messageList.filter { it.textType == WeworkMessageBean.TEXT_TYPE_IMAGE }.reversed()
@@ -595,6 +645,44 @@ object WeworkLoopImpl {
message = WeworkMessageBean.SubMessageBean(0, textType, itemMessageList, nameList) message = WeworkMessageBean.SubMessageBean(0, textType, itemMessageList, nameList)
//图片类型特殊处理 //图片类型特殊处理
if (imageCheck && Constant.pushImage && textType == WeworkMessageBean.TEXT_TYPE_IMAGE) { if (imageCheck && Constant.pushImage && textType == WeworkMessageBean.TEXT_TYPE_IMAGE) {
if (Constant.enableMediaProject) {
AccessibilityUtil.performClickWithSon(relativeLayoutContent)
AccessibilityExtraUtil.loadingPage("ShowImageController", Constant.CHANGE_PAGE_INTERVAL)
//图片双重校验
var image = 0
var image2 = 0
var byte: ByteArray? = null
do {
val bitmap = GetScreenShotActivity.startCapture()
byte = ImageUtils.bitmap2Bytes(bitmap)
LogUtils.v("bitmap byte: ${byte.size}")
image = byte.size
sleep(Constant.POP_WINDOW_INTERVAL / 2)
val bitmap2 = GetScreenShotActivity.startCapture()
val byte2 = ImageUtils.bitmap2Bytes(bitmap2)
LogUtils.v("bitmap2 byte: ${byte2.size}")
image2 = byte2.size
if (image != image2) {
LogUtils.e("图片双重校验失败")
}
} while (image != image2)
if (byte != null) {
if (titleList.isNotEmpty()) {
val lastImage = SPUtils.getInstance("lastImage").getInt(titleList.joinToString())
if (lastImage == byte.size) {
message.imageRepeat = true
} else {
message.imageSize = byte.size
message.image = byte
}
}
}
var retry = 3
while (retry-- > 0 && WeworkController.weworkService.currentClass == "com.tencent.wework.msg.controller.ShowImageController") {
AccessibilityUtil.performXYClick(WeworkController.weworkService, ScreenUtils.getScreenWidth() / 2F, BarUtils.getStatusBarHeight() * 2F)
sleep(Constant.POP_WINDOW_INTERVAL)
}
} else {
MultiFileObserver.createSet.clear() MultiFileObserver.createSet.clear()
MultiFileObserver.finishSet.clear() MultiFileObserver.finishSet.clear()
MultiFileObserver.saveSet.clear() MultiFileObserver.saveSet.clear()
@@ -647,6 +735,7 @@ object WeworkLoopImpl {
sleep(Constant.POP_WINDOW_INTERVAL) sleep(Constant.POP_WINDOW_INTERVAL)
} }
} }
}
} else if (Views.ImageView.equals(relativeLayoutItem.getChild(1).className)) { } else if (Views.ImageView.equals(relativeLayoutItem.getChild(1).className)) {
LogUtils.v("头像在右边 本条消息发送者为自己") LogUtils.v("头像在右边 本条消息发送者为自己")
var textType = WeworkMessageBean.TEXT_TYPE_UNKNOWN var textType = WeworkMessageBean.TEXT_TYPE_UNKNOWN

View File

@@ -1264,4 +1264,59 @@ object AccessibilityUtil {
sleep(SCROLL_INTERVAL) sleep(SCROLL_INTERVAL)
return dispatchGesture return dispatchGesture
} }
/**
* 等待文案消失
*/
fun waitForTextMissing(
node: AccessibilityNodeInfo?,
vararg textList: String,
exact: Boolean = false,
timeout: Long = 5000,
root: Boolean = true,
desc: Boolean = false
): Boolean {
var node = node ?: return true
val startTime = System.currentTimeMillis()
var currentTime = startTime
while (currentTime - startTime <= timeout) {
findOnceByText(node, *textList, exact = exact, desc = desc) ?: return true
sleep(SHORT_INTERVAL)
if (root) {
node = getRoot(true)
} else {
node.refresh()
}
currentTime = System.currentTimeMillis()
}
Log.e(tag, "waitForTextMissing ${if (desc) "desc" else "text"}: found: ${textList.joinToString()}")
return false
}
/**
* 等待控件消失
*/
fun waitForClazzMissing(
node: AccessibilityNodeInfo?,
vararg clazzList: String,
timeout: Long = 5000,
root: Boolean = true
): Boolean {
var node = node ?: return true
val startTime = System.currentTimeMillis()
var currentTime = startTime
while (currentTime - startTime <= timeout) {
findOnceByClazz(node, *clazzList) ?: return true
sleep(SHORT_INTERVAL)
if (root) {
node = getRoot(true)
} else {
node.refresh()
}
currentTime = System.currentTimeMillis()
}
LogUtils.e("waitForClazzMissing found: ${clazzList.joinToString()}")
return false
}
} }

View File

@@ -122,7 +122,7 @@ object HttpUtil {
json.put("groupRemark", null) json.put("groupRemark", null)
} }
} else { } else {
json.put("receivedName", titleList.lastOrNull() { !it.contains("") } ?: "") json.put("receivedName", titleList.lastOrNull { !it.contains("") } ?: "")
json.put("groupName", null) json.put("groupName", null)
json.put("groupRemark", null) json.put("groupRemark", null)
} }

View File

@@ -6,6 +6,7 @@ import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.LogUtils;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
import org.yameida.worktool.Constant;
import org.yameida.worktool.model.WeworkMessageBean; import org.yameida.worktool.model.WeworkMessageBean;
import org.yameida.worktool.model.WeworkMessageListBean; import org.yameida.worktool.model.WeworkMessageListBean;
import org.yameida.worktool.service.WeworkController; import org.yameida.worktool.service.WeworkController;
@@ -157,9 +158,11 @@ public class WebSocketManager {
//重连后刷新连接时间 //重连后刷新连接时间
lastConnectedTime = System.currentTimeMillis(); lastConnectedTime = System.currentTimeMillis();
} }
if (!Constant.INSTANCE.getEnableMediaProject()) {
if (System.currentTimeMillis() - lastConnectedTime > heartBeatRate * 3000 && !FloatWindowHelper.INSTANCE.isPause()) { if (System.currentTimeMillis() - lastConnectedTime > heartBeatRate * 3000 && !FloatWindowHelper.INSTANCE.isPause()) {
ToastUtils.show("机器人运行中 请勿人工操作手机~"); ToastUtils.show("机器人运行中 请勿人工操作手机~");
} }
}
}; };
//每heartBeatRate秒发一次心跳包 //每heartBeatRate秒发一次心跳包