讯飞语音android
2018-10-26 09:19:00 weixin_34413103 阅读数 29

讯飞准备工作

想要接入讯飞语音听写功能,需要在讯飞开放平台注册应用https://www.xfyun.cn/,并且开通语音听写服务

8794020-48df75d9bf25b873.png
image.png

添加libs文件
将在官网下载的Android SDK 压缩包中libs目录下所有子文件拷贝至Android工程的libs目录下
下载地址:https://www.xfyun.cn/sdk/dispatcher
更多关于SDK文档:https://doc.xfyun.cn/msc_android/index.html

清单文件中添加权限

<!--连接网络权限,用于执行云端语音能力 -->
<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" />

语音识别 基础的 Activity

 public static final String PRIVATE_SETTING="com.iflytek.setting";           //缓存数据的名称
    private static final String TAG = "BasicIatActivity";
    private EditText mContent;                          //显示内容
    // 语音听写对象
    private SpeechRecognizer mIat;
    // 语音听写UI
    private RecognizerDialog mIatDialog;
    // 用HashMap存储听写结果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
    private SharedPreferences mSharedPreferences;
    private Toast mToast;
    // 引擎类型
    private String mEngineType = SpeechConstant.TYPE_CLOUD;
    int ret = 0; // 函数调用返回值
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //XXXXXX:你的appid
        SpeechUtility.createUtility(this, SpeechConstant.APPID + "=XXXXXX");
        Log.d(TAG, "onCreate--->");
        initIat();
        //初始化组件   后期修改为,程序一进入的时候进行初始化
        mToast = Toast.makeText(IatBasicActivity.this,"",Toast.LENGTH_SHORT);
    }
    /**
     * 显示toast
     * @param content  待显示的内容
     */
    public void showTip(String content){
        mToast.setText(content);
        mToast.show();
    }
    /**
     * 初始化 EditText 在需要调用语音接口中的类的初始化方法中调用该方法
     *
     * @param mContent
     */
    public void initIatData(EditText mContent) {
        this.mContent = mContent;
    }
    /**
     * 初始化语音识别中的对象
     */
    private void initIat() {
        // 使用SpeechRecognizer对象,可根据回调消息自定义界面;
        mIat = SpeechRecognizer.createRecognizer(this, mInitListener);
        // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
        // 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
        mIatDialog = new RecognizerDialog(this, mInitListener);
        mSharedPreferences = getSharedPreferences(PRIVATE_SETTING,
                Activity.MODE_PRIVATE);
    }
    /**
     * 初始化监听器
     */
    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.d(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失败,错误码:" + code);
            }
        }
    };
    /**
     * 听写UI监听器
     */
    private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, results.getResultString());
            printResult(results, mContent);
            Log.d(TAG, results.getResultString());
        }
        /**
         * 识别回调错误.
         */
        public void onError(SpeechError error) {
            showTip(error.getPlainDescription(true));
        }
    };
    /**
     * 听写监听器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        @Override
        public void onBeginOfSpeech() {
            // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
            showTip("开始说话");
        }
        @Override
        public void onError(SpeechError error) {
            // Tips:
            // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
            // 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
            showTip(error.getPlainDescription(true));
        }
        @Override
        public void onEndOfSpeech() {
            // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
            showTip("结束说话");
        }
        @Override
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, results.getResultString());
            printResult(results, mContent);
            Log.d(TAG, results.getResultString());
            if (isLast) {
                // TODO 最后的结果
            }
        }
        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            showTip("当前正在说话,音量大小:" + volume);
            Log.d(TAG, "返回音频数据:" + data.length);
        }
        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
            //  if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //      String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //      Log.d(TAG, "session id =" + sid);
            //  }
        }
    };
    /**
     * 参数设置
     *
     * @param
     * @return
     */
    public void setParam() {
        // 清空参数
        mIat.setParameter(SpeechConstant.PARAMS, null);
        // 设置听写引擎
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
        // 设置返回结果格式
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
        String lag = mSharedPreferences.getString("iat_language_preference",
                "mandarin");
        if (lag.equals("en_us")) {
            // 设置语言
            mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
        } else {
            // 设置语言
            mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
            // 设置语言区域
            mIat.setParameter(SpeechConstant.ACCENT, lag);
        }
        // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
        mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000"));

        // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
        mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000"));

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1"));

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");
    }


    /**
     * 触发点击事件时的方法
     */
    public void clickMethod() {
        mContent.setText(null);// 清空显示内容
        mIatResults.clear();
        // 设置参数
        setParam();
        boolean isShowDialog = mSharedPreferences.getBoolean(getString(R.string.pref_key_iat_show), true);
        if (isShowDialog) {
            // 显示听写对话框
            mIatDialog.setListener(mRecognizerDialogListener);
            mIatDialog.show();
            showTip(getString(R.string.text_begin));
        } else {
            // 不显示听写对话框
            ret = mIat.startListening(mRecognizerListener);
            if (ret != ErrorCode.SUCCESS) {
                Log.d(TAG, "听写失败,错误码:" + ret);
            } else {
                showTip(getString(R.string.text_begin));
            }
        }
    }

    /**
     * 显示结果,并赋值到EditText文本框中
     *
     * @param results
     * @param editText
     */
    private void printResult(RecognizerResult results, EditText editText) {
        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));
        }
        String content = resultBuffer.toString();
        Log.d(TAG, content);
        content = content.replace("。", "".trim());           //去掉最后面的 。
        editText.setText(content);
        editText.setSelection(content.length());
    }

        @Override
        public void onStart() {
            super.onStart();
        }

        @Override
        public void onStop() {
            super.onStop();
        }

