Android 端离线语音控制设备管理系统:完整技术方案与实践

本文详细介绍如何在 Android 设备端实现离线语音识别与自然语言理解,通过语音指令直接控制 TMS(终端管理系统)APK 的设备管理功能。全程无需云端服务,完全在设备本地处理。

📋 目录

  1. 项目背景与需求
  2. 技术方案选型
  3. 核心架构设计
  4. 详细实现步骤
  5. 性能评估与优化
  6. 使用场景示例
  7. 常见问题与解决方案
  8. 总结与展望

项目背景与需求

1.1 业务场景

在 终端管理系统应用中,用户需要通过语音指令控制设备,例如:

  • 设备控制:锁定设备、重启设备、重置密码
  • 网络管理:打开/关闭 WiFi、蓝牙
  • 系统设置:调整音量、亮度
  • 信息查询:查询设备型号、电池电量、系统版本

1.2 核心需求

  • 完全离线:不依赖云端服务,保护隐私
  • 实时响应:语音识别延迟低,用户体验好
  • 资源占用小:适合移动设备,不影响系统性能
  • 直接调用:绕过云端,直接调用 TMS APK 内部能力

1.3 技术挑战

  1. STT(语音转文本):需要离线、轻量级的语音识别引擎
  2. NLU(自然语言理解):需要将自然语言转换为结构化命令
  3. 设备控制:需要直接调用 TMS APK 内部的 MDMService 能力

技术方案选型

2.1 STT(语音转文本)方案对比

经过深入调研,我们对比了多个开源方案:

方案 开源 离线 中文支持 资源占用 推荐度
Vosk 低(~50MB) ⭐⭐⭐⭐⭐
Whisper (whisper.cpp) 中(~100MB+) ⭐⭐⭐⭐
Android 系统语音服务 ⭐⭐⭐
Google Cloud STT - ⭐⭐

最终选择:Vosk

选择理由:

  • ✅ 完全开源,Apache 2.0 许可证
  • ✅ 专为移动端优化,轻量级模型仅 49MB
  • ✅ 支持中文,识别准确率高
  • ✅ 社区活跃,文档完善
  • ✅ 提供 Android Demo,可直接运行

2.2 NLU(自然语言理解)方案对比

方案 开源 离线 易用性 推荐度
基于规则的解析 极高 ⭐⭐⭐⭐⭐
TensorFlow Lite 中(需训练模型) ⭐⭐⭐
Snips NLU 高(已停止维护) ⭐⭐
Rasa

最终选择:基于规则的解析(Rule-based Parsing)

选择理由:

  • ✅ 对于固定命令集(如设备控制),规则解析 100% 准确
  • ✅ 零资源占用,响应速度快
  • ✅ 易于维护和扩展
  • ✅ 无需训练数据,开发成本低

2.3 模型选择

重要提醒:必须使用移动端模型!

Vosk 提供了多种中文模型,但只有轻量级模型适合移动端

模型 大小 用途 是否推荐
vosk-model-small-cn-0.3 ~49MB 移动端应用 强烈推荐
vosk-model-cn-0.22 1.3GB 服务器处理 ❌ 不适合移动端
vosk-model-cn-kaldi-multicn-0.15 1.5GB 服务器处理 ❌ 不适合移动端

为什么不能使用大型模型?

通过 adb 命令评估设备性能:

bash 复制代码
# 查看设备内存
adb shell "cat /proc/meminfo | grep 'MemTotal\|MemAvailable'"

# 实际测试结果(2.9GB RAM 设备)
Mem:  2902868K total,  2848700K used,    54168K free

结论:

  • 大型模型(1.3GB)需要至少 1.8GB 可用内存
  • 移动设备通常只有 2-4GB 总内存
  • 强行加载会导致 OOM(内存溢出)崩溃

核心架构设计

3.1 系统架构

