change
This commit is contained in:
@@ -58,7 +58,7 @@ object Constant {
|
||||
SPUtils.getInstance().put(weworkCorpName + "weworkMP", value)
|
||||
}
|
||||
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
|
||||
get() = SPUtils.getInstance().getBoolean("groupStrict", false)
|
||||
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,6 +22,7 @@ import org.yameida.worktool.utils.*
|
||||
import org.yameida.worktool.utils.capture.MediaProjectionHolder
|
||||
import org.yameida.worktool.utils.envcheck.CheckHook
|
||||
import org.yameida.worktool.utils.envcheck.CheckRoot
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
class ListenActivity : AppCompatActivity() {
|
||||
@@ -59,6 +60,7 @@ class ListenActivity : AppCompatActivity() {
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
unregisterReceiver(openWsReceiver)
|
||||
FloatWindowHelper.hideWindow()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -75,16 +77,11 @@ class ListenActivity : AppCompatActivity() {
|
||||
iv_settings.setOnClickListener {
|
||||
SettingsActivity.enterActivity(this)
|
||||
}
|
||||
et_channel.setText(Constant.robotId)
|
||||
bt_save.setOnClickListener {
|
||||
val channel = et_channel.text.toString().trim()
|
||||
Constant.robotId = channel
|
||||
ToastUtils.showLong("保存成功")
|
||||
sendBroadcast(Intent(Constant.WEWORK_NOTIFY).apply {
|
||||
putExtra("type", "modify_channel")
|
||||
})
|
||||
HttpUtil.getMyConfig(toast = false)
|
||||
MobclickAgent.onProfileSignIn(channel)
|
||||
tv_channel.text = Constant.robotId.ifBlank { "未生成" }
|
||||
bt_reset_channel.setOnClickListener {
|
||||
val channel = generateDefaultRobotId()
|
||||
tv_channel.text = channel
|
||||
saveChannel(channel, toast = "重置成功")
|
||||
}
|
||||
tv_host.text = Constant.host
|
||||
tv_host.setOnClickListener {
|
||||
@@ -185,13 +182,35 @@ class ListenActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
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.getMyConfig(toast = false)
|
||||
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")
|
||||
})
|
||||
HttpUtil.getMyConfig(toast = false)
|
||||
MobclickAgent.onProfileSignIn(channel)
|
||||
}
|
||||
|
||||
private fun initNotification() {
|
||||
if (!Constant.enableMediaProject) {
|
||||
return
|
||||
@@ -206,7 +225,7 @@ class ListenActivity : AppCompatActivity() {
|
||||
}, Context.BIND_AUTO_CREATE)
|
||||
//开启屏幕录制权限
|
||||
if (MediaProjectionHolder.mMediaProjection == null) {
|
||||
bt_save.postDelayed({
|
||||
window.decorView.postDelayed({
|
||||
fastStartActivity(this, GetScreenShotActivity::class.java)
|
||||
}, 1000)
|
||||
}
|
||||
@@ -282,8 +301,8 @@ class ListenActivity : AppCompatActivity() {
|
||||
.setNegativeButton("", null)
|
||||
.setPositiveButton("", null)
|
||||
val show = positiveButton.show()
|
||||
bt_save.postDelayed({ show.dismiss() }, 5000)
|
||||
bt_save.postDelayed({
|
||||
window.decorView.postDelayed({ show.dismiss() }, 5000)
|
||||
window.decorView.postDelayed({
|
||||
packageManager.getLaunchIntentForPackage(Constant.PACKAGE_NAMES)?.apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(this)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.yameida.worktool.service
|
||||
|
||||
import com.blankj.utilcode.util.*
|
||||
import org.yameida.worktool.Demo
|
||||
import org.yameida.worktool.annotation.RequestMapping
|
||||
import org.yameida.worktool.model.ExecCallbackBean
|
||||
import org.yameida.worktool.model.WeworkMessageBean
|
||||
@@ -159,7 +158,6 @@ object WeworkController {
|
||||
@RequestMapping
|
||||
fun test(message: WeworkMessageBean? = null) {
|
||||
LogUtils.d(message)
|
||||
Demo.test(true)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@ import androidx.core.text.isDigitsOnly
|
||||
import com.blankj.utilcode.util.*
|
||||
import com.hjq.toast.ToastUtils
|
||||
import org.yameida.worktool.Constant
|
||||
import org.yameida.worktool.Demo
|
||||
import org.yameida.worktool.MyApplication
|
||||
import org.yameida.worktool.activity.GetScreenShotActivity
|
||||
import org.yameida.worktool.model.WeworkMessageBean
|
||||
@@ -176,8 +175,7 @@ object WeworkLoopImpl {
|
||||
val nameList = passFriendRequest()
|
||||
if (nameList.isEmpty())
|
||||
break
|
||||
//todo 可自定义执行任务
|
||||
// Demo.test2(nameList[0])
|
||||
// todo 可自定义执行任务
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -13,11 +13,9 @@ import okhttp3.Response
|
||||
import okhttp3.WebSocket
|
||||
import okhttp3.WebSocketListener
|
||||
import org.yameida.worktool.Constant
|
||||
import org.yameida.worktool.Demo
|
||||
import org.yameida.worktool.observer.MultiFileObserver
|
||||
import org.yameida.worktool.utils.*
|
||||
import java.lang.Exception
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/**
|
||||
* 企业微信辅助服务
|
||||
@@ -47,8 +45,6 @@ class WeworkService : AccessibilityService() {
|
||||
MyLooper.init()
|
||||
//初始化图片接收
|
||||
initObserver()
|
||||
//开发者可以在这里添加测试代码 启动时调用一次
|
||||
thread { Demo.test(AppUtils.isAppDebug()) }
|
||||
|
||||
//监听是否修改链接号并重新长连接
|
||||
registerReceiver(object : BroadcastReceiver() {
|
||||
@@ -116,6 +112,7 @@ class WeworkService : AccessibilityService() {
|
||||
//隐藏软键盘模式
|
||||
softKeyboardController.showMode = SHOW_MODE_AUTO
|
||||
webSocketManager.close(1000, "service Destroy")
|
||||
FloatWindowHelper.hideWindow()
|
||||
}
|
||||
|
||||
inner class EchoWebSocketListener : WebSocketListener() {
|
||||
|
||||
@@ -31,6 +31,7 @@ import kotlin.concurrent.thread
|
||||
object FloatWindowHelper {
|
||||
|
||||
var isPause = false
|
||||
private var bound = false
|
||||
|
||||
fun showWindow() {
|
||||
LogUtils.d("FloatWindowHelper.showWindow()")
|
||||
@@ -39,7 +40,23 @@ object FloatWindowHelper {
|
||||
|
||||
val app = Utils.getApp()
|
||||
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))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,6 +160,7 @@ object FloatWindowHelper {
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
LogUtils.i("DefaultFloatService 服务断开")
|
||||
bound = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,32 +22,37 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import okio.ByteString;
|
||||
|
||||
public class WebSocketManager {
|
||||
|
||||
public static final String HEARTBEAT = "{\"type\":" + WeworkMessageBean.HEART_BEAT + "}";
|
||||
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<>();
|
||||
private static final int reconnectInt = 5000; //毫秒
|
||||
private static final long heartBeatRate = 5; //秒
|
||||
private Map<String, Long> messageIdMap = new ConcurrentHashMap<>();
|
||||
private ScheduledFuture task;
|
||||
private WebSocket socket;
|
||||
private String url;
|
||||
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;
|
||||
|
||||
public WebSocketManager(String url, WebSocketListener listener) {
|
||||
Log.e(url, "新建链接");
|
||||
this.url = url;
|
||||
this.listener = listener;
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
this.socket = client.newWebSocket(request, listener);
|
||||
socket.send("{\"td\":" + System.currentTimeMillis() + "}");
|
||||
this.socket = client.newWebSocket(new Request.Builder().url(url).build(), innerListener);
|
||||
webSocketManager.put(url, this);
|
||||
task = heartCheckStart();
|
||||
}
|
||||
@@ -83,7 +88,7 @@ public class WebSocketManager {
|
||||
|
||||
public void send(WeworkMessageListBean msg, boolean log) {
|
||||
String json = GsonUtils.toJson(msg);
|
||||
boolean success = socket.send(json);
|
||||
boolean success = socket != null && socket.send(json);
|
||||
if (log && success)
|
||||
LogUtils.d(url, json, "通讯消息发送成功!");
|
||||
if (!success)
|
||||
@@ -91,14 +96,19 @@ public class WebSocketManager {
|
||||
}
|
||||
|
||||
public void send(String msg) {
|
||||
boolean success = socket.send(msg);
|
||||
boolean success = socket != null && socket.send(msg);
|
||||
LogUtils.e(url, msg, (success ? "通讯消息发送成功!" : "通讯消息发送失败!"));
|
||||
}
|
||||
|
||||
public void close(int code, String reason) {
|
||||
manuallyClosed = true;
|
||||
if (task != null) {
|
||||
task.cancel(true);
|
||||
}
|
||||
Log.e("url", "task 取消");
|
||||
if (this.socket != null) {
|
||||
this.socket.close(code, reason);
|
||||
}
|
||||
Log.e(url, "链接关闭");
|
||||
}
|
||||
|
||||
@@ -112,44 +122,25 @@ public class WebSocketManager {
|
||||
}
|
||||
|
||||
public void reConnect() {
|
||||
if (manuallyClosed || connecting) {
|
||||
return;
|
||||
}
|
||||
connecting = true;
|
||||
opened = false;
|
||||
Log.e(url, "重连");
|
||||
boolean isConnect = false;
|
||||
int interval = reconnectInt;
|
||||
while (true) {
|
||||
try {
|
||||
isConnect = connect();
|
||||
if (isConnect) {
|
||||
connecting = false;
|
||||
break;
|
||||
if (socket != null) {
|
||||
socket.cancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
try {
|
||||
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;
|
||||
socket = client.newWebSocket(new Request.Builder().url(url).build(), innerListener);
|
||||
}
|
||||
|
||||
private ScheduledFuture heartCheckStart() {
|
||||
lastConnectedTime = System.currentTimeMillis();
|
||||
Runnable r = () -> {
|
||||
if (manuallyClosed) return;
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
|
||||
Log.d(url, "心跳检测" + df.format(new Date()));// new Date()为获取当前系统时间
|
||||
if (!connecting && (socket == null || !socket.send(HEARTBEAT))) {
|
||||
@@ -159,7 +150,7 @@ public class WebSocketManager {
|
||||
reConnect();
|
||||
//重连后刷新连接时间
|
||||
lastConnectedTime = System.currentTimeMillis();
|
||||
} else if (System.currentTimeMillis() % 1000 == 0) {
|
||||
} else if (opened && System.currentTimeMillis() % 1000 == 0) {
|
||||
socket.send("{\"td\":" + System.currentTimeMillis() + "}");
|
||||
}
|
||||
if (!Constant.INSTANCE.getEnableMediaProject()) {
|
||||
@@ -176,4 +167,46 @@ public class WebSocketManager {
|
||||
public static WebSocketManager getWebSocketManager(String 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:textSize="@dimen/setting_start_font_size" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_channel"
|
||||
<TextView
|
||||
android:id="@+id/tv_channel"
|
||||
android:layout_width="match_parent"
|
||||
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:textSize="@dimen/setting_end_font_size" />
|
||||
|
||||
@@ -344,17 +347,17 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_save"
|
||||
android:id="@+id/bt_reset_channel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="@drawable/comment_red_btn"
|
||||
android:paddingStart="50dp"
|
||||
android:paddingEnd="50dp"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingStart="42dp"
|
||||
android:paddingEnd="42dp"
|
||||
android:text="重置"
|
||||
android:textColor="@color/white"
|
||||
android:text="保存" />
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -56,7 +56,14 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -197,4 +204,10 @@ class DefaultFloatService : BaseFloatWindow(), View.OnClickListener {
|
||||
}
|
||||
|
||||
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 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) {
|
||||
startServiceSafe(Intent(context, service).apply {
|
||||
putExtra(EXTRA_ACTION, ACTION_SHOW)
|
||||
if (intent != null) {
|
||||
this.putExtras(intent)
|
||||
}
|
||||
@@ -22,6 +26,7 @@ object FloatWindowManager {
|
||||
|
||||
fun hide(service: Class<out BaseFloatWindow>, intent: Intent? = null) {
|
||||
startServiceSafe(Intent(context, service).apply {
|
||||
putExtra(EXTRA_ACTION, ACTION_HIDE)
|
||||
if (intent != null) {
|
||||
this.putExtras(intent)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user