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 # 日志适配器

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

相关推荐
骑驴看星星a5 小时前
【Three.js--manual script】4.光照
android·开发语言·javascript
Yooooung_Lee9 小时前
七家咨询公司的PPT标准配色模版(macos+Office LTSC Standard for Mac 2024)
macos·powerpoint
Digitally10 小时前
如何在Mac上同步iPhone短信
macos·ios·iphone
好想早点睡.10 小时前
Mac安装pnpm步骤以及会出现的问题
macos
TDengine (老段)11 小时前
TDengine 字符串函数 CONCAT_WS 用户手册
android·大数据·数据库·时序数据库·tdengine·涛思数据
会跑的兔子12 小时前
Android 16 Kotlin协程 第一部分
android·开发语言·kotlin
Meteors.13 小时前
安卓进阶——OpenGL ES
android
陈大头铃儿响叮当14 小时前
Mac 下配置Charles踩坑之旅
macos
椰羊sqrt14 小时前
CVE-2025-4334 深度分析:WordPress wp-registration 插件权限提升漏洞
android·开发语言·okhttp·网络安全