寫的第一篇博客,因爲最近姐姐說起了一個段子, 一男子在地鐵站手機找不到了,但是帶了藍牙耳機,耳機還有內容,男子想手機一定還在附近,隨即大喊一句,悟空你在哪兒, 手機循環回答,我在這.....這時,拿手機那哥們回了男子一個尷尬而不失禮貌的微笑,哈哈
所以我想起訊飛語音,就試着寫了一下語音喚醒的Demo, 也借鑑了很多前輩的博客, 就不一一列舉了,各位不喜勿噴
接下來進入正題,首先在訊飛官網下載對應的SDK, 下載之前需要開通服務,如圖
Step1: 進入訊飛開放平臺
進入後點擊立即開通
Step2: 創建應用開通服務
Step3: 應用可享受3個裝機量,5個喚醒詞, 35天試用,需要用到的就是提供的APPID
Step4: 進來服務管理後, 輸入5個喚醒詞,生成體驗包
Step5: 下載體驗包,注意,每個喚醒詞不一樣,服務不一樣,生成的SDK裏的資源是不一樣的
下載完後的目錄是這樣
libs下是要用到的jar包和各個平臺的so文件,直接放入項目的libs目錄
res目錄下的爲對應APPID生成的資源文件,把裏面的東西放入項目的assets目錄下
sample中是官方提供的Demo,其實還是比較全面的
其他幾個txt大家可以自己看一下,是一些版本更新日誌,wordlist是你的關鍵詞
Step6:
在工程 AndroidManifest.xml 文件中添加如下權限
<!--連接網絡權限,用於執行雲端語音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--獲取手機錄音機使用權限,聽寫、識別、語義理解需要用到此權限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--讀取網絡信息狀態 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--獲取當前wifi狀態 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允許程序改變網絡連接狀態 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--讀取手機信息權限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--讀取聯繫人權限,上傳聯繫人需要用到此權限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存儲寫權限,構建語法需要用到此權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存儲讀權限,構建語法需要用到此權限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置權限,用來記錄應用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手機定位信息,用來爲語義等功能提供定位,提供更精準的服務-->
<!--定位信息是敏感信息,可通過Setting.setLocationEnable(false)關閉定位請求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人臉識別,還要添加:攝相頭權限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
注意:如需在打包或者生成APK的時候進行混淆,請在proguard.cfg中添加如下代碼:
-keep class com.iflytek.**{*;}
-keepattributes Signature
Step7: 初始化, 可以放在Application或Activity的onCreate()中初始化(請勿在字符串加各種字符)
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=你的appid");
還有其他可以設置的參數
createUtility方法的第二個參數爲傳入的初始化參數列表,可配置的參數如下:
參數 | 說明 | 必填 |
---|---|---|
appid | 8位16進制數字字符串,應用的唯一標識,與下載的SDK一一對應。 | 是 |
usr | 開發者在雲平臺上註冊的賬號。 | 否 |
pwd | 賬號對應的密碼,與賬號同時存在。 | 否 |
engine_mode | 引擎模式,可選值爲:msc:只使用MSC的能力;plus:只使用語記能力;auto:雲端使用MSC,本地使用語記;默認取值爲auto。注:使用MSC本地功能的請設置爲msc。 | 否 |
force_login | 在createUtility時會對進程名稱進行檢查,如果名稱與應用包名不一致則不進行login操作,返回null,用以規避在子進程反覆進行調用的問題。此參數設置是否強制login。默認值:false (進行檢查,不強制login)。 | 否 |
lib_name | 在createUtility時會加載動態庫,此時可以傳入動態庫名稱。例如:libmsc_xxx_1072.so(xxx爲您的公司名,1072爲科大訊飛sdk版本號), 默認值:msc。注:如您是預裝軟件,爲了避免動態庫衝突建議修改名稱。 | 否 |
注意:參數需要以鍵值對的形式存儲在字符串中傳入createUtility方法,以逗號隔開,如“appid=12345678,usr=iflytekcloud,pwd=123456”。
Step8: 工具類
import org.json.JSONException;
import org.json.JSONObject;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
/**
* Created by Administrator on 2018/2/28.
* 訊飛語音喚醒
*/
public abstract class WakeUpUtil {
/**
* 喚醒的回調
*/
public abstract void wakeUp();
// Log標籤
private static final String TAG = "WakeUpUtil";
// 上下文
private Context mContext;
// 語音喚醒對象
private VoiceWakeuper mIvw;
private int curThresh = 40;
public WakeUpUtil(Context context) {
mContext = context;
// 初始化喚醒對象
mIvw = VoiceWakeuper.createWakeuper(context, null);
}
/**
* 獲取喚醒詞功能
*
* @return 返回文件位置
*/
private String getResource() {
final String resPath = ResourceUtil.generateResourcePath(mContext,RESOURCE_TYPE.assets, "ivw/" + mContext.getString(R.string.IflytekAPP_id) + ".jet");
return resPath;
}
/**
* 喚醒
*/
public void wake() {
// 非空判斷,防止因空指針使程序崩潰
mIvw = VoiceWakeuper.getWakeuper();
if (mIvw != null) {
// textView.setText(resultString);
// 清空參數
mIvw.setParameter(SpeechConstant.PARAMS, null);
// 設置喚醒資源路徑
mIvw.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
// 喚醒門限值,根據資源攜帶的喚醒詞個數按照“id:門限;id:門限”的格式傳入
mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:" + curThresh);
// 設置喚醒模式
mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
// 設置持續進行喚醒
mIvw.setParameter(SpeechConstant.KEEP_ALIVE, "1");
mIvw.startListening(mWakeuperListener);
} else {
Toast.makeText(mContext, "喚醒未初始化", Toast.LENGTH_SHORT).show();
}
}
public void stopWake() {
mIvw = VoiceWakeuper.getWakeuper();
if (mIvw != null) {
mIvw.stopListening();
} else {
Toast.makeText(mContext, "喚醒未初始化", Toast.LENGTH_SHORT).show();
}
}
String resultString = "";
private WakeuperListener mWakeuperListener = new WakeuperListener() {
@Override
public void onResult(WakeuperResult result) {
try {
String text = result.getResultString();
JSONObject object;
object = new JSONObject(text);
StringBuffer buffer = new StringBuffer();
buffer.append("【RAW】 " + text);
buffer.append("\n");
buffer.append("【操作類型】" + object.optString("sst"));
buffer.append("\n");
buffer.append("【喚醒詞id】" + object.optString("id"));
buffer.append("\n");
buffer.append("【得分】" + object.optString("score"));
buffer.append("\n");
buffer.append("【前端點】" + object.optString("bos"));
buffer.append("\n");
buffer.append("【尾端點】" + object.optString("eos"));
resultString = buffer.toString();
stopWake();
wakeUp();
} catch (JSONException e) {
resultString = "結果解析出錯";
e.printStackTrace();
}
}
@Override
public void onError(SpeechError error) {
Log.i(TAG, error.getPlainDescription(true));
}
@Override
public void onBeginOfSpeech() {
Log.i(TAG, "開始說話");
}
@Override
public void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
}
@Override
public void onVolumeChanged(int i) {
}
};
}
Step9: 測試類
public class MainActivity extends AppCompatActivity {
private TextView mTvLog;
private WakeUpUtil wakeUpUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=" +getString(R.string.IflytekAPP_id));
mTvLog = (TextView) findViewById(R.id.tv_log);
mTvLog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 開啓喚醒
wakeUpUtil.wake();
}
});
wakeUpUtil = new WakeUpUtil(this) {
@Override
public void wakeUp() {
Toast.makeText(MainActivity.this, "喚醒成功", Toast.LENGTH_SHORT).show();
// 開啓喚醒
wakeUpUtil.wake();
}
};
}
}
佈局:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#000">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF000000"
android:gravity="center"
android:padding="10dp"
android:text="喚醒詞:你好悟空, 悟空你好, 悟空出來"
android:textColor="#FFFFFFFF"
android:textSize="20dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFFFFFFF" />
<TextView
android:id="@+id/tv_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF000000"
android:gravity="center"
android:padding="10dp"
android:text="點擊開始喚醒"
android:textColor="#FFFFFFFF"
android:textSize="10dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFFFFFFF" />
</LinearLayout>
結果展示: