feat(voice): 完善语音交互服务并添加会话启动与辅助数据处理
This commit is contained in:
@@ -195,6 +195,9 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.speech.RecognitionService" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.speech"
|
||||
android:resource="@xml/my_recognition_service" />
|
||||
</service>
|
||||
|
||||
<!-- <receiver-->
|
||||
|
||||
@@ -1,15 +1,61 @@
|
||||
package com.ttstd.dialer.service;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.service.voice.VoiceInteractionService;
|
||||
import android.service.voice.VoiceInteractionSession;
|
||||
|
||||
import com.ttstd.dialer.utils.Logger;
|
||||
|
||||
/**
|
||||
* 语音交互服务类,作为语音助手的入口。
|
||||
*/
|
||||
public class MyVoiceInteractionService extends VoiceInteractionService {
|
||||
private static final String TAG = "MyVoiceInteractionService";
|
||||
|
||||
/**
|
||||
* 自定义 Action,用于从外部启动语音交互会话
|
||||
*/
|
||||
public static final String ACTION_SHOW_SESSION = "com.ttstd.dialer.ACTION_SHOW_SESSION";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Logger.d(TAG, "onCreate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
super.onReady();
|
||||
Logger.d(TAG, "onReady");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Logger.d(TAG, "onStartCommand: " + intent);
|
||||
if (intent != null) {
|
||||
String action = intent.getAction();
|
||||
if (ACTION_SHOW_SESSION.equals(action)) {
|
||||
// 确保服务是当前活跃的语音交互服务
|
||||
if (isActiveService(this, new ComponentName(this, MyVoiceInteractionService.class))) {
|
||||
Logger.d(TAG, "Showing session with assist and screenshot flags");
|
||||
// 核心:调用 showSession 并请求辅助数据(AssistStructure)和截图
|
||||
Bundle args = new Bundle();
|
||||
showSession(args,
|
||||
VoiceInteractionSession.SHOW_WITH_ASSIST |
|
||||
VoiceInteractionSession.SHOW_WITH_SCREENSHOT);
|
||||
} else {
|
||||
Logger.w(TAG, "Service is not the active voice interaction service");
|
||||
}
|
||||
}
|
||||
}
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShutdown() {
|
||||
super.onShutdown();
|
||||
Logger.d(TAG, "onShutdown");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,15 @@ package com.ttstd.dialer.service;
|
||||
import android.app.assist.AssistContent;
|
||||
import android.app.assist.AssistStructure;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.service.voice.VoiceInteractionSession;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.ttstd.dialer.utils.Logger;
|
||||
|
||||
public class MyVoiceInteractionSession extends VoiceInteractionSession {
|
||||
@@ -16,24 +21,69 @@ public class MyVoiceInteractionSession extends VoiceInteractionSession {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShow(Bundle args, int showFlags) {
|
||||
super.onShow(args, showFlags);
|
||||
Logger.d(TAG, "onShow: flags=" + showFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHide() {
|
||||
super.onHide();
|
||||
Logger.d(TAG, "onHide");
|
||||
}
|
||||
|
||||
@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);
|
||||
Logger.d(TAG, "onHandleAssist: data=" + data);
|
||||
processAssistStructure(structure);
|
||||
}
|
||||
|
||||
// Android 12 (API 31) 及以上建议使用此方法
|
||||
@Override
|
||||
public void onHandleAssist(@NonNull AssistState state) {
|
||||
super.onHandleAssist(state);
|
||||
Logger.d(TAG, "onHandleAssist(AssistState)");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
processAssistStructure(state.getAssistStructure());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHandleScreenshot(@Nullable Bitmap screenshot) {
|
||||
super.onHandleScreenshot(screenshot);
|
||||
Logger.d(TAG, "onHandleScreenshot: " + (screenshot != null ? "has screenshot" : "null"));
|
||||
}
|
||||
|
||||
private void processAssistStructure(AssistStructure structure) {
|
||||
if (structure == null) {
|
||||
Logger.w(TAG, "AssistStructure is null");
|
||||
return;
|
||||
}
|
||||
|
||||
int windowCount = structure.getWindowNodeCount();
|
||||
Logger.d(TAG, "Window count: " + windowCount);
|
||||
for (int i = 0; i < windowCount; i++) {
|
||||
AssistStructure.WindowNode windowNode = structure.getWindowNodeAt(i);
|
||||
if (windowNode != null) {
|
||||
traverseNode(windowNode.getRootViewNode(), "");
|
||||
Logger.d(TAG, "Window[" + i + "]: title=" + windowNode.getTitle());
|
||||
traverseNode(windowNode.getRootViewNode(), " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void traverseNode(AssistStructure.ViewNode node, String prefix) {
|
||||
if (node == null) return;
|
||||
|
||||
CharSequence text = node.getText();
|
||||
String id = node.getIdEntry();
|
||||
String className = node.getClassName();
|
||||
|
||||
Logger.d(TAG, prefix + "View: text=" + node.getText() + ", id=" + node.getIdEntry());
|
||||
|
||||
if (text != null || id != null) {
|
||||
Logger.d(TAG, prefix + "View: class=" + className + ", text=" + text + ", id=" + id);
|
||||
}
|
||||
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
traverseNode(node.getChildAt(i), prefix + " ");
|
||||
}
|
||||
@@ -41,7 +91,7 @@ public class MyVoiceInteractionSession extends VoiceInteractionSession {
|
||||
|
||||
@Override
|
||||
public View onCreateContentView() {
|
||||
// 可以返回一个自定义布局,用于在屏幕上显示助手界面
|
||||
return super.onCreateContentView();
|
||||
// 返回一个空的 View,以确保 Session 能够正确显示
|
||||
return new View(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
3
app/src/main/res/xml/my_recognition_service.xml
Normal file
3
app/src/main/res/xml/my_recognition_service.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<recognition-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="com.ttstd.dialer.activity.settings.home.SettingsActivity" />
|
||||
Reference in New Issue
Block a user