写的第一篇博客,因为最近姐姐说起了一个段子, 一男子在地铁站手机找不到了,但是带了蓝牙耳机,耳机还有内容,男子想手机一定还在附近,随即大喊一句,悟空你在哪儿, 手机循环回答,我在这.....这时,拿手机那哥们回了男子一个尴尬而不失礼貌的微笑,哈哈
所以我想起讯飞语音,就试着写了一下语音唤醒的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"/>
<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"/>
<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();
}
};
}
}
布局:
结果展示: