Unity 实战项目 ☀️| 接入科大讯飞语音SDK在Android Studio该如何操作! 系列共两万多字超级新手教程!
Posted 呆呆敲代码的小Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 实战项目 ☀️| 接入科大讯飞语音SDK在Android Studio该如何操作! 系列共两万多字超级新手教程!相关的知识,希望对你有一定的参考价值。
- 📢博客主页:https://blog.csdn.net/zhangay1998
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
- 📢未来很长,值得我们全力奔赴更美好的生活✨
目录
📢前言
-
系列文章总共分为三篇这是Unity接入语音识别的第二篇,第一篇是怎样获取到讯飞语音的相关SDK
-
没有看的小伙伴可以去看一下这篇文章,很简单的获取SDK介绍!
🍉在android Studio该如何操作讯飞语音SDK
- 虽然最终效果是在Unity中接入语音识别SDK,但是在Android Studio(下面统称AS)这一步才是最重要的
- 相关的语音识别的代码和逻辑都是在AS写的,最终实现在Unity中的效果也不过是调用AS端的接口来实现的
- 所以说这一块接入也是可以在AS中打包成APK直接导出的!
那这里就正式开始在AS端的操作吧!
🏳️🌈第一步:打开Android Studio新建一个项目
打开AS,新建一个项目,选择一个Empty Activity,点击Next
然后来到下一步,自己修改工程的名字和路径,其他的忽略即可!
也可以自定义一个最低支持的安卓版本Minimnum SDK,不过无伤大雅!看你心情~
点击Finish之后,一个工程就创建好了,打开就是如下画面。
但是我们并不使用这个Activity,具体接着往下看
🏳️🌈第二步:建立最终使用的Module文件夹
然后我们这里新建一个module,起一个名字
File-new-new Module(下图)
然后选中Android Library,点击Next
然后修改一个名字,点击Finish即可!
然后创建完成后就来到了下面这个页面,这个iFlytek项目就是我们要进行操作的文件夹。
红框里面的内容就是我们要操作的地方!
🏳️🌈第三步:讯飞SDK集成
这一步较为繁琐,跟配置环境差不多,就是将各种Jar包和so文件添加到AS中去
下面一步一步来看!
1.接入Unity的ckasses.jar包
-
我们首先需要拿到Unity的class包,这个包在安装Unity的路径下
-
具体路径:Unity\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Variations\\mono\\Release\\Classes
-
比如我的路径就是:D:\\QMDownload\\SoftMgr\\2020.3.8f1c1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Variations\\mono\\Release\\Classes
直接选中classes.jar复制到AS中的iflytek-libs文件夹下!
操作如下:
这样就把Unity的Jar包加到AS了,下面再把我们下载的讯飞SDK中的Jar包添加进去
2.接入讯飞语音的classess.jar包
找到我们下载解压的讯飞语音的SDK,进入libs文件夹下,将那三个文件前复制到libs中去!
与上一步Unity的Jar操作一样!
效果如下,我们总共添加了四个文件,分别是从Unity复制过去的Jar包和从讯飞的SDK复制过去的三个文件
3.关联两个classes.jar包
有的小伙伴复制过去是这样的,两个Jar包并不能展开
那是因为还没有关联,下面就来关联一下Jar包
第一种方法:
选中两个.jar包,右键
右键libs文件夹下两个.jar文件,Add As Libray…
第二种方法:
也可以右键 iflyte -> Open Module Settings
将.jar文件手动添加,添加完了记得点apply应用一下
关联之后,还是在 右键 iflyte -> Open Module Settings
这里可以看有没有关联完毕,没关联上的话,这里不会显示这俩个.jar包
4.添加libmsc.so
在iflytek的main文件夹下新建一个Jnilibs文件夹,注意字符不能打错!!
然后将libmsc.so添加进去,ibmsc.so在讯飞SDK文件夹里的libs\\armeabi-v7a下,最好连armeabi-v7a文件夹一起复制进去。
效果如下:
这样的话so文件就算是添加进去了,下一步 来修改AndroidManifest文件
5.修改AndroidManifest文件
将 app -> src -> main -> res 下的AndroidManifest中的所有内容
复制到我们iflytek -> src -> main -> res 的AndroidManifest中,如下
复制到我们下面这个iflytek -> src -> main -> res 的AndroidManifes之后会报红
那我们把中间框的报红的都删掉,上面的package也改一下名字,改为:com.example.iflytek
下面的也要改为:android:name=".MainPort",这里要注意哈
我下面写错了,这里一定要改成MainPort(要改成继承UnityPlayerActivity的类,这里是MainPort)
如果这里不对,app直接打不开,也算是一个小失误了
改完名字后是下面这样的,但是还没完!
还要在这里加上下面一行代码,注意加入代码的位置别放错了!
加入这一行是为了在Unity中可以正常调用,不加这一行到时候就调用不到啦!
<meta-data android:name="unityplayer.UnityActivity" android:value="true"/>
最后,再加上权限:
<!--连接网络权限,用于执行云端语音能力 -->
<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" />
AndroidManifes效果如下,我这里是有一行报错,直接右键自动修复就好了!
最终的效果如下,如果出现哪里报错,那应该是哪个地方添加代码的位置不对
或者多删除了某个符号,仔细看看就好了!
到这一步结束,其实算刚配置完环境
真正的代码还没开始写呢!下面一起来看看怎样写代码!
🏳️🌈第四步:新建一个class开始写代码
创建类
然后我们选中com.example.iflytek ->New->Java Class
新建一个Class写代码用的
改个名字点击OK即可!第一个asrManager类就建立完成了
然后老样子再来一次,创建一个新的
这里的话,将它改为一个接口,点击中间那个框将class改为Interface即可,点击OK
然后再创建两个类:MainPort和JsonParser
整理一下,我们现在一共有三个类和一个接口,如下所示:
上代码
-
直接上代码,然后下面再来说一下,每个脚本是干嘛的!
-
如果复制完一下代码,AS中的import com.unity3d.player.UnityPlayerActivity;这一行会报错
-
说明Unity的Jar包没有正确的导入关联,我第一次用2020版本的导入就是报红
-
所以换了一个unity2019的Jar包导入就正常了!
-
asrManager类:这个脚本特别需要注意!!!这个地方一定要换成我们去讯飞官网自己创建的应用
-
每个应用都有自己的APPID,这里使用我这个肯定会出问题,换成自己的APPID就好了!
-
之前有的小伙伴出错,很可能就是这里出错了!
package com.example.iflytek;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.example.iflytek.JsonParser;
import com.example.iflytek.MainPort;
import com.example.iflytek.UnityasrEventCallback;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.unity3d.player.UnityPlayer;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class asrManager {
private SpeechRecognizer mIat;
private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
private static Activity activity;
private static asrManager asrManager;
public static asrManager getasrManager(Activity context) {
if (asrManager == null) {
asrManager = new asrManager(context);
}
return asrManager;
}
public asrManager(Activity activity) {
this.activity=activity;
}
//初始化
public void Initasr() {
Log.i("@@@", "语音初始化+获取权限 ");
getPermission();
SpeechUtility.createUtility(activity, SpeechConstant.APPID + "=60307482");
mIat = SpeechRecognizer.createRecognizer(activity, null);
//设置mIat的参数
//表示是什么服务
mIat.setParameter(SpeechConstant.DOMAIN, "iat");
//设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//接受语言的类型
mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
//使用什么样引擎
mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
}
RecognizerListener mRecognizerLis=new RecognizerListener() {
@Override
public void onVolumeChanged(int i, byte[] bytes) {
}
@Override
public void onBeginOfSpeech() {
}
@Override
public void onEndOfSpeech() {
}
@Override
public void onResult(RecognizerResult recognizerResult, boolean b) {
printResult(recognizerResult);
}
@Override
public void onError(SpeechError speechError) {
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//解析Json的方法
//方法来自speechDemo->java->voicedemo->IatDemo中的printResult方法
private void printResult(RecognizerResult results) {
String text = JsonParser.parseIatResult(results.getResultString());
String sn = null;
// 读取json结果中的sn字段
try {
JSONObject resultJson = new JSONObject(results.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
}
mIatResults.put(sn, text);
StringBuffer resultBuffer = new StringBuffer();
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}
//将语音内容回调给Unity
mCallback.Speechcontent(resultBuffer.toString());
//显示完语音的Toast
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,"语音识别完成",Toast.LENGTH_SHORT).show();
}
});
}
//获取权限
public void getPermission() {
Log.d("@@@", "开始获取各类权限 ");
activity.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 0x01);
Log.d("@@@", "各类权限获取成功 ");
}
public void getBeginListen(){
Log.d("@@@", "开始判断权限是否获取 ");
//使用录音前首先需要获取权限
int permissionCheck= activity.checkSelfPermission(android.Manifest.permission.RECORD_AUDIO);
//如果有权限则返回PackageManager.PERMISSION_GRANTED,否则返回PackageManager.PERMISSION_DENIED。
if(permissionCheck!= PackageManager.PERMISSION_GRANTED) {//未获取权限时
//请求获取权限
Log.d("@@@", "正在请求权限 ");
activity.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 0x01);
//用new String[]的原因是可以在String[]中存储多个需要的权限,一次过请求
//将回调onRequestPermissionsResult()方法
}else{
//开始识别
mIat.startListening(mRecognizerLis);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,"语音识别开始",Toast.LENGTH_LONG).show();
}
});
}
}
public int beginTest(int a, int b){
//交互测试
return a+b;
}
//把消息发送给Unity场景中iFlytekASRController物体上的tryConnected方法
public void connected(){
//UnityPlayer.UnitySendMessage("iFlytekASRController","tryConnected","连通成功了");
Log.d("@@@", "SetListenerCB start ");
mCallback.Test1("连通成功了");
Log.d("@@@", "SetListenerCB end ");
}
private UnityasrEventCallback mCallback;
//获取接口内容
public void setCallback(UnityasrEventCallback callback){
Log.d("@@@", "UnitasrEventCallback setCallback start ");
mCallback = callback;
Log.d("@@@", "UnityasrEventCallback setCallback end ");
}
}
UnityasrEventCallback代码:
package com.example.iflytek;
public interface UnityasrEventCallback {
public void Speechcontent(String content);
public void Test1(String msg);
}
MainPort代码:
package com.example.iflytek;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.example.iflytek.UnityasrEventCallback;
import com.example.iflytek.asrManager;
import com.iflytek.cloud.SpeechUtility;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainPort extends UnityPlayerActivity {
private asrManager masrManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化
masrManager = asrManager.getasrManager(MainPort.this);
masrManager.Initasr();
UnityPlayer.UnitySendMessage("iFlytekASRController","InitCallBack","初始化成功了");
}
// =========================ASR========================= }
//得到Unity的回调
public void setUnityasrEventCallback(UnityasrEventCallback callback){
Log.d("@@@", "setUnityBatteryEventCallback callback ========= " +callback);
if(masrManager != null) {
masrManager.setCallback(callback);
}
}
public void unityStartSpeech(){
masrManager.getBeginListen();
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 0x01: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("@@@", "进入获取权限成功的回调了 ");
// permission was granted, yay以上是关于Unity 实战项目 ☀️| 接入科大讯飞语音SDK在Android Studio该如何操作! 系列共两万多字超级新手教程!的主要内容,如果未能解决你的问题,请参考以下文章
Unity 实战项目 ☀️| 接入科大讯飞语音SDK在Android Studio该如何操作! 系列共两万多字超级新手教程!
Unity 实战项目 ☀️| Unity接入 百度语音识别 SDK!一篇文章搞定在Unity中实现语音识别!(万字完整教程)