diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4ddf9e4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+启用 Content Capture:
+Shell Script
+settings put secure content_capture_service com.ttstd.dialer/com.ttstd.dialer.service.MyContentCaptureService
+
+启用 系统助手 (Assist):
+Shell Script
+settings put secure assistant com.ttstd.dialer/com.ttstd.dialer.service.MyVoiceInteractionService
+手动触发 Assist 采集: 在你的 Activity 或 Service 中,可以通过 showAssist(new Bundle()) 主动触发 onHandleAssist 回调,从而瞬间抓取屏幕信息。
+
+对于拥有系统签名的应用,可以通过 adb 或在代码中通过 settings 命令静默开启无障碍服务。
+# 1. 使用 ADB 命令手动开启
+ 在电脑终端输入以下两条命令:
+
+## 1. 将服务加入已启用列表
+adb shell settings put secure enabled_accessibility_services com.ttstd.dialer/com.ttstd.dialer.accessibility.DialerAccessibilityService
+
+## 2. 开启无障碍服务总开关
+adb shell settings put secure accessibility_enabled 1
+
+# 2. 在代码中自动开启 (利用系统签名)
+ 既然你的应用有系统签名,你可以直接通过你现有的 CmdUtil 在程序启动时自动激活自己,无需用户操作:
+
+ Java
+ public void autoEnableAccessibility(Context context) {
+ String serviceName = context.getPackageName() + "/com.ttstd.dialer.accessibility.DialerAccessibilityService";
+
+ // 1. 设置启用服务(如果已有其他服务,建议先获取当前值再追加,这里演示直接覆盖)
+ CmdUtil.execute("settings put secure enabled_accessibility_services " + serviceName);
+
+ // 2. 开启总开关
+ CmdUtil.execute("settings put secure accessibility_enabled 1");
+
+ Logger.d("Accessibility", "无障碍服务已尝试静默开启");
+ }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 264cf34..6294571 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,6 +31,8 @@
+
+
@@ -156,6 +158,35 @@
android:resource="@xml/accessibility_service_config" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/ttstd/dialer/service/MyContentCaptureService.java b/app/src/main/java/com/ttstd/dialer/service/MyContentCaptureService.java
new file mode 100644
index 0000000..b80bc1f
--- /dev/null
+++ b/app/src/main/java/com/ttstd/dialer/service/MyContentCaptureService.java
@@ -0,0 +1,42 @@
+package com.ttstd.dialer.service;
+
+import android.os.Build;
+import android.service.contentcapture.ContentCaptureService;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureSessionId;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.ttstd.dialer.utils.Logger;
+
+@RequiresApi(api = Build.VERSION_CODES.Q)
+public class MyContentCaptureService extends ContentCaptureService {
+ private static final String TAG = "MyContentCaptureService";
+
+ @Override
+ public void onConnected() {
+ super.onConnected();
+ Logger.d(TAG, "onConnected");
+ }
+
+ @Override
+ public void onDisconnected() {
+ super.onDisconnected();
+ Logger.d(TAG, "onDisconnected");
+ }
+
+ @Override
+ public void onContentCaptureEvent(@NonNull ContentCaptureSessionId sessionId, @NonNull ContentCaptureEvent event) {
+ // 这是核心方法,所有的界面变化都会在这里回调
+ Logger.v(TAG, "onContentCaptureEvent: type=" + event.getType());
+
+ if (event.getType() == ContentCaptureEvent.TYPE_VIEW_APPEARED) {
+ if (event.getViewNode() != null) {
+ CharSequence text = event.getViewNode().getText();
+ String id = event.getViewNode().getIdEntry();
+ Logger.d(TAG, "View Appeared: text=" + text + ", id=" + id);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionService.java b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionService.java
new file mode 100644
index 0000000..b467813
--- /dev/null
+++ b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionService.java
@@ -0,0 +1,15 @@
+package com.ttstd.dialer.service;
+
+import android.service.voice.VoiceInteractionService;
+
+import com.ttstd.dialer.utils.Logger;
+
+public class MyVoiceInteractionService extends VoiceInteractionService {
+ private static final String TAG = "MyVoiceInteractionService";
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Logger.d(TAG, "onCreate");
+ }
+}
diff --git a/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSession.java b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSession.java
new file mode 100644
index 0000000..841f85b
--- /dev/null
+++ b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSession.java
@@ -0,0 +1,47 @@
+package com.ttstd.dialer.service;
+
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.view.View;
+
+import com.ttstd.dialer.utils.Logger;
+
+public class MyVoiceInteractionSession extends VoiceInteractionSession {
+ private static final String TAG = "MyVoiceInteractionSession";
+
+ public MyVoiceInteractionSession(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
+ super.onHandleAssist(data, structure, content);
+ // 这是核心方法,structure 包含了整个屏幕的 View 树
+ Logger.d(TAG, "onHandleAssist");
+ if (structure != null) {
+ AssistStructure.WindowNode windowNode = structure.getWindowNodeAt(0);
+ if (windowNode != null) {
+ traverseNode(windowNode.getRootViewNode(), "");
+ }
+ }
+ }
+
+ private void traverseNode(AssistStructure.ViewNode node, String prefix) {
+ if (node == null) return;
+
+ Logger.d(TAG, prefix + "View: text=" + node.getText() + ", id=" + node.getIdEntry());
+
+ for (int i = 0; i < node.getChildCount(); i++) {
+ traverseNode(node.getChildAt(i), prefix + " ");
+ }
+ }
+
+ @Override
+ public View onCreateContentView() {
+ // 可以返回一个自定义布局,用于在屏幕上显示助手界面
+ return super.onCreateContentView();
+ }
+}
diff --git a/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSessionService.java b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSessionService.java
new file mode 100644
index 0000000..2dae993
--- /dev/null
+++ b/app/src/main/java/com/ttstd/dialer/service/MyVoiceInteractionSessionService.java
@@ -0,0 +1,17 @@
+package com.ttstd.dialer.service;
+
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.service.voice.VoiceInteractionSessionService;
+
+import com.ttstd.dialer.utils.Logger;
+
+public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService {
+ private static final String TAG = "MyVoiceInteractionSessionService";
+
+ @Override
+ public VoiceInteractionSession onNewSession(Bundle args) {
+ Logger.d(TAG, "onNewSession");
+ return new MyVoiceInteractionSession(this);
+ }
+}
diff --git a/app/src/main/res/xml/voice_interaction_service.xml b/app/src/main/res/xml/voice_interaction_service.xml
new file mode 100644
index 0000000..1394e15
--- /dev/null
+++ b/app/src/main/res/xml/voice_interaction_service.xml
@@ -0,0 +1,7 @@
+
+