refactor: 优化注释格式并修复WebSocket错误处理

This commit is contained in:
TongTongStudio
2026-07-26 21:40:51 +08:00
parent 63adb7f9f6
commit 11173eb04c

View File

@@ -10,43 +10,40 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ttstd.control.Action;
import com.ttstd.control.ControlMessage;
import com.ttstd.controlled.R;
import com.ttstd.controlled.accessibility.KeyboardAccessibilityService;
import com.ttstd.controlled.activity.connection.ConnectionRequestActivity;
import com.ttstd.controlled.activity.main.MainActivity;
import com.ttstd.controlled.accessibility.KeyboardAccessibilityService;
import com.ttstd.controlled.input.AccessibilityInputUtils;
import com.ttstd.controlled.input.InputCommandHandler;
import com.ttstd.controlled.input.InputExecutor;
import com.ttstd.controlled.input.RootShellInputUtils;
import com.ttstd.controlled.input.ShellInputUtils;
import com.ttstd.controlled.input.SystemInputUtils;
import com.ttstd.controlled.utils.SignatureUtils;
import com.ttstd.controlled.utils.InputSettings;
import com.ttstd.controlled.signaling.SignalMessage;
import com.ttstd.controlled.utils.AuthSettings;
import com.ttstd.controlled.signaling.WebSocketClient;
import com.ttstd.controlled.webrtc.WebRtcClient;
import com.ttstd.controlled.utils.AuthSettings;
import com.ttstd.controlled.utils.InputSettings;
import com.ttstd.controlled.utils.SignatureUtils;
import com.ttstd.controlled.webrtc.SelfCodecEncoder;
import com.ttstd.control.Action;
import com.ttstd.control.ControlMessage;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ttstd.controlled.webrtc.WebRtcClient;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
@@ -63,7 +60,9 @@ public class ScreenCaptureService extends Service {
public static final String EXTRA_SERVER_URL = "server_url";
public static final String EXTRA_DEVICE_ID = "device_id";
/** 静态授权结果,解决部分 Android 10 设备跨进程/Intent 传递 Intent 时 Token 失效的问题 */
/**
* 静态授权结果,解决部分 Android 10 设备跨进程/Intent 传递 Intent 时 Token 失效的问题
*/
public static int sResultCode = Activity.RESULT_CANCELED;
public static Intent sResultData = null;
@@ -74,34 +73,52 @@ public class ScreenCaptureService extends Service {
private EglBase eglBase;
private final Gson gson = new Gson();
/** 标记服务是否已经初始化,避免 onStartCommand 多次调用导致重复创建 */
/**
* 标记服务是否已经初始化,避免 onStartCommand 多次调用导致重复创建
*/
private boolean isInitialized = false;
/** 静态实例引用,供弹窗 Activity 在无需绑定的情况下回调本服务。 */
/**
* 静态实例引用,供弹窗 Activity 在无需绑定的情况下回调本服务。
*/
private static ScreenCaptureService instance;
public static ScreenCaptureService getInstance() {
return instance;
}
/** 本设备 ID注册到信令服务器用保存为字段以便弹窗回调使用。 */
/**
* 本设备 ID注册到信令服务器用保存为字段以便弹窗回调使用。
*/
private String deviceId;
/** 当前待处理的连接请求OFFER信息供用户在弹窗中确认或拒绝。 */
/**
* 当前待处理的连接请求OFFER信息供用户在弹窗中确认或拒绝。
*/
private String pendingControllerId;
private String pendingControllerName;
private String pendingOfferSdp;
/** 当前正在控制本设备的控制端名称(用户名或设备 ID用于断开提示。 */
/**
* 当前正在控制本设备的控制端名称(用户名或设备 ID用于断开提示。
*/
private String controllingName;
/** 设备真实屏幕分辨率,用于分辨率切换时按宽高比计算采集尺寸。 */
/**
* 设备真实屏幕分辨率,用于分辨率切换时按宽高比计算采集尺寸。
*/
private int realScreenWidth;
private int realScreenHeight;
/** 当前实际采集分辨率与帧率(运行时可被本地/远端请求切换)。 */
/**
* 当前实际采集分辨率与帧率(运行时可被本地/远端请求切换)。
*/
private int currentCaptureWidth;
private int currentCaptureHeight;
private int currentCaptureFps;
/** 主线程 Handler用于从 WebRTC 回调线程切回主线程执行 UI 提示。 */
/**
* 主线程 Handler用于从 WebRTC 回调线程切回主线程执行 UI 提示。
*/
private final Handler mainHandler = new Handler(Looper.getMainLooper());
/** 标记服务是否正在关闭,避免重复停止/重复弹窗。 */
/**
* 标记服务是否正在关闭,避免重复停止/重复弹窗。
*/
private boolean isShuttingDown = false;
// ---- 屏幕串流"自编码"模式 ----
@@ -190,7 +207,8 @@ public class ScreenCaptureService extends Service {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
refreshRate = wm.getDefaultDisplay().getRefreshRate();
} catch (Exception ignored) {}
} catch (Exception ignored) {
}
}
int fps = Math.round(refreshRate);
// 屏幕控制 30fps 已足够跟手,并显著降低 H264 硬编延迟(影响“跟手”体验)。
@@ -301,23 +319,30 @@ public class ScreenCaptureService extends Service {
/**
* 切换屏幕采集分辨率(本地 UI 调用)。
*
* @param longEdge 目标长边像素;<=0 表示使用设备原生分辨率(按屏幕宽高比缩放)。
*/
public void changeResolutionByLongEdge(int longEdge) {
requestResolutionChange(longEdge, 0, 0, false);
}
/** 返回当前采集分辨率(宽/高/帧率)。 */
/**
* 返回当前采集分辨率(宽/高/帧率)。
*/
public int[] getCurrentCaptureResolution() {
return new int[]{currentCaptureWidth, currentCaptureHeight, currentCaptureFps};
}
/** 返回设备原生分辨率的长边(像素),供 UI 生成“原始画质”选项。 */
/**
* 返回设备原生分辨率的长边(像素),供 UI 生成“原始画质”选项。
*/
public int getNativeLongEdge() {
return Math.max(realScreenWidth, realScreenHeight);
}
/** 控制端经 DataChannel 发来的 SET_RESOLUTION 指令入口。 */
/**
* 控制端经 DataChannel 发来的 SET_RESOLUTION 指令入口。
*/
private void onRemoteResolutionRequested(int width, int height, int fps) {
requestResolutionChange(width, height, fps, true);
}
@@ -368,7 +393,9 @@ public class ScreenCaptureService extends Service {
}
}
/** 根据指令参数解析出最终采集尺寸(保留屏幕宽高比、偶数对齐)。 */
/**
* 根据指令参数解析出最终采集尺寸(保留屏幕宽高比、偶数对齐)。
*/
private int[] resolveCaptureSize(int width, int height) {
int w, h;
if (width <= 0) {
@@ -393,7 +420,9 @@ public class ScreenCaptureService extends Service {
// ---- 屏幕串流"自编码"模式 ----
/** 控制端经 SET_STREAM_MODE 请求切换串流模式。 */
/**
* 控制端经 SET_STREAM_MODE 请求切换串流模式。
*/
private void onStreamModeRequested(int mode) {
setStreamMode(mode);
}
@@ -429,12 +458,16 @@ public class ScreenCaptureService extends Service {
reportStreamMode(mode);
}
/** 返回当前串流模式。 */
/**
* 返回当前串流模式。
*/
public int getCurrentStreamMode() {
return currentStreamMode;
}
/** 启动自编码通道。返回 false 表示启动失败(调用方应回退 WebRTC 模式)。 */
/**
* 启动自编码通道。返回 false 表示启动失败(调用方应回退 WebRTC 模式)。
*/
private boolean startSelfCodecEncoder() {
if (selfEncoder != null) {
Log.w(TAG, "self codec encoder already running");
@@ -490,7 +523,9 @@ public class ScreenCaptureService extends Service {
}
}
/** 经 control DataChannel 向控制端回报当前生效的串流模式。 */
/**
* 经 control DataChannel 向控制端回报当前生效的串流模式。
*/
private void reportStreamMode(int mode) {
if (webRtcClient == null) return;
try {
@@ -508,9 +543,14 @@ public class ScreenCaptureService extends Service {
* 状态回调。由已 bind 的 MainActivity 注册,用于把连接状态同步到界面。
*/
public interface ServiceStateListener {
/** 信令服务器断开WebSocket 断开)。 */
/**
* 信令服务器断开WebSocket 断开)。
*/
void onSignalDisconnected();
/** 远程控制端断开,参数为控制端名称(用户名或设备 ID。 */
/**
* 远程控制端断开,参数为控制端名称(用户名或设备 ID
*/
void onControllerDisconnected(String name);
}
@@ -586,11 +626,9 @@ public class ScreenCaptureService extends Service {
@Override
public void onError(String error) {
Log.e(TAG, "WebSocket error: " + error);
if(TextUtils.isEmpty(error)){
Log.e(TAG, "WebSocket onError: " + error);
mainHandler.post(() -> onSignalServerDisconnected());
}
}
@Override
public void onMessage(SignalMessage message) {
@@ -730,7 +768,9 @@ public class ScreenCaptureService extends Service {
return "未知的鉴权类型: " + authType;
}
/** 鉴权失败时,向控制端回送带原因的拒绝消息并清理待处理状态。 */
/**
* 鉴权失败时,向控制端回送带原因的拒绝消息并清理待处理状态。
*/
private void sendAuthRejected(String reason) {
if (pendingControllerId == null || wsClient == null) {
return;
@@ -860,6 +900,7 @@ public class ScreenCaptureService extends Service {
};
private int heartbeatCount = 0;
private void updateNotificationHeartbeat() {
String dots = "";
for (int i = 0; i < (heartbeatCount % 3) + 1; i++) dots += ".";