Compare commits
10 Commits
c6fbcec2d6
...
backup-bef
| Author | SHA1 | Date | |
|---|---|---|---|
| 57cf264e44 | |||
|
|
9bfb1a9040 | ||
| cad16fa7ca | |||
| 2ae2ab0ff5 | |||
| ccc0c3c4ae | |||
| 9a9ffb79d5 | |||
| 1d9a77a112 | |||
| 8efa4889be | |||
| 81615a27d9 | |||
| 473e2c2d89 |
@@ -58,7 +58,7 @@ object Constant {
|
|||||||
SPUtils.getInstance().put(weworkCorpName + "weworkMP", value)
|
SPUtils.getInstance().put(weworkCorpName + "weworkMP", value)
|
||||||
}
|
}
|
||||||
var encryptType: Int = SPUtils.getInstance().getInt("encryptType", 0)
|
var encryptType: Int = SPUtils.getInstance().getInt("encryptType", 0)
|
||||||
var autoReply: Int = SPUtils.getInstance().getInt("autoReply", 1)
|
var autoReply: Int = SPUtils.getInstance().getInt("autoReply", 0)
|
||||||
var groupStrict: Boolean
|
var groupStrict: Boolean
|
||||||
get() = SPUtils.getInstance().getBoolean("groupStrict", false)
|
get() = SPUtils.getInstance().getBoolean("groupStrict", false)
|
||||||
set(value) = SPUtils.getInstance().put("groupStrict", value)
|
set(value) = SPUtils.getInstance().put("groupStrict", value)
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package org.yameida.worktool
|
|
||||||
|
|
||||||
import com.blankj.utilcode.util.TimeUtils
|
|
||||||
import org.yameida.worktool.model.WeworkMessageBean
|
|
||||||
import org.yameida.worktool.service.MyLooper
|
|
||||||
import org.yameida.worktool.service.WeworkController
|
|
||||||
import org.yameida.worktool.service.WeworkLoopImpl
|
|
||||||
import org.yameida.worktool.service.getRoot
|
|
||||||
import org.yameida.worktool.utils.AccessibilityUtil
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例
|
|
||||||
*/
|
|
||||||
object Demo {
|
|
||||||
|
|
||||||
fun test(flag: Boolean) {
|
|
||||||
if (!flag) return
|
|
||||||
|
|
||||||
MyLooper.getInstance().removeCallbacksAndMessages(null)
|
|
||||||
|
|
||||||
//打印当前视图树
|
|
||||||
// AccessibilityUtil.printNodeClazzTree(getRoot())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test2(name: String) {
|
|
||||||
val time = TimeUtils.date2String(Date(), "MMddHHmm")
|
|
||||||
val groupName = "测试群$time"
|
|
||||||
val json = """
|
|
||||||
{
|
|
||||||
"socketType":2,
|
|
||||||
"list":[
|
|
||||||
{
|
|
||||||
"type":203,
|
|
||||||
"titleList":[
|
|
||||||
"$name"
|
|
||||||
],
|
|
||||||
"receivedContent":"你好~我是机器人,你可以@我和我聊天,你也可以通过API文档来让我发送消息或完成建群等任务。接口文档:https://www.apifox.cn/apidoc/project-1035094/api-23520034"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": 206,
|
|
||||||
"groupName": "$groupName",
|
|
||||||
"selectList": [
|
|
||||||
"$name",
|
|
||||||
"甲仑"
|
|
||||||
],
|
|
||||||
"groupAnnouncement": "(自动拉群+自动群公告) WorkTool欢迎大家~WorkTool管家是机器人,有问题可以在QQ群反馈~@我可以聊天~"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
MyLooper.onMessage(null, json)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -22,11 +22,13 @@ import org.yameida.worktool.utils.*
|
|||||||
import org.yameida.worktool.utils.capture.MediaProjectionHolder
|
import org.yameida.worktool.utils.capture.MediaProjectionHolder
|
||||||
import org.yameida.worktool.utils.envcheck.CheckHook
|
import org.yameida.worktool.utils.envcheck.CheckHook
|
||||||
import org.yameida.worktool.utils.envcheck.CheckRoot
|
import org.yameida.worktool.utils.envcheck.CheckRoot
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
class ListenActivity : AppCompatActivity() {
|
class ListenActivity : AppCompatActivity() {
|
||||||
|
|
||||||
var riskRetry: Int = 0
|
var riskRetry: Int = 0
|
||||||
|
private var updatingAccessibilitySwitch = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
@@ -59,12 +61,13 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
unregisterReceiver(openWsReceiver)
|
unregisterReceiver(openWsReceiver)
|
||||||
|
FloatWindowHelper.hideWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
sw_overlay.isChecked = Settings.canDrawOverlays(Utils.getApp()) && FlowPermissionHelper.canBackgroundStart(Utils.getApp())
|
sw_overlay.isChecked = Settings.canDrawOverlays(Utils.getApp()) && FlowPermissionHelper.canBackgroundStart(Utils.getApp())
|
||||||
sw_accessibility.isChecked = PermissionHelper.isAccessibilitySettingOn()
|
refreshAccessibilitySwitch()
|
||||||
if (needToWork) {
|
if (needToWork) {
|
||||||
needToWork = false
|
needToWork = false
|
||||||
goToWork()
|
goToWork()
|
||||||
@@ -75,16 +78,11 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
iv_settings.setOnClickListener {
|
iv_settings.setOnClickListener {
|
||||||
SettingsActivity.enterActivity(this)
|
SettingsActivity.enterActivity(this)
|
||||||
}
|
}
|
||||||
et_channel.setText(Constant.robotId)
|
tv_channel.text = Constant.robotId.ifBlank { "未生成" }
|
||||||
bt_save.setOnClickListener {
|
bt_reset_channel.setOnClickListener {
|
||||||
val channel = et_channel.text.toString().trim()
|
val channel = generateDefaultRobotId()
|
||||||
Constant.robotId = channel
|
tv_channel.text = channel
|
||||||
ToastUtils.showLong("保存成功")
|
saveChannel(channel, toast = "重置成功")
|
||||||
sendBroadcast(Intent(Constant.WEWORK_NOTIFY).apply {
|
|
||||||
putExtra("type", "modify_channel")
|
|
||||||
})
|
|
||||||
HttpUtil.getMyConfig(toast = false)
|
|
||||||
MobclickAgent.onProfileSignIn(channel)
|
|
||||||
}
|
}
|
||||||
tv_host.text = Constant.host
|
tv_host.text = Constant.host
|
||||||
tv_host.setOnClickListener {
|
tv_host.setOnClickListener {
|
||||||
@@ -131,6 +129,9 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun initAccessibility() {
|
private fun initAccessibility() {
|
||||||
sw_accessibility.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
|
sw_accessibility.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
|
||||||
|
if (updatingAccessibilitySwitch) {
|
||||||
|
return@OnCheckedChangeListener
|
||||||
|
}
|
||||||
LogUtils.i("sw_accessibility onCheckedChanged: $isChecked")
|
LogUtils.i("sw_accessibility onCheckedChanged: $isChecked")
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
if (Constant.robotId.isBlank()) {
|
if (Constant.robotId.isBlank()) {
|
||||||
@@ -185,13 +186,45 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initData() {
|
private fun initData() {
|
||||||
Constant.robotId = "2038521871751249921"
|
// 链接号为空时自动生成一次并持久化,避免每次启动覆盖用户手动保存的链接号
|
||||||
Constant.host = "ws://8.166.130.74:18680"
|
if (Constant.robotId.isBlank()) {
|
||||||
|
Constant.robotId = generateDefaultRobotId()
|
||||||
|
tv_channel.text = Constant.robotId
|
||||||
|
}
|
||||||
// HttpUtil.checkUpdate()
|
// HttpUtil.checkUpdate()
|
||||||
HttpUtil.getMyConfig(toast = false)
|
HttpUtil.getMyConfig(toast = false)
|
||||||
CacheUtil.autoDelete()
|
CacheUtil.autoDelete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateDefaultRobotId(): String {
|
||||||
|
val suffix = Random.nextInt(1000, 9999)
|
||||||
|
return "${System.currentTimeMillis()}$suffix"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveChannel(channel: String, toast: String) {
|
||||||
|
if (channel.isBlank()) {
|
||||||
|
ToastUtils.showLong("链接号不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Constant.robotId = channel
|
||||||
|
ToastUtils.showLong(toast)
|
||||||
|
sendBroadcast(Intent(Constant.WEWORK_NOTIFY).apply {
|
||||||
|
putExtra("type", "modify_channel")
|
||||||
|
})
|
||||||
|
if (WeworkController.isServiceReady()) {
|
||||||
|
runCatching {
|
||||||
|
WeworkController.weworkService.reconnectWebSocket("modify_channel_direct")
|
||||||
|
}.onFailure {
|
||||||
|
LogUtils.w("重置后直连重连失败,等待广播触发: ${it.message}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ToastUtils.showLong("无障碍服务未运行,请先开启后再重置")
|
||||||
|
LogUtils.w("重置时服务未就绪,无法触发直连重连")
|
||||||
|
}
|
||||||
|
HttpUtil.getMyConfig(toast = false)
|
||||||
|
MobclickAgent.onProfileSignIn(channel)
|
||||||
|
}
|
||||||
|
|
||||||
private fun initNotification() {
|
private fun initNotification() {
|
||||||
if (!Constant.enableMediaProject) {
|
if (!Constant.enableMediaProject) {
|
||||||
return
|
return
|
||||||
@@ -206,7 +239,7 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
}, Context.BIND_AUTO_CREATE)
|
}, Context.BIND_AUTO_CREATE)
|
||||||
//开启屏幕录制权限
|
//开启屏幕录制权限
|
||||||
if (MediaProjectionHolder.mMediaProjection == null) {
|
if (MediaProjectionHolder.mMediaProjection == null) {
|
||||||
bt_save.postDelayed({
|
window.decorView.postDelayed({
|
||||||
fastStartActivity(this, GetScreenShotActivity::class.java)
|
fastStartActivity(this, GetScreenShotActivity::class.java)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
@@ -282,8 +315,8 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
.setNegativeButton("", null)
|
.setNegativeButton("", null)
|
||||||
.setPositiveButton("", null)
|
.setPositiveButton("", null)
|
||||||
val show = positiveButton.show()
|
val show = positiveButton.show()
|
||||||
bt_save.postDelayed({ show.dismiss() }, 5000)
|
window.decorView.postDelayed({ show.dismiss() }, 5000)
|
||||||
bt_save.postDelayed({
|
window.decorView.postDelayed({
|
||||||
packageManager.getLaunchIntentForPackage(Constant.PACKAGE_NAMES)?.apply {
|
packageManager.getLaunchIntentForPackage(Constant.PACKAGE_NAMES)?.apply {
|
||||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
@@ -293,10 +326,21 @@ class ListenActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val openWsReceiver = object : BroadcastReceiver() {
|
private val openWsReceiver = object : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (intent.getStringExtra("type") == "openWs") {
|
when (intent.getStringExtra("type")) {
|
||||||
|
"openWs" -> {
|
||||||
needToWork = intent.getBooleanExtra("switch", false)
|
needToWork = intent.getBooleanExtra("switch", false)
|
||||||
}
|
}
|
||||||
|
"accessibility_state" -> {
|
||||||
|
refreshAccessibilitySwitch(intent.getBooleanExtra("enabled", PermissionHelper.isAccessibilitySettingOn()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun refreshAccessibilitySwitch(checked: Boolean = PermissionHelper.isAccessibilitySettingOn()) {
|
||||||
|
updatingAccessibilitySwitch = true
|
||||||
|
sw_accessibility.isChecked = checked
|
||||||
|
updatingAccessibilitySwitch = false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,6 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
})
|
})
|
||||||
rl_reply_strategy.setOnClickListener { showReplyStrategyDialog() }
|
rl_reply_strategy.setOnClickListener { showReplyStrategyDialog() }
|
||||||
rl_log.setOnClickListener { showLogDialog() }
|
rl_log.setOnClickListener { showLogDialog() }
|
||||||
rl_update.setOnClickListener { showUpdateDialog() }
|
|
||||||
rl_donate.setOnClickListener { showDonateDialog() }
|
|
||||||
rl_share.setOnClickListener { showShareDialog() }
|
|
||||||
rl_advance.setOnClickListener { SettingsAdvanceActivity.enterActivity(this) }
|
rl_advance.setOnClickListener { SettingsAdvanceActivity.enterActivity(this) }
|
||||||
freshOpenFlow()
|
freshOpenFlow()
|
||||||
bt_open_flow.setOnClickListener {
|
bt_open_flow.setOnClickListener {
|
||||||
@@ -148,37 +145,6 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showUpdateDialog() {
|
|
||||||
if (Constant.getMasterCheckUpdateUrl() == Constant.getCheckUpdateUrl()) {
|
|
||||||
HttpUtil.checkUpdate()
|
|
||||||
} else {
|
|
||||||
QMUIDialog.CheckableDialogBuilder(this)
|
|
||||||
.setTitle("检查新版本")
|
|
||||||
.addItems(arrayOf("检查当前Host新版本", "检查${getString(R.string.app_name)}官方新版本")) { dialog, which ->
|
|
||||||
dialog.dismiss()
|
|
||||||
if (which == 0) {
|
|
||||||
HttpUtil.checkUpdate()
|
|
||||||
} else {
|
|
||||||
HttpUtil.checkUpdate(Constant.getMasterCheckUpdateUrl())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.create(R.style.QMUI_Dialog)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showDonateDialog() {
|
|
||||||
DonateUtil.zfbDonate(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showShareDialog() {
|
|
||||||
startActivity(Intent.createChooser(Intent().apply {
|
|
||||||
action = Intent.ACTION_SEND
|
|
||||||
type = ShareUtil.TEXT
|
|
||||||
putExtra(Intent.EXTRA_TEXT, "我发现一个非常好用的企业微信机器人程序,文档地址: https://worktool.apifox.cn/ APP下载地址是: https://cdn.asrtts.cn/uploads/worktool/apk/worktool-latest.apk")
|
|
||||||
}, "分享"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun freshOpenFlow() {
|
private fun freshOpenFlow() {
|
||||||
if (Settings.canDrawOverlays(Utils.getApp())) {
|
if (Settings.canDrawOverlays(Utils.getApp())) {
|
||||||
if (FlowPermissionHelper.canBackgroundStart(Utils.getApp())) {
|
if (FlowPermissionHelper.canBackgroundStart(Utils.getApp())) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.yameida.worktool.service
|
package org.yameida.worktool.service
|
||||||
|
|
||||||
import com.blankj.utilcode.util.*
|
import com.blankj.utilcode.util.*
|
||||||
import org.yameida.worktool.Demo
|
|
||||||
import org.yameida.worktool.annotation.RequestMapping
|
import org.yameida.worktool.annotation.RequestMapping
|
||||||
import org.yameida.worktool.model.ExecCallbackBean
|
import org.yameida.worktool.model.ExecCallbackBean
|
||||||
import org.yameida.worktool.model.WeworkMessageBean
|
import org.yameida.worktool.model.WeworkMessageBean
|
||||||
@@ -18,6 +17,8 @@ object WeworkController {
|
|||||||
/** 是否正在等待回复 - 等待时会暂停主循环扫描新消息 */
|
/** 是否正在等待回复 - 等待时会暂停主循环扫描新消息 */
|
||||||
var waitingForReply = false
|
var waitingForReply = false
|
||||||
|
|
||||||
|
fun isServiceReady(): Boolean = ::weworkService.isInitialized
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交互通知
|
* 交互通知
|
||||||
* @see WeworkMessageBean.TYPE_CONSOLE_TOAST
|
* @see WeworkMessageBean.TYPE_CONSOLE_TOAST
|
||||||
@@ -159,7 +160,6 @@ object WeworkController {
|
|||||||
@RequestMapping
|
@RequestMapping
|
||||||
fun test(message: WeworkMessageBean? = null) {
|
fun test(message: WeworkMessageBean? = null) {
|
||||||
LogUtils.d(message)
|
LogUtils.d(message)
|
||||||
Demo.test(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import androidx.core.text.isDigitsOnly
|
|||||||
import com.blankj.utilcode.util.*
|
import com.blankj.utilcode.util.*
|
||||||
import com.hjq.toast.ToastUtils
|
import com.hjq.toast.ToastUtils
|
||||||
import org.yameida.worktool.Constant
|
import org.yameida.worktool.Constant
|
||||||
import org.yameida.worktool.Demo
|
|
||||||
import org.yameida.worktool.MyApplication
|
import org.yameida.worktool.MyApplication
|
||||||
import org.yameida.worktool.activity.GetScreenShotActivity
|
import org.yameida.worktool.activity.GetScreenShotActivity
|
||||||
import org.yameida.worktool.model.WeworkMessageBean
|
import org.yameida.worktool.model.WeworkMessageBean
|
||||||
@@ -176,8 +175,7 @@ object WeworkLoopImpl {
|
|||||||
val nameList = passFriendRequest()
|
val nameList = passFriendRequest()
|
||||||
if (nameList.isEmpty())
|
if (nameList.isEmpty())
|
||||||
break
|
break
|
||||||
//todo 可自定义执行任务
|
// todo 可自定义执行任务
|
||||||
// Demo.test2(nameList[0])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -638,7 +636,7 @@ object WeworkLoopImpl {
|
|||||||
* 检查首页-聊天列表是否有未读红点并点击进入
|
* 检查首页-聊天列表是否有未读红点并点击进入
|
||||||
*/
|
*/
|
||||||
private fun checkUnreadChatRoom(list: AccessibilityNodeInfo): Boolean {
|
private fun checkUnreadChatRoom(list: AccessibilityNodeInfo): Boolean {
|
||||||
val spotNodeList = arrayListOf<AccessibilityNodeInfo>()
|
val unreadRowNodeList = arrayListOf<AccessibilityNodeInfo>()
|
||||||
for (i in 0 until list.childCount) {
|
for (i in 0 until list.childCount) {
|
||||||
val item = list.getChild(i)
|
val item = list.getChild(i)
|
||||||
if (item != null && Views.RelativeLayout.equals(item.className)) {
|
if (item != null && Views.RelativeLayout.equals(item.className)) {
|
||||||
@@ -649,20 +647,22 @@ object WeworkLoopImpl {
|
|||||||
&& spotNode.text != null
|
&& spotNode.text != null
|
||||||
&& spotNode.text.toString().replace("+", "").isDigitsOnly()
|
&& spotNode.text.toString().replace("+", "").isDigitsOnly()
|
||||||
) {
|
) {
|
||||||
spotNodeList.add(spotNode)
|
unreadRowNodeList.add(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spotNodeList.size > 0) {
|
if (unreadRowNodeList.isNotEmpty()) {
|
||||||
LogUtils.i("发现未读消息: " + spotNodeList.size + "条")
|
LogUtils.i("发现未读消息: " + unreadRowNodeList.size + "条")
|
||||||
log("发现未读消息: " + spotNodeList.size + "条")
|
log("发现未读消息: " + unreadRowNodeList.size + "条")
|
||||||
if (AccessibilityUtil.performClick(spotNodeList.firstOrNull())) {
|
val firstUnreadRow = unreadRowNodeList.firstOrNull()
|
||||||
//进入聊天页 下一步 getChatMessageList
|
val clicked = AccessibilityUtil.performClick(firstUnreadRow)
|
||||||
} else {
|
|| AccessibilityUtil.clickByNode(WeworkController.weworkService, firstUnreadRow)
|
||||||
AccessibilityUtil.clickByNode(WeworkController.weworkService, spotNodeList.firstOrNull()?.parent)
|
if (!clicked) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return true
|
// 避免“点击红点但未实际进会话”的假成功
|
||||||
|
return AccessibilityUtil.waitForPageMissing("WwMainActivity", "GlobalSearchActivity", timeout = 2000)
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.FileObserver
|
import android.os.FileObserver
|
||||||
|
import android.os.Message
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.accessibility.AccessibilityEvent
|
import android.view.accessibility.AccessibilityEvent
|
||||||
import com.blankj.utilcode.util.*
|
import com.blankj.utilcode.util.*
|
||||||
@@ -13,11 +14,10 @@ import okhttp3.Response
|
|||||||
import okhttp3.WebSocket
|
import okhttp3.WebSocket
|
||||||
import okhttp3.WebSocketListener
|
import okhttp3.WebSocketListener
|
||||||
import org.yameida.worktool.Constant
|
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.observer.MultiFileObserver
|
||||||
import org.yameida.worktool.utils.*
|
import org.yameida.worktool.utils.*
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业微信辅助服务
|
* 企业微信辅助服务
|
||||||
@@ -39,24 +39,23 @@ class WeworkService : AccessibilityService() {
|
|||||||
LogUtils.i("初始化成功")
|
LogUtils.i("初始化成功")
|
||||||
//隐藏软键盘模式
|
//隐藏软键盘模式
|
||||||
softKeyboardController.showMode = SHOW_MODE_HIDDEN
|
softKeyboardController.showMode = SHOW_MODE_HIDDEN
|
||||||
|
// 服务重启后恢复主功能默认运行态,避免被上一次暂停状态卡住
|
||||||
|
FloatWindowHelper.isPause = false
|
||||||
WeworkController.weworkService = this
|
WeworkController.weworkService = this
|
||||||
WeworkController.enableLoopRunning = true
|
WeworkController.enableLoopRunning = true
|
||||||
|
notifyAccessibilityState(true)
|
||||||
//初始化长连接
|
//初始化长连接
|
||||||
initWebSocket()
|
initWebSocket()
|
||||||
//初始化消息处理器
|
//初始化消息处理器
|
||||||
MyLooper.init()
|
MyLooper.init()
|
||||||
//初始化图片接收
|
//初始化图片接收
|
||||||
initObserver()
|
initObserver()
|
||||||
//开发者可以在这里添加测试代码 启动时调用一次
|
|
||||||
thread { Demo.test(AppUtils.isAppDebug()) }
|
|
||||||
|
|
||||||
//监听是否修改链接号并重新长连接
|
//监听是否修改链接号并重新长连接
|
||||||
registerReceiver(object : BroadcastReceiver() {
|
registerReceiver(object : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (intent.getStringExtra("type") == "modify_channel") {
|
if (intent.getStringExtra("type") == "modify_channel") {
|
||||||
LogUtils.e("更新channel")
|
reconnectWebSocket("modify_channel")
|
||||||
webSocketManager.close(1000, "modify_channel")
|
|
||||||
initWebSocket()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, IntentFilter(Constant.WEWORK_NOTIFY))
|
}, IntentFilter(Constant.WEWORK_NOTIFY))
|
||||||
@@ -69,6 +68,14 @@ class WeworkService : AccessibilityService() {
|
|||||||
webSocketManager = WebSocketManager(url, listener)
|
webSocketManager = WebSocketManager(url, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun reconnectWebSocket(reason: String) {
|
||||||
|
LogUtils.i("reconnectWebSocket: $reason")
|
||||||
|
if (::webSocketManager.isInitialized) {
|
||||||
|
webSocketManager.close(1000, reason)
|
||||||
|
}
|
||||||
|
initWebSocket()
|
||||||
|
}
|
||||||
|
|
||||||
private fun initObserver() {
|
private fun initObserver() {
|
||||||
if (!Constant.pushImage) return
|
if (!Constant.pushImage) return
|
||||||
try {
|
try {
|
||||||
@@ -113,16 +120,24 @@ class WeworkService : AccessibilityService() {
|
|||||||
LogUtils.i("onDestroy")
|
LogUtils.i("onDestroy")
|
||||||
//关闭自动回复
|
//关闭自动回复
|
||||||
WeworkController.enableLoopRunning = false
|
WeworkController.enableLoopRunning = false
|
||||||
|
// 关闭主功能时清理暂停态,确保下次开启可立即进入检测
|
||||||
|
FloatWindowHelper.isPause = false
|
||||||
|
notifyAccessibilityState(false)
|
||||||
//隐藏软键盘模式
|
//隐藏软键盘模式
|
||||||
softKeyboardController.showMode = SHOW_MODE_AUTO
|
softKeyboardController.showMode = SHOW_MODE_AUTO
|
||||||
webSocketManager.close(1000, "service Destroy")
|
webSocketManager.close(1000, "service Destroy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun notifyAccessibilityState(enabled: Boolean) {
|
||||||
|
sendBroadcast(Intent(Constant.WEWORK_NOTIFY).apply {
|
||||||
|
putExtra("type", "accessibility_state")
|
||||||
|
putExtra("enabled", enabled)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
inner class EchoWebSocketListener : WebSocketListener() {
|
inner class EchoWebSocketListener : WebSocketListener() {
|
||||||
private val TAG = "WeworkService.EchoWebSocketListener"
|
private val TAG = "WeworkService.EchoWebSocketListener"
|
||||||
private lateinit var socket: WebSocket
|
|
||||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||||
socket = webSocket
|
|
||||||
Log.e(TAG, "连接建立")
|
Log.e(TAG, "连接建立")
|
||||||
val robotId = Constant.robotId
|
val robotId = Constant.robotId
|
||||||
val appVersion = SPUtils.getInstance().getString("appVersion", "")
|
val appVersion = SPUtils.getInstance().getString("appVersion", "")
|
||||||
@@ -131,6 +146,13 @@ class WeworkService : AccessibilityService() {
|
|||||||
val hook = SPUtils.getInstance().getBoolean("hook", false)
|
val hook = SPUtils.getInstance().getBoolean("hook", false)
|
||||||
LogUtils.i("连接建立: $robotId appVersion: $appVersion workVersion: $workVersion deviceRooted: $deviceRooted hook: $hook")
|
LogUtils.i("连接建立: $robotId appVersion: $appVersion workVersion: $workVersion deviceRooted: $deviceRooted hook: $hook")
|
||||||
log("连接建立: $robotId appVersion: $appVersion workVersion: $workVersion deviceRooted: $deviceRooted hook: $hook")
|
log("连接建立: $robotId appVersion: $appVersion workVersion: $workVersion deviceRooted: $deviceRooted hook: $hook")
|
||||||
|
// 断线后会被置为false;重连成功时主动恢复主循环,避免出现“提示运行中但未检测消息”
|
||||||
|
WeworkController.enableLoopRunning = true
|
||||||
|
MyLooper.getInstance().removeMessages(WeworkMessageBean.LOOP_RECEIVE_NEW_MESSAGE)
|
||||||
|
MyLooper.getInstance().sendMessage(Message.obtain().apply {
|
||||||
|
what = WeworkMessageBean.LOOP_RECEIVE_NEW_MESSAGE
|
||||||
|
obj = WeworkMessageBean().apply { type = WeworkMessageBean.LOOP_RECEIVE_NEW_MESSAGE }
|
||||||
|
})
|
||||||
LogUtils.i("设置自动跳转企业微信")
|
LogUtils.i("设置自动跳转企业微信")
|
||||||
sendBroadcast(true)
|
sendBroadcast(true)
|
||||||
}
|
}
|
||||||
@@ -154,7 +176,7 @@ class WeworkService : AccessibilityService() {
|
|||||||
|
|
||||||
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
||||||
super.onClosing(webSocket, code, reason)
|
super.onClosing(webSocket, code, reason)
|
||||||
socket.close(code, reason)
|
webSocket.close(code, reason)
|
||||||
Log.e(TAG, "服务端关闭连接 $code: $reason")
|
Log.e(TAG, "服务端关闭连接 $code: $reason")
|
||||||
sendBroadcast(false)
|
sendBroadcast(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import kotlin.concurrent.thread
|
|||||||
object FloatWindowHelper {
|
object FloatWindowHelper {
|
||||||
|
|
||||||
var isPause = false
|
var isPause = false
|
||||||
|
private var bound = false
|
||||||
|
|
||||||
fun showWindow() {
|
fun showWindow() {
|
||||||
LogUtils.d("FloatWindowHelper.showWindow()")
|
LogUtils.d("FloatWindowHelper.showWindow()")
|
||||||
@@ -39,7 +40,23 @@ object FloatWindowHelper {
|
|||||||
|
|
||||||
val app = Utils.getApp()
|
val app = Utils.getApp()
|
||||||
val intent = Intent(app, DefaultFloatService::class.java)
|
val intent = Intent(app, DefaultFloatService::class.java)
|
||||||
app.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
|
if (!bound) {
|
||||||
|
bound = app.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideWindow() {
|
||||||
|
LogUtils.d("FloatWindowHelper.hideWindow()")
|
||||||
|
val app = Utils.getApp()
|
||||||
|
FloatWindowManager.hide(DefaultFloatService::class.java)
|
||||||
|
if (bound) {
|
||||||
|
try {
|
||||||
|
app.unbindService(serviceConnection)
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
}
|
||||||
|
bound = false
|
||||||
|
}
|
||||||
|
app.stopService(Intent(app, DefaultFloatService::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,35 +102,6 @@ object FloatWindowHelper {
|
|||||||
service.onClickListener = object : OnClickListener {
|
service.onClickListener = object : OnClickListener {
|
||||||
override fun onClick(v: View, event: Int) {
|
override fun onClick(v: View, event: Int) {
|
||||||
when (event) {
|
when (event) {
|
||||||
1 -> {
|
|
||||||
if (PermissionHelper.isAccessibilitySettingOn()) {
|
|
||||||
if (!isPause) {
|
|
||||||
ToastUtils.showShort("请先暂停Awin WorkTool主功能~")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
thread {
|
|
||||||
val printNodeClazzTree =
|
|
||||||
AccessibilityUtil.printNodeClazzTree(getRoot(true))
|
|
||||||
val df = SimpleDateFormat("MMdd_HHmmss")
|
|
||||||
val filePath = "${
|
|
||||||
Utils.getApp().getExternalFilesDir("share")
|
|
||||||
}/${df.format(Date())}/${df.format(Date())}_printNode.txt"
|
|
||||||
val newFile = File(filePath)
|
|
||||||
val create = FileUtils.createFileByDeleteOldFile(newFile)
|
|
||||||
if (create && newFile.canWrite()) {
|
|
||||||
printNodeClazzTree.append("\n")
|
|
||||||
.append(WeworkController.weworkService.currentPackage)
|
|
||||||
.append("\n")
|
|
||||||
.append(WeworkController.weworkService.currentClass)
|
|
||||||
newFile.writeBytes(printNodeClazzTree.toString().toByteArray())
|
|
||||||
LogUtils.i("打印节点文件存储本地成功 $filePath", "当前页面: ${WeworkController.weworkService.currentClass}")
|
|
||||||
}
|
|
||||||
ShareUtil.share("*/*", newFile)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ToastUtils.showShort("请先打开Awin WorkTool主功能~")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2 -> {
|
2 -> {
|
||||||
if (PermissionHelper.isAccessibilitySettingOn()) {
|
if (PermissionHelper.isAccessibilitySettingOn()) {
|
||||||
if (isPause) {
|
if (isPause) {
|
||||||
@@ -127,6 +115,28 @@ object FloatWindowHelper {
|
|||||||
ToastUtils.showShort("请先打开Awin WorkTool主功能~")
|
ToastUtils.showShort("请先打开Awin WorkTool主功能~")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5 -> {
|
||||||
|
if (PermissionHelper.isAccessibilitySettingOn()) {
|
||||||
|
if (isPause) {
|
||||||
|
Glide.with(Utils.getApp()).load(R.drawable.float_icon_pause).into(v as ImageView)
|
||||||
|
accessibilityServiceResume()
|
||||||
|
} else {
|
||||||
|
Glide.with(Utils.getApp()).load(R.drawable.float_icon_play).into(v as ImageView)
|
||||||
|
accessibilityServicePause()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ToastUtils.showShort("请先打开Awin WorkTool主功能~")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6 -> {
|
||||||
|
if (PermissionHelper.isAccessibilitySettingOn()) {
|
||||||
|
// 停止主功能时复位暂停状态,避免下次开启后主循环被卡住
|
||||||
|
isPause = false
|
||||||
|
WeworkController.weworkService.disableSelf()
|
||||||
|
} else {
|
||||||
|
ToastUtils.showShort("主功能已关闭~")
|
||||||
|
}
|
||||||
|
}
|
||||||
3 -> {
|
3 -> {
|
||||||
Utils.getApp().packageManager.getLaunchIntentForPackage(Constant.PACKAGE_NAMES)?.apply {
|
Utils.getApp().packageManager.getLaunchIntentForPackage(Constant.PACKAGE_NAMES)?.apply {
|
||||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
@@ -143,6 +153,7 @@ object FloatWindowHelper {
|
|||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
override fun onServiceDisconnected(name: ComponentName?) {
|
||||||
LogUtils.i("DefaultFloatService 服务断开")
|
LogUtils.i("DefaultFloatService 服务断开")
|
||||||
|
bound = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,10 @@ object HttpUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(response: Response<String>) {
|
override fun onError(response: Response<String>) {
|
||||||
ToastUtils.showLong("获取配置失败 请检查机器人ID")
|
if (toast) {
|
||||||
LogUtils.e("获取配置失败 请检查机器人ID")
|
ToastUtils.showLong("获取配置失败,请检查网络/Host/机器人ID")
|
||||||
|
}
|
||||||
|
LogUtils.e("获取配置失败: ${response.code()} ${response.exception?.message}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,32 +22,37 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
import okhttp3.WebSocket;
|
import okhttp3.WebSocket;
|
||||||
import okhttp3.WebSocketListener;
|
import okhttp3.WebSocketListener;
|
||||||
|
import okio.ByteString;
|
||||||
|
|
||||||
public class WebSocketManager {
|
public class WebSocketManager {
|
||||||
|
|
||||||
public static final String HEARTBEAT = "{\"type\":" + WeworkMessageBean.HEART_BEAT + "}";
|
public static final String HEARTBEAT = "{\"type\":" + WeworkMessageBean.HEART_BEAT + "}";
|
||||||
private static final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
private static final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private static final OkHttpClient client = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(10, TimeUnit.SECONDS)
|
||||||
|
.pingInterval(25, TimeUnit.SECONDS)
|
||||||
|
.retryOnConnectionFailure(true)
|
||||||
|
.build();
|
||||||
public static Map<String, WebSocketManager> webSocketManager = new ConcurrentHashMap<>();
|
public static Map<String, WebSocketManager> webSocketManager = new ConcurrentHashMap<>();
|
||||||
private static final int reconnectInt = 5000; //毫秒
|
|
||||||
private static final long heartBeatRate = 5; //秒
|
private static final long heartBeatRate = 5; //秒
|
||||||
private Map<String, Long> messageIdMap = new ConcurrentHashMap<>();
|
private Map<String, Long> messageIdMap = new ConcurrentHashMap<>();
|
||||||
private ScheduledFuture task;
|
private ScheduledFuture task;
|
||||||
private WebSocket socket;
|
private WebSocket socket;
|
||||||
private String url;
|
private String url;
|
||||||
private WebSocketListener listener;
|
private WebSocketListener listener;
|
||||||
private boolean connecting = false;
|
private volatile boolean connecting = false;
|
||||||
|
private volatile boolean manuallyClosed = false;
|
||||||
|
private volatile boolean opened = false;
|
||||||
private long lastConnectedTime = 0L;
|
private long lastConnectedTime = 0L;
|
||||||
|
|
||||||
public WebSocketManager(String url, WebSocketListener listener) {
|
public WebSocketManager(String url, WebSocketListener listener) {
|
||||||
Log.e(url, "新建链接");
|
Log.e(url, "新建链接");
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
OkHttpClient client = new OkHttpClient();
|
this.socket = client.newWebSocket(new Request.Builder().url(url).build(), innerListener);
|
||||||
Request request = new Request.Builder().url(url).build();
|
|
||||||
this.socket = client.newWebSocket(request, listener);
|
|
||||||
socket.send("{\"td\":" + System.currentTimeMillis() + "}");
|
|
||||||
webSocketManager.put(url, this);
|
webSocketManager.put(url, this);
|
||||||
task = heartCheckStart();
|
task = heartCheckStart();
|
||||||
}
|
}
|
||||||
@@ -83,7 +88,7 @@ public class WebSocketManager {
|
|||||||
|
|
||||||
public void send(WeworkMessageListBean msg, boolean log) {
|
public void send(WeworkMessageListBean msg, boolean log) {
|
||||||
String json = GsonUtils.toJson(msg);
|
String json = GsonUtils.toJson(msg);
|
||||||
boolean success = socket.send(json);
|
boolean success = socket != null && socket.send(json);
|
||||||
if (log && success)
|
if (log && success)
|
||||||
LogUtils.d(url, json, "通讯消息发送成功!");
|
LogUtils.d(url, json, "通讯消息发送成功!");
|
||||||
if (!success)
|
if (!success)
|
||||||
@@ -91,14 +96,19 @@ public class WebSocketManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void send(String msg) {
|
public void send(String msg) {
|
||||||
boolean success = socket.send(msg);
|
boolean success = socket != null && socket.send(msg);
|
||||||
LogUtils.e(url, msg, (success ? "通讯消息发送成功!" : "通讯消息发送失败!"));
|
LogUtils.e(url, msg, (success ? "通讯消息发送成功!" : "通讯消息发送失败!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close(int code, String reason) {
|
public void close(int code, String reason) {
|
||||||
|
manuallyClosed = true;
|
||||||
|
if (task != null) {
|
||||||
task.cancel(true);
|
task.cancel(true);
|
||||||
|
}
|
||||||
Log.e("url", "task 取消");
|
Log.e("url", "task 取消");
|
||||||
|
if (this.socket != null) {
|
||||||
this.socket.close(code, reason);
|
this.socket.close(code, reason);
|
||||||
|
}
|
||||||
Log.e(url, "链接关闭");
|
Log.e(url, "链接关闭");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,44 +122,25 @@ public class WebSocketManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reConnect() {
|
public void reConnect() {
|
||||||
|
if (manuallyClosed || connecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
connecting = true;
|
connecting = true;
|
||||||
|
opened = false;
|
||||||
Log.e(url, "重连");
|
Log.e(url, "重连");
|
||||||
boolean isConnect = false;
|
|
||||||
int interval = reconnectInt;
|
|
||||||
while (true) {
|
|
||||||
try {
|
try {
|
||||||
isConnect = connect();
|
if (socket != null) {
|
||||||
if (isConnect) {
|
socket.cancel();
|
||||||
connecting = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception ignore) {
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
try {
|
socket = client.newWebSocket(new Request.Builder().url(url).build(), innerListener);
|
||||||
Thread.sleep(interval);
|
|
||||||
if (interval < 600000) {
|
|
||||||
interval *= 2;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean connect() {
|
|
||||||
WebSocket s = new OkHttpClient().newWebSocket(new Request.Builder().url(url).build(), listener);
|
|
||||||
if (s.send(WebSocketManager.HEARTBEAT)) {
|
|
||||||
this.socket = s;
|
|
||||||
s.send("{\"td\":" + System.currentTimeMillis() + "}");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduledFuture heartCheckStart() {
|
private ScheduledFuture heartCheckStart() {
|
||||||
lastConnectedTime = System.currentTimeMillis();
|
lastConnectedTime = System.currentTimeMillis();
|
||||||
Runnable r = () -> {
|
Runnable r = () -> {
|
||||||
|
if (manuallyClosed) return;
|
||||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
|
||||||
Log.d(url, "心跳检测" + df.format(new Date()));// new Date()为获取当前系统时间
|
Log.d(url, "心跳检测" + df.format(new Date()));// new Date()为获取当前系统时间
|
||||||
if (!connecting && (socket == null || !socket.send(HEARTBEAT))) {
|
if (!connecting && (socket == null || !socket.send(HEARTBEAT))) {
|
||||||
@@ -159,7 +150,7 @@ public class WebSocketManager {
|
|||||||
reConnect();
|
reConnect();
|
||||||
//重连后刷新连接时间
|
//重连后刷新连接时间
|
||||||
lastConnectedTime = System.currentTimeMillis();
|
lastConnectedTime = System.currentTimeMillis();
|
||||||
} else if (System.currentTimeMillis() % 1000 == 0) {
|
} else if (opened && System.currentTimeMillis() % 1000 == 0) {
|
||||||
socket.send("{\"td\":" + System.currentTimeMillis() + "}");
|
socket.send("{\"td\":" + System.currentTimeMillis() + "}");
|
||||||
}
|
}
|
||||||
if (!Constant.INSTANCE.getEnableMediaProject()) {
|
if (!Constant.INSTANCE.getEnableMediaProject()) {
|
||||||
@@ -176,4 +167,46 @@ public class WebSocketManager {
|
|||||||
public static WebSocketManager getWebSocketManager(String id) {
|
public static WebSocketManager getWebSocketManager(String id) {
|
||||||
return webSocketManager.get(id);
|
return webSocketManager.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final WebSocketListener innerListener = new WebSocketListener() {
|
||||||
|
@Override
|
||||||
|
public void onOpen(WebSocket webSocket, Response response) {
|
||||||
|
opened = true;
|
||||||
|
connecting = false;
|
||||||
|
lastConnectedTime = System.currentTimeMillis();
|
||||||
|
listener.onOpen(webSocket, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(WebSocket webSocket, String text) {
|
||||||
|
listener.onMessage(webSocket, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(WebSocket webSocket, ByteString bytes) {
|
||||||
|
listener.onMessage(webSocket, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClosing(WebSocket webSocket, int code, String reason) {
|
||||||
|
opened = false;
|
||||||
|
connecting = false;
|
||||||
|
listener.onClosing(webSocket, code, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClosed(WebSocket webSocket, int code, String reason) {
|
||||||
|
opened = false;
|
||||||
|
connecting = false;
|
||||||
|
listener.onClosed(webSocket, code, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||||
|
opened = false;
|
||||||
|
connecting = false;
|
||||||
|
WeworkController.INSTANCE.setEnableLoopRunning(false);
|
||||||
|
listener.onFailure(webSocket, t, response);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,11 +326,14 @@
|
|||||||
android:textColor="@color/color_333333"
|
android:textColor="@color/color_333333"
|
||||||
android:textSize="@dimen/setting_start_font_size" />
|
android:textSize="@dimen/setting_start_font_size" />
|
||||||
|
|
||||||
<EditText
|
<TextView
|
||||||
android:id="@+id/et_channel"
|
android:id="@+id/tv_channel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="请输入申请的机器人ID"
|
android:paddingTop="4dp"
|
||||||
|
android:paddingBottom="4dp"
|
||||||
|
android:text="未生成"
|
||||||
|
android:textIsSelectable="true"
|
||||||
android:textColor="@color/color_999999"
|
android:textColor="@color/color_999999"
|
||||||
android:textSize="@dimen/setting_end_font_size" />
|
android:textSize="@dimen/setting_end_font_size" />
|
||||||
|
|
||||||
@@ -344,17 +347,17 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/bt_save"
|
android:id="@+id/bt_reset_channel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:background="@drawable/comment_red_btn"
|
android:background="@drawable/comment_red_btn"
|
||||||
android:paddingStart="50dp"
|
android:paddingStart="42dp"
|
||||||
android:paddingEnd="50dp"
|
android:paddingEnd="42dp"
|
||||||
android:textSize="18sp"
|
android:text="重置"
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:text="保存" />
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -473,172 +473,6 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/rl_update"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="@dimen/setting_start_padding"
|
|
||||||
android:paddingTop="@dimen/setting_vertical_padding"
|
|
||||||
android:paddingEnd="@dimen/setting_end_padding"
|
|
||||||
android:paddingBottom="@dimen/setting_vertical_padding">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_rec_update_"
|
|
||||||
android:layout_width="@dimen/setting_start_image_width"
|
|
||||||
android:layout_height="@dimen/setting_start_image_width"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:scaleX="1.1"
|
|
||||||
android:scaleY="1.1"
|
|
||||||
android:src="@drawable/settings_directory" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_select_update"
|
|
||||||
android:layout_width="@dimen/setting_end_font_width"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_end_start_padding"
|
|
||||||
android:textColor="@color/float_time_color"
|
|
||||||
android:textSize="@dimen/setting_end_font_size"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_start_padding"
|
|
||||||
android:layout_toStartOf="@id/tv_select_update"
|
|
||||||
android:layout_toEndOf="@id/iv_rec_update_"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="检查新版本"
|
|
||||||
android:textColor="@color/color_333333"
|
|
||||||
android:textSize="@dimen/setting_start_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="版本更新检查"
|
|
||||||
android:textColor="@color/color_999999"
|
|
||||||
android:textSize="@dimen/setting_end_font_size" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/rl_donate"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="@dimen/setting_start_padding"
|
|
||||||
android:paddingTop="@dimen/setting_vertical_padding"
|
|
||||||
android:paddingEnd="@dimen/setting_end_padding"
|
|
||||||
android:paddingBottom="@dimen/setting_vertical_padding">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_rec_donate_"
|
|
||||||
android:layout_width="@dimen/setting_start_image_width"
|
|
||||||
android:layout_height="@dimen/setting_start_image_width"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:src="@drawable/settings_rate_us" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_select_donate"
|
|
||||||
android:layout_width="@dimen/setting_end_font_width"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_end_start_padding"
|
|
||||||
android:textColor="@color/float_time_color"
|
|
||||||
android:textSize="@dimen/setting_end_font_size"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_start_padding"
|
|
||||||
android:layout_toStartOf="@id/tv_select_donate"
|
|
||||||
android:layout_toEndOf="@id/iv_rec_donate_"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="赞助我们"
|
|
||||||
android:textColor="@color/color_333333"
|
|
||||||
android:textSize="@dimen/setting_start_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="还有机会成为我们的内测用户体验新功能"
|
|
||||||
android:textColor="@color/color_999999"
|
|
||||||
android:textSize="@dimen/setting_end_font_size" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/rl_share"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="@dimen/setting_start_padding"
|
|
||||||
android:paddingTop="@dimen/setting_vertical_padding"
|
|
||||||
android:paddingEnd="@dimen/setting_end_padding"
|
|
||||||
android:paddingBottom="@dimen/setting_vertical_padding">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_rec_share_"
|
|
||||||
android:layout_width="@dimen/setting_start_image_width"
|
|
||||||
android:layout_height="@dimen/setting_start_image_width"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:scaleX="1.1"
|
|
||||||
android:scaleY="1.1"
|
|
||||||
android:src="@drawable/settings_share" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_select_share"
|
|
||||||
android:layout_width="@dimen/setting_end_font_width"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_end_start_padding"
|
|
||||||
android:textColor="@color/float_time_color"
|
|
||||||
android:textSize="@dimen/setting_end_font_size"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/setting_start_padding"
|
|
||||||
android:layout_toStartOf="@id/tv_select_share"
|
|
||||||
android:layout_toEndOf="@id/iv_rec_share_"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="分享应用"
|
|
||||||
android:textColor="@color/color_333333"
|
|
||||||
android:textSize="@dimen/setting_start_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="把本应用分享给其他人"
|
|
||||||
android:textColor="@color/color_999999"
|
|
||||||
android:textSize="@dimen/setting_end_font_size" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -56,7 +56,14 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
|||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
LogUtils.d(TAG, "onStartCommand: ${intent?.data}")
|
LogUtils.d(TAG, "onStartCommand: ${intent?.data}")
|
||||||
show()
|
when (intent?.getStringExtra(FloatWindowManager.EXTRA_ACTION)) {
|
||||||
|
FloatWindowManager.ACTION_HIDE -> {
|
||||||
|
hide()
|
||||||
|
stopForeground(true)
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
else -> show()
|
||||||
|
}
|
||||||
return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,9 +88,6 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
|||||||
if (v == leftView.iv_logo_left || v == rightView.iv_logo_right || v == leftView.iv_logo_left2 || v == rightView.iv_logo_right2) {
|
if (v == leftView.iv_logo_left || v == rightView.iv_logo_right || v == leftView.iv_logo_left2 || v == rightView.iv_logo_right2) {
|
||||||
onClickListener?.onClick(v, 0)
|
onClickListener?.onClick(v, 0)
|
||||||
}
|
}
|
||||||
if (v == leftView.iv_start_left || v == rightView.iv_start_right) {
|
|
||||||
onClickListener?.onClick(v,1)
|
|
||||||
}
|
|
||||||
if (v == leftView.iv_shot_left || v == rightView.iv_shot_right) {
|
if (v == leftView.iv_shot_left || v == rightView.iv_shot_right) {
|
||||||
onClickListener?.onClick(v,2)
|
onClickListener?.onClick(v,2)
|
||||||
}
|
}
|
||||||
@@ -105,7 +109,6 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
|||||||
leftView = inflater.inflate(R.layout.layout_menu_left, null)
|
leftView = inflater.inflate(R.layout.layout_menu_left, null)
|
||||||
leftView.iv_logo_left.setOnClickListener(this)
|
leftView.iv_logo_left.setOnClickListener(this)
|
||||||
leftView.iv_logo_left2.setOnClickListener(this)
|
leftView.iv_logo_left2.setOnClickListener(this)
|
||||||
leftView.iv_start_left.setOnClickListener(this)
|
|
||||||
leftView.iv_shot_left.setOnClickListener(this)
|
leftView.iv_shot_left.setOnClickListener(this)
|
||||||
leftView.iv_back_left.setOnClickListener(this)
|
leftView.iv_back_left.setOnClickListener(this)
|
||||||
leftView.iv_resume_pause_left.setOnClickListener(this)
|
leftView.iv_resume_pause_left.setOnClickListener(this)
|
||||||
@@ -119,7 +122,6 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
|||||||
rightView = inflater.inflate(R.layout.layout_menu_right, null)
|
rightView = inflater.inflate(R.layout.layout_menu_right, null)
|
||||||
rightView.iv_logo_right.setOnClickListener(this)
|
rightView.iv_logo_right.setOnClickListener(this)
|
||||||
rightView.iv_logo_right2.setOnClickListener(this)
|
rightView.iv_logo_right2.setOnClickListener(this)
|
||||||
rightView.iv_start_right.setOnClickListener(this)
|
|
||||||
rightView.iv_shot_right.setOnClickListener(this)
|
rightView.iv_shot_right.setOnClickListener(this)
|
||||||
rightView.iv_back_right.setOnClickListener(this)
|
rightView.iv_back_right.setOnClickListener(this)
|
||||||
rightView.iv_resume_pause_right.setOnClickListener(this)
|
rightView.iv_resume_pause_right.setOnClickListener(this)
|
||||||
@@ -197,4 +199,10 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyed() {}
|
override fun onDestroyed() {}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
hide()
|
||||||
|
stopForeground(true)
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ object FloatWindowManager {
|
|||||||
private val TAG = FloatWindowManager::class.java.simpleName
|
private val TAG = FloatWindowManager::class.java.simpleName
|
||||||
|
|
||||||
private var context = Utils.getApp()
|
private var context = Utils.getApp()
|
||||||
|
const val EXTRA_ACTION = "float_action"
|
||||||
|
const val ACTION_SHOW = "show"
|
||||||
|
const val ACTION_HIDE = "hide"
|
||||||
|
|
||||||
fun show(service: Class<out BaseFloatWindow>, intent: Intent? = null) {
|
fun show(service: Class<out BaseFloatWindow>, intent: Intent? = null) {
|
||||||
startServiceSafe(Intent(context, service).apply {
|
startServiceSafe(Intent(context, service).apply {
|
||||||
|
putExtra(EXTRA_ACTION, ACTION_SHOW)
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
this.putExtras(intent)
|
this.putExtras(intent)
|
||||||
}
|
}
|
||||||
@@ -22,6 +26,7 @@ object FloatWindowManager {
|
|||||||
|
|
||||||
fun hide(service: Class<out BaseFloatWindow>, intent: Intent? = null) {
|
fun hide(service: Class<out BaseFloatWindow>, intent: Intent? = null) {
|
||||||
startServiceSafe(Intent(context, service).apply {
|
startServiceSafe(Intent(context, service).apply {
|
||||||
|
putExtra(EXTRA_ACTION, ACTION_HIDE)
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
this.putExtras(intent)
|
this.putExtras(intent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,12 @@
|
|||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_start_left"
|
|
||||||
android:layout_width="@dimen/float_size"
|
|
||||||
android:layout_height="@dimen/float_size"
|
|
||||||
android:layout_marginEnd="@dimen/float_margin_start"
|
|
||||||
android:src="@drawable/float_icon_record" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_shot_left"
|
android:id="@+id/iv_shot_left"
|
||||||
android:layout_width="@dimen/float_size"
|
android:layout_width="@dimen/float_size"
|
||||||
android:layout_height="@dimen/float_size"
|
android:layout_height="@dimen/float_size"
|
||||||
android:layout_marginStart="@dimen/float_margin_start"
|
android:layout_marginStart="@dimen/float_margin_start"
|
||||||
android:layout_marginTop="29dp"
|
android:layout_marginTop="0dp"
|
||||||
android:src="@drawable/float_icon_pause" />
|
android:src="@drawable/float_icon_pause" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -44,7 +37,7 @@
|
|||||||
android:id="@+id/iv_logo_left"
|
android:id="@+id/iv_logo_left"
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
android:layout_below="@id/iv_start_left"
|
android:layout_below="@id/iv_shot_left"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="55dp"
|
android:layout_marginEnd="55dp"
|
||||||
|
|||||||
@@ -15,18 +15,11 @@
|
|||||||
android:layout_height="190dp"
|
android:layout_height="190dp"
|
||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_start_right"
|
|
||||||
android:layout_width="@dimen/float_size"
|
|
||||||
android:layout_height="@dimen/float_size"
|
|
||||||
android:layout_marginStart="@dimen/float_margin_start"
|
|
||||||
android:src="@drawable/float_icon_record" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_shot_right"
|
android:id="@+id/iv_shot_right"
|
||||||
android:layout_width="@dimen/float_size"
|
android:layout_width="@dimen/float_size"
|
||||||
android:layout_height="@dimen/float_size"
|
android:layout_height="@dimen/float_size"
|
||||||
android:layout_marginTop="29dp"
|
android:layout_marginTop="0dp"
|
||||||
android:src="@drawable/float_icon_pause" />
|
android:src="@drawable/float_icon_pause" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -41,7 +34,7 @@
|
|||||||
android:id="@+id/iv_logo_right"
|
android:id="@+id/iv_logo_right"
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
android:layout_below="@id/iv_start_right"
|
android:layout_below="@id/iv_shot_right"
|
||||||
android:layout_marginStart="55dp"
|
android:layout_marginStart="55dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:src="@mipmap/ic_launcher_round" />
|
android:src="@mipmap/ic_launcher_round" />
|
||||||
|
|||||||
Reference in New Issue
Block a user