params = new TreeMap<>();
356 | params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
357 | params.put(SpeechConstant.WP_WORDS_FILE, "assets:///WakeUp.bin");
358 | InFileStream.setContext(this);
359 | String json;
360 | json = new JSONObject(params).toString();
361 | wakeup.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);
362 | }
363 |
364 | private void stop() {
365 | wakeup.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0); //
366 | }
367 |
368 | @Override
369 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
370 |
371 | if (params != null && !params.isEmpty()) {
372 | try {
373 | JSONObject json = new JSONObject(params);
374 | String word = json.getString("word");
375 | Log.d("WORD",word);
376 | setResult(word);
377 | } catch (JSONException e) {
378 | e.printStackTrace();
379 | }
380 | }
381 | }
382 |
383 | public String getResult(){
384 | return mResult;
385 | }
386 |
387 | public void setResult(String result){
388 | this.mResult = result;
389 | }
390 |
391 | @Override
392 | public void onInterrupt() {
393 | stop();
394 | wakeup.send(SpeechConstant.WAKEUP_STOP, "{}", null, 0, 0);
395 | Log.d(TAG, "AccessibilityEvent end.");
396 | }
397 |
398 | @Override
399 | protected void onServiceConnected() {
400 | super.onServiceConnected();
401 | Toast.makeText(getApplicationContext(), "无障碍服务开启成功,若出现错误,请重新开启", Toast.LENGTH_LONG).show();
402 | Log.d(TAG,"onServiceConnected: success.");
403 | }
404 |
405 | }
406 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
21 |
22 |
29 |
30 |
34 |
35 |
39 |
40 |
47 |
48 |
49 |
55 |
56 |
60 |
72 |
73 |
84 |
85 |
86 |
87 |
95 |
96 |
97 |
107 |
108 |
118 |
119 |
129 |
130 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/short_video_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/app/src/main/res/mipmap-xhdpi/short_video_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4D96FF
4 | #F84B4B
5 | #FF03DAC5
6 | #FF018786
7 | #FF000000
8 | #FFFFFFFF
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 短视频辅助器
3 | 欢迎使用Bunny开发的自动化操作服务
4 | 点击按钮打开,辅助您刷短视频
5 | 短视频辅助器
6 | 语音唤醒测试(测试完无错误,请重启软件)
7 | 开始识别
8 | 停止识别
9 | 开启无障碍
10 | By Bunny
11 | Version 1.0.0
12 | 使用步骤: 必须先 进入抖音 → 打开本软件 → 授予权限 → 打开 “短视频辅助器” 无障碍服务 → (可选:允许后台运行) → 用指令刷短视频(不使用时请关闭本软件)
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/short_video_assist_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/test/java/com/bunny/shortvideoassist/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.bunny.shortvideoassist;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '7.1.2' apply false
4 | id 'com.android.library' version '7.1.2' apply false
5 | }
6 |
7 | task clean(type: Delete) {
8 | delete rootProject.buildDir
9 | }
--------------------------------------------------------------------------------
/core/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/core/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 |
4 | android {
5 | compileSdkVersion 28
6 |
7 | defaultConfig {
8 | minSdkVersion 16
9 | targetSdkVersion 28
10 | }
11 |
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | packagingOptions{
19 | doNotStrip "*/*/libvad.dnn.so"
20 | doNotStrip "*/*/libbd_easr_s1_merge_normal_20151216.dat.so"
21 | }
22 | }
23 |
24 |
25 |
26 | dependencies {
27 | api fileTree(include: ['*.jar'], dir: 'libs')
28 | implementation 'androidx.appcompat:appcompat:1.0.2'
29 | }
30 |
--------------------------------------------------------------------------------
/core/libs/bdasr_V3_20210628_cfe8c44.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/libs/bdasr_V3_20210628_cfe8c44.jar
--------------------------------------------------------------------------------
/core/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/core/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/core/src/main/assets/README.txt:
--------------------------------------------------------------------------------
1 | 百度语音识别SDK在demo程序中assets目录的文件解释说明:
2 | WakeUp.bin 唤醒功能的唤醒词配置文件, 需要在百度语音开发平台中定义和导出 http://speech.baidu.com/wake
3 | baidu_speech_grammar.bsg 自定义语义以及离线命令词识别共用的语法文件, 需要在百度语音开发平台中定义和导出 http://speech.baidu.com/asr
--------------------------------------------------------------------------------
/core/src/main/assets/WakeUp.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/assets/WakeUp.bin
--------------------------------------------------------------------------------
/core/src/main/assets/baidu_speech_grammar.bsg:
--------------------------------------------------------------------------------
1 | %7B%0A%20%20%20%20%22version%22%3A%20%220.1%22%2C%0A%20%20%20%20%22slots%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E5%BC%A0%E4%B8%89%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E6%9D%8E%E5%9B%9B%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E7%8E%8B%E4%BA%94%22%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22appname%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E5%BE%AE%E4%BF%A1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E7%9F%AD%E4%BF%A1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%E8%AE%A1%E7%AE%97%E5%99%A8%22%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22msgbody%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22.%2B%22%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22rules%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22telephone.call%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%89%93%E7%94%B5%E8%AF%9D%E7%BB%99%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%89%93%E7%94%B5%E8%AF%9D%E7%BB%99(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%89%93%E7%BB%99%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%89%93%E7%BB%99(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E5%91%BC%E5%8F%AB%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E5%91%BC%E5%8F%AB(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E7%BB%99%3Cname%3E%E6%89%93%E7%94%B5%E8%AF%9D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E7%BB%99(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%E6%89%93%E7%94%B5%E8%AF%9D%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22contacts.view%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%9F%A5%E7%9C%8B%3Cname%3E%E7%9A%84%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%9F%A5%E7%9C%8B(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%E7%9A%84%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%9F%A5%E7%9C%8B%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%9F%A5%E7%9C%8B(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22contacts.create%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%96%B0%E5%BB%BA%E8%81%94%E7%B3%BB%E4%BA%BA%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%96%B0%E5%BB%BA%E8%81%94%E7%B3%BB%E4%BA%BA(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22contacts.remove%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E5%88%A0%E9%99%A4%3Cname%3E%E7%9A%84%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E5%88%A0%E9%99%A4(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%E7%9A%84%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22message.view%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%9F%A5%E7%9C%8B%E6%9C%AA%E8%AF%BB%E7%9F%AD%E4%BF%A1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%9F%A5%E7%9C%8B%E6%9C%AA%E8%AF%BB%E7%9F%AD%E4%BF%A1%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22message.send%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%E5%86%85%E5%AE%B9%E6%98%AF%3Cmsgbody%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99(%E5%BC%A0%E4%B8%89%7C%E6%9D%8E%E5%9B%9B%7C%E7%8E%8B%E4%BA%94)%E5%86%85%E5%AE%B9%E6%98%AF(.%2B)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22msgbody%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22app.open%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%89%93%E5%BC%80%3Cappname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%89%93%E5%BC%80(%E5%BE%AE%E4%BF%A1%7C%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%7C%E7%9F%AD%E4%BF%A1%7C%E8%AE%A1%E7%AE%97%E5%99%A8)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22appname%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E5%90%AF%E5%8A%A8%3Cappname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E5%90%AF%E5%8A%A8(%E5%BE%AE%E4%BF%A1%7C%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%7C%E7%9F%AD%E4%BF%A1%7C%E8%AE%A1%E7%AE%97%E5%99%A8)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22appname%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22app.search%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E6%90%9C%E7%B4%A2%3Cappname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E6%90%9C%E7%B4%A2(%E5%BE%AE%E4%BF%A1%7C%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%7C%E7%9F%AD%E4%BF%A1%7C%E8%AE%A1%E7%AE%97%E5%99%A8)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22appname%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%22app.download%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22origin%22%3A%20%22%E4%B8%8B%E8%BD%BD%3Cappname%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22pattern%22%3A%20%22%5E%E4%B8%8B%E8%BD%BD(%E5%BE%AE%E4%BF%A1%7C%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%7C%E7%9F%AD%E4%BF%A1%7C%E8%AE%A1%E7%AE%97%E5%99%A8)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22groups%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22appname%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22grammar%22%3A%20%22%3Cname%3E%20%3D%20%E5%BC%A0%E4%B8%89%7C%20%5Cn%E6%9D%8E%E5%9B%9B%7C%20%5Cn%E7%8E%8B%E4%BA%94%3B%5Cn%3Cappname%3E%20%3D%20%E5%BE%AE%E4%BF%A1%7C%20%5Cn%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%7C%20%5Cn%E7%9F%AD%E4%BF%A1%7C%20%5Cn%E8%AE%A1%E7%AE%97%E5%99%A8%3B%5Cn%3Cmsgbody%3E%20%3D%20%E8%AF%8D%E6%9D%A1%E9%BB%98%E8%AE%A4%E5%80%BC%3B%5Cn%3Cauto_create_node%3E%20%3D%20%E6%9F%A5%E7%9C%8B%E6%9C%AA%E8%AF%BB%E7%9F%AD%E4%BF%A1%3B%5Cn%3C_wakeup%3E%20%3D%20%E5%94%A4%E9%86%92%E8%AF%8D%E5%8D%A0%E4%BD%8D%E7%AC%A6%3B%5Cn%5Cn%5Cn_SCENE_ID_%200%5Cn%5Cn(%20%3Cauto_create_node%3E%20)%5Cn%5Cn(%20%3C_wakeup%3E%3Cauto_create_node%3E%20)%5Cn%5Cn(%20%E6%89%93%E7%94%B5%E8%AF%9D%E7%BB%99%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%89%93%E7%94%B5%E8%AF%9D%E7%BB%99%3Cname%3E%20)%5Cn(%20%E6%89%93%E7%BB%99%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%89%93%E7%BB%99%3Cname%3E%20)%5Cn(%20%E5%91%BC%E5%8F%AB%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E5%91%BC%E5%8F%AB%3Cname%3E%20)%5Cn(%20%E7%BB%99%3Cname%3E%E6%89%93%E7%94%B5%E8%AF%9D%20)%5Cn(%20%3C_wakeup%3E%E7%BB%99%3Cname%3E%E6%89%93%E7%94%B5%E8%AF%9D%20)%5Cn(%20%E6%9F%A5%E7%9C%8B%3Cname%3E%E7%9A%84%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%20)%5Cn(%20%3C_wakeup%3E%E6%9F%A5%E7%9C%8B%3Cname%3E%E7%9A%84%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%20)%5Cn(%20%E6%9F%A5%E7%9C%8B%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%9F%A5%E7%9C%8B%3Cname%3E%20)%5Cn(%20%E6%96%B0%E5%BB%BA%E8%81%94%E7%B3%BB%E4%BA%BA%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%96%B0%E5%BB%BA%E8%81%94%E7%B3%BB%E4%BA%BA%3Cname%3E%20)%5Cn(%20%E5%88%A0%E9%99%A4%3Cname%3E%E7%9A%84%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F%20)%5Cn(%20%3C_wakeup%3E%E5%88%A0%E9%99%A4%3Cname%3E%E7%9A%84%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F%20)%5Cn(%20%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%20)%5Cn(%20%3C_wakeup%3E%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%20)%5Cn(%20%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%E5%86%85%E5%AE%B9%E6%98%AF%3Cmsgbody%3E%20)%5Cn(%20%3C_wakeup%3E%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%E5%86%85%E5%AE%B9%E6%98%AF%3Cmsgbody%3E%20)%5Cn(%20%E6%89%93%E5%BC%80%3Cappname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%89%93%E5%BC%80%3Cappname%3E%20)%5Cn(%20%E5%90%AF%E5%8A%A8%3Cappname%3E%20)%5Cn(%20%3C_wakeup%3E%E5%90%AF%E5%8A%A8%3Cappname%3E%20)%5Cn(%20%E6%90%9C%E7%B4%A2%3Cappname%3E%20)%5Cn(%20%3C_wakeup%3E%E6%90%9C%E7%B4%A2%3Cappname%3E%20)%5Cn(%20%E4%B8%8B%E8%BD%BD%3Cappname%3E%20)%5Cn(%20%3C_wakeup%3E%E4%B8%8B%E8%BD%BD%3Cappname%3E%20)%5Cn%22%2C%0A%20%20%20%20%22origin_slots%22%3A%20%22name%20%3D%20%E5%BC%A0%E4%B8%89%2C%20%E6%9D%8E%E5%9B%9B%2C%20%E7%8E%8B%E4%BA%94%5Cnappname%20%3D%20%E5%BE%AE%E4%BF%A1%2C%20%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE%2C%20%E7%9F%AD%E4%BF%A1%2C%20%E8%AE%A1%E7%AE%97%E5%99%A8%5Cnmsgbody%20%3D%20*%22%2C%0A%20%20%20%20%22origin_rules%22%3A%20%22telephone.call%20%20%20%20%20%3D%20%E6%89%93%E7%94%B5%E8%AF%9D%E7%BB%99%3Cname%3E%2C%20%E6%89%93%E7%BB%99%3Cname%3E%2C%20%E5%91%BC%E5%8F%AB%3Cname%3E%2C%E7%BB%99%3Cname%3E%E6%89%93%E7%94%B5%E8%AF%9D%5Cncontacts.view%20%20%20%20%20%3D%20%E6%9F%A5%E7%9C%8B%3Cname%3E%E7%9A%84%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%2C%20%E6%9F%A5%E7%9C%8B%3Cname%3E%5Cncontacts.create%20%20%3D%20%E6%96%B0%E5%BB%BA%E8%81%94%E7%B3%BB%E4%BA%BA%3Cname%3E%5Cncontacts.remove%3D%20%E5%88%A0%E9%99%A4%3Cname%3E%E7%9A%84%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F%5Cnmessage.view%20%20%20%20%20%3D%20%E6%9F%A5%E7%9C%8B%E6%9C%AA%E8%AF%BB%E7%9F%AD%E4%BF%A1%5Cnmessage.send%20%20%20%20%3D%20%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%2C%20%E5%8F%91%E7%9F%AD%E4%BF%A1%E7%BB%99%3Cname%3E%E5%86%85%E5%AE%B9%E6%98%AF%3Cmsgbody%3E%5Cnapp.open%20%20%20%20%20%20%20%20%20%20%20%20%3D%20%E6%89%93%E5%BC%80%3Cappname%3E%2C%20%E5%90%AF%E5%8A%A8%3Cappname%3E%5Cnapp.search%20%20%20%20%20%20%20%20%20%3D%20%E6%90%9C%E7%B4%A2%3Cappname%3E%5Cnapp.download%20%20%20%20%3D%20%E4%B8%8B%E8%BD%BD%3Cappname%3E%22%0A%7D
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/inputstream/FileAudioInputStream.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.inputstream;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.FileInputStream;
6 | import java.io.FileNotFoundException;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.math.BigInteger;
10 | import java.security.MessageDigest;
11 | import java.security.NoSuchAlgorithmException;
12 |
13 | /**
14 | * Created by fujiayi on 2017/11/27.
15 | *
16 | * 解决大文件的输入问题。
17 | * 文件大时不能通过Infile参数一下子输入。
18 | */
19 |
20 | public class FileAudioInputStream extends InputStream {
21 |
22 | private InputStream in;
23 |
24 | private long nextSleepTime = -1;
25 |
26 | private long totalSleepMs = 0;
27 |
28 | private static final String TAG = "FileAudioInputStream";
29 |
30 | public FileAudioInputStream(String file) throws FileNotFoundException {
31 | in = new FileInputStream(file);
32 | }
33 |
34 | public FileAudioInputStream(InputStream in) {
35 | this.in = in;
36 | }
37 |
38 | @Override
39 | public int read() throws IOException {
40 | throw new UnsupportedOperationException();
41 | }
42 |
43 | @Override
44 | public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
45 | int bytePerMs = 16000 * 2 / 1000;
46 | int count = bytePerMs * 20; // 20ms 音频数据
47 | if (byteCount < count) {
48 | count = byteCount;
49 | }
50 | if (nextSleepTime > 0) {
51 | try {
52 | long sleepMs = nextSleepTime - System.currentTimeMillis();
53 | if (sleepMs > 0) {
54 | Log.i(TAG, "will sleep " + sleepMs);
55 | Thread.sleep(sleepMs); // 每20ms的音频 ,比如等待20ms传输下一批
56 | totalSleepMs += sleepMs;
57 | }
58 | } catch (InterruptedException e) {
59 | e.printStackTrace();
60 | }
61 | }
62 | int r = in.read(buffer, byteOffset, count);
63 |
64 | /*
65 | if (r >= 0) {
66 | Log.i("FileAudioInputStream", "Debug:" + System.currentTimeMillis() + ": " + md5(buffer, byteOffset, r));
67 | } else {
68 | Log.i("FileAudioInputStream", "Debug:" + System.currentTimeMillis() + ": return " + r);
69 | }
70 | */
71 | nextSleepTime = System.currentTimeMillis() + r / bytePerMs;
72 |
73 | // 如果是长语音,在r=-1的情况下,需要手动调用stop
74 | return r;
75 | }
76 |
77 | @Override
78 | public void close() throws IOException {
79 | super.close();
80 | Log.i(TAG, "time sleeped " + totalSleepMs);
81 | if (null != in) {
82 | in.close();
83 | }
84 | }
85 |
86 | private String md5(byte[] buffer, int byteOffset, int byteCount) {
87 | try {
88 | MessageDigest digest = MessageDigest.getInstance("MD5");
89 | digest.reset();
90 | digest.update(buffer, byteOffset, byteCount);
91 | BigInteger bigInt = new BigInteger(1, digest.digest());
92 | return bigInt.toString(16);
93 | } catch (NoSuchAlgorithmException e) {
94 | e.printStackTrace();
95 | }
96 | return null;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/inputstream/InFileStream.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.inputstream;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 |
6 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
7 |
8 | import java.io.FileNotFoundException;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 |
12 | /**
13 | * Created by fujiayi on 2017/6/20.
14 | */
15 |
16 | public class InFileStream {
17 |
18 | private static Context context;
19 |
20 | private static final String TAG = "InFileStream";
21 |
22 | private static volatile String filename;
23 |
24 | private static volatile InputStream is;
25 |
26 | // 以下3个setContext
27 |
28 | /**
29 | * 必须要先调用这个方法
30 | * 如之后调用create16kStream,使用默认的app/src/main/assets/outfile.pcm作为输入
31 | * 如之后调用createMyPipedInputStream, 见 InPipedStream
32 | *
33 | * @param context
34 | */
35 | public static void setContext(Context context) {
36 | InFileStream.context = context;
37 | }
38 |
39 | /**
40 | * 使用pcm文件作为输入
41 | *
42 | * @param context
43 | * @param filename
44 | */
45 | public static void setContext(Context context, String filename) {
46 | InFileStream.context = context;
47 | InFileStream.filename = filename;
48 | }
49 |
50 | public static void setContext(Context context, InputStream is) {
51 | InFileStream.context = context;
52 | InFileStream.is = is;
53 | }
54 |
55 | public static Context getContext() {
56 | return context;
57 | }
58 |
59 | public static void reset() {
60 | filename = null;
61 | is = null;
62 | }
63 |
64 |
65 | public static InputStream createMyPipedInputStream() {
66 | return InPipedStream.createAndStart(context);
67 | }
68 |
69 | /**
70 | * 默认使用必须要先调用setContext
71 | * 默认从createFileStream中读取InputStream
72 | *
73 | * @return
74 | */
75 | public static InputStream create16kStream() {
76 | if (is == null && filename == null) {
77 | // 没有任何设置的话,从createFileStream中读取
78 | return new FileAudioInputStream(createFileStream());
79 | }
80 |
81 | if (is != null) { // 默认为null,setInputStream调用后走这个逻辑
82 | return new FileAudioInputStream(is);
83 | } else if (filename != null) { // 默认为null, setFileName调用后走这个逻辑
84 | try {
85 | return new FileAudioInputStream(filename);
86 | } catch (FileNotFoundException e) {
87 | e.printStackTrace();
88 | }
89 | }
90 |
91 | return null;
92 | }
93 |
94 | private static InputStream createFileStream() {
95 | try {
96 | // 这里抛异常表示没有调用 setContext方法
97 | InputStream is = context.getAssets().open("outfile.pcm");
98 | MyLogger.info(TAG, "create input stream ok " + is.available());
99 | return is;
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | throw new RuntimeException(e);
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/inputstream/InPipedStream.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.inputstream;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.PipedInputStream;
8 | import java.io.PipedOutputStream;
9 |
10 | /**
11 | * 本示例从app/src/main/assets/outfile.pcm作为byte[]的输入
12 | * 生成PipedInputStream作为SDK里IN_FILE的参数
13 | */
14 | public class InPipedStream {
15 |
16 | private PipedInputStream pipedInputStream;
17 | private PipedOutputStream pipedOutputStream;
18 | private Context context;
19 |
20 | private InPipedStream(Context context) {
21 | pipedInputStream = new PipedInputStream();
22 | pipedOutputStream = new PipedOutputStream();
23 | this.context = context;
24 | }
25 |
26 | private void start() throws IOException {
27 | /** 准备绑定 **/
28 | pipedInputStream.connect(pipedOutputStream);
29 |
30 | /** 准备文件 **/
31 |
32 | /** 新线程中放入 20ms 音频数据,注意从新线程放入**/
33 | Runnable run = new Runnable() {
34 | @Override
35 | public void run() {
36 |
37 | try {
38 | final InputStream is = context.getAssets().open("outfile.pcm");
39 | /** 读取20ms的音频二进制数据 放入buffer 中**/
40 | int bytePerMs = 16000 * 2 / 1000;
41 | int count = bytePerMs * 20; // 20ms 音频数据
42 | int r = 0;
43 | byte[] buffer = new byte[count];
44 | do {
45 | r = is.read(buffer);
46 | int sleepTime = 0;
47 | if (r > 0) {
48 | pipedOutputStream.write(buffer, 0, count);
49 | sleepTime = r / bytePerMs;
50 | } else if (r == 0) {
51 | sleepTime = 100; // 这里数值按照自己情况而定
52 | }
53 | if (sleepTime > 0) {
54 | try {
55 | Thread.sleep(sleepTime);
56 | } catch (InterruptedException e) {
57 | e.printStackTrace();
58 | }
59 | }
60 |
61 | } while (r >= 0);
62 | is.close();
63 | } catch (IOException e) {
64 | e.printStackTrace();
65 | throw new RuntimeException(e);
66 | }
67 | }
68 | };
69 | (new Thread(run)).start();
70 | }
71 |
72 | public static PipedInputStream createAndStart(Context context) {
73 | InPipedStream obj = new InPipedStream(context);
74 | try {
75 | obj.start();
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | throw new RuntimeException(e);
79 | }
80 | return obj.pipedInputStream;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/inputstream/MyMicrophoneInputStream.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.inputstream;
2 |
3 | import android.content.Context;
4 | import android.media.AudioFormat;
5 | import android.media.AudioRecord;
6 | import android.media.MediaRecorder;
7 | import android.util.Log;
8 |
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 |
12 | /**
13 | * Created by fujiayi on 2017/11/27.
14 | */
15 |
16 | public class MyMicrophoneInputStream extends InputStream {
17 | private static AudioRecord audioRecord;
18 |
19 | private static MyMicrophoneInputStream is;
20 |
21 | private boolean isStarted = false;
22 |
23 | private static final String TAG = "MyMicrophoneInputStream";
24 |
25 | public MyMicrophoneInputStream() {
26 | if (audioRecord == null) {
27 | int bufferSize = AudioRecord.getMinBufferSize(16000,
28 | AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) * 16;
29 | audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
30 | 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
31 |
32 |
33 | }
34 |
35 |
36 | }
37 |
38 | public static MyMicrophoneInputStream getInstance() {
39 | if (is == null) {
40 | synchronized (MyMicrophoneInputStream.class) {
41 | if (is == null) {
42 | is = new MyMicrophoneInputStream();
43 | }
44 | }
45 | }
46 | return is;
47 | }
48 |
49 | public void start() {
50 | Log.i(TAG, " MyMicrophoneInputStream start recoding!");
51 | try {
52 | if (audioRecord == null
53 | || audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
54 | throw new IllegalStateException(
55 | "startRecording() called on an uninitialized AudioRecord." + (audioRecord == null));
56 | }
57 |
58 | Context context = InFileStream.getContext();
59 |
60 | audioRecord.startRecording();
61 |
62 | } catch (Exception e) {
63 | Log.e(TAG, e.getClass().getSimpleName(), e);
64 | }
65 | Log.i(TAG, " MyMicrophoneInputStream start recoding finished");
66 | }
67 |
68 | @Override
69 | public int read() throws IOException {
70 | throw new UnsupportedOperationException();
71 | }
72 |
73 | @Override
74 | public int read(byte[] b, int off, int len) throws IOException {
75 |
76 | if (!isStarted) {
77 | start(); // 建议在CALLBACK_EVENT_ASR_READY事件中调用。
78 | isStarted = true;
79 | }
80 | try {
81 | int count = audioRecord.read(b, off, len);
82 | return count;
83 | } catch (Exception e) {
84 | Log.e(TAG, e.getClass().getSimpleName(), e);
85 | throw e;
86 | }
87 |
88 | }
89 |
90 | // 建议在建议在CALLBACK_EVENT_ASR_EXIT事件中调用
91 | @Override
92 | public void close() throws IOException {
93 | Log.i(TAG, " MyMicrophoneInputStream close");
94 | if (audioRecord != null) {
95 | audioRecord.stop();
96 | // audioRecord.release(); 程序结束别忘记自行释放
97 | isStarted = false;
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/mini/ActivityMiniRecog.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.mini;
2 |
3 | import android.Manifest;
4 | import android.content.pm.PackageManager;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.os.Message;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.Button;
11 | import android.widget.TextView;
12 |
13 | import androidx.appcompat.app.AppCompatActivity;
14 | import androidx.core.app.ActivityCompat;
15 | import androidx.core.content.ContextCompat;
16 |
17 | import com.baidu.aip.asrwakeup3.core.R;
18 | import com.baidu.aip.asrwakeup3.core.inputstream.InFileStream;
19 | import com.baidu.speech.EventListener;
20 | import com.baidu.speech.EventManager;
21 | import com.baidu.speech.EventManagerFactory;
22 | import com.baidu.speech.asr.SpeechConstant;
23 |
24 | import org.json.JSONObject;
25 |
26 | import java.util.ArrayList;
27 | import java.util.LinkedHashMap;
28 | import java.util.Map;
29 |
30 | /**
31 | * 集成文档: http://ai.baidu.com/docs#/ASR-Android-SDK/top 集成指南一节
32 | * demo目录下doc_integration_DOCUMENT
33 | * ASR-INTEGRATION-helloworld ASR集成指南-集成到helloworld中 对应 ActivityMiniRecog
34 | * ASR-INTEGRATION-TTS-DEMO ASR集成指南-集成到合成DEMO中 对应 ActivityRecog
35 | */
36 |
37 | public class ActivityMiniRecog extends AppCompatActivity implements EventListener {
38 | protected TextView txtLog;
39 | protected TextView txtResult;
40 | protected Button btn;
41 | protected Button stopBtn;
42 | private static String DESC_TEXT = "精简版识别,带有SDK唤醒运行的最少代码,仅仅展示如何调用,\n" +
43 | "也可以用来反馈测试SDK输入参数及输出回调。\n" +
44 | "本示例需要自行根据文档填写参数,可以使用之前识别示例中的日志中的参数。\n" +
45 | "需要完整版请参见之前的识别示例。\n" +
46 | "需要测试离线命令词识别功能可以将本类中的enableOffline改成true,首次测试离线命令词请联网使用。之后请说出“打电话给李四”";
47 |
48 | private EventManager asr;
49 |
50 | private boolean logTime = true;
51 |
52 | protected boolean enableOffline = false; // 测试离线命令词,需要改成true
53 |
54 | /**
55 | * 基于SDK集成2.2 发送开始事件
56 | * 点击开始按钮
57 | * 测试参数填在这里
58 | */
59 | private void start() {
60 | txtLog.setText("");
61 | Map params = new LinkedHashMap();
62 | String event = null;
63 | event = SpeechConstant.ASR_START; // 替换成测试的event
64 |
65 | if (enableOffline) {
66 | params.put(SpeechConstant.DECODER, 2);
67 | }
68 | // 基于SDK集成2.1 设置识别参数
69 | params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
70 | // params.put(SpeechConstant.NLU, "enable");
71 | // params.put(SpeechConstant.BDS_ASR_ENABLE_LONG_SPEECH, true);//长语音 优先级高于VAD_ENDPOINT_TIMEOUT
72 | // params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 0); // 长语音
73 |
74 | // params.put(SpeechConstant.IN_FILE, "res:///com/baidu/android/voicedemo/16k_test.pcm");
75 | // params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN);
76 | // params.put(SpeechConstant.PID, 1537); // 中文输入法模型,有逗号
77 |
78 | /* 语音自训练平台特有参数 */
79 | // params.put(SpeechConstant.PID, 8002);
80 | // 语音自训练平台特殊pid,8002:模型类似开放平台 1537 具体是8001还是8002,看自训练平台页面上的显示
81 | // params.put(SpeechConstant.LMID,1068);
82 | // 语音自训练平台已上线的模型ID,https://ai.baidu.com/smartasr/model
83 | // 注意模型ID必须在你的appId所在的百度账号下
84 | /* 语音自训练平台特有参数 */
85 |
86 | /* 测试InputStream*/
87 | // InFileStream.setContext(this);
88 | // params.put(SpeechConstant.IN_FILE,
89 | // "#com.baidu.aip.asrwakeup3.core.inputstream.InFileStream.createMyPipedInputStream()");
90 |
91 | // 请先使用如‘在线识别’界面测试和生成识别参数。 params同ActivityRecog类中myRecognizer.start(params);
92 | // 复制此段可以自动检测错误
93 | (new AutoCheck(getApplicationContext(), new Handler() {
94 | public void handleMessage(Message msg) {
95 | if (msg.what == 100) {
96 | AutoCheck autoCheck = (AutoCheck) msg.obj;
97 | synchronized (autoCheck) {
98 | String message = autoCheck.obtainErrorMessage(); // autoCheck.obtainAllMessage();
99 | txtLog.append(message + "\n");
100 | ; // 可以用下面一行替代,在logcat中查看代码
101 | // Log.w("AutoCheckMessage", message);
102 | }
103 | }
104 | }
105 | }, enableOffline)).checkAsr(params);
106 | String json = null; // 可以替换成自己的json
107 | json = new JSONObject(params).toString(); // 这里可以替换成你需要测试的json
108 | asr.send(event, json, null, 0, 0);
109 | printLog("输入参数:" + json);
110 | }
111 |
112 | /**
113 | * 点击停止按钮
114 | * 基于SDK集成4.1 发送停止事件
115 | */
116 | private void stop() {
117 | printLog("停止识别:ASR_STOP");
118 | asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); //
119 | }
120 |
121 |
122 | /**
123 | * enableOffline设为true时,在onCreate中调用
124 | * 基于SDK离线命令词1.4 加载离线资源(离线时使用)
125 | */
126 | private void loadOfflineEngine() {
127 | Map params = new LinkedHashMap();
128 | params.put(SpeechConstant.DECODER, 2);
129 | params.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets://baidu_speech_grammar.bsg");
130 | asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, new JSONObject(params).toString(), null, 0, 0);
131 | }
132 |
133 | /**
134 | * enableOffline为true时,在onDestory中调用,与loadOfflineEngine对应
135 | * 基于SDK集成5.1 卸载离线资源步骤(离线时使用)
136 | */
137 | private void unloadOfflineEngine() {
138 | asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0); //
139 | }
140 |
141 | @Override
142 | protected void onCreate(Bundle savedInstanceState) {
143 | super.onCreate(savedInstanceState);
144 | setContentView(R.layout.common_mini);
145 | initView();
146 | initPermission();
147 | // 基于sdk集成1.1 初始化EventManager对象
148 | asr = EventManagerFactory.create(this, "asr");
149 | // 基于sdk集成1.3 注册自己的输出事件类
150 | asr.registerListener(this); // EventListener 中 onEvent方法
151 | btn.setOnClickListener(new View.OnClickListener() {
152 |
153 | @Override
154 | public void onClick(View v) {
155 | start();
156 | }
157 | });
158 | stopBtn.setOnClickListener(new View.OnClickListener() {
159 |
160 | @Override
161 | public void onClick(View v) {
162 | stop();
163 | }
164 | });
165 | if (enableOffline) {
166 | loadOfflineEngine(); // 测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
167 | }
168 | }
169 |
170 | @Override
171 | protected void onPause() {
172 | super.onPause();
173 | asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
174 | Log.i("ActivityMiniRecog", "On pause");
175 | }
176 |
177 | @Override
178 | protected void onDestroy() {
179 | super.onDestroy();
180 | // 基于SDK集成4.2 发送取消事件
181 | asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
182 | if (enableOffline) {
183 | unloadOfflineEngine(); // 测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
184 | }
185 |
186 | // 基于SDK集成5.2 退出事件管理器
187 | // 必须与registerListener成对出现,否则可能造成内存泄露
188 | asr.unregisterListener(this);
189 | }
190 |
191 | // 基于sdk集成1.2 自定义输出事件类 EventListener 回调方法
192 | // 基于SDK集成3.1 开始回调事件
193 | @Override
194 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
195 | String logTxt = "name: " + name;
196 |
197 | if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
198 | // 识别相关的结果都在这里
199 | if (params == null || params.isEmpty()) {
200 | return;
201 | }
202 | if (params.contains("\"nlu_result\"")) {
203 | // 一句话的语义解析结果
204 | if (length > 0 && data.length > 0) {
205 | logTxt += ", 语义解析结果:" + new String(data, offset, length);
206 | }
207 | } else if (params.contains("\"partial_result\"")) {
208 | // 一句话的临时识别结果
209 | logTxt += ", 临时识别结果:" + params;
210 | } else if (params.contains("\"final_result\"")) {
211 | // 一句话的最终识别结果
212 | logTxt += ", 最终识别结果:" + params;
213 | } else {
214 | // 一般这里不会运行
215 | logTxt += " ;params :" + params;
216 | if (data != null) {
217 | logTxt += " ;data length=" + data.length;
218 | }
219 | }
220 | } else {
221 | // 识别开始,结束,音量,音频数据回调
222 | if (params != null && !params.isEmpty()){
223 | logTxt += " ;params :" + params;
224 | }
225 | if (data != null) {
226 | logTxt += " ;data length=" + data.length;
227 | }
228 | }
229 |
230 |
231 | printLog(logTxt);
232 | }
233 |
234 | private void printLog(String text) {
235 | if (logTime) {
236 | text += " ;time=" + System.currentTimeMillis();
237 | }
238 | text += "\n";
239 | Log.i(getClass().getName(), text);
240 | txtLog.append(text + "\n");
241 | }
242 |
243 |
244 | private void initView() {
245 | txtResult = (TextView) findViewById(R.id.txtResult);
246 | txtLog = (TextView) findViewById(R.id.txtLog);
247 | btn = (Button) findViewById(R.id.btn);
248 | stopBtn = (Button) findViewById(R.id.btn_stop);
249 | txtLog.setText(DESC_TEXT + "\n");
250 | }
251 |
252 | /**
253 | * android 6.0 以上需要动态申请权限
254 | */
255 | private void initPermission() {
256 | String permissions[] = {Manifest.permission.RECORD_AUDIO,
257 | Manifest.permission.ACCESS_NETWORK_STATE,
258 | Manifest.permission.INTERNET,
259 | Manifest.permission.WRITE_EXTERNAL_STORAGE
260 | };
261 |
262 | ArrayList toApplyList = new ArrayList();
263 |
264 | for (String perm : permissions) {
265 | if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
266 | toApplyList.add(perm);
267 | // 进入到这里代表没有权限.
268 |
269 | }
270 | }
271 | String tmpList[] = new String[toApplyList.size()];
272 | if (!toApplyList.isEmpty()) {
273 | ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
274 | }
275 |
276 | }
277 |
278 | @Override
279 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
280 | // 此处为android 6.0以上动态授权的回调,用户自行实现。
281 | }
282 |
283 | }
284 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/mini/ActivityMiniUnit.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.mini;
2 |
3 | import android.Manifest;
4 | import android.content.pm.PackageManager;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.os.Message;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.Button;
11 | import android.widget.TextView;
12 |
13 | import androidx.appcompat.app.AppCompatActivity;
14 | import androidx.core.app.ActivityCompat;
15 | import androidx.core.content.ContextCompat;
16 |
17 | import com.baidu.aip.asrwakeup3.core.R;
18 | import com.baidu.speech.EventListener;
19 | import com.baidu.speech.EventManager;
20 | import com.baidu.speech.EventManagerFactory;
21 | import com.baidu.speech.asr.SpeechConstant;
22 | import org.json.JSONArray;
23 | import org.json.JSONException;
24 | import org.json.JSONObject;
25 |
26 | import java.util.ArrayList;
27 | import java.util.LinkedHashMap;
28 | import java.util.Map;
29 |
30 | /**
31 | * 集成文档: http://ai.baidu.com/docs#/ASR-Android-SDK/top 集成指南一节
32 | * demo目录下doc_integration_DOCUMENT
33 | * ASR-INTEGRATION-helloworld ASR集成指南-集成到helloworld中 对应 ActivityMiniRecog
34 | * ASR-INTEGRATION-TTS-DEMO ASR集成指南-集成到合成DEMO中 对应 ActivityRecog
35 | */
36 |
37 | public class ActivityMiniUnit extends AppCompatActivity implements EventListener {
38 | protected TextView txtLog;
39 | protected TextView txtResult;
40 | protected Button btn;
41 | protected Button stopBtn;
42 | private static String DESC_TEXT =
43 | "UNIT 2.0为自定义语义解析+多轮会话等功能。语音SDK使用时,仅省去一次http请求。(语音SDK调用Unit实际效果)=(语音识别后的文字+Unit http请求结果)\n\n"+
44 | "精简版Unit,带有SDKUnit功能的最少代码,仅仅展示如何调用,\n" +
45 | "结果返回‘我不知道应该怎么答复您。’表示测试成功。 \n" +
46 | "上述句子测试成功后,Unit 2.0具体功能请通过Unit的QQ群,工单,论坛咨询。语音相关反馈方式不回复Unit相关问题。https://ai.baidu.com/unit/home";
47 |
48 | private EventManager asr;
49 |
50 | private boolean logTime = true;
51 |
52 | protected boolean enableOffline = false; // 测试Unit 2.0 功能,必须一直联网
53 |
54 | private String BOT_ID = "26435"; // 修改你自己的AppId AppKey AppSecret后,换成你自己的BOT_ID测试
55 |
56 | /**
57 | * 基于SDK集成2.2 发送开始事件
58 | * 点击开始按钮
59 | * 测试参数填在这里
60 | */
61 | private void start() {
62 | txtLog.setText("");
63 | Map params = new LinkedHashMap();
64 | String event = null;
65 | event = SpeechConstant.ASR_START; // 替换成测试的event
66 |
67 | if (enableOffline) {
68 | params.put(SpeechConstant.DECODER, 2);
69 | }
70 | // 基于SDK集成2.1 设置识别参数
71 | params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
72 | params.put(SpeechConstant.PID, 15374); // 或 19364 Unit 2.0 固定pid,仅支持中文普通话
73 | // params.put(SpeechConstant.NLU, "enable");
74 | // params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 0); // 长语音
75 | // params.put(SpeechConstant.IN_FILE, "res:///com/baidu/android/voicedemo/16k_test.pcm");
76 | // params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN);
77 |
78 | // 请先使用如‘在线识别’界面测试和生成识别参数。 params同ActivityRecog类中myRecognizer.start(params);
79 | params.put(SpeechConstant.BOT_SESSION_LIST, unitParams());
80 | // 复制此段可以自动检测错误
81 | (new AutoCheck(getApplicationContext(), new Handler() {
82 | public void handleMessage(Message msg) {
83 | if (msg.what == 100) {
84 | AutoCheck autoCheck = (AutoCheck) msg.obj;
85 | synchronized (autoCheck) {
86 | String message = autoCheck.obtainErrorMessage(); // autoCheck.obtainAllMessage();
87 | txtLog.append(message + "\n");
88 | ; // 可以用下面一行替代,在logcat中查看代码
89 | // Log.w("AutoCheckMessage", message);
90 | }
91 | }
92 | }
93 | },enableOffline)).checkAsr(params);
94 | String json = null; // 可以替换成自己的json
95 | json = new JSONObject(params).toString(); // 这里可以替换成你需要测试的json
96 | asr.send(event, json, null, 0, 0);
97 | printLog("输入参数:" + json);
98 | }
99 |
100 | /**
101 | * 点击停止按钮
102 | * 基于SDK集成4.1 发送停止事件
103 | */
104 | private void stop() {
105 | printLog("停止识别:ASR_STOP");
106 | asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); //
107 | }
108 |
109 |
110 | /**
111 | * enableOffline设为true时,在onCreate中调用
112 | * 基于SDK离线命令词1.4 加载离线资源(离线时使用)
113 | */
114 | private void loadOfflineEngine() {
115 | Map params = new LinkedHashMap();
116 | params.put(SpeechConstant.DECODER, 2);
117 | params.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets://baidu_speech_grammar.bsg");
118 | asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, new JSONObject(params).toString(), null, 0, 0);
119 | }
120 |
121 | /**
122 | * enableOffline为true时,在onDestory中调用,与loadOfflineEngine对应
123 | * 基于SDK集成5.1 卸载离线资源步骤(离线时使用)
124 | */
125 | private void unloadOfflineEngine() {
126 | asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0); //
127 | }
128 |
129 | @Override
130 | protected void onCreate(Bundle savedInstanceState) {
131 | super.onCreate(savedInstanceState);
132 | setContentView(R.layout.common_mini);
133 | initView();
134 | initPermission();
135 | // 基于sdk集成1.1 初始化EventManager对象
136 | asr = EventManagerFactory.create(this, "asr");
137 | // 基于sdk集成1.3 注册自己的输出事件类
138 | asr.registerListener(this); // EventListener 中 onEvent方法
139 | btn.setOnClickListener(new View.OnClickListener() {
140 |
141 | @Override
142 | public void onClick(View v) {
143 | start();
144 | }
145 | });
146 | stopBtn.setOnClickListener(new View.OnClickListener() {
147 |
148 | @Override
149 | public void onClick(View v) {
150 | stop();
151 | }
152 | });
153 | if (enableOffline) {
154 | loadOfflineEngine(); // 测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
155 | }
156 | }
157 |
158 | @Override
159 | protected void onPause(){
160 | super.onPause();
161 | asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
162 | Log.i("ActivityMiniRecog","On pause");
163 | }
164 |
165 | @Override
166 | protected void onDestroy() {
167 | super.onDestroy();
168 | // 基于SDK集成4.2 发送取消事件
169 | asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
170 | if (enableOffline) {
171 | unloadOfflineEngine(); // 测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
172 | }
173 |
174 | // 基于SDK集成5.2 退出事件管理器
175 | // 必须与registerListener成对出现,否则可能造成内存泄露
176 | asr.unregisterListener(this);
177 | }
178 |
179 | /**
180 | * Unit 2.0具体功能请通过Unit的QQ群,工单,论坛咨询。语音相关反馈方式不回复Unit相关问题
181 | * @return
182 | */
183 | private JSONArray unitParams() {
184 | JSONArray json = new JSONArray();
185 | try {
186 | JSONObject bot = new JSONObject();
187 | bot.put("bot_id",BOT_ID);
188 | bot.put("bot_session_id","");
189 | bot.put("bot_session","");
190 | json.put(bot);
191 | } catch (JSONException e) {
192 | e.printStackTrace();
193 | }
194 | return json;
195 | }
196 |
197 | // 基于sdk集成1.2 自定义输出事件类 EventListener 回调方法
198 | // 基于SDK集成3.1 开始回调事件
199 | @Override
200 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
201 | String logTxt = "name: " + name;
202 |
203 |
204 | if (params != null && !params.isEmpty()) {
205 | logTxt += " ;params :" + params;
206 | }
207 | if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
208 | if (params != null && params.contains("\"nlu_result\"")) {
209 | if (length > 0 && data.length > 0) {
210 | logTxt += ", 语义解析结果:" + new String(data, offset, length);
211 | }
212 | }
213 | } else if (data != null) {
214 | logTxt += " ;data length=" + data.length;
215 | }
216 | printLog(logTxt);
217 | }
218 |
219 | private void printLog(String text) {
220 | if (logTime) {
221 | text += " ;time=" + System.currentTimeMillis();
222 | }
223 | text += "\n";
224 | Log.i(getClass().getName(), text);
225 | txtLog.append(text + "\n");
226 | }
227 |
228 |
229 | private void initView() {
230 | txtResult = (TextView) findViewById(R.id.txtResult);
231 | txtLog = (TextView) findViewById(R.id.txtLog);
232 | btn = (Button) findViewById(R.id.btn);
233 | stopBtn = (Button) findViewById(R.id.btn_stop);
234 | txtLog.setText(DESC_TEXT + "\n");
235 | }
236 |
237 | /**
238 | * android 6.0 以上需要动态申请权限
239 | */
240 | private void initPermission() {
241 | String permissions[] = {Manifest.permission.RECORD_AUDIO,
242 | Manifest.permission.ACCESS_NETWORK_STATE,
243 | Manifest.permission.INTERNET,
244 | Manifest.permission.WRITE_EXTERNAL_STORAGE
245 | };
246 |
247 | ArrayList toApplyList = new ArrayList();
248 |
249 | for (String perm : permissions) {
250 | if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
251 | toApplyList.add(perm);
252 | // 进入到这里代表没有权限.
253 |
254 | }
255 | }
256 | String tmpList[] = new String[toApplyList.size()];
257 | if (!toApplyList.isEmpty()) {
258 | ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
259 | }
260 |
261 | }
262 |
263 | @Override
264 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
265 | // 此处为android 6.0以上动态授权的回调,用户自行实现。
266 | }
267 |
268 | }
269 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/mini/ActivityMiniWakeUp.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.mini;
2 |
3 | import android.Manifest;
4 | import android.content.pm.PackageManager;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.TextView;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 | import androidx.core.app.ActivityCompat;
13 | import androidx.core.content.ContextCompat;
14 |
15 | import com.baidu.aip.asrwakeup3.core.R;
16 | import com.baidu.aip.asrwakeup3.core.inputstream.InFileStream;
17 | import com.baidu.speech.EventListener;
18 | import com.baidu.speech.EventManager;
19 | import com.baidu.speech.EventManagerFactory;
20 | import com.baidu.speech.asr.SpeechConstant;
21 | import org.json.JSONObject;
22 |
23 | import java.util.ArrayList;
24 | import java.util.Map;
25 | import java.util.TreeMap;
26 |
27 | /**
28 | * Created by fujiayi on 2017/8/15.
29 | */
30 |
31 | public class ActivityMiniWakeUp extends AppCompatActivity implements EventListener {
32 | protected TextView txtLog;
33 | protected TextView txtResult;
34 | protected Button btn;
35 | protected Button stopBtn;
36 | private static String DESC_TEXT = "精简版唤醒,带有SDK唤醒运行的最少代码,仅仅展示如何调用,\n" +
37 | "也可以用来反馈测试SDK输入参数及输出回调。\n" +
38 | "本示例需要自行根据文档填写参数,可以使用之前唤醒示例中的日志中的参数。\n" +
39 | "需要完整版请参见之前的唤醒示例。\n\n" +
40 | "唤醒词是纯离线功能,需要获取正式授权文件(与离线命令词的正式授权文件是同一个)。 第一次联网使用唤醒词功能自动获取正式授权文件。之后可以断网测试\n" +
41 | "请说“小度你好”或者 “百度一下”\n\n";
42 |
43 | private EventManager wakeup;
44 |
45 | private boolean logTime = true;
46 |
47 | /**
48 | * 测试参数填在这里
49 | * 基于SDK唤醒词集成第2.1 设置唤醒的输入参数
50 | */
51 | private void start() {
52 | txtLog.setText("");
53 | // 基于SDK唤醒词集成第2.1 设置唤醒的输入参数
54 | Map params = new TreeMap();
55 | params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
56 | params.put(SpeechConstant.WP_WORDS_FILE, "assets:///WakeUp.bin");
57 | // "assets:///WakeUp.bin" 表示WakeUp.bin文件定义在assets目录下
58 | InFileStream.setContext(this);
59 | String json = null; // 这里可以替换成你需要测试的json
60 | json = new JSONObject(params).toString();
61 | wakeup.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);
62 | printLog("输入参数:" + json);
63 | }
64 |
65 | // 基于SDK唤醒词集成第4.1 发送停止事件
66 | private void stop() {
67 | wakeup.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0); //
68 | }
69 |
70 |
71 | @Override
72 | protected void onCreate(Bundle savedInstanceState) {
73 | super.onCreate(savedInstanceState);
74 | setContentView(R.layout.common_mini);
75 | initView();
76 | initPermission();
77 | // 基于SDK唤醒词集成1.1 初始化EventManager
78 | wakeup = EventManagerFactory.create(this, "wp");
79 | // 基于SDK唤醒词集成1.3 注册输出事件
80 | wakeup.registerListener(this); // EventListener 中 onEvent方法
81 | btn.setOnClickListener(new View.OnClickListener() {
82 |
83 | @Override
84 | public void onClick(View v) {
85 | start();
86 | }
87 | });
88 | stopBtn.setOnClickListener(new View.OnClickListener() {
89 |
90 | @Override
91 | public void onClick(View v) {
92 | stop();
93 | }
94 | });
95 | }
96 |
97 | @Override
98 | protected void onDestroy() {
99 | super.onDestroy();
100 | wakeup.send(SpeechConstant.WAKEUP_STOP, "{}", null, 0, 0);
101 | }
102 |
103 | // 基于SDK唤醒词集成1.2 自定义输出事件类 EventListener 回调方法
104 | // 基于SDK唤醒3.1 开始回调事件
105 | @Override
106 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
107 | String logTxt = "name: " + name;
108 | if (params != null && !params.isEmpty()) {
109 | logTxt += " ;params :" + params;
110 | } else if (data != null) {
111 | logTxt += " ;data length=" + data.length;
112 | }
113 | printLog(logTxt);
114 | }
115 |
116 | private void printLog(String text) {
117 | if (logTime) {
118 | text += " ;time=" + System.currentTimeMillis();
119 | }
120 | text += "\n";
121 | Log.i(getClass().getName(), text);
122 | txtLog.append(text + "\n");
123 | }
124 |
125 |
126 | private void initView() {
127 | txtResult = (TextView) findViewById(R.id.txtResult);
128 | txtLog = (TextView) findViewById(R.id.txtLog);
129 | btn = (Button) findViewById(R.id.btn);
130 | stopBtn = (Button) findViewById(R.id.btn_stop);
131 | txtLog.setText(DESC_TEXT + "\n");
132 | }
133 |
134 | /**
135 | * android 6.0 以上需要动态申请权限
136 | */
137 | private void initPermission() {
138 | String[] permissions = {Manifest.permission.RECORD_AUDIO,
139 | Manifest.permission.ACCESS_NETWORK_STATE,
140 | Manifest.permission.INTERNET,
141 | Manifest.permission.WRITE_EXTERNAL_STORAGE
142 | };
143 |
144 | ArrayList toApplyList = new ArrayList();
145 |
146 | for (String perm : permissions) {
147 | if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
148 | toApplyList.add(perm);
149 | // 进入到这里代表没有权限.
150 |
151 | }
152 | }
153 | String[] tmpList = new String[toApplyList.size()];
154 | if (!toApplyList.isEmpty()) {
155 | ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
156 | }
157 |
158 | }
159 |
160 | @Override
161 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
162 | // 此处为android 6.0以上动态授权的回调,用户自行实现。
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/mini/AutoCheck.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.mini;
2 |
3 | import android.Manifest;
4 | import android.content.Context;
5 | import android.content.pm.PackageManager;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.os.Message;
9 | import android.util.Log;
10 |
11 | import androidx.core.content.ContextCompat;
12 |
13 | import com.baidu.speech.asr.SpeechConstant;
14 | import org.json.JSONObject;
15 |
16 | import java.io.BufferedReader;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.InputStreamReader;
21 | import java.net.URL;
22 | import java.net.UnknownHostException;
23 | import java.util.ArrayList;
24 | import java.util.HashMap;
25 | import java.util.LinkedHashMap;
26 | import java.util.Map;
27 | import java.util.TreeSet;
28 |
29 | import javax.net.ssl.HttpsURLConnection;
30 |
31 | public class AutoCheck {
32 | public static final boolean isOnlineLited = false; // 是否只需要是纯在线识别功能
33 | private LinkedHashMap checks;
34 |
35 | private Context context;
36 | private Handler handler;
37 |
38 | private boolean hasError;
39 | private boolean enableOffline;
40 | private boolean isFinished = false;
41 |
42 | private String name;
43 |
44 | private static final String TAG = "AutoCheck";
45 |
46 | public AutoCheck(Context context, final Handler handler, boolean enableOffline) {
47 | this.context = context;
48 | checks = new LinkedHashMap<>();
49 | this.handler = handler;
50 | this.enableOffline = enableOffline;
51 | }
52 |
53 | public void checkAsr(final Map params) {
54 | Thread t = new Thread(new Runnable() {
55 | @Override
56 | public void run() {
57 | AutoCheck obj = checkAsrInternal(params);
58 | name = "识别";
59 | synchronized (obj) { // 偶发,同步线程信息
60 | isFinished = true;
61 | Message msg = handler.obtainMessage(100, obj);
62 | handler.sendMessage(msg);
63 | }
64 | }
65 | });
66 | t.start();
67 | }
68 |
69 | public String obtainErrorMessage() {
70 | PrintConfig config = new PrintConfig();
71 | return formatString(config);
72 | }
73 |
74 | public String obtainDebugMessage() {
75 | PrintConfig config = new PrintConfig();
76 | config.withInfo = true;
77 | return formatString(config);
78 | }
79 |
80 | public String obtainAllMessage() {
81 | PrintConfig config = new PrintConfig();
82 | config.withLog = true;
83 | config.withInfo = true;
84 | config.withLogOnSuccess = true;
85 | return formatString(config);
86 | }
87 |
88 | private String formatString(PrintConfig config) {
89 | StringBuilder sb = new StringBuilder();
90 | hasError = false;
91 |
92 | for (HashMap.Entry entry : checks.entrySet()) {
93 | Check check = entry.getValue();
94 | String testName = entry.getKey();
95 | if (check.hasError()) {
96 | if (!hasError) {
97 | hasError = true;
98 | }
99 |
100 | sb.append("【错误】【").append(testName).append(" 】 ").append(check.getErrorMessage()).append("\n");
101 | Log.e("AutoCheck", sb.toString());
102 | if (check.hasFix()) {
103 | sb.append("【修复方法】【").append(testName).append(" 】 ").append(check.getFixMessage()).append("\n");
104 | }
105 | } else if (config.withEachCheckInfo) {
106 | sb.append("【无报错】【").append(testName).append(" 】 ").append("\n");
107 | }
108 | if (config.withInfo && check.hasInfo()) {
109 | sb.append("【请手动检查】【").append(testName).append("】 ").append(check.getInfoMessage()).append("\n");
110 | }
111 | if (config.withLog && (config.withLogOnSuccess || hasError) && check.hasLog()) {
112 | sb.append("【log】:" + check.getLogMessage()).append("\n");
113 | }
114 | }
115 | if (!hasError) {
116 | sb.append("【" + name + "】集成自动排查工具: 恭喜没有检测到任何问题\n");
117 | }
118 | return sb.toString();
119 | }
120 |
121 | private AutoCheck checkAsrInternal(Map params) {
122 | commonSetting(params);
123 | checks.put("外部音频文件存在校验", new FileCheck(context, params, SpeechConstant.IN_FILE));
124 | checks.put("离线命令词及本地语义bsg文件存在校验",
125 | new FileCheck(context, params, SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH));
126 | for (Map.Entry e : checks.entrySet()) {
127 | Check check = e.getValue();
128 | check.check();
129 | if (check.hasError()) {
130 | break;
131 | }
132 | }
133 | return this;
134 | }
135 |
136 | private void commonSetting(Map params) {
137 | checks.put("检查申请的Android权限", new PermissionCheck(context));
138 | checks.put("检查so文件是否存在", new JniCheck(context));
139 | AppInfoCheck infoCheck = null;
140 | try {
141 | infoCheck = new AppInfoCheck(context, params);
142 | checks.put("检查AppId AppKey SecretKey", infoCheck);
143 | } catch (PackageManager.NameNotFoundException e) {
144 | e.printStackTrace();
145 | Log.e(TAG, "检查AppId AppKey SecretKey 错误", e);
146 | return;
147 | }
148 | if (enableOffline) {
149 | checks.put("检查包名", new ApplicationIdCheck(context, infoCheck.appId));
150 | }
151 |
152 | }
153 |
154 | private static class PrintConfig {
155 | public boolean withEachCheckInfo = false;
156 | public boolean withInfo = false;
157 | public boolean withLog = false;
158 | public boolean withLogOnSuccess = false;
159 | }
160 |
161 |
162 | private static class PermissionCheck extends Check {
163 | private Context context;
164 |
165 | public PermissionCheck(Context context) {
166 | this.context = context;
167 | }
168 |
169 | @Override
170 | public void check() {
171 | String[] permissions = {
172 | Manifest.permission.RECORD_AUDIO,
173 | Manifest.permission.ACCESS_NETWORK_STATE,
174 | Manifest.permission.INTERNET,
175 | // Manifest.permission.WRITE_EXTERNAL_STORAGE,
176 | };
177 |
178 | ArrayList toApplyList = new ArrayList();
179 | for (String perm : permissions) {
180 | if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(context, perm)) {
181 | toApplyList.add(perm);
182 | // 进入到这里代表没有权限.
183 | }
184 | }
185 | if (!toApplyList.isEmpty()) {
186 | errorMessage = "缺少权限:" + toApplyList;
187 | fixMessage = "请从AndroidManifest.xml复制相关权限";
188 | }
189 | }
190 | }
191 |
192 | private static class JniCheck extends Check {
193 | private Context context;
194 |
195 | private String[] soNames;
196 |
197 | public JniCheck(Context context) {
198 | this.context = context;
199 | if (isOnlineLited) {
200 | soNames = new String[]{"libBaiduSpeechSDK.so", "libvad.dnn.so"};
201 | } else {
202 | soNames = new String[]{"libBaiduSpeechSDK.so", "libvad.dnn.so",
203 | "libbd_easr_s1_merge_normal_20151216.dat.so", "libbdEASRAndroid.so",
204 | "libbdSpilWakeup.so"};
205 | }
206 | }
207 |
208 | @Override
209 | public void check() {
210 | String path = context.getApplicationInfo().nativeLibraryDir;
211 | appendLogMessage("Jni so文件目录 " + path);
212 | File[] files = new File(path).listFiles();
213 | TreeSet set = new TreeSet<>();
214 | if (files != null) {
215 | for (File file : files) {
216 | set.add(file.getName());
217 | }
218 | }
219 | // String debugMessage = "Jni目录内文件: " + set.toString();
220 | // boolean isSuccess = true;
221 | for (String name : soNames) {
222 | if (!set.contains(name)) {
223 | errorMessage = "Jni目录" + path + " 缺少so文件:" + name + ", 该目录文件列表: " + set.toString();
224 | fixMessage = "如果您的app内没有其它so文件,请复制demo里的src/main/jniLibs至同名目录。"
225 | + " 如果app内有so文件,请合并目录放一起(注意目录取交集,多余的目录删除)。";
226 | break;
227 | }
228 | }
229 | }
230 | }
231 |
232 | private static class AppInfoCheck extends Check {
233 | private String appId;
234 | private String appKey;
235 | private String secretKey;
236 |
237 | public AppInfoCheck(Context context, Map params) throws PackageManager.NameNotFoundException {
238 | Bundle metaData = context.getPackageManager().getApplicationInfo(context.getPackageName(),
239 | PackageManager.GET_META_DATA).metaData;
240 | if (params.get(SpeechConstant.APP_ID) != null) {
241 | appId = params.get(SpeechConstant.APP_ID).toString();
242 | } else {
243 | int id = metaData.getInt("com.baidu.speech.APP_ID", 0);
244 | if (id > 0) {
245 | appId = "" + id;
246 | }
247 | }
248 | if (params.get(SpeechConstant.APP_KEY) != null) {
249 | appKey = params.get(SpeechConstant.APP_KEY).toString();
250 | } else {
251 | appKey = metaData.getString("com.baidu.speech.API_KEY", "");
252 | }
253 |
254 | if (params.get(SpeechConstant.SECRET) != null) {
255 | secretKey = params.get(SpeechConstant.SECRET).toString();
256 | } else {
257 | secretKey = metaData.getString("com.baidu.speech.SECRET_KEY", "");
258 | }
259 | }
260 |
261 |
262 | public void check() {
263 | do {
264 | appendLogMessage("try to check appId " + appId + " ,appKey=" + appKey + " ,secretKey" + secretKey);
265 | if (appId == null || appId.isEmpty()) {
266 | errorMessage = "appId 为空";
267 | fixMessage = "填写appID";
268 | break;
269 | }
270 | if (appKey == null || appKey.isEmpty()) {
271 | errorMessage = "appKey 为空";
272 | fixMessage = "填写appID";
273 | break;
274 | }
275 | if (secretKey == null || secretKey.isEmpty()) {
276 | errorMessage = "secretKey 为空";
277 | fixMessage = "secretKey";
278 | break;
279 | }
280 |
281 |
282 | try {
283 | checkOnline();
284 | } catch (UnknownHostException e) {
285 | infoMessage = "无网络或者网络不连通,忽略检测 : " + e.getMessage();
286 | } catch (Exception e) {
287 | errorMessage = e.getClass().getCanonicalName() + ":" + e.getMessage();
288 | fixMessage = " 重新检测appId, appKey, appSecret是否正确";
289 | }
290 | } while (false);
291 | }
292 |
293 | public void checkOnline() throws Exception {
294 | String urlpath = "https://openapi.baidu.com/oauth/2.0/token?client_id="
295 | + appKey + "&client_secret=" + secretKey + "&grant_type=client_credentials";
296 | Log.i("AutoCheck", "Url is " + urlpath);
297 | URL url = new URL(urlpath);
298 | HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
299 | conn.setRequestMethod("GET");
300 | conn.setConnectTimeout(1000);
301 | InputStream is = conn.getInputStream();
302 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
303 | StringBuilder result = new StringBuilder();
304 | String line = "";
305 | do {
306 | line = reader.readLine();
307 | if (line != null) {
308 | result.append(line);
309 | }
310 | } while (line != null);
311 | String res = result.toString();
312 | if (!res.contains("audio_voice_assistant_get")) {
313 | errorMessage = "appid:" + appId + ",没有audio_voice_assistant_get 权限,请在网页上开通\"语音识别\"能力";
314 | fixMessage = "secretKey";
315 | return;
316 | }
317 | appendLogMessage("openapi return " + res);
318 | JSONObject jsonObject = new JSONObject(res);
319 | String error = jsonObject.optString("error");
320 | if (error != null && !error.isEmpty()) {
321 | errorMessage = "appkey secretKey 错误" + ", error:" + error + ", json is" + result;
322 | fixMessage = " 重新检测appId对应的 appKey, appSecret是否正确";
323 | return;
324 | }
325 | String token = jsonObject.getString("access_token");
326 | if (token == null || !token.endsWith("-" + appId)) {
327 | errorMessage = "appId 与 appkey及 appSecret 不一致。appId = " + appId + " ,token = " + token;
328 | fixMessage = " 重新检测appId对应的 appKey, appSecret是否正确";
329 | }
330 | }
331 | }
332 |
333 | private static class ApplicationIdCheck extends Check {
334 |
335 | private String appId;
336 | private Context context;
337 |
338 | public ApplicationIdCheck(Context context, String appId) {
339 | this.appId = appId;
340 | this.context = context;
341 | }
342 |
343 | @Override
344 | public void check() {
345 | infoMessage = "如果您集成过程中遇见离线命令词或者唤醒初始化问题,请检查网页上appId:" + appId
346 | + " 应用填写了Android包名:"
347 | + getApplicationId();
348 | }
349 |
350 | private String getApplicationId() {
351 | return context.getPackageName();
352 | }
353 | }
354 |
355 | private static class FileCheck extends Check {
356 | private Map params;
357 | private String key;
358 | private Context context;
359 | private boolean allowRes = false;
360 | private boolean allowAssets = true;
361 |
362 | public FileCheck(Context context, Map params, String key) {
363 | this.context = context;
364 | this.params = params;
365 | this.key = key;
366 | if (key.equals(SpeechConstant.IN_FILE)) {
367 | allowRes = true;
368 | allowAssets = false;
369 | }
370 | }
371 |
372 | @Override
373 | public void check() {
374 | if (!params.containsKey(key)) {
375 | return;
376 | }
377 | String value = params.get(key).toString();
378 | if (allowAssets) {
379 | int len = "assets".length();
380 | int totalLen = len + ":///".length();
381 | if (value.startsWith("assets")) {
382 | String filename = value.substring(totalLen);
383 | if (!":///".equals(value.substring(len, totalLen)) || filename.isEmpty()) {
384 | errorMessage = "参数:" + key + "格式错误:" + value;
385 | fixMessage = "修改成" + "assets:///sdcard/xxxx.yyy";
386 | }
387 | try {
388 | context.getAssets().open(filename);
389 | } catch (IOException e) {
390 | errorMessage = "assets 目录下,文件不存在:" + filename;
391 | fixMessage = "demo的assets目录是:src/main/assets";
392 | e.printStackTrace();
393 | }
394 | appendLogMessage("assets 检验完毕:" + filename);
395 | }
396 | }
397 | if (allowRes) {
398 | int len = "res".length();
399 | int totalLen = len + ":///".length();
400 | if (value.startsWith("res")) {
401 | String filename = value.substring(totalLen);
402 | if (!":///".equals(value.substring(len, totalLen)) || filename.isEmpty()) {
403 | errorMessage = "参数:" + key + "格式错误:" + value;
404 | fixMessage = "修改成" + "res:///com/baidu/android/voicedemo/16k_test.pcm";
405 | }
406 | InputStream is = getClass().getClassLoader().getResourceAsStream(filename);
407 | if (is == null) {
408 | errorMessage = "res,文件不存在:" + filename;
409 | fixMessage = "demo的res目录是:app/src/main/resources";
410 | } else {
411 | try {
412 | is.close();
413 | } catch (IOException e) {
414 | e.printStackTrace();
415 | }
416 | }
417 | appendLogMessage("res 检验完毕:" + filename);
418 | }
419 | }
420 | if (value.startsWith("/")) {
421 | if (!new File(value).canRead()) {
422 | errorMessage = "文件不存在:" + value;
423 | fixMessage = "请查看文件是否存在";
424 | }
425 | appendLogMessage("文件路径 检验完毕:" + value);
426 | }
427 | }
428 | }
429 |
430 | private abstract static class Check {
431 | protected String errorMessage = null;
432 |
433 | protected String fixMessage = null;
434 |
435 | protected String infoMessage = null;
436 |
437 | protected StringBuilder logMessage;
438 |
439 | public Check() {
440 | logMessage = new StringBuilder();
441 | }
442 |
443 | public abstract void check();
444 |
445 | public boolean hasError() {
446 | return errorMessage != null;
447 | }
448 |
449 | public boolean hasFix() {
450 | return fixMessage != null;
451 | }
452 |
453 | public boolean hasInfo() {
454 | return infoMessage != null;
455 | }
456 |
457 | public boolean hasLog() {
458 | return !logMessage.toString().isEmpty();
459 | }
460 |
461 | public void appendLogMessage(String message) {
462 | logMessage.append(message + "\n");
463 | }
464 |
465 | public String getErrorMessage() {
466 | return errorMessage;
467 | }
468 |
469 | public String getFixMessage() {
470 | return fixMessage;
471 | }
472 |
473 | public String getInfoMessage() {
474 | return infoMessage;
475 | }
476 |
477 | public String getLogMessage() {
478 | return logMessage.toString();
479 | }
480 | }
481 | }
482 |
483 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/IStatus.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog;
2 |
3 | /**
4 | * Created by fujiayi on 2017/6/14.
5 | */
6 |
7 | public interface IStatus {
8 |
9 | int STATUS_NONE = 2;
10 |
11 | int STATUS_READY = 3;
12 | int STATUS_SPEAKING = 4;
13 | int STATUS_RECOGNITION = 5;
14 |
15 | int STATUS_FINISHED = 6;
16 | int STATUS_LONG_SPEECH_FINISHED = 7;
17 | int STATUS_STOPPED = 10;
18 |
19 | int STATUS_WAITING_READY = 8001;
20 | int WHAT_MESSAGE_STATUS = 9001;
21 |
22 | int STATUS_WAKEUP_SUCCESS = 7001;
23 | int STATUS_WAKEUP_EXIT = 7003;
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/MyRecognizer.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog;
2 |
3 | import android.content.Context;
4 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
5 | import com.baidu.speech.EventListener;
6 | import com.baidu.speech.EventManager;
7 | import com.baidu.speech.EventManagerFactory;
8 | import com.baidu.speech.asr.SpeechConstant;
9 | import org.json.JSONObject;
10 | import com.baidu.aip.asrwakeup3.core.recog.listener.IRecogListener;
11 | import com.baidu.aip.asrwakeup3.core.recog.listener.RecogEventAdapter;
12 |
13 | import java.util.Map;
14 |
15 | /**
16 | * Created by fujiayi on 2017/6/13.
17 | * EventManager内的方法如send 都可以在主线程中进行,SDK中做过处理
18 | */
19 |
20 | public class MyRecognizer {
21 | /**
22 | * SDK 内部核心 EventManager 类
23 | */
24 | private EventManager asr;
25 |
26 | // SDK 内部核心 事件回调类, 用于开发者写自己的识别回调逻辑
27 | private EventListener eventListener;
28 |
29 | // 是否加载离线资源
30 | private static boolean isOfflineEngineLoaded = false;
31 |
32 | // 未release前,只能new一个
33 | private static volatile boolean isInited = false;
34 |
35 | private static final String TAG = "MyRecognizer";
36 |
37 | /**
38 | * 初始化
39 | *
40 | * @param context
41 | * @param recogListener 将EventListener结果做解析的DEMO回调。使用RecogEventAdapter 适配EventListener
42 | */
43 | public MyRecognizer(Context context, IRecogListener recogListener) {
44 | this(context, new RecogEventAdapter(recogListener));
45 | }
46 |
47 | /**
48 | * 初始化 提供 EventManagerFactory需要的Context和EventListener
49 | *
50 | * @param context
51 | * @param eventListener 识别状态和结果回调
52 | */
53 | public MyRecognizer(Context context, EventListener eventListener) {
54 | if (isInited) {
55 | MyLogger.error(TAG, "还未调用release(),请勿新建一个新类");
56 | throw new RuntimeException("还未调用release(),请勿新建一个新类");
57 | }
58 | isInited = true;
59 | this.eventListener = eventListener;
60 | // SDK集成步骤 初始化asr的EventManager示例,多次得到的类,只能选一个使用
61 | asr = EventManagerFactory.create(context, "asr");
62 | // SDK集成步骤 设置回调event, 识别引擎会回调这个类告知重要状态和识别结果
63 | asr.registerListener(eventListener);
64 | }
65 |
66 |
67 | /**
68 | * 离线命令词,在线不需要调用
69 | *
70 | * @param params 离线命令词加载参数,见文档“ASR_KWS_LOAD_ENGINE 输入事件参数”
71 | */
72 | public void loadOfflineEngine(Map params) {
73 | String json = new JSONObject(params).toString();
74 | MyLogger.info(TAG + ".Debug", "离线命令词初始化参数(反馈请带上此行日志):" + json);
75 | // SDK集成步骤(可选)加载离线命令词(离线时使用)
76 | asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, json, null, 0, 0);
77 | isOfflineEngineLoaded = true;
78 | }
79 |
80 | /**
81 | * @param params
82 | */
83 | public void start(Map params) {
84 | if (!isInited) {
85 | throw new RuntimeException("release() was called");
86 | }
87 | // SDK集成步骤 拼接识别参数
88 | String json = new JSONObject(params).toString();
89 | MyLogger.info(TAG + ".Debug", "识别参数(反馈请带上此行日志)" + json);
90 | asr.send(SpeechConstant.ASR_START, json, null, 0, 0);
91 | }
92 |
93 |
94 | /**
95 | * 提前结束录音等待识别结果。
96 | */
97 | public void stop() {
98 | MyLogger.info(TAG, "停止录音");
99 | // SDK 集成步骤(可选)停止录音
100 | if (!isInited) {
101 | throw new RuntimeException("release() was called");
102 | }
103 | asr.send(SpeechConstant.ASR_STOP, "{}", null, 0, 0);
104 | }
105 |
106 | /**
107 | * 取消本次识别,取消后将立即停止不会返回识别结果。
108 | * cancel 与stop的区别是 cancel在stop的基础上,完全停止整个识别流程,
109 | */
110 | public void cancel() {
111 | MyLogger.info(TAG, "取消识别");
112 | if (!isInited) {
113 | throw new RuntimeException("release() was called");
114 | }
115 | // SDK集成步骤 (可选) 取消本次识别
116 | asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
117 | }
118 |
119 | public void release() {
120 | if (asr == null) {
121 | return;
122 | }
123 | cancel();
124 | if (isOfflineEngineLoaded) {
125 | // SDK集成步骤 如果之前有调用过 加载离线命令词,这里要对应释放
126 | asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0);
127 | isOfflineEngineLoaded = false;
128 | }
129 | // SDK 集成步骤(可选),卸载listener
130 | asr.unregisterListener(eventListener);
131 | asr = null;
132 | isInited = false;
133 | }
134 |
135 | public void setEventListener(IRecogListener recogListener) {
136 | if (!isInited) {
137 | throw new RuntimeException("release() was called");
138 | }
139 | this.eventListener = new RecogEventAdapter(recogListener);
140 | asr.registerListener(eventListener);
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/RecogResult.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONException;
5 | import org.json.JSONObject;
6 |
7 | /**
8 | * Created by fujiayi on 2017/6/24.
9 | */
10 | public class RecogResult {
11 | private static final int ERROR_NONE = 0;
12 |
13 | private String origalJson;
14 | private String[] resultsRecognition;
15 | private String origalResult;
16 | private String sn; // 日志id, 请求有问题请提问带上sn
17 | private String desc;
18 | private String resultType;
19 | private int error = -1;
20 | private int subError = -1;
21 |
22 | public static RecogResult parseJson(String jsonStr) {
23 | RecogResult result = new RecogResult();
24 | result.setOrigalJson(jsonStr);
25 | try {
26 | JSONObject json = new JSONObject(jsonStr);
27 | int error = json.optInt("error");
28 | int subError = json.optInt("sub_error");
29 | result.setError(error);
30 | result.setDesc(json.optString("desc"));
31 | result.setResultType(json.optString("result_type"));
32 | result.setSubError(subError);
33 | if (error == ERROR_NONE) {
34 | result.setOrigalResult(json.getString("origin_result"));
35 | JSONArray arr = json.optJSONArray("results_recognition");
36 | if (arr != null) {
37 | int size = arr.length();
38 | String[] recogs = new String[size];
39 | for (int i = 0; i < size; i++) {
40 | recogs[i] = arr.getString(i);
41 | }
42 | result.setResultsRecognition(recogs);
43 | }
44 |
45 |
46 | }
47 | } catch (JSONException e) {
48 | e.printStackTrace();
49 | }
50 |
51 | return result;
52 | }
53 |
54 | public boolean hasError() {
55 | return error != ERROR_NONE;
56 | }
57 |
58 | public boolean isFinalResult() {
59 | return "final_result".equals(resultType);
60 | }
61 |
62 |
63 | public boolean isPartialResult() {
64 | return "partial_result".equals(resultType);
65 | }
66 |
67 | public boolean isNluResult() {
68 | return "nlu_result".equals(resultType);
69 | }
70 |
71 | public String getOrigalJson() {
72 | return origalJson;
73 | }
74 |
75 | public void setOrigalJson(String origalJson) {
76 | this.origalJson = origalJson;
77 | }
78 |
79 | public String[] getResultsRecognition() {
80 | return resultsRecognition;
81 | }
82 |
83 | public void setResultsRecognition(String[] resultsRecognition) {
84 | this.resultsRecognition = resultsRecognition;
85 | }
86 |
87 | public String getSn() {
88 | return sn;
89 | }
90 |
91 | public void setSn(String sn) {
92 | this.sn = sn;
93 | }
94 |
95 | public int getError() {
96 | return error;
97 | }
98 |
99 | public void setError(int error) {
100 | this.error = error;
101 | }
102 |
103 | public String getDesc() {
104 | return desc;
105 | }
106 |
107 | public void setDesc(String desc) {
108 | this.desc = desc;
109 | }
110 |
111 | public String getOrigalResult() {
112 | return origalResult;
113 | }
114 |
115 | public void setOrigalResult(String origalResult) {
116 | this.origalResult = origalResult;
117 | }
118 |
119 | public String getResultType() {
120 | return resultType;
121 | }
122 |
123 | public void setResultType(String resultType) {
124 | this.resultType = resultType;
125 | }
126 |
127 | public int getSubError() {
128 | return subError;
129 | }
130 |
131 | public void setSubError(int subError) {
132 | this.subError = subError;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/listener/ChainRecogListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog.listener;
2 |
3 |
4 | import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
5 |
6 | import java.util.ArrayList;
7 |
8 | /**
9 | * Created by fujiayi on 2017/10/18.
10 | */
11 |
12 | public class ChainRecogListener implements IRecogListener {
13 |
14 | private ArrayList listeners;
15 |
16 | public ChainRecogListener() {
17 | listeners = new ArrayList();
18 | }
19 |
20 | public void addListener(IRecogListener listener) {
21 | listeners.add(listener);
22 | }
23 |
24 | /**
25 | * ASR_START 输入事件调用后,引擎准备完毕
26 | */
27 | @Override
28 | public void onAsrReady() {
29 | for (IRecogListener listener : listeners) {
30 | listener.onAsrReady();
31 | }
32 | }
33 |
34 | /**
35 | * onAsrReady后检查到用户开始说话
36 | */
37 | @Override
38 | public void onAsrBegin() {
39 | for (IRecogListener listener : listeners) {
40 | listener.onAsrBegin();
41 | }
42 | }
43 |
44 | /**
45 | * 检查到用户开始说话停止,或者ASR_STOP 输入事件调用后,
46 | */
47 | @Override
48 | public void onAsrEnd() {
49 | for (IRecogListener listener : listeners) {
50 | listener.onAsrEnd();
51 | }
52 | }
53 |
54 | /**
55 | * onAsrBegin 后 随着用户的说话,返回的临时结果
56 | *
57 | * @param results 可能返回多个结果,请取第一个结果
58 | * @param recogResult 完整的结果
59 | */
60 | @Override
61 | public void onAsrPartialResult(String[] results, RecogResult recogResult) {
62 | for (IRecogListener listener : listeners) {
63 | listener.onAsrPartialResult(results, recogResult);
64 | }
65 | }
66 |
67 | /**
68 | * 最终的识别结果
69 | *
70 | * @param results 可能返回多个结果,请取第一个结果
71 | * @param recogResult 完整的结果
72 | */
73 | @Override
74 | public void onAsrFinalResult(String[] results, RecogResult recogResult) {
75 | for (IRecogListener listener : listeners) {
76 | listener.onAsrFinalResult(results, recogResult);
77 | }
78 | }
79 |
80 | @Override
81 | public void onAsrFinish(RecogResult recogResult) {
82 | for (IRecogListener listener : listeners) {
83 | listener.onAsrFinish(recogResult);
84 | }
85 | }
86 |
87 | @Override
88 | public void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
89 | RecogResult recogResult) {
90 | for (IRecogListener listener : listeners) {
91 | listener.onAsrFinishError(errorCode, subErrorCode, descMessage, recogResult);
92 | }
93 | }
94 |
95 | /**
96 | * 长语音识别结束
97 | */
98 | @Override
99 | public void onAsrLongFinish() {
100 | for (IRecogListener listener : listeners) {
101 | listener.onAsrLongFinish();
102 | }
103 | }
104 |
105 | @Override
106 | public void onAsrVolume(int volumePercent, int volume) {
107 | for (IRecogListener listener : listeners) {
108 | listener.onAsrVolume(volumePercent, volume);
109 | }
110 | }
111 |
112 | @Override
113 | public void onAsrAudio(byte[] data, int offset, int length) {
114 | for (IRecogListener listener : listeners) {
115 | listener.onAsrAudio(data, offset, length);
116 | }
117 | }
118 |
119 | @Override
120 | public void onAsrExit() {
121 | for (IRecogListener listener : listeners) {
122 | listener.onAsrExit();
123 | }
124 | }
125 |
126 | @Override
127 | public void onAsrOnlineNluResult(String nluResult) {
128 | for (IRecogListener listener : listeners) {
129 | listener.onAsrOnlineNluResult(nluResult);
130 | }
131 | }
132 |
133 | @Override
134 | public void onOfflineLoaded() {
135 | for (IRecogListener listener : listeners) {
136 | listener.onOfflineLoaded();
137 | }
138 | }
139 |
140 | @Override
141 | public void onOfflineUnLoaded() {
142 | for (IRecogListener listener : listeners) {
143 | listener.onOfflineUnLoaded();
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/listener/IRecogListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog.listener;
2 |
3 | import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
4 |
5 | /**
6 | * 与SDK中回调参数的对应关系定义在RecogEventAdapter类中
7 | */
8 |
9 | public interface IRecogListener {
10 |
11 | /**
12 | * CALLBACK_EVENT_ASR_READY
13 | * ASR_START 输入事件调用后,引擎准备完毕
14 | */
15 | void onAsrReady();
16 |
17 | /**
18 | * CALLBACK_EVENT_ASR_BEGIN
19 | * onAsrReady后检查到用户开始说话
20 | */
21 | void onAsrBegin();
22 |
23 | /**
24 | * CALLBACK_EVENT_ASR_END
25 | * 检查到用户开始说话停止,或者ASR_STOP 输入事件调用后,
26 | */
27 | void onAsrEnd();
28 |
29 | /**
30 | * CALLBACK_EVENT_ASR_PARTIAL resultType=partial_result
31 | * onAsrBegin 后 随着用户的说话,返回的临时结果
32 | *
33 | * @param results 可能返回多个结果,请取第一个结果
34 | * @param recogResult 完整的结果
35 | */
36 | void onAsrPartialResult(String[] results, RecogResult recogResult);
37 |
38 | /**
39 | * 语音的在线语义结果
40 | *
41 | * CALLBACK_EVENT_ASR_PARTIAL resultType=nlu_result
42 | * @param nluResult
43 | */
44 | void onAsrOnlineNluResult(String nluResult);
45 |
46 | /**
47 | * 不开启长语音仅回调一次,长语音的每一句话都会回调一次
48 | * CALLBACK_EVENT_ASR_PARTIAL resultType=final_result
49 | * 最终的识别结果
50 | *
51 | * @param results 可能返回多个结果,请取第一个结果
52 | * @param recogResult 完整的结果
53 | */
54 | void onAsrFinalResult(String[] results, RecogResult recogResult);
55 |
56 | /**
57 | * CALLBACK_EVENT_ASR_FINISH
58 | * @param recogResult 结束识别
59 | */
60 | void onAsrFinish(RecogResult recogResult);
61 |
62 | /**
63 | * CALLBACK_EVENT_ASR_FINISH error!=0
64 | *
65 | * @param errorCode
66 | * @param subErrorCode
67 | * @param descMessage
68 | * @param recogResult
69 | */
70 | void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
71 | RecogResult recogResult);
72 |
73 | /**
74 | * 长语音识别结束
75 | */
76 | void onAsrLongFinish();
77 |
78 | /**
79 | * CALLBACK_EVENT_ASR_VOLUME
80 | * 音量回调
81 | *
82 | * @param volumePercent 音量的相对值,百分比,0-100
83 | * @param volume 音量绝对值
84 | */
85 | void onAsrVolume(int volumePercent, int volume);
86 |
87 | /**
88 | * CALLBACK_EVENT_ASR_AUDIO
89 | * @param data pcm格式,16bits 16000采样率
90 | *
91 | * @param offset
92 | * @param length
93 | */
94 | void onAsrAudio(byte[] data, int offset, int length);
95 |
96 | /**
97 | * CALLBACK_EVENT_ASR_EXIT
98 | * 引擎完成整个识别,空闲中
99 | */
100 | void onAsrExit();
101 |
102 | /**
103 | * CALLBACK_EVENT_ASR_LOADED
104 | * 离线命令词资源加载成功
105 | */
106 | void onOfflineLoaded();
107 |
108 | /**
109 | * CALLBACK_EVENT_ASR_UNLOADED
110 | * 离线命令词资源释放成功
111 | */
112 | void onOfflineUnLoaded();
113 | }
114 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/listener/MessageStatusRecogListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog.listener;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.util.Log;
6 | import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
7 | import com.baidu.speech.asr.SpeechConstant;
8 |
9 | /**
10 | * Created by fujiayi on 2017/6/16.
11 | */
12 |
13 | public class MessageStatusRecogListener extends StatusRecogListener {
14 | private Handler handler;
15 |
16 | private long speechEndTime = 0;
17 |
18 | private boolean needTime = true;
19 |
20 | private static final String TAG = "MesStatusRecogListener";
21 |
22 | public MessageStatusRecogListener(Handler handler) {
23 | this.handler = handler;
24 | }
25 |
26 |
27 | @Override
28 | public void onAsrReady() {
29 | super.onAsrReady();
30 | speechEndTime = 0;
31 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_WAKEUP_READY, "引擎就绪,可以开始说话。");
32 | }
33 |
34 | @Override
35 | public void onAsrBegin() {
36 | super.onAsrBegin();
37 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN, "检测到用户说话");
38 | }
39 |
40 | @Override
41 | public void onAsrEnd() {
42 | super.onAsrEnd();
43 | speechEndTime = System.currentTimeMillis();
44 | sendMessage("【asr.end事件】检测到用户说话结束");
45 | }
46 |
47 | @Override
48 | public void onAsrPartialResult(String[] results, RecogResult recogResult) {
49 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
50 | "临时识别结果,结果是“" + results[0] + "”;原始json:" + recogResult.getOrigalJson());
51 | super.onAsrPartialResult(results, recogResult);
52 | }
53 |
54 | @Override
55 | public void onAsrFinalResult(String[] results, RecogResult recogResult) {
56 | super.onAsrFinalResult(results, recogResult);
57 | String message = "识别结束,结果是”" + results[0] + "”";
58 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
59 | message + ";原始json:" + recogResult.getOrigalJson());
60 | if (speechEndTime > 0) {
61 | long currentTime = System.currentTimeMillis();
62 | long diffTime = currentTime - speechEndTime;
63 | message += ";说话结束到识别结束耗时【" + diffTime + "ms】" + currentTime;
64 |
65 | }
66 | speechEndTime = 0;
67 | sendMessage(message, status, true);
68 | }
69 |
70 | @Override
71 | public void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
72 | RecogResult recogResult) {
73 | super.onAsrFinishError(errorCode, subErrorCode, descMessage, recogResult);
74 | String message = "【asr.finish事件】识别错误, 错误码:" + errorCode + " ," + subErrorCode + " ; " + descMessage;
75 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, message);
76 | if (speechEndTime > 0) {
77 | long diffTime = System.currentTimeMillis() - speechEndTime;
78 | message += "。说话结束到识别结束耗时【" + diffTime + "ms】";
79 | }
80 | speechEndTime = 0;
81 | sendMessage(message, status, true);
82 | speechEndTime = 0;
83 | }
84 |
85 | @Override
86 | public void onAsrOnlineNluResult(String nluResult) {
87 | super.onAsrOnlineNluResult(nluResult);
88 | if (!nluResult.isEmpty()) {
89 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, "原始语义识别结果json:" + nluResult);
90 | }
91 | }
92 |
93 | @Override
94 | public void onAsrFinish(RecogResult recogResult) {
95 | super.onAsrFinish(recogResult);
96 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_FINISH, "识别一段话结束。如果是长语音的情况会继续识别下段话。");
97 |
98 | }
99 |
100 | /**
101 | * 长语音识别结束
102 | */
103 | @Override
104 | public void onAsrLongFinish() {
105 | super.onAsrLongFinish();
106 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH, "长语音识别结束。");
107 | }
108 |
109 |
110 | /**
111 | * 使用离线命令词时,有该回调说明离线语法资源加载成功
112 | */
113 | @Override
114 | public void onOfflineLoaded() {
115 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LOADED, "离线资源加载成功。没有此回调可能离线语法功能不能使用。");
116 | }
117 |
118 | /**
119 | * 使用离线命令词时,有该回调说明离线语法资源加载成功
120 | */
121 | @Override
122 | public void onOfflineUnLoaded() {
123 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED, "离线资源卸载成功。");
124 | }
125 |
126 | @Override
127 | public void onAsrExit() {
128 | super.onAsrExit();
129 | sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_EXIT, "识别引擎结束并空闲中");
130 | }
131 |
132 | private void sendStatusMessage(String eventName, String message) {
133 | message = "[" + eventName + "]" + message;
134 | sendMessage(message, status);
135 | }
136 |
137 | private void sendMessage(String message) {
138 | sendMessage(message, WHAT_MESSAGE_STATUS);
139 | }
140 |
141 | private void sendMessage(String message, int what) {
142 | sendMessage(message, what, false);
143 | }
144 |
145 |
146 | private void sendMessage(String message, int what, boolean highlight) {
147 |
148 |
149 | if (needTime && what != STATUS_FINISHED) {
150 | message += " ;time=" + System.currentTimeMillis();
151 | }
152 | if (handler == null) {
153 | Log.i(TAG, message);
154 | return;
155 | }
156 | Message msg = Message.obtain();
157 | msg.what = what;
158 | msg.arg1 = status;
159 | if (highlight) {
160 | msg.arg2 = 1;
161 | }
162 | msg.obj = message + "\n";
163 | handler.sendMessage(msg);
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/listener/RecogEventAdapter.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog.listener;
2 |
3 | import android.util.Log;
4 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
5 | import com.baidu.speech.EventListener;
6 | import com.baidu.speech.asr.SpeechConstant;
7 | import org.json.JSONException;
8 | import org.json.JSONObject;
9 | import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
10 |
11 | /**
12 | * Created by fujiayi on 2017/6/14.
13 | */
14 |
15 | public class RecogEventAdapter implements EventListener {
16 |
17 | private IRecogListener listener;
18 |
19 | private static final String TAG = "RecogEventAdapter";
20 |
21 | public RecogEventAdapter(IRecogListener listener) {
22 | this.listener = listener;
23 | }
24 |
25 | // 基于DEMO集成3.1 开始回调事件
26 | @Override
27 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
28 | String currentJson = params;
29 | String logMessage = "name:" + name + "; params:" + params;
30 |
31 | // logcat 中 搜索RecogEventAdapter,即可以看见下面一行的日志
32 | Log.i(TAG, logMessage);
33 | if (false) { // 可以调试,不需要后续逻辑
34 | return;
35 | }
36 | if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_LOADED)) {
37 | listener.onOfflineLoaded();
38 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED)) {
39 | listener.onOfflineUnLoaded();
40 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)) {
41 | // 引擎准备就绪,可以开始说话
42 | listener.onAsrReady();
43 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN)) {
44 | // 检测到用户的已经开始说话
45 | listener.onAsrBegin();
46 |
47 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_END)) {
48 | // 检测到用户的已经停止说话
49 | listener.onAsrEnd();
50 |
51 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
52 | RecogResult recogResult = RecogResult.parseJson(params);
53 | // 识别结果
54 | String[] results = recogResult.getResultsRecognition();
55 | if (recogResult.isFinalResult()) {
56 | // 最终识别结果,长语音每一句话会回调一次
57 | listener.onAsrFinalResult(results, recogResult);
58 | } else if (recogResult.isPartialResult()) {
59 | // 临时识别结果
60 | listener.onAsrPartialResult(results, recogResult);
61 | } else if (recogResult.isNluResult()) {
62 | // 语义理解结果
63 | listener.onAsrOnlineNluResult(new String(data, offset, length));
64 | }
65 |
66 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {
67 | // 识别结束
68 | RecogResult recogResult = RecogResult.parseJson(params);
69 | if (recogResult.hasError()) {
70 | int errorCode = recogResult.getError();
71 | int subErrorCode = recogResult.getSubError();
72 | MyLogger.error(TAG, "asr error:" + params);
73 | listener.onAsrFinishError(errorCode, subErrorCode, recogResult.getDesc(), recogResult);
74 | } else {
75 | listener.onAsrFinish(recogResult);
76 | }
77 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH)) { // 长语音
78 | listener.onAsrLongFinish(); // 长语音
79 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_EXIT)) {
80 | listener.onAsrExit();
81 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_VOLUME)) {
82 | // Logger.info(TAG, "asr volume event:" + params);
83 | Volume vol = parseVolumeJson(params);
84 | listener.onAsrVolume(vol.volumePercent, vol.volume);
85 | } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_AUDIO)) {
86 | if (data.length != length) {
87 | MyLogger.error(TAG, "internal error: asr.audio callback data length is not equal to length param");
88 | }
89 | listener.onAsrAudio(data, offset, length);
90 | }
91 | }
92 |
93 | private Volume parseVolumeJson(String jsonStr) {
94 | Volume vol = new Volume();
95 | vol.origalJson = jsonStr;
96 | try {
97 | JSONObject json = new JSONObject(jsonStr);
98 | vol.volumePercent = json.getInt("volume-percent");
99 | vol.volume = json.getInt("volume");
100 | } catch (JSONException e) {
101 | e.printStackTrace();
102 | }
103 | return vol;
104 | }
105 |
106 | private class Volume {
107 | private int volumePercent = -1;
108 | private int volume = -1;
109 | private String origalJson;
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/recog/listener/StatusRecogListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.recog.listener;
2 |
3 | /**
4 | * Created by fujiayi on 2017/6/14.
5 | */
6 |
7 | import android.util.Log;
8 | import com.baidu.aip.asrwakeup3.core.recog.IStatus;
9 | import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
10 |
11 | /**
12 | * 根据回调,判断asr引擎的状态
13 | *
14 | * 通常状态变化如下:
15 | *
16 | * STATUS_NONE 初始状态
17 | * STATUS_READY 引擎准备完毕
18 | * STATUS_SPEAKING 用户开始说话到用户说话完毕前
19 | * STATUS_RECOGNITION 用户说话完毕后,识别结束前
20 | * STATUS_FINISHED 获得最终识别结果
21 | */
22 | public class StatusRecogListener implements IRecogListener, IStatus {
23 |
24 | private static final String TAG = "StatusRecogListener";
25 |
26 | /**
27 | * 识别的引擎当前的状态
28 | */
29 | protected int status = STATUS_NONE;
30 |
31 | @Override
32 | public void onAsrReady() {
33 | status = STATUS_READY;
34 | }
35 |
36 | @Override
37 | public void onAsrBegin() {
38 | status = STATUS_SPEAKING;
39 | }
40 |
41 | @Override
42 | public void onAsrEnd() {
43 | status = STATUS_RECOGNITION;
44 | }
45 |
46 | @Override
47 | public void onAsrPartialResult(String[] results, RecogResult recogResult) {
48 |
49 | }
50 |
51 | @Override
52 | public void onAsrFinalResult(String[] results, RecogResult recogResult) {
53 | status = STATUS_FINISHED;
54 | }
55 |
56 | @Override
57 | public void onAsrFinish(RecogResult recogResult) {
58 | status = STATUS_FINISHED;
59 | }
60 |
61 |
62 | @Override
63 | public void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
64 | RecogResult recogResult) {
65 | status = STATUS_FINISHED;
66 | }
67 |
68 | @Override
69 | public void onAsrLongFinish() {
70 | status = STATUS_LONG_SPEECH_FINISHED;
71 | }
72 |
73 | @Override
74 | public void onAsrVolume(int volumePercent, int volume) {
75 | Log.i(TAG, "音量百分比" + volumePercent + " ; 音量" + volume);
76 | }
77 |
78 | @Override
79 | public void onAsrAudio(byte[] data, int offset, int length) {
80 | if (offset != 0 || data.length != length) {
81 | byte[] actualData = new byte[length];
82 | System.arraycopy(data, 0, actualData, 0, length);
83 | data = actualData;
84 | }
85 |
86 | Log.i(TAG, "音频数据回调, length:" + data.length);
87 | }
88 |
89 | @Override
90 | public void onAsrExit() {
91 | status = STATUS_NONE;
92 | }
93 |
94 | @Override
95 | public void onAsrOnlineNluResult(String nluResult) {
96 | status = STATUS_FINISHED;
97 | }
98 |
99 | @Override
100 | public void onOfflineLoaded() {
101 |
102 | }
103 |
104 | @Override
105 | public void onOfflineUnLoaded() {
106 |
107 | }
108 |
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/util/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.util;
2 |
3 | import android.content.res.AssetManager;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 |
10 | /**
11 | * Created by fujiayi on 2017/5/19.
12 | */
13 |
14 | public class FileUtil {
15 |
16 | public static boolean makeDir(String dirPath) {
17 | File file = new File(dirPath);
18 | if (!file.exists()) {
19 | return file.mkdirs();
20 | } else {
21 | return true;
22 | }
23 | }
24 |
25 | public static String getContentFromAssetsFile(AssetManager assets, String source) {
26 | InputStream is = null;
27 | FileOutputStream fos = null;
28 | String result = "";
29 | try {
30 | is = assets.open(source);
31 | int lenght = is.available();
32 | byte[] buffer = new byte[lenght];
33 | is.read(buffer);
34 | result = new String(buffer, "utf8");
35 | } catch (IOException e) {
36 | e.printStackTrace();
37 | }
38 | return result;
39 | }
40 |
41 | public static boolean copyFromAssets(AssetManager assets, String source, String dest,
42 | boolean isCover) throws IOException {
43 | File file = new File(dest);
44 | boolean isCopyed = false;
45 | if (isCover || (!isCover && !file.exists())) {
46 | InputStream is = null;
47 | FileOutputStream fos = null;
48 | try {
49 | is = assets.open(source);
50 | String path = dest;
51 | fos = new FileOutputStream(path);
52 | byte[] buffer = new byte[1024];
53 | int size = 0;
54 | while ((size = is.read(buffer, 0, 1024)) >= 0) {
55 | fos.write(buffer, 0, size);
56 | }
57 | isCopyed = true;
58 | } finally {
59 | if (fos != null) {
60 | try {
61 | fos.close();
62 | } finally {
63 | if (is != null) {
64 | is.close();
65 | }
66 | }
67 | }
68 | }
69 |
70 | }
71 | return isCopyed;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/util/MyLogger.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.util;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.util.Log;
6 |
7 |
8 | /**
9 | * 记录日志的时候, 顺带往handler记录一份
10 | */
11 |
12 | public class MyLogger {
13 | private static final String TAG = "MyLogger";
14 |
15 | private static final String INFO = "INFO";
16 |
17 | private static final String ERROR = "ERROR";
18 |
19 | private static final boolean ENABLE = true;
20 |
21 | private static Handler handler;
22 |
23 | public static void info(String message) {
24 | info(TAG, message);
25 | }
26 |
27 | public static void info(String tag, String message) {
28 | log(INFO, tag, message);
29 | }
30 |
31 | public static void error(String message) {
32 | error(TAG, message);
33 | }
34 |
35 | public static void error(String tag, String message) {
36 | log(ERROR, tag, message);
37 | }
38 |
39 | public static void setHandler(Handler handler) {
40 | MyLogger.handler = handler;
41 | }
42 |
43 | private static void log(String level, String tag, String message) {
44 | if (!ENABLE) {
45 | return;
46 | }
47 | if (level.equals(INFO)) {
48 | Log.i(tag, message);
49 |
50 | } else if (level.equals(ERROR)) {
51 | Log.e(tag, message);
52 | }
53 | if (handler != null) {
54 | Message msg = Message.obtain();
55 | msg.obj = "[" + level + "]" + message + "\n";
56 | handler.sendMessage(msg);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/util/bluetooth/AndroidAudioManager.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.util.bluetooth;
2 |
3 | import android.bluetooth.BluetoothAdapter;
4 | import android.bluetooth.BluetoothDevice;
5 | import android.bluetooth.BluetoothHeadset;
6 | import android.bluetooth.BluetoothProfile;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.IntentFilter;
10 | import android.media.AudioManager;
11 | import android.util.Log;
12 |
13 | import java.util.List;
14 |
15 | import static android.media.AudioManager.STREAM_VOICE_CALL;
16 |
17 | public class AndroidAudioManager {
18 |
19 | private static volatile AndroidAudioManager instance;
20 |
21 | private BluetoothAdapter mBluetoothAdapter;
22 |
23 | private AudioManager mAudioManager;
24 |
25 | private boolean mIsBluetoothHeadsetConnected;
26 |
27 | private boolean mIsBluetoothHeadsetScoConnected;
28 |
29 | private BluetoothReceiver mBluetoothReceiver;
30 |
31 | private HeadsetReceiver mHeadsetReceiver;
32 |
33 | private boolean mAudioFocused;
34 |
35 | private Context mContext;
36 | private BluetoothHeadset mBluetoothHeadset;
37 |
38 | private AndroidAudioManager(Context context) {
39 | mAudioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE));
40 | this.mContext = context.getApplicationContext();
41 | }
42 |
43 | public AudioManager getAudioManager() {
44 | return mAudioManager;
45 | }
46 |
47 | public static AndroidAudioManager getInstance(Context context) {
48 | if (instance == null) {
49 | synchronized (AndroidAudioManager.class) {
50 | if (instance == null) {
51 | instance = new AndroidAudioManager(context);
52 | }
53 | }
54 | }
55 | return instance;
56 | }
57 |
58 | public void startBluetooth() {
59 | mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
60 | if (mBluetoothAdapter != null) {
61 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] Adapter found");
62 | if (mAudioManager.isBluetoothScoAvailableOffCall()) {
63 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] SCO available off call, continue");
64 | } else {
65 | Log.w("AndroidAudioManager", "[Audio Manager] [Bluetooth] SCO not available off call !");
66 | }
67 | if (mBluetoothAdapter.isEnabled()) {
68 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] Adapter enabled");
69 | mBluetoothReceiver = new BluetoothReceiver();
70 | mIsBluetoothHeadsetConnected = false;
71 | mIsBluetoothHeadsetScoConnected = false;
72 |
73 | BluetoothProfile.ServiceListener bluetoothServiceListener =
74 | new BluetoothProfile.ServiceListener() {
75 | public void onServiceConnected(int profile, BluetoothProfile proxy) {
76 | if (profile == BluetoothProfile.HEADSET) {
77 | Log.i("AndroidAudioManager",
78 | "[Audio Manager] [Bluetooth] HEADSET profile connected");
79 | mBluetoothHeadset = (BluetoothHeadset) proxy;
80 |
81 | List devices =
82 | mBluetoothHeadset.getConnectedDevices();
83 | if (devices.size() > 0) {
84 | Log.i("AndroidAudioManager",
85 | "[Audio Manager] [Bluetooth] A device is already connected");
86 | bluetoothHeadetConnectionChanged(true);
87 | }
88 |
89 | Log.i("AndroidAudioManager",
90 | "[Audio Manager] [Bluetooth] Registering bluetooth receiver");
91 |
92 | IntentFilter filter = new IntentFilter();
93 | filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
94 | filter.addAction(
95 | BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
96 | filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
97 | filter.addAction(
98 | BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
99 |
100 | Intent sticky =
101 | mContext.registerReceiver(mBluetoothReceiver, filter);
102 | int state =
103 | sticky.getIntExtra(
104 | AudioManager.EXTRA_SCO_AUDIO_STATE,
105 | AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
106 | if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
107 | Log.i("AndroidAudioManager",
108 | "[Audio Manager] [Bluetooth] Bluetooth headset SCO connected");
109 | bluetoothHeadetScoConnectionChanged(true);
110 | } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
111 | Log.i("AndroidAudioManager",
112 | "[Audio Manager] [Bluetooth] Bluetooth headset SCO disconnected");
113 | bluetoothHeadetScoConnectionChanged(false);
114 | } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) {
115 | Log.i("AndroidAudioManager",
116 | "[Audio Manager] [Bluetooth] Bluetooth headset SCO connecting");
117 | } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) {
118 | Log.i("AndroidAudioManager",
119 | "[Audio Manager] [Bluetooth] Bluetooth headset SCO connection error");
120 | } else {
121 | Log.w("AndroidAudioManager",
122 | "[Audio Manager] [Bluetooth] Bluetooth headset " +
123 | "unknown SCO state changed: "
124 | + state);
125 | }
126 | }
127 | }
128 |
129 | public void onServiceDisconnected(int profile) {
130 | if (profile == BluetoothProfile.HEADSET) {
131 | Log.i("AndroidAudioManager",
132 | "[Audio Manager] [Bluetooth] HEADSET profile disconnected");
133 | mBluetoothHeadset = null;
134 | mIsBluetoothHeadsetConnected = false;
135 | mIsBluetoothHeadsetScoConnected = false;
136 | }
137 | }
138 | };
139 | mBluetoothAdapter.getProfileProxy(
140 | mContext, bluetoothServiceListener, BluetoothProfile.HEADSET);
141 | }
142 | }
143 | }
144 |
145 |
146 | // Bluetooth
147 |
148 | public synchronized void bluetoothHeadetConnectionChanged(boolean connected) {
149 | mIsBluetoothHeadsetConnected = connected;
150 | mAudioManager.setBluetoothScoOn(connected);
151 | mAudioManager.startBluetoothSco();
152 | routeAudioToBluetooth();
153 | }
154 |
155 |
156 | public synchronized boolean isBluetoothHeadsetConnected() {
157 | return mIsBluetoothHeadsetConnected;
158 | }
159 |
160 | public synchronized void bluetoothHeadetScoConnectionChanged(boolean connected) {
161 | mIsBluetoothHeadsetScoConnected = connected;
162 | }
163 |
164 | public synchronized boolean isUsingBluetoothAudioRoute() {
165 | return mIsBluetoothHeadsetScoConnected;
166 | }
167 |
168 | public synchronized void routeAudioToBluetooth() {
169 | if (!isBluetoothHeadsetConnected()) {
170 | Log.w("AndroidAudioManager", "[Audio Manager] [Bluetooth] No headset connected");
171 | return;
172 | }
173 | if (mAudioManager.getMode() != AudioManager.MODE_IN_COMMUNICATION) {
174 | Log.w("AndroidAudioManager",
175 | "[Audio Manager] [Bluetooth] Changing audio mode to MODE_IN_COMMUNICATION " +
176 | "and requesting STREAM_VOICE_CALL focus");
177 | mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
178 | requestAudioFocus(STREAM_VOICE_CALL);
179 | }
180 | changeBluetoothSco(true);
181 | }
182 |
183 | private void requestAudioFocus(int stream) {
184 | if (!mAudioFocused) {
185 | int res =
186 | mAudioManager.requestAudioFocus(
187 | null, stream, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE);
188 | Log.d("AndroidAudioManager",
189 | "[Audio Manager] Audio focus requested: "
190 | + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
191 | ? "Granted"
192 | : "Denied"));
193 | if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
194 | mAudioFocused = true;
195 | }
196 | }
197 | }
198 |
199 | private synchronized void changeBluetoothSco(final boolean enable) {
200 | // IT WILL TAKE A CERTAIN NUMBER OF CALLS TO EITHER START/STOP BLUETOOTH SCO FOR IT TO WORK
201 | if (enable && mIsBluetoothHeadsetScoConnected) {
202 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] SCO already enabled, skipping");
203 | return;
204 | } else if (!enable && !mIsBluetoothHeadsetScoConnected) {
205 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] SCO already disabled, skipping");
206 | return;
207 | }
208 |
209 | new Thread() {
210 | @Override
211 | public void run() {
212 | boolean resultAcknoledged;
213 | int retries = 0;
214 | do {
215 | try {
216 | Thread.sleep(200);
217 | } catch (InterruptedException e) {
218 | Log.e("AndroidAudioManager", e.getMessage(), e);
219 | }
220 |
221 | synchronized (AndroidAudioManager.this) {
222 | if (enable) {
223 | Log.i("AndroidAudioManager",
224 | "[Audio Manager] [Bluetooth] Starting SCO: try number "
225 | + retries);
226 | mAudioManager.startBluetoothSco();
227 | } else {
228 | Log.i("AndroidAudioManager",
229 | "[Audio Manager] [Bluetooth] Stopping SCO: try number "
230 | + retries);
231 | mAudioManager.stopBluetoothSco();
232 | }
233 | resultAcknoledged = isUsingBluetoothAudioRoute() == enable;
234 | retries++;
235 | }
236 | } while (!resultAcknoledged && retries < 10);
237 | }
238 | }.start();
239 | }
240 |
241 | public void destroy() {
242 | if (mBluetoothAdapter != null && mBluetoothHeadset != null) {
243 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] Closing HEADSET profile proxy");
244 | mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
245 | }
246 |
247 | Log.i("AndroidAudioManager", "[Audio Manager] [Bluetooth] Unegistering bluetooth receiver");
248 | if (mBluetoothReceiver != null) {
249 | mContext.unregisterReceiver(mBluetoothReceiver);
250 | }
251 | synchronized (AndroidAudioManager.class) {
252 | mContext = null;
253 | instance = null;
254 | }
255 | }
256 |
257 |
258 | public void startSimpleBluetooth() {
259 | mAudioManager.setBluetoothScoOn(true);
260 | mAudioManager.startBluetoothSco();
261 | }
262 |
263 | public void destorySimpleBluetooth() {
264 | mAudioManager.setBluetoothScoOn(false);
265 | mAudioManager.stopBluetoothSco();
266 | }
267 |
268 | // HEADSET 插耳机的
269 |
270 | public void enableHeadsetReceiver() {
271 | mHeadsetReceiver = new HeadsetReceiver();
272 |
273 | Log.i("AndroidAudioManager", "[Audio Manager] Registering headset receiver");
274 | mContext.registerReceiver(
275 | mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
276 | mContext.registerReceiver(
277 | mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_HEADSET_PLUG));
278 | }
279 |
280 | public void routeAudioToEarPiece() {
281 | routeAudioToSpeakerHelper(false);
282 | }
283 |
284 | public void routeAudioToSpeakerHelper(boolean speakerOn) {
285 | Log.w("AndroidAudioManager", "[Audio Manager] Routing audio to " + (speakerOn ? "speaker" : "earpiece"));
286 | if (mIsBluetoothHeadsetScoConnected) {
287 | Log.w("AndroidAudioManager", "[Audio Manager] [Bluetooth] Disabling bluetooth audio route");
288 | changeBluetoothSco(false);
289 | }
290 |
291 | mAudioManager.setSpeakerphoneOn(speakerOn);
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/util/bluetooth/BluetoothReceiver.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.util.bluetooth;
2 |
3 | import android.bluetooth.BluetoothHeadset;
4 | import android.content.BroadcastReceiver;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.media.AudioManager;
8 | import android.util.Log;
9 |
10 | public class BluetoothReceiver extends BroadcastReceiver {
11 | @Override
12 | public void onReceive(Context context, Intent intent) {
13 | String action = intent.getAction();
14 | if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
15 | int state =
16 | intent.getIntExtra(
17 | BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
18 | if (state == BluetoothHeadset.STATE_CONNECTED) {
19 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset connected");
20 | AndroidAudioManager.getInstance(context).bluetoothHeadetConnectionChanged(true);
21 | } else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
22 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset disconnected");
23 | AndroidAudioManager.getInstance(context).bluetoothHeadetConnectionChanged(false);
24 | } else {
25 | Log.w("BluetoothReceiver", "[Bluetooth] Bluetooth headset unknown state changed: " + state);
26 | }
27 | } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
28 | int state =
29 | intent.getIntExtra(
30 | BluetoothHeadset.EXTRA_STATE,
31 | BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
32 | if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
33 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset audio connected");
34 | // AndroidAudioManager.getInstance(context).bluetoothHeadetAudioConnectionChanged(true);
35 | } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
36 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset audio disconnected");
37 | // AndroidAudioManager.getInstance(context).bluetoothHeadetAudioConnectionChanged(false);
38 | } else {
39 | Log.w("BluetoothReceiver", "[Bluetooth] Bluetooth headset unknown audio state changed: " + state);
40 | }
41 | } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
42 | int state =
43 | intent.getIntExtra(
44 | AudioManager.EXTRA_SCO_AUDIO_STATE,
45 | AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
46 | if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
47 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset SCO connected");
48 | AndroidAudioManager.getInstance(context).bluetoothHeadetScoConnectionChanged(true);
49 | } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
50 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset SCO disconnected");
51 | AndroidAudioManager.getInstance(context).bluetoothHeadetScoConnectionChanged(false);
52 | } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) {
53 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset SCO connecting");
54 | } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) {
55 | Log.i("BluetoothReceiver", "[Bluetooth] Bluetooth headset SCO connection error");
56 | } else {
57 | Log.w("BluetoothReceiver", "[Bluetooth] Bluetooth headset unknown SCO state changed: " + state);
58 | }
59 | } else if (action.equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
60 | String command =
61 | intent.getStringExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
62 | int type =
63 | intent.getIntExtra(
64 | BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE, -1);
65 |
66 | String commandType;
67 | switch (type) {
68 | case BluetoothHeadset.AT_CMD_TYPE_ACTION:
69 | commandType = "AT Action";
70 | break;
71 | case BluetoothHeadset.AT_CMD_TYPE_READ:
72 | commandType = "AT Read";
73 | break;
74 | case BluetoothHeadset.AT_CMD_TYPE_TEST:
75 | commandType = "AT Test";
76 | break;
77 | case BluetoothHeadset.AT_CMD_TYPE_SET:
78 | commandType = "AT Set";
79 | break;
80 | case BluetoothHeadset.AT_CMD_TYPE_BASIC:
81 | commandType = "AT Basic";
82 | break;
83 | default:
84 | commandType = "AT Unknown";
85 | break;
86 | }
87 | Log.i("BluetoothReceiver", "[Bluetooth] Vendor action " + commandType + " : " + command);
88 | } else {
89 | Log.w("BluetoothReceiver", "[Bluetooth] Bluetooth unknown action: " + action);
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/util/bluetooth/HeadsetReceiver.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.util.bluetooth;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.media.AudioManager;
7 | import android.util.Log;
8 |
9 | public class HeadsetReceiver extends BroadcastReceiver {
10 | @Override
11 | public void onReceive(Context context, Intent intent) {
12 | String action = intent.getAction();
13 | if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
14 | // This happens when the user plugs a Jack headset to the device for example
15 | int state = intent.getIntExtra("state", 0);
16 | String name = intent.getStringExtra("name");
17 | int hasMicrophone = intent.getIntExtra("microphone", 0);
18 |
19 | if (state == 0) {
20 | Log.i("HeadsetReceiver", "[Headset] Headset disconnected:" + name);
21 | } else if (state == 1) {
22 | Log.i("HeadsetReceiver", "[Headset] Headset connected:" + name);
23 | if (hasMicrophone == 1) {
24 | Log.i("HeadsetReceiver", "[Headset] Headset " + name + " has a microphone");
25 | }
26 | } else {
27 | Log.w("HeadsetReceiver", "[Headset] Unknown headset plugged state: " + state);
28 | }
29 |
30 | AndroidAudioManager.getInstance(context).routeAudioToEarPiece();
31 | // LinphoneManager.getCallManager().refreshInCallActions();
32 | } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
33 | // This happens when the user disconnect a headset, so we shouldn't play audio loudly
34 | Log.i("HeadsetReceiver", "[Headset] Noisy state detected, most probably a headset has been disconnected");
35 | AndroidAudioManager.getInstance(context).routeAudioToEarPiece();
36 | // LinphoneManager.getCallManager().refreshInCallActions();
37 | } else {
38 | Log.w("HeadsetReceiver", "[Headset] Unknown action: " + action);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/MyWakeup.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup;
2 |
3 | import android.content.Context;
4 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
5 | import com.baidu.aip.asrwakeup3.core.wakeup.listener.IWakeupListener;
6 | import com.baidu.speech.EventListener;
7 | import com.baidu.speech.EventManager;
8 | import com.baidu.speech.EventManagerFactory;
9 | import com.baidu.speech.asr.SpeechConstant;
10 | import org.json.JSONObject;
11 |
12 | import java.util.Map;
13 |
14 | /**
15 | * Created by fujiayi on 2017/6/20.
16 | */
17 |
18 | public class MyWakeup {
19 |
20 |
21 | private static boolean isInited = false;
22 |
23 | private EventManager wp;
24 | private EventListener eventListener;
25 |
26 | private static final String TAG = "MyWakeup";
27 |
28 | public MyWakeup(Context context, EventListener eventListener) {
29 | if (isInited) {
30 | MyLogger.error(TAG, "还未调用release(),请勿新建一个新类");
31 | throw new RuntimeException("还未调用release(),请勿新建一个新类");
32 | }
33 | isInited = true;
34 | this.eventListener = eventListener;
35 | wp = EventManagerFactory.create(context, "wp");
36 | wp.registerListener(eventListener);
37 | }
38 |
39 | public MyWakeup(Context context, IWakeupListener eventListener) {
40 | this(context, new WakeupEventAdapter(eventListener));
41 | }
42 |
43 | public void start(Map params) {
44 | String json = new JSONObject(params).toString();
45 | MyLogger.info(TAG + ".Debug", "wakeup params(反馈请带上此行日志):" + json);
46 | wp.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);
47 | }
48 |
49 | public void stop() {
50 | MyLogger.info(TAG, "唤醒结束");
51 | wp.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);
52 | }
53 |
54 | public void setEventListener(EventListener eventListener) {
55 | this.eventListener = eventListener;
56 | }
57 |
58 | public void setEventListener(IWakeupListener eventListener) {
59 | this.eventListener = new WakeupEventAdapter(eventListener);
60 | }
61 |
62 | public void release() {
63 | stop();
64 | wp.unregisterListener(eventListener);
65 | wp = null;
66 | isInited = false;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/WakeUpResult.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup;
2 |
3 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
4 | import com.baidu.speech.asr.SpeechConstant;
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 |
8 | /**
9 | * Created by fujiayi on 2017/6/24.
10 | */
11 | public class WakeUpResult {
12 | private String name;
13 | private String origalJson;
14 | private String word;
15 | private String desc;
16 | private int errorCode;
17 |
18 | private static int ERROR_NONE = 0;
19 |
20 | private static final String TAG = "WakeUpResult";
21 |
22 | public boolean hasError() {
23 | return errorCode != ERROR_NONE;
24 | }
25 |
26 | public String getOrigalJson() {
27 | return origalJson;
28 | }
29 |
30 | public void setOrigalJson(String origalJson) {
31 | this.origalJson = origalJson;
32 | }
33 |
34 | public String getWord() {
35 | return word;
36 | }
37 |
38 | public void setWord(String word) {
39 | this.word = word;
40 | }
41 |
42 | public String getDesc() {
43 | return desc;
44 | }
45 |
46 | public void setDesc(String desc) {
47 | this.desc = desc;
48 | }
49 |
50 | public int getErrorCode() {
51 | return errorCode;
52 | }
53 |
54 | public void setErrorCode(int errorCode) {
55 | this.errorCode = errorCode;
56 | }
57 |
58 | public String getName() {
59 | return name;
60 | }
61 |
62 | public void setName(String name) {
63 | this.name = name;
64 | }
65 |
66 | public static WakeUpResult parseJson(String name, String jsonStr) {
67 | WakeUpResult result = new WakeUpResult();
68 | result.setOrigalJson(jsonStr);
69 | try {
70 | JSONObject json = new JSONObject(jsonStr);
71 | if (SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS.equals(name)) {
72 | int error = json.optInt("errorCode");
73 | result.setErrorCode(error);
74 | result.setDesc(json.optString("errorDesc"));
75 | if (!result.hasError()) {
76 | result.setWord(json.optString("word"));
77 | }
78 | } else {
79 | int error = json.optInt("error");
80 | result.setErrorCode(error);
81 | result.setDesc(json.optString("desc"));
82 | }
83 |
84 | } catch (JSONException e) {
85 | MyLogger.error(TAG, "Json parse error" + jsonStr);
86 | e.printStackTrace();
87 | }
88 |
89 | return result;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/WakeupEventAdapter.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup;
2 |
3 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
4 | import com.baidu.aip.asrwakeup3.core.wakeup.listener.IWakeupListener;
5 | import com.baidu.speech.EventListener;
6 | import com.baidu.speech.asr.SpeechConstant;
7 |
8 | /**
9 | * Created by fujiayi on 2017/6/20.
10 | */
11 |
12 | public class WakeupEventAdapter implements EventListener {
13 | private IWakeupListener listener;
14 |
15 | public WakeupEventAdapter(IWakeupListener listener) {
16 | this.listener = listener;
17 | }
18 |
19 | private static final String TAG = "WakeupEventAdapter";
20 | // 基于DEMO唤醒3.1 开始回调事件
21 | @Override
22 | public void onEvent(String name, String params, byte[] data, int offset, int length) {
23 | // android studio日志Monitor 中搜索 WakeupEventAdapter即可看见下面一行的日志
24 | MyLogger.info(TAG, "wakeup name:" + name + "; params:" + params);
25 | if (SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS.equals(name)) { // 识别唤醒词成功
26 | WakeUpResult result = WakeUpResult.parseJson(name, params);
27 | int errorCode = result.getErrorCode();
28 | if (result.hasError()) { // error不为0依旧有可能是异常情况
29 | listener.onError(errorCode, "", result);
30 | } else {
31 | String word = result.getWord();
32 | listener.onSuccess(word, result);
33 |
34 | }
35 | } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR.equals(name)) { // 识别唤醒词报错
36 | WakeUpResult result = WakeUpResult.parseJson(name, params);
37 | int errorCode = result.getErrorCode();
38 | if (result.hasError()) {
39 | listener.onError(errorCode, "", result);
40 | }
41 | } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED.equals(name)) { // 关闭唤醒词
42 | listener.onStop();
43 | } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO.equals(name)) { // 音频回调
44 | listener.onASrAudio(data, offset, length);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/listener/IWakeupListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup.listener;
2 |
3 | import com.baidu.aip.asrwakeup3.core.wakeup.WakeUpResult;
4 |
5 | /**
6 | * Created by fujiayi on 2017/6/21.
7 | */
8 |
9 | public interface IWakeupListener {
10 |
11 |
12 | void onSuccess(String word, WakeUpResult result);
13 |
14 | void onStop();
15 |
16 | void onError(int errorCode, String errorMessge, WakeUpResult result);
17 |
18 | void onASrAudio(byte[] data, int offset, int length);
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/listener/RecogWakeupListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup.listener;
2 |
3 | import android.os.Handler;
4 | import com.baidu.aip.asrwakeup3.core.recog.IStatus;
5 | import com.baidu.aip.asrwakeup3.core.wakeup.WakeUpResult;
6 |
7 | /**
8 | * Created by fujiayi on 2017/9/21.
9 | */
10 |
11 | public class RecogWakeupListener extends SimpleWakeupListener implements IStatus {
12 |
13 | private static final String TAG = "RecogWakeupListener";
14 |
15 | private Handler handler;
16 |
17 | public RecogWakeupListener(Handler handler) {
18 | this.handler = handler;
19 | }
20 |
21 | @Override
22 | public void onSuccess(String word, WakeUpResult result) {
23 | super.onSuccess(word, result);
24 | handler.sendMessage(handler.obtainMessage(STATUS_WAKEUP_SUCCESS));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/java/com/baidu/aip/asrwakeup3/core/wakeup/listener/SimpleWakeupListener.java:
--------------------------------------------------------------------------------
1 | package com.baidu.aip.asrwakeup3.core.wakeup.listener;
2 |
3 |
4 | import com.baidu.aip.asrwakeup3.core.util.MyLogger;
5 | import com.baidu.aip.asrwakeup3.core.wakeup.WakeUpResult;
6 |
7 | /**
8 | * Created by fujiayi on 2017/6/21.
9 | */
10 |
11 | public class SimpleWakeupListener implements IWakeupListener {
12 |
13 | private static final String TAG = "SimpleWakeupListener";
14 |
15 | @Override
16 | public void onSuccess(String word, WakeUpResult result) {
17 | MyLogger.info(TAG, "唤醒成功,唤醒词:" + word);
18 | }
19 |
20 | @Override
21 | public void onStop() {
22 | MyLogger.info(TAG, "唤醒词识别结束:");
23 | }
24 |
25 | @Override
26 | public void onError(int errorCode, String errorMessge, WakeUpResult result) {
27 | MyLogger.info(TAG, "唤醒错误:" + errorCode + ";错误消息:" + errorMessge + "; 原始返回" + result.getOrigalJson());
28 | }
29 |
30 | @Override
31 | public void onASrAudio(byte[] data, int offset, int length) {
32 | MyLogger.error(TAG, "audio data: " + data.length);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/core/src/main/jniLibs/arm64-v8a/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/arm64-v8a/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/arm64-v8a/libbdEASRAndroid.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/arm64-v8a/libbdEASRAndroid.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/arm64-v8a/libbdSpilWakeup.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/arm64-v8a/libbdSpilWakeup.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/arm64-v8a/libbd_easr_s1_merge_normal_20151216.dat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/arm64-v8a/libbd_easr_s1_merge_normal_20151216.dat.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/arm64-v8a/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/arm64-v8a/libvad.dnn.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi-v7a/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi-v7a/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi-v7a/libbdEASRAndroid.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi-v7a/libbdEASRAndroid.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi-v7a/libbdSpilWakeup.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi-v7a/libbdSpilWakeup.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi-v7a/libbd_easr_s1_merge_normal_20151216.dat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi-v7a/libbd_easr_s1_merge_normal_20151216.dat.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi-v7a/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi-v7a/libvad.dnn.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi/libbdEASRAndroid.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi/libbdEASRAndroid.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi/libbdSpilWakeup.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi/libbdSpilWakeup.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi/libbd_easr_s1_merge_normal_20151216.dat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi/libbd_easr_s1_merge_normal_20151216.dat.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/armeabi/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/armeabi/libvad.dnn.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86/libbdEASRAndroid.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86/libbdEASRAndroid.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86/libbdSpilWakeup.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86/libbdSpilWakeup.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86/libbd_easr_s1_merge_normal_20151216.dat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86/libbd_easr_s1_merge_normal_20151216.dat.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86/libvad.dnn.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86_64/libBaiduSpeechSDK.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86_64/libBaiduSpeechSDK.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86_64/libbdEASRAndroid.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86_64/libbdEASRAndroid.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86_64/libbdSpilWakeup.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86_64/libbdSpilWakeup.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86_64/libbd_easr_s1_merge_normal_20151216.dat.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86_64/libbd_easr_s1_merge_normal_20151216.dat.so
--------------------------------------------------------------------------------
/core/src/main/jniLibs/x86_64/libvad.dnn.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/core/src/main/jniLibs/x86_64/libvad.dnn.so
--------------------------------------------------------------------------------
/core/src/main/res/layout/common_mini.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
18 |
19 |
24 |
25 |
30 |
31 |
32 |
38 |
39 |
45 |
--------------------------------------------------------------------------------
/core/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BaseAsr
3 |
4 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Enables namespacing of each library's R class so that its R class includes only the
19 | # resources declared in the library itself and none from the library's dependencies,
20 | # thereby reducing the size of the R class for that library
21 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bunny-chz/ShortVideoAssistant/ff3d525221189c30ed9e6d92d785f94ebd0c54d0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Mar 10 17:33:27 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "短视频辅助器"
16 | include ':app'
17 | include ':core'
18 |
--------------------------------------------------------------------------------