Android 百度語音識別(詳細步驟+源碼)

前言

因爲項目中用到了語音識別的技術,但是項目源碼我不能公開,所以,重新寫一個簡單的集成教程,不喜可不看,不做鍵盤俠,文明你我他。
效果圖
在這裏插入圖片描述
識別結果
在這裏插入圖片描述
最終效果
在這裏插入圖片描述

源碼地址

正文

下面是詳細步驟,不漏過任何一個細節,力求讓你一步到位

① 創建平臺應用

既然使用了百度語音,自然免不了要註冊該平臺的賬號,否則憑什麼讓你使用,點擊百度智能雲進入,沒有賬號的可以先註冊賬號,註冊應該就不用我講解了吧?這裏默認都有賬號了,然後登錄
在這裏插入圖片描述
然後左側導航欄點擊找到語音技術
在這裏插入圖片描述
然後會進入一個應用總覽頁面,
在這裏插入圖片描述
然後點擊創建應用
在這裏插入圖片描述
在這裏插入圖片描述
立即創建
在這裏插入圖片描述
點擊查看應用詳情
在這裏插入圖片描述
這幾個值都是等下項目中要用的,請注意,最好是複製粘貼,不要手打,上圖中有一個下載SDK,點擊進入下載頁面,第一個就是
在這裏插入圖片描述
點擊下載到本地,下載之後是一個壓縮文件,解壓之後先不用管它,然後在Android Studio裏面創建一個項目

② 創建Android項目並配置

在這裏插入圖片描述
在這裏插入圖片描述
這時候你運行到自己的手機上,如果出現Hello World!,就說明你這個項目沒有問題。哎呀~不得了啊!你真是一個百年不遇的代碼奇才! 繼續啊!
File → New → Import Module…
在這裏插入圖片描述
通過上面的步驟,插入一個模塊進來
在這裏插入圖片描述
在這裏插入圖片描述
點擊OK

在這裏插入圖片描述
很明顯,我找到了,你呢?找到了就找到了,說個🔨啊,人格分裂 繼續啊,點擊Finish 就會在你當前的項目中加入這個模塊,與app是平級的。
在這裏插入圖片描述
這裏就是在加載模塊中的文件了,加載完畢之後,你可以打開settings.gradle,會發現多了一個 ‘:core’,當然這是在工程中加入了這個模塊。
在這裏插入圖片描述
還要在你的app裏面加入這個才能使用,
加入的方法有兩個,

1. 手動選擇

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
點擊OK,然後再點擊一次OK
在這裏插入圖片描述
模塊已經添加進來了,當然這樣比較繁瑣,還有更簡單的辦法下面可以自動添加依賴。

2. 自動添加依賴

在這裏插入圖片描述
找到app下面的build.gradle配置文件,在dependencies閉包下,加入

implementation project(path: ':core')

然後右上角點擊 Sync 同步到項目中

下面修改core的AndroidManifest.xml文件中的APP_ID、API_KEY、SECRET_KEY,裏面的值修改爲之前在平臺註冊應用生成的值。
在這裏插入圖片描述
在這裏插入圖片描述
改好之後,請注意,每個人都是不一樣,你如果發現你創建的應用的配置的值和我創建的是一模一樣的,你馬上去百度提BUG,他們的程序員要就要下崗了~

OK,現在配置也完成了,接下來就是使用了。

③ 使用

首先是修改
在這裏插入圖片描述
佈局修改的代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:gravity="center"
        android:id="@+id/tv_txt"
        android:padding="20dp"
        android:textColor="#000"
        android:text="識別到的內容"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="停止" />

    <Button
        android:id="@+id/btn_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="開始" />

</LinearLayout>

說道語音識別自然要用到這個麥克風,這個權限是需要動態申請的。

 /**
     * android 6.0 以上需要動態申請權限
     */
    private void initPermission() {
        String permissions[] = {Manifest.permission.RECORD_AUDIO,
                Manifest.permission.ACCESS_NETWORK_STATE,
                Manifest.permission.INTERNET,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        ArrayList<String> toApplyList = new ArrayList<String>();

        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);
        }

    }

    /**
     * 權限申請回調,可以作進一步處理
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        // 此處爲android 6.0以上動態授權的回調,用戶自行實現。
    }

得到權限之後就可以進行下一步了,首先是初始化控件以及語音是被的核心SDK

	protected TextView txtResult;//識別結果
    protected Button startBtn;//開始識別  一直不說話會自動停止,需要再次打開
    protected Button stopBtn;//停止識別

    private EventManager asr;//語音識別核心庫
	/**
     * 初始化控件
     */
    private void initView() {
        txtResult = (TextView) findViewById(R.id.tv_txt);
        startBtn = (Button) findViewById(R.id.btn_start);
        stopBtn = (Button) findViewById(R.id.btn_stop);

        startBtn.setOnClickListener(new View.OnClickListener() {//開始
            @Override
            public void onClick(View v) {
                asr.send(SpeechConstant.ASR_START, null, null, 0, 0);
            }
        });
        stopBtn.setOnClickListener(new View.OnClickListener() {//停止
            @Override
            public void onClick(View v) {
                asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);
            }
        });
    }

在onCreate方法中調用
在這裏插入圖片描述

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initPermission();

        //初始化EventManager對象
        asr = EventManagerFactory.create(this, "asr");
        //註冊自己的輸出事件類
        asr.registerListener(this); //  EventListener 中 onEvent方法
    }