复制代码
┌─────────────────────────────────────────────────────────┐
│                   用户语音输入                           │
│              "请帮我锁定这台设备"                        │
└────────────────────┬──────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  阶段一:语音识别 (STT)                                  │
│  ┌──────────────────────────────────────────────────┐  │
│  │  Vosk 引擎                                        │  │
│  │  - 捕获麦克风音频                                 │  │
│  │  - 离线语音识别                                   │  │
│  │  - 输出文本:"请帮我锁定这台设备"                  │  │
│  └──────────────────────────────────────────────────┘  │
└────────────────────┬──────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  阶段二:自然语言理解 (NLU)                              │
│  ┌──────────────────────────────────────────────────┐  │
│  │  规则解析器 (TmsCommandParser)                    │  │
│  │  - 文本规范化                                     │  │
│  │  - 关键词匹配                                     │  │
│  │  - 意图识别:LOCK_DEVICE                          │  │
│  │  - 参数提取:无                                   │  │
│  └──────────────────────────────────────────────────┘  │
└────────────────────┬──────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  阶段三:设备控制执行                                     │
│  ┌──────────────────────────────────────────────────┐  │
│  │  TMS APK 内部能力                                │  │
│  │  - 发送广播:android.intent.action.lockdevice   │  │
│  │  - MDMService 接收并执行                         │  │
│  │  - 设备锁定完成                                  │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

3.2 数据流

复制代码
用户语音 → Vosk STT → 文本字符串 → 规则解析器 → TmsIntent → TMS 广播 → 设备执行

3.3 核心组件

  1. VoskActivity:主活动,管理语音识别生命周期
  2. TmsCommandParser:NLU 解析器,将文本转换为命令
  3. TmsIntent:结构化命令数据
  4. DeviceInfoHelper:设备信息获取工具
  5. RecognitionLogAdapter:识别日志显示适配器

详细实现步骤

4.1 项目初始化

4.1.1 添加依赖

app/build.gradle 中添加:

gradle 复制代码
dependencies {
    // Vosk 语音识别库
    implementation 'com.alphacephei:vosk-android:0.3.47@aar'
    implementation 'net.java.dev.jna:jna:5.13.0@aar'
    
    // AndroidX 支持
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
    implementation 'androidx.cardview:cardview:1.0.0'
}
4.1.2 配置 AAPT 选项

防止模型文件被压缩:

gradle 复制代码
android {
    aaptOptions {
        noCompress 'fst', 'mdl', 'conf', 'int', 'txt', 
                   'carpa', 'mat', 'raw', 'dubm', 'ie', 'stats'
    }
}
4.1.3 添加权限

AndroidManifest.xml 中:

xml 复制代码
<uses-permission android:name="android.permission.RECORD_AUDIO" />

4.2 模型集成

4.2.1 下载模型

Vosk 模型下载页面 下载:

  • 模型名称vosk-model-small-cn-0.3
  • 大小:约 49MB
  • 语言:中文
4.2.2 放置模型文件

将解压后的模型文件夹放到:

复制代码
app/src/main/assets/vosk-model-small-cn-0.3/
├── am/
├── conf/
├── graph/
├── ivector/
├── rescore/
└── rnnlm/
4.2.3 自动生成 UUID

build.gradle 中添加:

gradle 复制代码
tasks.register('genModelUUID') {
    def uuid = UUID.randomUUID().toString()
    def odir = file("$projectDir/src/main/assets/vosk-model-small-cn-0.3")
    def ofile = file("$odir/uuid")
    doLast {
        mkdir odir
        ofile.text = uuid
    }
}

preBuild.dependsOn(genModelUUID)

4.3 核心代码实现

4.3.1 模型初始化
java 复制代码
import org.vosk.Model;
import org.vosk.android.StorageService;
import org.vosk.android.SpeechService;
import org.vosk.android.RecognitionListener;

public class VoskActivity extends Activity implements RecognitionListener {
    private Model model;
    private SpeechService speechService;
    private TmsCommandParser nluParser;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // 初始化 NLU 解析器
        nluParser = new TmsCommandParser();
        