MainActivity


public class MainActivity  extends IatBasicActivity implements View.OnClickListener {

    private EditText mContent;
    private Button mBtnVoice;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

    }

    /**
     * 初始化视图
     */
    private void initView(){
        mContent = findViewById(R.id.et_content);
        mBtnVoice =findViewById(R.id.btn_voice);
        mBtnVoice.setOnClickListener(this);
        //调用父类方法
        initIatData(mContent);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_voice:
                requestPower();
                break;
        }
public void requestPower(){
        //判断是否已经赋予权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED){
//            //如果应用之前请求过此权限,但是用户拒绝了请求,此方法放回true
//            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
//                    Manifest.permission.RECORD_AUDIO)){
//                //写对话框,为什么申请权限,并在对话框的确认键后续再次申请权限
//                Toast.makeText(this, "申请权限", Toast.LENGTH_SHORT).show();
//            }else {
                //申请权限,字符串数组内是一个或多个要申请的权限,
                // 1是申请权限结果的返回参数,在onRequestPermissionsResult可以得知申请结果
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.RECORD_AUDIO,}, 1);
//            }
        }else {
            clickMethod();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode ==1){
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i]==PERMISSION_GRANTED) {
                    clickMethod();
                }else {
                    Toast.makeText(this, "权限"+permissions[i]+"申请失败", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
 }

2016-10-31 12:59:36 u013806766 阅读数 1036

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

前段时间火了一个很牛的讯飞语音,去看官方文档,瞬间蒙逼,官方是用的eclipse,我用的Android Studio。好了,能上代码尽量不BB。
先来看看gradle里面要配置的东西。

module里面:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.jakewharton.butterknife'

添加butterknife,然后再来看看

dependencies里面要写的:

compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
compile files('libs/Msc.jar')
compile files('libs/Sunflower.jar')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.code.gson:gson:2.7'

添加了butterknife的包,并apt,然后呢,就要把官方要的包给放进去,没错,就是Msc.jar和Sunflower.jar,并把gson给弄进去,说到gson解析,那是没的说,好用。

Project的gradle里面的dependencies:

classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

到这里,还不算结束,因为还有so文件,将项目换成Project Files展示方式,找到app–>src–>main,新建jniLibs,记得L要大写,然后把东西放进去。嗯,对,就像这样:

这里写图片描述

不要问我为什么文件都是红色,本来想传git,结果不会弄。。。
到这里,项目需要的包就弄完了。下面来看看manifest里面需要添加的权限

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" />

来来来,看看他的返回结果然后来写我们的bean
这里写图片描述

可以看到,一共3个list,我。。。还是先写最里面的吧。记得Getter and Setter啊
另外,变量的名字要和他返回的相同,便于gson解析。

TalkBackChineseWordVo

    /**
     * word,单字
     */
    private String w;
    /**
     * score,分数
     */
    private int sc;

TalkBackWordsVo

    /**
     * begin,开始
     */
    private int bg;
    /**
     * chinese word,中文分词
     */
    private List<TalkBackChineseWordVo> cw;

TalkBackVo

/**
     * sentence,第几句
     */
    private int sn;
    /**
     * last sentence,是否最后一句
     */
    private boolean ls;
    /**
     * begin,开始
     */
    private int bg;
    /**
     * end,结束
     */
    private int ed;
    /**
     * words,词
     */
    private List<TalkBackWordsVo> ws;

在Activity中声明:

//语音合成器
private SpeechSynthesizer mSynthesizer;

onCreate中:
APPID是自己申请的,直接把12345678替换成申请好的ID

//语音初始化,在使用应用使用时需要初始化一次就好,如果没有这句会出现10111初始化失败
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=12345678");
//处理语音合成关键类
mSynthesizer = SpeechSynthesizer.createSynthesizer(this, mInitListener);

mInitListener

    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.e("tag", "initListener init code = " + code);
        }
    };

