android集成百度语音识别demo apk遇到的坑

【开发环境】android studio 3.4.2

image

先到百度语音官网上查看集成指南

百度AI开放平台-全球领先的人工智能服务平台-百度AI开放平台

image

然后再去下载语音识别 https://ai.baidu.com/sdk#asr

image

离在线融合SDK(audiobd_speech_sdk_asr_v3.0.12.3_20190515_c9eed5d.zip)

直接参考SDK中的ActivityMiniRecog类


【代码部分】

1、app\build.gradle


apply plugin: 'com.android.application'

android {

    compileSdkVersion 28

    buildToolsVersion "29.0.1"

    defaultConfig {

        applicationId "com.unionman.speechdemo"

        minSdkVersion 16

        targetSdkVersion 28

        versionCode 1

        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        }

    }

}

dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation 'androidx.appcompat:appcompat:1.1.0'

    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

    testImplementation 'junit:junit:4.12'

    androidTestImplementation 'androidx.test:runner:1.2.0'

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation files('libs/bdasr_V3_20190515_c9eed5d.jar')

    api fileTree(exclude: '*.bak', dir: 'libs')

    api 'com.google.code.gson:gson:2.8.5'

    implementation 'com.android.support:appcompat-v7:28.0.0'

    implementation 'com.android.support:support-v4:28.0.0'

}

2、AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.unionman.speechdemo">

    <!-- begin: baidu speech sdk  权限 -->

    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!-- end: baidu speech sdk  权限 -->

        android:allowBackup="true"

        android:icon="@mipmap/ic_launcher"

        android:label="@string/app_name"

        android:supportsRtl="true"

        android:theme="@style/AppTheme">

            android:name="com.baidu.speech.APP_ID"

            android:value="替换成你申请的AppID"/>

            android:name="com.baidu.speech.API_KEY"

            android:value="替换成你申请的API_KEY" />

            android:name="com.baidu.speech.SECRET_KEY"

            android:value="替换成你申请的SECRET_KEY" />

            android:name="com.baidu.speech.VoiceRecognitionService"

            android:exported="false" />

        <activity android:name=".MainActivity"

            android:configChanges="orientation|keyboardHidden|screenLayout"

            android:screenOrientation="portrait">

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

</manifest>

image

**3、将SDK中的app/libs/bdasr_V3_20190515_c9eed5d.jar 复制到您的项目的同名目录中。 **记得之后add as library

**4、将SDK中的app/src/main/jniLibs 下armeabi等5个目录,复制到您的项目的同名目录中。 **

5、activity_main.xml


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/activity_main"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    tools:context="com.unionman.speechdemo.MainActivity">

        android:id="@+id/btnStartRecord"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="@string/start_record"/>

        android:id="@+id/btnStopRecord"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="@string/stop_record"/>

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:layout_weight="2"

        android:orientation="vertical">

            android:layout_width="match_parent"

            android:layout_height="3dp"

            android:background="#000"/>

            android:layout_width="match_parent"

            android:layout_height="wrap_content">

                android:id="@+id/tvResult"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                android:text="@string/parse_process" />

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:layout_weight="1"

        android:orientation="vertical">

            android:layout_width="match_parent"

            android:layout_height="3dp"

            android:background="#000"/>

            android:layout_width="match_parent"

            android:layout_height="wrap_content">

                android:id="@+id/tvParseResult"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                android:text="@string/parse_result" />

6、MainActivity.java


package com.***.***;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.Manifest;

import android.content.pm.PackageManager;

//import android.support.v4.app.ActivityCompat;

//import android.support.v4.content.ContextCompat;

//import android.support.v7.app.AppCompatActivity;

import androidx.core.content.ContextCompat;

import androidx.core.app.ActivityCompat;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

import com.baidu.speech.EventListener;

import com.baidu.speech.EventManager;

import com.baidu.speech.EventManagerFactory;

import com.baidu.speech.asr.SpeechConstant;

import com.google.gson.Gson;

import com.unionman.speechdemo.asrfinishjson.AsrFinishJsonData;

import com.unionman.speechdemo.asrpartialjson.AsrPartialJsonData;