同時還需要實現EventListener,注意到這個實現的是百度的,不是自帶的。
在這裏插入圖片描述
實現之後還需要一個回調方法,如下:

	/**
     * 自定義輸出事件類 EventListener 回調方法
     */
    @Override
    public void onEvent(String name, String params, byte[] data, int offset, int length) {
        
        if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
            // 識別相關的結果都在這裏
            if (params == null || params.isEmpty()) {
                return;
            }
            if (params.contains("\"final_result\"")) {
                // 一句話的最終識別結果
                txtResult.setText(params);
            } 
        }
        
    }

最後就是在onDestroy裏面關閉和處理

	@Override
    protected void onDestroy() {
        super.onDestroy();
        //發送取消事件
        asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
        //退出事件管理器
        // 必須與registerListener成對出現,否則可能造成內存泄露
        asr.unregisterListener(this);
    }

可以運行了
在這裏插入圖片描述
點擊開始,然後說 “你好”,識別出結果
在這裏插入圖片描述

可以看到,識別的結果還是蠻精準的,但是我們要的數據就只有那兩個字而已,所以要進行數據的解析了

④ JSON數據解析

通過剛纔代碼的中大日誌打印拿到JSON字符串,將這個字符串轉成實體bean.
在這裏插入圖片描述
轉出來的實體bean, 命名爲ASRresponse,代碼如下:

package com.llw.asrdemo;

import java.util.List;

public class ASRresponse {

    /**
     * results_recognition : ["你好,"]
     * result_type : final_result
     * best_result : 你好,
     * origin_result : {"asr_align_begin":80,"asr_align_end":130,"corpus_no":6835867007181645805,"err_no":0,"raf":133,"result":{"word":["你好,"]},"sn":"82d975e0-6eb4-43ac-a0e7-850bb149f28e"}
     * error : 0
     */

    private String result_type;
    private String best_result;
    private OriginResultBean origin_result;
    private int error;
    private List<String> results_recognition;

    public String getResult_type() {
        return result_type;
    }

    public void setResult_type(String result_type) {
        this.result_type = result_type;
    }

    public String getBest_result() {
        return best_result;
    }

    public void setBest_result(String best_result) {
        this.best_result = best_result;
    }

    public OriginResultBean getOrigin_result() {
        return origin_result;
    }

    public void setOrigin_result(OriginResultBean origin_result) {
        this.origin_result = origin_result;
    }

    public int getError() {
        return error;
    }

    public void setError(int error) {
        this.error = error;
    }

    public List<String> getResults_recognition() {
        return results_recognition;
    }

    public void setResults_recognition(List<String> results_recognition) {
        this.results_recognition = results_recognition;
    }

    public static class OriginResultBean {
        /**
         * asr_align_begin : 80
         * asr_align_end : 130
         * corpus_no : 6835867007181645805
         * err_no : 0
         * raf : 133
         * result : {"word":["你好,"]}
         * sn : 82d975e0-6eb4-43ac-a0e7-850bb149f28e
         */

        private int asr_align_begin;
        private int asr_align_end;
        private long corpus_no;
        private int err_no;
        private int raf;
        private ResultBean result;
        private String sn;

        public int getAsr_align_begin() {
            return asr_align_begin;
        }

        public void setAsr_align_begin(int asr_align_begin) {
            this.asr_align_begin = asr_align_begin;
        }

        public int getAsr_align_end() {
            return asr_align_end;
        }

        public void setAsr_align_end(int asr_align_end) {
            this.asr_align_end = asr_align_end;
        }

        public long getCorpus_no() {
            return corpus_no;
        }

        public void setCorpus_no(long corpus_no) {
            this.corpus_no = corpus_no;
        }

        public int getErr_no() {
            return err_no;
        }

        public void setErr_no(int err_no) {
            this.err_no = err_no;
        }

        public int getRaf() {
            return raf;
        }

        public void setRaf(int raf) {
            this.raf = raf;
        }

        public ResultBean getResult() {
            return result;
        }

        public void setResult(ResultBean result) {
            this.result = result;
        }

        public String getSn() {
            return sn;
        }

        public void setSn(String sn) {
            this.sn = sn;
        }

        public static class ResultBean {
            private List<String> word;

            public List<String> getWord() {
                return word;
            }

            public void setWord(List<String> word) {
                this.word = word;
            }
        }
    }
}

這裏我用GSON來解析JSON數據。
在這裏插入圖片描述

	//GSON
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

記得Sync一下
然後回到MainActivity
在這裏插入圖片描述
修改的代碼如下:

		Gson gson = new Gson();
        ASRresponse asRresponse = gson.fromJson(params, ASRresponse.class);//數據解析轉實體bean

        if(asRresponse == null) return;
        //從日誌中,得出Best_result的值纔是需要的,但是後面跟了一箇中文輸入法下的逗號,
        if(asRresponse.getBest_result().contains(",")){//包含逗號  則將逗號替換爲空格,這個地方還會問題,還可以進一步做出來,你知道嗎?
			txtResult.setText(asRresponse.getBest_result().replace(',',' ').trim());//替換爲空格之後,通過trim去掉字符串的首尾空格
        }else {//不包含
			txtResult.setText(asRresponse.getBest_result().trim());
        }

然後再運行一下
在這裏插入圖片描述
OK,搞定了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章