初始化成功就会打印tag: initListener init code = 0,不要问我为什么,因为成功状态的code就是0,哈哈哈哈。
接下来,看下语音播报

                //设置发音人
                mSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
                //设置音调
                mSynthesizer.setParameter(SpeechConstant.PITCH, "50");
                //设置音量
                mSynthesizer.setParameter(SpeechConstant.VOLUME, "50");
                int code;
                code = mSynthesizer.startSpeaking("你想要我说什么?", mTtsListener);
                Log.e("tag", "mSynthesizer start code = " + code);

发音人还有很多选项,大家可参照官方文档中的发音人列表选择自己喜欢的。
startSpeaking方法的第一个参数就是播报的内容。

mTtsListender代码如下:
里面的方法,一猜名字就看懂了的,我就不贴出来咯

    //语音合成器listener
    private SynthesizerListener mTtsListener = new SynthesizerListener() {
        /**
        *方法未贴出,完整方法有onSpeakBegin,onBufferProgress,onSpeakPaused,
        *             onSpeakResumed,onSpeakProgress,onCompleted,onEvent
        */
    };

接下来就是语音识别了,官方给出的是用dialog来实现,方法已经封装好了,我们就先来搞一搞。
语音识别dialog

                //语音识别dialog
                RecognizerDialog mDialog = new RecognizerDialog(this, mInitListener);
                //设置accent、language等参数
                mDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
                mDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
                mDialog.setListener(mRecognizerDialogListerer);
                mDialog.show();

诶,敲黑板啦,重点来了:

看这名字也知道,识别器的监听嘛,哈哈。

private RecognizerDialogListener mRecognizerDialogListerer = new RecognizerDialogListener() {
    @Override
    public void onResult(RecognizerResult recognizerResult, boolean isLast) {}

    @Override
    public void onError(SpeechError speechError) {}
};

其中,onResult方法中,是重点,这时候会把识别结果返回给我们,期间可能会多次调用此方法。
recognizerResult就是返回的结果,isLast即判断是否是返回结果的最后一条
记得声明gson和list

private static Gson gson = new Gson();
private List<TalkBackVo> talkBackVoList;

下面来看看怎么去获取最终的返回结果。