import org.json.JSONObject;

import java.util.ArrayList;

import java.util.LinkedHashMap;

import java.util.Map;

public class MainActivityextends AppCompatActivityimplements EventListener {

private static final StringTAG ="MainActivity";

    private ButtonbtnStartRecord;

    private ButtonbtnStopRecord;

    private TextViewtvResult;

    private TextViewtvParseResult;

    private EventManagerasr;

    private boolean logTime =true;

    private Stringfinal_result;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        initView();

        initPermission();

        asr = EventManagerFactory.create(this, "asr");

        asr.registerListener(this); //  EventListener 中 onEvent方法

        btnStartRecord.setOnClickListener(new View.OnClickListener() {

@Override

            public void onClick(View v) {

start();

            }

});

        btnStopRecord.setOnClickListener(new View.OnClickListener() {

@Override

            public void onClick(View v) {

stop();

            }

});

    }

private void initView() {

tvResult = (TextView) findViewById(R.id.tvResult);

        tvParseResult = (TextView) findViewById(R.id.tvParseResult);

        btnStartRecord = (Button) findViewById(R.id.btnStartRecord);

        btnStopRecord = (Button) findViewById(R.id.btnStopRecord);

        btnStopRecord.setVisibility(View.GONE);

    }

/**

    * android 6.0 以上需要动态申请权限

    */

    private void initPermission() {

String permissions[] = {Manifest.permission.RECORD_AUDIO,

                Manifest.permission.ACCESS_NETWORK_STATE,

                Manifest.permission.INTERNET,

                Manifest.permission.READ_PHONE_STATE,

                Manifest.permission.WRITE_EXTERNAL_STORAGE

        };

        ArrayList toApplyList =new ArrayList();

        for (String perm :permissions){

if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {

toApplyList.add(perm);

                //进入到这里代表没有权限.

            }

}

String tmpList[] =new String[toApplyList.size()];

        if (!toApplyList.isEmpty()){

ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);

        }

}

@Override

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

// 此处为android 6.0以上动态授权的回调,用户自行实现。

    }

/*

    * EventListener  回调方法    * name:回调事件    * params: JSON数据,其格式如下:*

* */

    @Override

    public void onEvent(String name, String params, byte[] data, int offset, int length) {

String result ="";

        if (length >0 && data.length >0) {

result +=", 语义解析结果:" +new String(data, offset, length);

        }

if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)) {

// 引擎准备就绪,可以开始说话

            result +="引擎准备就绪,可以开始说话";

        }else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN)) {

// 检测到用户的已经开始说话

            result +="检测到用户的已经开始说话";

        }else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_END)) {

// 检测到用户的已经停止说话

            result +="检测到用户的已经停止说话";

            if (params !=null && !params.isEmpty()) {

result +="params :" + params +"\n";

            }

}else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {

// 临时识别结果, 长语音模式需要从此消息中取出结果

            result +="识别临时识别结果";

            if (params !=null && !params.isEmpty()) {

result +="params :" + params +"\n";

            }

//            Log.d(TAG, "Temp Params:"+params);

            parseAsrPartialJsonData(params);

        }else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {

// 识别结束, 最终识别结果或可能的错误

            result +="识别结束";

            btnStartRecord.setEnabled(true);

            asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);

            if (params !=null && !params.isEmpty()) {

result +="params :" + params +"\n";

            }

Log.d(TAG, "Result Params:"+params);

            parseAsrFinishJsonData(params);

        }

printResult(result);

    }

private void printResult(String text) {

tvResult.append(text +"\n");

    }

private void start() {

tvResult.setText("");

        btnStartRecord.setEnabled(false);

        Map params =new LinkedHashMap();

        String event =null;

        event = SpeechConstant.ASR_START;

        params.put(SpeechConstant.PID, 1737); // 默认1536

        params.put(SpeechConstant.DECODER, 0); // 纯在线(默认)

        params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN); // 语音活动检测

        params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 2000); // 不开启长语音。开启VAD尾点检测,即静音判断的毫秒数。建议设置800ms-3000ms

        params.put(SpeechConstant.ACCEPT_AUDIO_DATA, false);// 是否需要语音音频数据回调

        params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);// 是否需要语音音量数据回调

        String json =null; //可以替换成自己的json

        json =new JSONObject(params).toString(); // 这里可以替换成你需要测试的json

        asr.send(event, json, null, 0, 0);

        printResult("输入参数:" + json);

    }