        // 检查权限
        if (ContextCompat.checkSelfPermission(this, 
                Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
            initModel();
        } else {
            ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.RECORD_AUDIO},
                PERMISSIONS_REQUEST_RECORD_AUDIO);
        }
    }
    
    private void initModel() {
        Log.d(TAG, "开始加载模型: vosk-model-small-cn-0.3");
        StorageService.unpack(this, "vosk-model-small-cn-0.3", "model",
            (model) -> {
                this.model = model;
                Log.d(TAG, "模型加载成功");
                runOnUiThread(() -> {
                    setUiState(STATE_READY);
                });
            },
            (exception) -> {
                Log.e(TAG, "模型加载失败", exception);
                setErrorState("模型加载失败: " + exception.getMessage());
            });
    }
}
4.3.2 语音识别实现
java 复制代码
private void recognizeMicrophone() {
    if (model == null) {
        setErrorState("模型未加载,请等待模型加载完成");
        return;
    }
    
    try {
        // 创建识别器,采样率 16000 Hz
        Recognizer rec = new Recognizer(model, 16000.0f);
        
        // 创建语音服务
        speechService = new SpeechService(rec, 16000.0f);
        
        // 开始监听
        speechService.startListening(this);
        Log.d(TAG, "录音监听已启动");
    } catch (IOException e) {
        Log.e(TAG, "启动录音失败", e);
        setErrorState(e.getMessage());
    }
}

// 实现 RecognitionListener 接口
@Override
public void onResult(String hypothesis) {
    // 最终识别结果
    String text = "";
    try {
        JSONObject json = new JSONObject(hypothesis);
        if (json.has("text")) {
            text = json.getString("text").replace(" ", "");
            Log.d(TAG, "识别文本: " + text);
        }
    } catch (JSONException e) {
        Log.w(TAG, "JSON 解析失败", e);
    }
    
    if (text.isEmpty()) {
        return;
    }
    
    // 将文本送入 NLU 解析器
    TmsIntent tmsIntent = nluParser.parse(text);
    
    // 显示识别结果
    displayResult(text, tmsIntent, false);
    
    // 执行 TMS 命令
    executeTmsCommand(tmsIntent, text);
}

@Override
public void onPartialResult(String hypothesis) {
    // 部分识别结果(实时更新)
    String text = "";
    try {
        JSONObject json = new JSONObject(hypothesis);
        if (json.has("partial")) {
            text = json.getString("partial");
        }
    } catch (JSONException e) {
        text = hypothesis;
    }
    
    if (!text.isEmpty()) {
        updateRecognitionLog("[部分] " + text, false);
    }
}
4.3.3 NLU 规则解析器
java 复制代码
public class TmsCommandParser {
    