String jsonStr = new String(recognizerResult.getResultString());
//此处type中写TalkBackVo。
Type type = new TypeToken<TalkBackVo>() {}.getType();
TalkBackVo talkBackVo = gson.fromJson(jsonStr, type);
talkBackVoList.add(talkBackVo);//将此vo添加到我们的list中
String finalStr = "";//识别的最终结果
//当是最后一句话时,才执行拼接字段操作
if (isLast) {
    for (int i = 0; i < talkBackVoList.size(); i++) {
        for (int j = 0; j < talkBackVoList.get(i).getWs().size(); j++) {
            for (int k = 0; k < talkBackVoList.get(i).getWs().get(j).getCw().size(); k++) {
                finalStr = finalStr + talkBackVoList.get(i).getWs().get(j).getCw().get(k).getW();
            }
         }
     }
}

gson会自动根据key去把value设置进去,省去手动解析的大半时间。

一定要最后一条的时候才去拼接。但是不知道为什么,我说“英雄联盟”的时候,他先给我返回一条“英雄”和“联盟”,然后再是一条“。”是的,只有一个句号。不过拼接出来就是完整的“英雄联盟。”

好了,我的装逼到此结束,谢谢各位。demo中还有开启悬浮框的代码,还有不用dialog语音识别的代码段,买一赠N,哈哈哈,良心商家。

讯飞开发平台:http://www.xfyun.cn/doccenter/awd
demo地址:http://download.csdn.net/detail/u013806766/9668792


2016年11月1日更新,搞定github了,请各位审阅,以后如有更新,均在github。

github地址:https://github.com/SimbaLiu/VCApp

2019-03-14 09:59:22 weixin_43117800 阅读数 88

在这里插入图片描述
1:讯飞开放平台注册登录:https://www.xfyun.cn/?ch=bdtg
2:在这里插入图片描述

3:创建新应用获取APPID值
在这里插入图片描述

4:注册好就可以直接在项目中使用appid值
5:将下载的sdk中libs文件下得jar包放入项目中libs文件下,全选右键add添加一下
在这里插入图片描述

6:清单文件中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" />


    <application
        ***android:name=".app.App"***//记住加入这个
        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">

        <activity android:name=".StartActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity" />
    </application>

7:代码结构
在这里插入图片描述

8:App

public class App extends Application {


    private static Context context = null;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        //讯飞语音播报平台--因权限申请,初始化放在StartActivity
//        SpeechUtility.createUtility(this, "appid=");//=号后面写自己应用的APPID
//        Setting.setShowLog(true); //设置日志开关(默认为true),设置成false时关闭语音云SDK日志打印
//        TTSUtils.getInstance().init(); //初始化工具类

    }

    public static Context getContext() {
        return context;
    }
}

9:CourseUtils

public class CourseUtils {

    public static boolean resultProcess(String pid) {
        String processName = getProcessName(App.getContext(), android.os.Process.myPid());
        return (!TextUtils.isEmpty(processName) && pid.equals(processName));

    }

    private static String getProcessName(Context cxt, int pid) {
        ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
        if (runningApps == null) {
            return null;
        }
        for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
            if (procInfo.pid == pid) {
                return procInfo.processName;
            }
        }
        return null;
    }
}

10:TTSUtils

public class TTSUtils implements InitListener, SynthesizerListener {

    private static volatile TTSUtils instance = null;
    private boolean isInitSuccess = false;
    private SpeechSynthesizer mTts;

    //单例模式
    public static TTSUtils getInstance() {
        if (instance == null) {
            synchronized (TTSUtils.class) {
                if (instance == null) {
                    instance = new TTSUtils();
                }
            }
        }
        return instance;
    }

    public TTSUtils() {

    }

    // 初始化合成对象
    public void init() {
        //判断进程是否已启动,初始化多次会报错
        //个人遇到问题:极光推送引入后,不加该条件回报错
        if (CourseUtils.resultProcess(清单文件中的项目包名,例如:"com.tech.haha")) {

            mTts = SpeechSynthesizer.createSynthesizer(App.getContext(), this);
            // 清空参数
            mTts.setParameter(SpeechConstant.PARAMS, null);
            // 设置在线云端
            mTts.setParameter(SpeechConstant.ENGINE_TYPE,
                    SpeechConstant.TYPE_CLOUD);

            // 设置发音人--发音人选择--具体见values-string
            mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoqi");

            // 设置发音语速
            mTts.setParameter(SpeechConstant.SPEED, "50");
            // 设置音调
            mTts.setParameter(SpeechConstant.PITCH, "50");
            // 设置合成音量
            mTts.setParameter(SpeechConstant.VOLUME, "100");
            // 设置播放器音频流类型
            mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
            // 设置播放合成音频打断音乐播放,默认为true
            mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
            // 设置音频保存路径,需要申请WRITE_EXTERNAL_STORAGE权限,如不需保存注释该行代码
//        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH,"./sdcard/iflytek.pcm");
            Log.i("zhh", "--初始化成完成-");
        }

    }