private void stop() {

asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);

    }

@Override

    protected void onDestroy() {

super.onDestroy();

        asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);

    }

private void parseAsrPartialJsonData(String data) {

Log.d(TAG, "parseAsrPartialJsonData data:"+data);

        Gson gson =new Gson();

        AsrPartialJsonData jsonData = gson.fromJson(data, AsrPartialJsonData.class);

        String resultType = jsonData.getResult_type();

        Log.d(TAG, "resultType:"+resultType);

        if(resultType !=null && resultType.equals("final_result")){

final_result = jsonData.getBest_result();

//            tvParseResult.setText("解析结果:" + final_result);

        }

}

private void parseAsrFinishJsonData(String data) {

Log.d(TAG, "parseAsrFinishJsonData data:"+data);

        Gson gson =new Gson();

        AsrFinishJsonData jsonData = gson.fromJson(data, AsrFinishJsonData.class);

        String desc = jsonData.getDesc();

        if(desc !=null && desc.equals("Speech Recognize success.")){

tvParseResult.setText("解析结果:" +final_result);

        }else{

String errorCode ="\n错误码:" + jsonData.getError();

            String errorSubCode ="\n错误子码:"+ jsonData.getSub_error();

            String errorResult = errorCode + errorSubCode;

            tvParseResult.setText("解析错误,原因是:" + desc +"\n" + errorResult);

        }

}

}

7、asrfinishjson/AsrFinishJsonData.java


package com.unionman.speechdemo.asrfinishjson;

public class AsrFinishJsonData {

private Stringerror;

    private Stringsub_error;

    private Stringdesc;

    private OriginResultorigin_result;

    public StringgetError() {

return error;

    }

public StringgetSub_error() {

return sub_error;

    }

public StringgetDesc() {

return desc;

    }

public OriginResultgetOrigin_result() {

return origin_result;

    }

}

8、asrfinishjson\OriginResult.java


package com.unionman.speechdemo.asrfinishjson;

public class OriginResult {

private Stringerror;

    private Stringsub_error;

    private Stringsn;

    private Stringdesc;

    public StringgetSn() {

return sn;

    }

public StringgetDesc() {

return desc;

    }

public StringgetError() {

return error;

    }

public StringgetSub_error() {

return sub_error;

    }

}

9、asrpartialjson\AsrPartialJsonData.java


package com.unionman.speechdemo.asrpartialjson;

import java.util.ArrayList;

public class AsrPartialJsonData {

private ArrayListresults_recognition;

    private OriginResultorigin_result;

    private Stringerror;

    private Stringbest_result;

    private Stringresult_type;

    public ArrayListgetResults_recognition() {

return results_recognition;

    }

public OriginResultgetOrigin_result() {

return origin_result;

    }

public StringgetBest_result() {

return best_result;

    }

public StringgetError() {

return error;

    }

public StringgetResult_type() {

return result_type;

    }

}

10、asrpartialjson\OriginResult.java


package com.unionman.speechdemo.asrpartialjson;

public class OriginResult {

private Stringcorpus_no;

    private Stringerr_no;

    private Stringsn;

    private Resultresult;

    public ResultgetResult() {

return result;

    }

public StringgetCorpus_no() {

return corpus_no;

    }

public StringgetErr_no() {

return err_no;

    }

public StringgetSn() {

return sn;

    }

}

11、asrpartialjson\Result.java


package com.unionman.speechdemo.asrpartialjson;

import java.util.ArrayList;

import java.util.List;

public class Result {

private ArrayListuncertain_word;

    private ArrayListword;

    public ArrayListgetUncertain_word() {

return uncertain_word;

    }

public ArrayListgetWord() {

return word;

    }

}


工程文件如下:

image

最终demo如下图:


demo.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342