Merge branch 'master' of https://github.com/gallonyin/worktool into master

This commit is contained in:
gallonyin
2023-02-06 23:45:27 +08:00
16 changed files with 459 additions and 51 deletions

View File

@@ -4,9 +4,10 @@ import com.blankj.utilcode.util.SPUtils
object Constant {
val AVAILABLE_VERSION = arrayListOf("4.0.2", "4.0.6", "4.0.8", "4.0.10", "4.0.12", "4.0.16", "4.0.18", "4.0.19", "4.0.20")
val AVAILABLE_VERSION = arrayListOf("4.0.2", "4.0.6", "4.0.8", "4.0.10", "4.0.12", "4.0.16", "4.0.18", "4.0.19", "4.0.20", "4.1.0")
const val PACKAGE_NAMES = "com.tencent.wework"
const val WEWORK_NOTIFY = "wework_notify"
const val LONG_INTERVAL = 5000L
const val CHANGE_PAGE_INTERVAL = 1000L
const val POP_WINDOW_INTERVAL = 500L
private const val DEFAULT_HOST = "wss://worktool.asrtts.cn"
@@ -21,6 +22,8 @@ object Constant {
var autoReply = SPUtils.getInstance().getInt("autoReply", 1)
var groupStrict = false
var friendRemarkStrict = false
var pushImage = false
var autoPublishComment = false
var robotId: String
get() = SPUtils.getInstance().getString("robotId", SPUtils.getInstance().getString("LISTEN_CHANNEL_ID", ""))
set(value) {

View File

@@ -10,9 +10,11 @@ import com.umeng.analytics.MobclickAgent
import kotlinx.android.synthetic.main.activity_listen.*
import org.yameida.worktool.*
import android.content.*
import android.os.FileObserver
import android.text.InputType
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.qmuiteam.qmui.widget.dialog.QMUIDialog
import org.yameida.worktool.observer.MultiFileObserver
import org.yameida.worktool.utils.*
import org.yameida.worktool.utils.envcheck.CheckHook
import org.yameida.worktool.utils.envcheck.CheckRoot
@@ -20,6 +22,8 @@ import org.yameida.worktool.utils.envcheck.CheckRoot
class ListenActivity : AppCompatActivity() {
private var mFileObserver: FileObserver? = null
companion object {
/**
* @param type 0=游客登录
@@ -42,6 +46,7 @@ class ListenActivity : AppCompatActivity() {
initView()
initAccessibility()
initOverlays()
initObserver()
initData()
PermissionUtils.permission("android.permission.READ_EXTERNAL_STORAGE").request()
registerReceiver(openWsReceiver, IntentFilter(Constant.WEWORK_NOTIFY))
@@ -155,6 +160,14 @@ class ListenActivity : AppCompatActivity() {
}
}
private fun initObserver() {
if (mFileObserver == null) {
mFileObserver =
MultiFileObserver("/storage/emulated/0/Android/data/com.tencent.wework/files/imagecache/imagemsg2");
mFileObserver?.startWatching()
}
}
private fun initData() {
HttpUtil.checkUpdate()
HttpUtil.getMyConfig(toast = false)

View File

@@ -174,6 +174,8 @@ public class WeworkMessageBean {
public String extraText;
//接收消息类型
public Integer textType;
//最大尝试次数
public Integer maxRetryCount;
//群名
public String groupName;

View File

@@ -0,0 +1,152 @@
package org.yameida.worktool.observer;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import android.os.FileObserver;
import android.util.Log;
public class MultiFileObserver extends FileObserver {
public HashMap<String, Long> map = new HashMap<>();
public static String lastPicPath = "";
public static Long lastPicCreateTime = 0L;
/** Only modification events */
public static int CHANGES_ONLY = CREATE | MODIFY | DELETE | CLOSE_WRITE
| DELETE_SELF | MOVE_SELF | MOVED_FROM | MOVED_TO;
private List<SingleFileObserver> mObservers;
private String mPath;
private int mMask;
public MultiFileObserver(String path) {
this(path, ALL_EVENTS);
}
public MultiFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
mMask = mask;
}
@Override
public void startWatching() {
if (mObservers != null)
return;
mObservers = new ArrayList<SingleFileObserver>();
Stack<String> stack = new Stack<String>();
stack.push(mPath);
while (!stack.isEmpty()) {
String parent = stack.pop();
mObservers.add(new SingleFileObserver(parent, mMask));
File path = new File(parent);
File[] files = path.listFiles();
if (null == files)
continue;
for (File f : files) {
if (f.isDirectory() && !f.getName().equals(".")
&& !f.getName().equals("..")) {
stack.push(f.getPath());
}
}
}
for (int i = 0; i < mObservers.size(); i++) {
SingleFileObserver sfo = mObservers.get(i);
sfo.startWatching();
}
}
@Override
public void stopWatching() {
if (mObservers == null)
return;
for (int i = 0; i < mObservers.size(); i++) {
SingleFileObserver sfo = mObservers.get(i);
sfo.stopWatching();
}
mObservers.clear();
mObservers = null;
}
@Override
public void onEvent(int event, String path) {
switch (event) {
case FileObserver.ACCESS:
case FileObserver.CLOSE_NOWRITE:
if (path.endsWith(".0") && !map.containsKey(path)) {
Log.i("RecursiveFileObserver", "发现新图片: " + path);
map.put(path, System.currentTimeMillis());
lastPicPath = path;
}
break;
case FileObserver.CREATE:
Log.i("RecursiveFileObserver", "CREATE: " + path);
lastPicCreateTime = System.currentTimeMillis();
break;
case FileObserver.ATTRIB:
// Log.i("RecursiveFileObserver", "ATTRIB: " + path);
break;
case FileObserver.CLOSE_WRITE:
// Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path);
break;
case FileObserver.DELETE:
// Log.i("RecursiveFileObserver", "DELETE: " + path);
break;
case FileObserver.DELETE_SELF:
// Log.i("RecursiveFileObserver", "DELETE_SELF: " + path);
break;
case FileObserver.MODIFY:
// Log.i("RecursiveFileObserver", "MODIFY: " + path);
break;
case FileObserver.MOVE_SELF:
// Log.i("RecursiveFileObserver", "MOVE_SELF: " + path);
break;
case FileObserver.MOVED_FROM:
// Log.i("RecursiveFileObserver", "MOVED_FROM: " + path);
break;
case FileObserver.MOVED_TO:
// Log.i("RecursiveFileObserver", "MOVED_TO: " + path);
break;
case FileObserver.OPEN:
// Log.i("RecursiveFileObserver", "OPEN: " + path);
break;
default:
// Log.i("RecursiveFileObserver", "DEFAULT(" + event + " : " + path);
break;
}
}
/**
* Monitor single directory and dispatch all events to its parent, with full
* path.
*/
class SingleFileObserver extends FileObserver {
String mPath;
public SingleFileObserver(String path) {
this(path, ALL_EVENTS);
mPath = path;
}
public SingleFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
}
@Override
public void onEvent(int event, String path) {
String newPath = mPath + "/" + path;
MultiFileObserver .this.onEvent(event, newPath);
}
}
}

View File

@@ -135,6 +135,7 @@ fun getRoot(ignoreCheck: Boolean): AccessibilityNodeInfo {
* 后退
*/
fun backPress() {
val clazz = WeworkController.weworkService.currentClass
val textView = AccessibilityUtil.findOnceByClazz(getRoot(), Views.TextView)
if (textView != null && textView.text.isNullOrBlank() && AccessibilityUtil.performClick(textView, retry = false)) {
LogUtils.v("找到回退按钮")
@@ -164,10 +165,12 @@ fun backPress() {
} else {
LogUtils.d("未找到对话框 点击bar中心")
AccessibilityUtil.performXYClick(WeworkController.weworkService, ScreenUtils.getScreenWidth() / 2F, BarUtils.getStatusBarHeight() * 2F)
sleep(Constant.POP_WINDOW_INTERVAL)
val firstEmptyTextView = AccessibilityUtil.findAllByClazz(getRoot(), Views.TextView).firstOrNull { it.text.isNullOrEmpty() }
if (firstEmptyTextView != null && firstEmptyTextView.isClickable) {
AccessibilityUtil.performClick(firstEmptyTextView)
sleep(Constant.CHANGE_PAGE_INTERVAL * 2)
if (WeworkController.weworkService.currentClass == clazz) {
val firstEmptyTextView = AccessibilityUtil.findAllByClazz(getRoot(), Views.TextView).firstOrNull { it.text.isNullOrEmpty() }
if (firstEmptyTextView != null && firstEmptyTextView.isClickable) {
AccessibilityUtil.performClick(firstEmptyTextView)
}
}
}
}

View File

@@ -51,6 +51,8 @@ object MyLooper {
fun init() {
LogUtils.i("init myLooper...")
SPUtils.getInstance("noTipMessage").clear()
SPUtils.getInstance("lastSyncMessage").clear()
SPUtils.getInstance("noSyncMessage").clear()
SPUtils.getInstance("limit").clear()
}

View File

@@ -334,7 +334,8 @@ object WeworkController {
message.fileUrl,
message.fileBase64,
message.fileType,
message.extraText
message.extraText,
message.maxRetryCount
)
}

View File

@@ -2,15 +2,19 @@ package org.yameida.worktool.service
import android.view.accessibility.AccessibilityNodeInfo
import androidx.core.text.isDigitsOnly
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.*
import org.yameida.worktool.Constant
import org.yameida.worktool.Demo
import org.yameida.worktool.model.WeworkMessageBean
import org.yameida.worktool.observer.MultiFileObserver
import org.yameida.worktool.service.WeworkController.mainLoopRunning
import org.yameida.worktool.utils.*
import java.io.File
import java.lang.Exception
import java.lang.StringBuilder
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
/**
* 获取数据类型 201 202 主循环
@@ -26,7 +30,7 @@ object WeworkLoopImpl {
mainLoopRunning = true
try {
while (mainLoopRunning) {
if (!isAtHome() && WeworkRoomUtil.getRoomType(false) != WeworkMessageBean.ROOM_TYPE_UNKNOWN) {
if (!isAtHome()) {
LogUtils.d("当前在房间: ")
getChatMessageList()
if (mainLoopRunning) {
@@ -112,7 +116,7 @@ object WeworkLoopImpl {
if (titleList.contains("对方正在输入…")) {
titleList = WeworkRoomUtil.getFriendName()
}
if (titleList.size > 0) {
if (roomType != WeworkMessageBean.ROOM_TYPE_UNKNOWN && titleList.size > 0) {
val title = titleList.joinToString()
LogUtils.v("聊天: $title")
log("聊天: $title")
@@ -128,7 +132,7 @@ object WeworkLoopImpl {
for (i in 0 until list.childCount) {
val item = list.getChild(i)
if (item != null && item.childCount > 0) {
messageList.add(parseChatMessageItem(item, roomType))
messageList.add(parseChatMessageItem(item, titleList, roomType))
}
}
}
@@ -140,7 +144,7 @@ object WeworkLoopImpl {
for (i in 0 until list2.childCount) {
val item = list2.getChild(i)
if (item != null && item.childCount > 0) {
messageList2.add(parseChatMessageItem(item, roomType))
messageList2.add(parseChatMessageItem(item, titleList, roomType))
}
}
}
@@ -159,6 +163,7 @@ object WeworkLoopImpl {
null
)
)
SPUtils.getInstance("lastSyncMessage").put(title, messageList.last().itemMessageList.lastOrNull()?.text)
//推测是否回复并在房间等待指令
if (needInfer) {
val lastMessage = messageList.lastOrNull()
@@ -203,6 +208,20 @@ object WeworkLoopImpl {
LogUtils.e("未找到聊天消息列表")
error("未找到聊天消息列表")
}
} else if (Constant.autoPublishComment && WeworkController.weworkService.currentClass == "com.tencent.wework.moments.controller.MomentsIndexListActivity") {
LogUtils.d("自动发表朋友圈")
val tvGoPublish = AccessibilityUtil.findOneByText(getRoot(), "去发表", exact = true)
if (tvGoPublish != null) {
AccessibilityUtil.performClick(tvGoPublish)
AccessibilityExtraUtil.loadingPage("MomentsEnterpriseNotificationListActivity")
val tvPublishList = AccessibilityUtil.findAllByText(getRoot(), "发表", exact = true)
LogUtils.d("发现${tvPublishList.size}条待发送")
for (tvPublish in tvPublishList) {
AccessibilityUtil.performClick(tvPublish)
}
}
} else {
LogUtils.v("退出非聊天房间 ${WeworkController.weworkService.currentClass}")
}
return false
}
@@ -280,8 +299,9 @@ object WeworkLoopImpl {
val listview = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView, Views.ViewGroup)
if (listview != null && listview.childCount >= 2) {
if (hasNewMessage != null) {
//发现新消息
if (checkUnreadChatRoom(listview)) {
//如果有红点 点击进入聊天页
//如果房间有红点 点击进入聊天页
return true
} else {
AccessibilityUtil.clickByNode(WeworkController.weworkService, hasNewMessage)
@@ -290,14 +310,18 @@ object WeworkLoopImpl {
sleep(Constant.POP_WINDOW_INTERVAL / 5)
//双击消息再试一次
if (checkUnreadChatRoom(listview)) {
//如果有红点 点击进入聊天页
//如果房间有红点 点击进入聊天页
return true
}
}
} else {
//未发现新消息
if (checkNoTipMessage(listview) == 1) {
//如果发现拉入群聊/修改群名/移出群聊 点击进入聊天页
return true
} else if (checkNoSyncMessage(listview) == 1) {
//消息不一致
return true
} else {
LogUtils.v("未发现新消息或无提示消息")
}
@@ -336,6 +360,9 @@ object WeworkLoopImpl {
if (checkNoTipMessage(listview) != 0) {
return true
}
if (checkNoSyncMessage(listview) != 0) {
return true
}
return false
}
})
@@ -388,14 +415,14 @@ object WeworkLoopImpl {
val listBriefList = arrayListOf<List<CharSequence>>()
for (i in 0 until list.childCount) {
val item = list.getChild(i)
val tvList = AccessibilityUtil.findAllOnceByClazz(item, Views.TextView).mapNotNull { it.text }
val tvList = AccessibilityUtil.findAllOnceByClazz(item, Views.TextView).mapNotNull { it.text?.toString() }
listBriefList.add(tvList)
//tvList title/time/content
if (tvList.size == 3) {
//只查看最近一周内的消息
if (tvList[1].isBlank() || tvList[1].contains("(刚刚)|(分钟前)|(上午)|(下午)|(昨天)|(星期)|(日程)|(会议)".toRegex())) {
if (tvList[2].contains("(移出了群聊)|(邀请你加入了)|(修改群名为)|(此群为外部群)|(加入了外部群)".toRegex())) {
val interval = System.currentTimeMillis() / 1000 - SPUtils.getInstance("noTipMessage").getLong(tvList[0].toString(), 0)
val interval = System.currentTimeMillis() / 1000 - SPUtils.getInstance("noTipMessage").getLong(tvList[0], 0)
if (interval > 3600) {
LogUtils.i("发现无提示消息: $tvList")
log("发现无提示消息: $tvList")
@@ -404,7 +431,7 @@ object WeworkLoopImpl {
} else {
AccessibilityUtil.clickByNode(WeworkController.weworkService, item)
}
SPUtils.getInstance("noTipMessage").put(tvList[0].toString(), System.currentTimeMillis() / 1000)
SPUtils.getInstance("noTipMessage").put(tvList[0], System.currentTimeMillis() / 1000)
return 1
} else {
LogUtils.v("发现无提示消息: $tvList 消息在 $interval 秒前已被查看")
@@ -418,11 +445,54 @@ object WeworkLoopImpl {
return 0
}
/**
* 检查首页-聊天列表是否有不一致消息
* @return -1当前列表不存在一周内消息 0未发现不一致消息 1发现不一致消息
*/
private fun checkNoSyncMessage(list: AccessibilityNodeInfo): Int {
list.refresh()
val listBriefList = arrayListOf<List<CharSequence>>()
for (i in 0 until list.childCount) {
val item = list.getChild(i)
val tvList = AccessibilityUtil.findAllOnceByClazz(item, Views.TextView).mapNotNull { it.text?.toString() }
listBriefList.add(tvList)
//tvList title/time/content
if (tvList.size == 3) {
//只查看最近一周内的消息
val title = tvList[0]
if (tvList[1].isBlank() || tvList[1].contains("(刚刚)|(分钟前)|(上午)|(下午)|(昨天)|(星期)|(日程)|(会议)".toRegex())) {
val lastSyncMessage = SPUtils.getInstance("lastSyncMessage").getString(title, null)
?: continue
if (tvList[2].contains(lastSyncMessage.replace("\n", " "))) {
continue
}
if (SPUtils.getInstance("noSyncMessage").getString(title) != lastSyncMessage) {
LogUtils.e("发现不一致消息: $tvList")
error("发现不一致消息: $tvList $lastSyncMessage")
SPUtils.getInstance("noSyncMessage").put(title, lastSyncMessage)
if (AccessibilityUtil.performClick(item)) {
//进入聊天页 下一步 getChatMessageList
} else {
AccessibilityUtil.clickByNode(WeworkController.weworkService, item)
}
return 1
} else {
LogUtils.v("消息多次不一致: $tvList")
}
} else {
return -1
}
}
}
return 0
}
/**
* 解析消息列表里的一条消息
*/
private fun parseChatMessageItem(
node: AccessibilityNodeInfo,
titleList: ArrayList<String>,
roomType: Int
): WeworkMessageBean.SubMessageBean {
val message: WeworkMessageBean.SubMessageBean
@@ -466,6 +536,52 @@ object WeworkLoopImpl {
}
}
message = WeworkMessageBean.SubMessageBean(0, textType, itemMessageList, nameList)
//图片类型特殊处理
if (Constant.pushImage && textType == 2) {
val lastPicCreateTime = MultiFileObserver.lastPicCreateTime
val lastPicPath = MultiFileObserver.lastPicPath
LogUtils.d("发现图片类型应该点击")
AccessibilityUtil.performClickWithSon(relativeLayoutContent)
AccessibilityExtraUtil.loadingPage("com.tencent.wework.msg.controller.ShowImageController", Constant.CHANGE_PAGE_INTERVAL)
LogUtils.d("发现图片类型 查看图片检查有无新图片产生")
if (MultiFileObserver.lastPicCreateTime > lastPicCreateTime) {
LogUtils.d("正在下载图片...")
var downloading = true
val startTime = System.currentTimeMillis()
var currentTime = startTime
while (currentTime - startTime < Constant.LONG_INTERVAL) {
if (!lastPicPath.equals(MultiFileObserver.lastPicPath)) {
LogUtils.d("下载图片完成")
downloading = false
try {
val df = SimpleDateFormat("MMdd_HHmmss")
val targetPath = "${
Utils.getApp().getExternalFilesDir("copy")
}/${df.format(Date())}/${File(MultiFileObserver.lastPicPath).name}.png"
if (FileUtils.copy(MultiFileObserver.lastPicPath, targetPath)) {
LogUtils.d("复制图片完成: $targetPath")
} else {
LogUtils.e("复制图片失败 请检查权限: $targetPath")
}
} catch (e: Exception) {
LogUtils.e("接收图片出错", e)
}
break
}
sleep(Constant.POP_WINDOW_INTERVAL / 5)
currentTime = System.currentTimeMillis()
}
if (downloading) {
LogUtils.e("下载图片失败")
}
} else {
LogUtils.d("该图片已下载 忽略")
}
while (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 if (Views.ImageView.equals(relativeLayoutItem.getChild(1).className)) {
LogUtils.v("头像在右边 本条消息发送者为自己")
var textType = WeworkMessageBean.TEXT_TYPE_UNKNOWN

View File

@@ -549,8 +549,10 @@ object WeworkOperationImpl {
fileUrl: String?,
fileBase64: String?,
fileType: String,
extraText: String? = null
extraText: String? = null,
maxRetryCount: Int? = null
): Boolean {
val retryCount = maxRetryCount ?: 1
val startTime = System.currentTimeMillis()
if (!PermissionUtils.isGrantedDrawOverlays()) {
LogUtils.e("未打开悬浮窗权限")
@@ -601,6 +603,9 @@ object WeworkOperationImpl {
return true
} else {
LogUtils.e("文件转发失败: $objectName")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_RELAY,
@@ -611,6 +616,9 @@ object WeworkOperationImpl {
}
} else {
LogUtils.e("文件存储本地失败 $filePath")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_FILE_STORAGE,
@@ -621,6 +629,9 @@ object WeworkOperationImpl {
}
} else {
LogUtils.e("文件下载失败")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_FILE_DOWNLOAD,
@@ -668,6 +679,9 @@ object WeworkOperationImpl {
return true
} else {
LogUtils.e("文件转发失败: $objectName")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_RELAY,
@@ -678,6 +692,9 @@ object WeworkOperationImpl {
}
} else {
LogUtils.e("文件存储本地失败 $filePath")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_FILE_STORAGE,
@@ -687,6 +704,10 @@ object WeworkOperationImpl {
return false
}
} else {
LogUtils.e("未找到文件资源参数")
if (retryCount > 0) {
return pushFile(message, titleList, objectName, fileUrl, fileBase64, fileType, extraText, retryCount - 1)
}
uploadCommandResult(
message,
ExecCallbackBean.ERROR_ILLEGAL_DATA,
@@ -1059,7 +1080,9 @@ object WeworkOperationImpl {
if (tvCorp != null) {
LogUtils.d("找到目标企业: $objectName")
AccessibilityUtil.performClick(tvCorp)
uploadCommandResult(message, ExecCallbackBean.SUCCESS, "切换企业成功: $objectName", startTime)
goHome()
WeworkGetImpl.getMyInfo(message)
return true
} else {
LogUtils.e("未找到目标企业: $objectName")

View File

@@ -5,6 +5,7 @@ import android.content.Context
import android.net.Uri
import android.os.Build
import android.provider.Settings
import org.yameida.worktool.utils.envcheck.CheckRoot
import java.lang.reflect.Method
object FlowPermissionHelper {
@@ -26,6 +27,10 @@ object FlowPermissionHelper {
}
fun canBackgroundStart(context: Context): Boolean {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 || CheckRoot.isDeviceRooted()) {
return true
}
if (isXiaoMi()) {
return isXiaomiBgStartPermissionAllowed(context)
}

View File

@@ -13,9 +13,13 @@ import org.yameida.worktool.R
import org.yameida.worktool.model.network.CheckUpdateResult
import org.yameida.worktool.model.network.GetMyConfigResult
import update.UpdateAppUtils
import java.io.File
object HttpUtil {
/**
* 检查更新
*/
fun checkUpdate() {
OkGo.get<String>(Constant.getCheckUpdateUrl())
.execute(object : StringCallback() {
@@ -63,6 +67,9 @@ object HttpUtil {
})
}
/**
* 获取机器人配置
*/
fun getMyConfig(toast: Boolean = true) {
if (Constant.robotId.isBlank()) {
if (toast) {
@@ -101,4 +108,24 @@ object HttpUtil {
}
})
}
/**
* 推送图片
*/
fun pushImage(url: String, groupName: String, receivedName: String?, imagePath: String) {
OkGo.post<String>(url)
.params("groupName", groupName)
.params("receivedName", receivedName ?: "")
.params("image", File(imagePath))
.execute(object : StringCallback() {
override fun onSuccess(response: Response<String>) {
LogUtils.d("推送图片成功: $groupName $receivedName $imagePath")
}
override fun onError(response: Response<String>) {
ToastUtils.showLong("推送图片失败")
LogUtils.e("推送图片失败")
}
})
}
}

View File

@@ -0,0 +1,26 @@
package org.yameida.worktool.utils;
import com.blankj.utilcode.util.LogUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class ImageDepthSizeUtil {
public static boolean checkRawImage(String path) {
try {
File file = new File(path);
FileInputStream fileInputStream = new FileInputStream(file);
byte[] b = new byte[1000000];
fileInputStream.read(b);
int bitsPerPixel = (b[25] & 0xff) == 2 || (b[25] & 0xff) == 6 ? (b[24] & 0xff) * 3 : b[24] & 0xff;
LogUtils.v("path: " + path, "bitsPerPixel: " + bitsPerPixel);
return bitsPerPixel == 24;
} catch (IOException e) {
LogUtils.e("ImageDepthSize Check Error", e);
}
return false;
}
}

View File

@@ -35,32 +35,37 @@ public class PermissionPageManagement {
* @param activity
*/
public static void goToSetting(Activity activity){
switch (Build.MANUFACTURER){
case MANUFACTURER_HUAWEI:
Huawei(activity);
break;
case MANUFACTURER_MEIZU:
Meizu(activity);
break;
case MANUFACTURER_XIAOMI:
Xiaomi(activity);
break;
case MANUFACTURER_SONY:
Sony(activity);
break;
case MANUFACTURER_OPPO:
OPPO(activity);
break;
case MANUFACTURER_VIVO:
VIVO(activity);
break;
case MANUFACTURER_LG:
LG(activity);
break;
default:
ApplicationInfo(activity);
Log.e("goToSetting", "目前暂不支持此系统");
break;
try {
switch (Build.MANUFACTURER) {
case MANUFACTURER_HUAWEI:
Huawei(activity);
break;
case MANUFACTURER_MEIZU:
Meizu(activity);
break;
case MANUFACTURER_XIAOMI:
Xiaomi(activity);
break;
case MANUFACTURER_SONY:
Sony(activity);
break;
case MANUFACTURER_OPPO:
OPPO(activity);
break;
case MANUFACTURER_VIVO:
VIVO(activity);
break;
case MANUFACTURER_LG:
LG(activity);
break;
default:
ApplicationInfo(activity);
Log.e("goToSetting", "目前暂不支持此系统");
break;
}
} catch (Exception e) {
Log.e("goToSetting", "Error 目前暂不支持此系统");
ApplicationInfo(activity);
}
}

View File

@@ -0,0 +1,26 @@
package org.yameida.worktool.utils
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
object RuntimeUtil {
@Throws(Exception::class)
fun exec(cmd: String): String? {
var ret: String? = null
val p = Runtime.getRuntime().exec(arrayOf("sh", "-c", cmd))
val inputStream: InputStream = p.inputStream
val reader = BufferedReader(InputStreamReader(inputStream))
var line: String? = reader.readLine()
while (line != null) {
ret = line
line = reader.readLine()
}
p.waitFor()
inputStream.close()
reader.close()
p.destroy()
return ret
}
}