    public TmsIntent parse(String text) {
        if (text == null || text.isEmpty()) {
            return new TmsIntent(TmsIntent.Command.UNKNOWN, null);
        }
        
        // 文本规范化:转小写,移除空格和标点符号
        String normalizedText = text.toLowerCase()
            .replace(" ", "")
            .replace(",", "")
            .replace(",", "")
            .replace("。", "")
            .replace(".", "")
            .trim();
        
        // 规则 1:锁定设备
        if (normalizedText.contains("锁定设备") || normalizedText.contains("锁屏")) {
            return new TmsIntent(TmsIntent.Command.LOCK_DEVICE, null);
        }
        
        // 规则 2:WiFi 控制
        if (normalizedText.contains("wifi") || normalizedText.contains("wi-fi") || 
            normalizedText.contains("网络") || normalizedText.contains("无线")) {
            Map<String, String> params = new HashMap<>();
            if (normalizedText.contains("关闭") || normalizedText.contains("关掉")) {
                params.put("state", "off");
                return new TmsIntent(TmsIntent.Command.WIFI_SWITCH, params);
            }
            if (normalizedText.contains("打开") || normalizedText.contains("开启")) {
                params.put("state", "on");
                return new TmsIntent(TmsIntent.Command.WIFI_SWITCH, params);
            }
        }
        
        // 规则 3:音量控制
        if (normalizedText.contains("音量") || normalizedText.contains("声音")) {
            Map<String, String> params = new HashMap<>();
            if (normalizedText.contains("增加") || normalizedText.contains("提高") || 
                normalizedText.contains("调大")) {
                params.put("action", "increase");
                return new TmsIntent(TmsIntent.Command.VOLUME_CONTROL, params);
            }
            if (normalizedText.contains("减少") || normalizedText.contains("降低") || 
                normalizedText.contains("调小")) {
                params.put("action", "decrease");
                return new TmsIntent(TmsIntent.Command.VOLUME_CONTROL, params);
            }
            if (normalizedText.contains("最大") || normalizedText.contains("满")) {
                params.put("action", "max");
                return new TmsIntent(TmsIntent.Command.VOLUME_CONTROL, params);
            }
            if (normalizedText.contains("最小") || normalizedText.contains("静音")) {
                params.put("action", "min");
                return new TmsIntent(TmsIntent.Command.VOLUME_CONTROL, params);
            }
        }
        
        // 规则 4:亮度控制
        if (normalizedText.contains("亮度") || normalizedText.contains("屏幕亮度")) {
            Map<String, String> params = new HashMap<>();
            if (normalizedText.contains("增加") || normalizedText.contains("提高") || 
                normalizedText.contains("调大") || normalizedText.contains("亮")) {
                params.put("action", "increase");
                return new TmsIntent(TmsIntent.Command.BRIGHTNESS_CONTROL, params);
            }
            if (normalizedText.contains("减少") || normalizedText.contains("降低") || 
                normalizedText.contains("调小") || normalizedText.contains("暗")) {
                params.put("action", "decrease");
                return new TmsIntent(TmsIntent.Command.BRIGHTNESS_CONTROL, params);
            }
            if (normalizedText.contains("最大") || normalizedText.contains("满")) {
                params.put("action", "max");
                return new TmsIntent(TmsIntent.Command.BRIGHTNESS_CONTROL, params);
            }
            if (normalizedText.contains("最小")) {
                params.put("action", "min");
                return new TmsIntent(TmsIntent.Command.BRIGHTNESS_CONTROL, params);
            }
        }
        
        // 规则 5:设备信息查询
        if (normalizedText.contains("读取设备信息") || normalizedText.contains("查看设备信息")) {
            return new TmsIntent(TmsIntent.Command.GET_DEVICE_INFO, null);
        }
        
        // 规则 6:单独信息项查询
        if (normalizedText.contains("设备型号") || 
            (normalizedText.contains("型号") && !normalizedText.contains("设备信息"))) {
            Map<String, String> params = new HashMap<>();
            params.put("item", "设备型号");
            return new TmsIntent(TmsIntent.Command.GET_DEVICE_INFO_ITEM, params);
        }
        
        // 更多规则...
        
        return new TmsIntent(TmsIntent.Command.UNKNOWN, null);
    }
}
4.3.4 命令执行
java 复制代码
private void executeTmsCommand(TmsIntent intent, String originalText) {
    String result = "";
    
    switch (intent.command) {
        case LOCK_DEVICE:
            // 发送锁定设备广播
            Intent lockIntent = new Intent("android.intent.action.lockdevice");
            lockIntent.putExtra("strState", "0");
            sendBroadcast(lockIntent);
            result = "设备已锁定";
            break;
            
        case WIFI_SWITCH:
            String wifiState = intent.parameters != null ? 
                intent.parameters.get("state") : "unknown";
            boolean wifiEnable = "on".equals(wifiState);
            result = controlWifi(wifiEnable);
            break;
            
        case VOLUME_CONTROL:
            String volumeAction = intent.parameters != null ? 
                intent.parameters.get("action") : "unknown";
            result = controlVolume(volumeAction);
            break;
            
        case BRIGHTNESS_CONTROL:
            String brightnessAction = intent.parameters != null ? 
                intent.parameters.get("action") : "unknown";
            result = controlBrightness(brightnessAction);
            break;
            
        case GET_DEVICE_INFO:
            result = deviceInfoHelper.getFormattedDeviceInfo();
            break;
            
        case GET_DEVICE_INFO_ITEM:
            String itemName = intent.parameters != null ? 
                intent.parameters.get("item") : "未知";
            String itemValue = deviceInfoHelper.getDeviceInfoItem(itemName);
            result = itemName + ": " + itemValue;
            break;
            
        case UNKNOWN:
            result = "未识别的命令";
            break;
    }
    
    // 显示执行结果
    showToast(result);
    appendLogMessage(result);
}

4.4 设备控制实现

