實作這個功能的目的,是我看見我公司硬體工程師給客戶回答問題的時候用公司研發的APP,每次都是手動輸入打字,看著他帶著老花鏡的樣子,于心不忍,畢竟咱就是干這個的.
實作效果

集成 百度語音實時識別
https://ai.baidu.com/sdk#asr

AndroidManifest.xml 檔案
<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.WRITE_EXTERNAL_STORAGE" />
<!-- 藍牙錄音使用,不需要可以去除 -->
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<!-- 百度控制臺申請的KEY -->
<meta-data
android:name="com.baidu.speech.APP_ID"
android:value="22611822"/>
<meta-data
android:name="com.baidu.speech.API_KEY"
android:value="YoR10GzzuZ58FYLpQ1utD5vy"/>
<meta-data
android:name="com.baidu.speech.SECRET_KEY"
android:value="gGQvipUXC0dSSGmAQNMeHCMKTW4fGGrH"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
build.gradle
packagingOptions{
doNotStrip "*/*/libvad.dnn.so"
doNotStrip "*/*/libbd_easr_s1_merge_normal_20151216.dat.so"
}
集成jar包
dependencies {
//...省略
implementation files('libs\\bdasr_V3_20191210_81acdf5.jar')
}

到這里基本就可以集成了百度語音實時識別,但是這里有個坑.就是語音申請的時候得領取配額

一定要領取配額,不然一頓 4004,一開始我以為是集成錯誤導致了,包名檢查了N次…
使用方法
這里我直接附上我寫的代碼了
protected TextView txtResult;
private EventManager asr;
protected boolean enableOffline = false; // 測驗Unit 2.0 功能,必須一直聯網
private EditText etText;
private LinearLayout llView;
private CustomPopWindow mCustomPopWindowCause;
private TextView tvContent;
private TextView tvState;
private LinearLayout llClick;
/**
* 基于SDK集成2.2 發送開始事件
* 點擊開始按鈕
* 測驗引數填在這里
*/
@SuppressLint("HandlerLeak")
private void start() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
String event = null;
event = SpeechConstant.ASR_START; // 替換成測驗的event
if (enableOffline) {
params.put(SpeechConstant.DECODER, 2);
}
// 基于SDK集成2.1 設定識別引數
params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
params.put(SpeechConstant.PID, 15374); // 或 19364 Unit 2.0 固定pid,僅支持中文普通話
params.put(SpeechConstant.NLU, "enable");
params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 0); // 長語音
String json = null; // 可以替換成自己的json
json = new JSONObject(params).toString(); // 這里可以替換成你需要測驗的json
asr.send(event, json, null, 0, 0);
Log.e("X000", json + "");
}
/**
* 點擊停止按鈕
* 基于SDK集成4.1 發送停止事件
*/
private void stop() {
asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); //
}
/**
* enableOffline設為true時,在onCreate中呼叫
* 基于SDK離線命令詞1.4 加載離線資源(離線時使用)
*/
private void loadOfflineEngine() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put(SpeechConstant.DECODER, 2);
params.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets://baidu_speech_grammar.bsg");
asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, new JSONObject(params).toString(), null, 0, 0);
}
/**
* enableOffline為true時,在onDestory中呼叫,與loadOfflineEngine對應
* 基于SDK集成5.1 卸載離線資源步驟(離線時使用)
*/
private void unloadOfflineEngine() {
asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0); //
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.common_mini);
EventBus.getDefault().register(this);
initView();
initPermission();
// 基于sdk集成1.1 初始化EventManager物件
asr = EventManagerFactory.create(this, "asr");
// 基于sdk集成1.3 注冊自己的輸出事件類
asr.registerListener(this); // EventListener 中 onEvent方法
if (enableOffline) {
loadOfflineEngine(); // 測驗離線命令詞請開啟, 測驗 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 引數時開啟
}
}
// 基于sdk集成1.2 自定義輸出事件類 EventListener 回呼方法
// 基于SDK集成3.1 開始回呼事件
@Override
public void onEvent(String name, String params, byte[] data, int offset, int length) {
if (params != null && !params.isEmpty()) {
try {
JSONObject object = new JSONObject(params);
JSONArray jsonArray = object.getJSONArray("results_recognition");
StringBuffer str = new StringBuffer();
if (jsonArray != null || jsonArray.length() != 0) {
for (int i = 0; i < jsonArray.length(); i++) {
String msg = jsonArray.getString(i);
str.append(msg + " ");
}
tvContent.setText(str.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void initView() {
txtResult = (TextView) findViewById(R.id.txtResult);
etText = findViewById(R.id.et_text);
llView = findViewById(R.id.ll_layout);
findViewById(R.id.btn_x).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ShowVoice();
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void ConsultEvent(XYTextEvent item) {
String context = item.getContext();
String trim = etText.getText().toString().trim();
if (!trim.isEmpty()) {
etText.setText(trim + context);
} else {
etText.setText(context);
}
}
/**
* 展示語音
*/
@SuppressLint("ClickableViewAccessibility")
private void ShowVoice() {
final View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_windows, null);
mCustomPopWindowCause = new CustomPopWindow.PopupWindowBuilder(MainActivity.this)
.setView(contentView)
.enableBackgroundDark(true) //彈出popWindow時,背景是否變暗
.setBgDarkAlpha(0.6f) // 控制亮度
.enableOutsideTouchableDissmiss(true)
.create();
mCustomPopWindowCause.showAtLocation(llView, Gravity.FILL, 0, 0);
tvContent = contentView.findViewById(R.id.tv_content);
tvState = contentView.findViewById(R.id.tv_state);
llClick = contentView.findViewById(R.id.ll_click);
//觸摸手勢事件
llClick.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
tvState.setText("正在說...~");
llClick.setBackgroundResource(R.drawable.ra_bg);
start();
break;
case MotionEvent.ACTION_UP:
tvState.setText("按住說話~");
llClick.setBackgroundResource(R.drawable.re_bg);
stop();
EventBus.getDefault().post(new XYTextEvent(tvContent.getText().toString()));
mCustomPopWindowCause.dissmiss();
// etText.setText(tvContent.getText().toString());
break;
}
return true;
}
});
}
/**
* 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);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// 此處為android 6.0以上動態授權的回呼,用戶自行實作,
}
@Override
protected void onPause() {
super.onPause();
asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 基于SDK集成4.2 發送取消事件
asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
if (enableOffline) {
unloadOfflineEngine(); // 測驗離線命令詞請開啟, 測驗 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 引數時開啟
}
// 基于SDK集成5.2 退出事件管理器
// 必須與registerListener成對出現,否則可能造成記憶體泄露
asr.unregisterListener(this);
if (EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
}
附帶三方庫
implementation 'com.github.pinguo-zhouwei:CustomPopwindow:2.1.1'
implementation 'org.greenrobot:eventbus:3.1.1'
后記 :功能實作了,老工程師很開心.他跟我說他之所以打字,是因為他在給客戶回答問題的時候得思索一下…
至于語音輸入功能,他說現在的輸入法都有這個功能了.要不你打字的時候,試一下長按空格鍵…-_-||
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/41764.html
標籤:其他
上一篇:學習總結--第一周
下一篇:iOS 性能優化(二)安裝包瘦身