    //开始合成
    public void speak(String msg) {
        if (isInitSuccess) {
            if (mTts.isSpeaking()) {
                stop();
            }
            mTts.startSpeaking(msg, this);
        } else {
            init();
        }
    }

    // 取消合成
    public void stop() {
        mTts.stopSpeaking();
    }

    @Override
    public void onEvent(int eventType, int i1, int i2, Bundle bundle) {
        //以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
        if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            String sid = bundle.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
        }
    }

    @Override
    public void onInit(int code) {
        if (code == ErrorCode.SUCCESS) {
            isInitSuccess = true;
            Log.i("zhh", "tts初始话success");
        }
    }

    @Override
    public void onSpeakBegin() {
        // 监听:开始播放
    }

    @Override
    public void onBufferProgress(int percent, int beginPos, int endPos,
                                 String info) {
        // 合成进度
    }

    @Override
    public void onSpeakPaused() {

11:StartActivity 初始化语音播报+权限申请

public class StartActivity extends AppCompatActivity {


    private List<String> permissionList = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SystemClock.sleep(1000);//延时加载
        requestPermissions();
    }

    private void openActivity(Class<? extends AppCompatActivity> clazz) {
        initTTS();
        startActivity(new Intent(this, clazz));
        finish();
    }

    //权限申请
    private void requestPermissions() {
        // 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            addListPermission();
            boolean isGranted = false;//是否全部授权
            // 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
            Iterator<String> iterator = permissionList.iterator();
            while (iterator.hasNext()) {
                // 检查该权限是否已经获取
                int granted = ContextCompat.checkSelfPermission(this, iterator.next());
                if (granted == PackageManager.PERMISSION_GRANTED) {
                    iterator.remove();//已授权则remove
                }
            }
            if (permissionList.size() > 0) {
                // 如果没有授予该权限,就去提示用户请求
                //将List转为数组
                String[] permissions = permissionList.toArray(new String[permissionList.size()]);
                // 开始提交请求权限
                ActivityCompat.requestPermissions(this, permissions, 0x10);
            } else {
                Log.i("zhh", "权限已申请");
                openActivity(MainActivity.class);
            }

        } else {
            openActivity(MainActivity.class);
        }
    }

    //初始化语音合成
    private void initTTS() {
        //讯飞语音播报平台
        SpeechUtility.createUtility(this, "appid= ");//=号后面写自己创建应用的APPID
        Setting.setShowLog(true); //设置日志开关(默认为true),设置成false时关闭语音云SDK日志打印
        TTSUtils.getInstance().init(); //初始化工具类
    }


    /**
     * 权限申请返回结果
     *
     * @param requestCode  请求码
     * @param permissions  权限数组
     * @param grantResults 申请结果数组,里面都是int类型的数
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 0x10:
                if(grantResults.length>0&&ifGrantResult(grantResults)){
                    Toast.makeText(this, "同意权限申请", Toast.LENGTH_SHORT).show();
                    openActivity(MainActivity.class);
                }else{
                    Toast.makeText(this, "权限被拒绝了", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
                break;
        }


    }

    private boolean ifGrantResult(int[] grants) {
        boolean isGrant = true;
        for (int grant : grants) {
            if (grant == PackageManager.PERMISSION_DENIED) {
                isGrant = false;
                break;
            }
        }
        return isGrant;
    }


    //敏感权限添加
    private void addListPermission() {
        if (null == permissionList) {
            permissionList = new ArrayList<>();
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
            permissionList.add(Manifest.permission.RECORD_AUDIO);
        }
    }


}

12:MainActivity讯飞语音播放

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private EditText et = null;

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

        et = findViewById(R.id.et);
        findViewById(R.id.btn0).setOnClickListener(this);
        findViewById(R.id.btn1).setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn0:
                TTSUtils.getInstance().speak("你今天怎么这么美");
                break;
            case R.id.btn1:
                String msg = et.getText().toString();
                TTSUtils.getInstance().speak(TextUtils.isEmpty(msg) ? "输入信息为空" : msg);
                break;
            default:
                break;
        }
    }

    @Override
    protected void onResume() {
        //移动数据统计分析--不用可不用加入
        FlowerCollector.onResume(MainActivity.this);
        FlowerCollector.onPageStart(TAG);
        super.onResume();
    }

    @Override
    protected void onPause() {
        //移动数据统计分析
        FlowerCollector.onPageEnd(TAG);
        FlowerCollector.onPause(MainActivity.this);
        super.onPause();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        TTSUtils.getInstance().release();//释放资源
    }


}

13:activity_main.xml布局

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

    <Button
        android:id="@+id/btn0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击播报内容" />

    <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:hint="请输入要播报的内容!" />

    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="讯飞自定义播报" />
</LinearLayout>

2018-09-12 13:33:05 as89751 阅读数 356

 

砖友们,先去了解一下科大讯飞

1.今天接入的是科大讯飞的语音,同样有一些SDK需要砖友们,去抢夺

科大讯飞开放平台直通车  创建App和下载SDK都可以哦

 

并附上一张图  cp到相应的位置就行

2.我们还要提前导入Gson(录入语音完毕后要用到)

implementation 'com.google.code.gson:gson:2.8.4'

3.因为集成语音需要知道用户说什么,所有需要多个权限

<!--连接网络权限,用于执行云端语音能力 -->
<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" />

 

4.上代码,在XXXActivity中写入

private TextView tv;

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

    SpeechUtility.createUtility(this, SpeechConstant.APPID + "=5b72badf");

    tv = findViewById(R.id.tv);

}

public void initSpeech(final Context context) {

    //1.创建RecognizerDialog对象

    RecognizerDialog mDialog = new RecognizerDialog(context, null);

    //2.设置accent、language等参数

    mDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");

    mDialog.setParameter(SpeechConstant.ACCENT, "mandarin");

    //3.设置回调接口

    mDialog.setListener(new RecognizerDialogListener() {

        @Override

        public void onResult(RecognizerResult recognizerResult, boolean isLast) {

            if (!isLast) {

                //解析语音

                //返回的result为识别后的汉字,直接赋值到TextView上即可

                String result = parseVoice(recognizerResult.getResultString());

                tv.setText(result);
            }

        }

        @Override

        public void onError(SpeechError speechError) {

        }

    });

    //4.显示dialog,接收语音输入

    mDialog.show();

}

/**
 * 解析语音json
 */

public String parseVoice(String resultString) {

    Gson gson = new Gson();

    Voice voiceBean = gson.fromJson(resultString, Voice.class);

    StringBuffer sb = new StringBuffer();

    ArrayList<Voice.WSBean> ws = voiceBean.ws;

    for (Voice.WSBean wsBean : ws) {

        String word = wsBean.cw.get(0).w;

        sb.append(word);

    }

    return sb.toString();

}

public void onClick(View view) {

    initSpeech(MainActivity.this);

}

/**
 * 语音对象封装
 */

public class Voice {

    public ArrayList<WSBean> ws;


    public class WSBean {

        public ArrayList<CWBean> cw;

    }

    public class CWBean {

        public String w;

    }

}

 

到这里语音就集成完毕了 是不是很简单呢?

 

想了解很多技术点?

                                        Android 集成支付宝支付

 

2017-07-08 14:04:53 Li_peilun 阅读数 264

使用讯飞语音

博文 来自: A_sendy
没有更多推荐了,返回首页