4.4.1 WiFi 控制
java 复制代码
private String controlWifi(boolean enable) {
    try {
        WifiManager wifiManager = (WifiManager) 
            getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            return "WiFi控制失败: 无法获取WiFi服务";
        }
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10+ 需要用户手动操作
            try {
                Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                startActivity(intent);
                return enable ? "请手动开启WiFi" : "请手动关闭WiFi";
            } catch (Exception e) {
                return "WiFi控制失败: " + e.getMessage();
            }
        } else {
            // Android 10以下可以直接控制
            boolean success = wifiManager.setWifiEnabled(enable);
            if (success) {
                return enable ? "WiFi已开启" : "WiFi已关闭";
            } else {
                return "WiFi控制失败";
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "WiFi控制失败", e);
        return "WiFi控制失败: " + e.getMessage();
    }
}
4.4.2 音量控制
java 复制代码
private String controlVolume(String action) {
    try {
        AudioManager audioManager = (AudioManager) 
            getSystemService(Context.AUDIO_SERVICE);
        if (audioManager == null) {
            return "音量控制失败: 无法获取音频服务";
        }
        
        int streamType = AudioManager.STREAM_MUSIC;
        int currentVolume = audioManager.getStreamVolume(streamType);
        int maxVolume = audioManager.getStreamMaxVolume(streamType);
        int newVolume = currentVolume;
        
        switch (action) {
            case "increase":
                newVolume = Math.min(currentVolume + (maxVolume / 10), maxVolume);
                audioManager.setStreamVolume(streamType, newVolume, 0);
                break;
            case "decrease":
                newVolume = Math.max(currentVolume - (maxVolume / 10), 0);
                audioManager.setStreamVolume(streamType, newVolume, 0);
                break;
            case "max":
                newVolume = maxVolume;
                audioManager.setStreamVolume(streamType, maxVolume, 0);
                break;
            case "min":
                newVolume = 0;
                audioManager.setStreamVolume(streamType, 0, 0);
                break;
            default:
                return "音量控制失败: 未知操作";
        }
        
        int volumePercent = (int) ((newVolume / (float) maxVolume) * 100);
        return "音量已调整到 " + volumePercent + "%";
    } catch (Exception e) {
        Log.e(TAG, "音量控制失败", e);
        return "音量控制失败: " + e.getMessage();
    }
}

性能评估与优化

5.1 设备性能评估

使用 adb 命令评估设备性能:

bash 复制代码
# 查看存储空间
adb shell df -h

# 查看内存信息
adb shell "cat /proc/meminfo | grep 'MemTotal\|MemAvailable'"

# 查看 CPU 使用情况
adb shell top -n 1

实际测试结果(2.9GB RAM 设备):

复制代码
存储空间: 19GB 可用 ✅
总内存: 2.9GB
可用内存: 54MB(运行 Vosk 后)
Vosk 占用: 549MB RAM

结论:

  • ✅ 轻量模型(49MB)完全可行
  • ❌ 大型模型(1.3GB)会导致 OOM 崩溃

5.2 性能优化建议

  1. 模型选择 :必须使用 vosk-model-small-cn-0.3(49MB)
  2. 内存管理:及时释放模型资源
  3. 识别优化:使用部分结果减少延迟
  4. UI 优化:使用 RecyclerView 显示日志,避免内存泄漏

使用场景示例

6.1 驾驶场景

场景描述:驾驶时,双手需要控制方向盘,无法操作手机。

语音指令示例

  • "打开 WiFi" - 连接车载 WiFi
  • "增加音量" - 调高音乐音量
  • "读取设备信息" - 查看手机状态
  • "设备型号" - 快速查询设备型号

优势

  • ✅ 无需分心操作手机
  • ✅ 提高驾驶安全性
  • ✅ 快速响应需求

6.2 厨房场景

场景描述:做饭时,双手沾满水或油,无法触摸手机。

语音指令示例

  • "增加亮度" - 调亮屏幕查看菜谱
  • "减少音量" - 降低视频音量
  • "电池电量" - 查看手机电量
  • "关闭 WiFi" - 节省电量

优势

  • ✅ 保持双手清洁
  • ✅ 无需中断烹饪
  • ✅ 快速调整设置

6.3 运动场景

场景描述:运动时,手机放在口袋或运动包中,不方便取出。

语音指令示例

  • "最大音量" - 调高音乐音量
  • "打开蓝牙" - 连接蓝牙耳机
  • "WiFi 状态" - 检查网络连接
  • "锁定设备" - 防止误触

优势

  • ✅ 无需停止运动
  • ✅ 快速响应需求
  • ✅ 保持运动节奏

6.4 办公场景

场景描述:开会或演示时,需要快速调整设备设置。

语音指令示例

  • "增加亮度" - 提高屏幕亮度便于演示
  • "静音" - 快速静音避免打扰
  • "关闭蓝牙" - 断开不必要的连接
  • "读取设备信息" - 查看设备配置

优势

  • ✅ 快速响应
  • ✅ 不影响会议流程
  • ✅ 专业高效

6.5 无障碍场景

场景描述:视障或行动不便的用户,无法方便地操作手机。

语音指令示例

  • "设备型号" - 查询设备信息
  • "电池电量" - 检查电量
  • "WiFi 状态" - 检查网络
  • "增加音量" - 调整音量

优势

  • ✅ 提高可访问性
  • ✅ 降低操作难度
  • ✅ 增强用户体验

常见问题与解决方案

7.1 模型加载失败

问题:模型加载时出现异常

解决方案

  1. 检查模型文件是否完整
  2. 确保模型文件在 assets 目录下
  3. 检查 aaptOptions 配置是否正确
  4. 查看日志获取详细错误信息

7.2 识别准确率低

问题:语音识别结果不准确

解决方案

  1. 确保在安静环境中使用
  2. 说话清晰,语速适中
  3. 距离麦克风适当距离(30-50cm)
  4. 可以尝试使用更大的模型(如果设备性能允许)

7.3 内存占用过高

问题:应用占用内存过多

解决方案

  1. 使用轻量级模型(vosk-model-small-cn-0.3)
  2. 及时释放模型资源
  3. 优化 UI 显示,使用 RecyclerView
  4. 避免内存泄漏

7.4 权限问题

问题:无法访问麦克风或系统设置

解决方案

  1. 检查 AndroidManifest.xml 中的权限声明
  2. 运行时动态请求权限
  3. 对于系统级控制,需要系统权限或设备管理员权限

总结与展望

8.1 技术总结

本项目成功实现了:

  1. 离线语音识别:使用 Vosk 轻量级模型,完全离线运行
  2. 自然语言理解:基于规则的解析器,准确率高
  3. 设备控制:直接调用 TMS APK 内部能力
  4. 性能优化:资源占用小,响应速度快

8.2 技术优势

  • 完全离线:不依赖网络,保护隐私
  • 轻量级:模型仅 49MB,适合移动设备
  • 高准确率:规则解析 100% 准确
  • 易于维护:代码简洁,易于扩展

8.5 参考资料


附录:完整代码示例

A.1 TmsIntent.java

java 复制代码
package org.vosk.demo;

import java.util.Map;

public class TmsIntent {
    public enum Command {
        LOCK_DEVICE,
        WIFI_SWITCH,
        BLUETOOTH_SWITCH,
        VOLUME_CONTROL,
        BRIGHTNESS_CONTROL,
        RESET_PASSWORD,
        GET_DEVICE_INFO,
        GET_DEVICE_INFO_ITEM,
        UNKNOWN
    }
    
    public final Command command;
    public final Map<String, String> parameters;
    
    public TmsIntent(Command command, Map<String, String> parameters) {
        this.command = command;
        this.parameters = parameters;
    }
}

A.2 项目结构

复制代码
app/src/main/java/org/vosk/demo/
├── VoskActivity.java          # 主活动
├── TmsCommandParser.java      # NLU 解析器
├── TmsIntent.java             # 命令数据结构
├── DeviceInfoHelper.java      # 设备信息工具
└── RecognitionLogAdapter.java # 日志适配器

如果本文对您有帮助,欢迎点赞、收藏、转发!如有问题,欢迎在评论区讨论。

相关推荐
李艺为4 小时前
Fake Device Test作假屏幕分辨率分析
android·java
zh_xuan4 小时前
github远程library仓库升级
android·github
Digitally4 小时前
如何将 iPad 上的视频无损传输到 Mac
macos·音视频·ipad
峥嵘life4 小时前
Android蓝牙停用绝对音量原理
android
Maynor9964 小时前
Codex 中国站正式上线!
人工智能·gpt·macos·github
XuecWu35 小时前
【Mac系统】一次 Keychain 异常导致的 Trae 卡死问题排查
macos
czlczl200209255 小时前
IN和BETWEEN在索引效能的区别
android·adb
Volunteer Technology5 小时前
ES高级搜索功能
android·大数据·elasticsearch
北京自在科技6 小时前
Find Hub App 小更新
android·ios·安卓·findmy·airtag
青山_FPGA6 小时前
以太网 MAC-PHY 接口总结
嵌入式硬件·macos