Android中语音识别与语音播报功能(记录)

功能需求:

(1)语音识别,将语音识别为文字,用于语音文字输入功能。

(2)语音播报,将文字通过语音的形式播放出来。

主要思路:

(1)语音识别:使用百度的第三方免费语音识别SDK。(特别注意,只要是使用第三方,强烈建议直接看官方文档,不要看一些博文什么玩意的,除非它的日期是非常非常新的。)

(2)语音播报:使用Android自带的TextToSpeech控件即可。

效果图:

Android中语音识别与语音播报功能(记录)_第1张图片

Android中语音识别与语音播报功能(记录)_第2张图片

Android中语音识别与语音播报功能(记录)_第3张图片

 【语音识别】功能步骤如下:

一、登录百度AI开放平台:http://ai.baidu.com/,选择【开发资源】下的【SDK下载】,然后下载相应的SDK,如下图

Android中语音识别与语音播报功能(记录)_第4张图片

 (备注:里面包含完整Demo,特别注意,一定要看【使用说明】)

二、解压下载好的压缩包文件,将SDK集成到项目中,即导入相应的jar包和so库文件,导入后的目录如下:

Android中语音识别与语音播报功能(记录)_第5张图片

(备注:1、将jar包添加到libs下,并add as Modules。2、在main下创建jniLibs文件夹,并把相应的so库文件添加进去)

三、修改AndroidManifest.xml清单文件,添加申请到的APP_ID,API_KEY,SECRET_KEY到application中,如下图:



(备注:上述三个信息,自己到控制台里的应用列表中,创建一个新的应用,并且选中百度语音接口,确定之后,就可以在应用列表中找到你想要的信息。) 

Android中语音识别与语音播报功能(记录)_第6张图片

四、准备工作已完成,接下来就可以直接使用该SDK进行开发了。相应的MainActivity.java代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, EventListener {

    private Context mContext;
    private RxPermissions rxPermissions;

    private TextView tvResult, tvLog;
    private Button btnStop, btnStart;
    private LinearLayout lLayoutLoading;

    private EventManager eventManager;
    protected boolean enableOffline = false; // 测试离线命令词,需要改成true

    private String[] arrayResult;

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

        baseDataInit();
        checkUserPermissions();
        bindViews();
        viewsAddListener();
        viewsDataInit();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 基于SDK集成4.2 发送取消事件
        eventManager.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
        if (enableOffline) {
            unloadOfflineEngine(); // 测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
        }
        // 基于SDK集成5.2 退出事件管理器
        // 必须与registerListener成对出现,否则可能造成内存泄露
        eventManager.unregisterListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        eventManager.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
    }

    private void baseDataInit() {
        mContext = this;
        rxPermissions = new RxPermissions(MainActivity.this);
    }

    private void bindViews() {
        tvResult = findViewById(R.id.Main_tvResult);
        tvLog = findViewById(R.id.Main_tvLog);
        btnStop = findViewById(R.id.Main_btnStop);
        btnStart = findViewById(R.id.Main_btnStart);
        lLayoutLoading = findViewById(R.id.LoadingLayout);
    }

    private void viewsAddListener() {
        btnStart.setOnClickListener(this);
        btnStop.setOnClickListener(this);
        // 基于sdk集成1.1 初始化EventManager对象
        eventManager = EventManagerFactory.create(this, "asr");
        // 基于sdk集成1.3 注册自己的输出事件类
        eventManager.registerListener(this); //  EventListener 中 onEvent方法
    }

    private void viewsDataInit() {
        tvResult.setText("语音识别");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.Main_btnStop: {
                stop();
                break;
            }
            case R.id.Main_btnStart: {
                btnStart.setEnabled(false);
                arrayResult = null;
                lLayoutLoading.setVisibility(View.VISIBLE);
                tvLog.setText("开始识别……");
                start();
                break;
            }
        }
    }

    @Override
    public void onEvent(String s, String s1, byte[] bytes, int i, int i1) {
        if (s.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
            RecognitionResult recognitionResult = RecognitionResult.parseJson(s1);
            //临时识别结果
            arrayResult = recognitionResult.getResultsRecognition();
        } else if (s.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {
            //最终识别结果
            String result = "识别结果:无";
            if (arrayResult != null) {
                if (arrayResult.length > 0) {
                    result = "识别结果:" + arrayResult[0];
                }
            }
            tvLog.setText(result);
            btnStart.setEnabled(true);
            lLayoutLoading.setVisibility(View.GONE);
        }
    }

    /**
     * 基于SDK集成2.2 发送开始事件
     * 点击开始按钮
     * 测试参数填在这里
     */
    private void start() {
        Map params = new LinkedHashMap();
        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同ActivityRecog类中myRecognizer.start(params);
        // 复制此段可以自动检测错误
        (new AutoCheck(getApplicationContext(), new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == 100) {
                    AutoCheck autoCheck = (AutoCheck) msg.obj;
                    synchronized (autoCheck) {
                        String message = autoCheck.obtainErrorMessage(); // autoCheck.obtainAllMessage();
                        Log.e("AutoCheckMessage", message);
                    }
                }
            }
        }, enableOffline)).checkAsr(params);
        String json = null; // 可以替换成自己的json
        json = new JSONObject(params).toString(); // 这里可以替换成你需要测试的json
        eventManager.send(event, json, null, 0, 0);
        Log.e("输入参数", json);
    }

    /**
     * 点击停止按钮
     *  基于SDK集成4.1 发送停止事件
     */
    private void stop() {
        Log.e("停止识别", "ASR_STOP");
        eventManager.send(SpeechConstant.ASR_STOP, null, null, 0, 0);
    }

    /**
     * enableOffline为true时,在onDestory中调用,与loadOfflineEngine对应
     * 基于SDK集成5.1 卸载离线资源步骤(离线时使用)
     */
    private void unloadOfflineEngine() {
        eventManager.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0); //
    }

    /**
     * 检查并获取用户权限
     */
    private void checkUserPermissions() {
        rxPermissions
                .requestEach(Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET,
                        Manifest.permission.READ_PHONE_STATE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                )
                .subscribe(permission -> {
                    if (permission.granted) {
                    } else if (permission.shouldShowRequestPermissionRationale) {
                    } else {}
                });
    }
}

至此,语音识别功能已完成。

【语音播报】功能步骤如下:

这个是用了TextToSpeech控件,很简单,主要是两个步骤:

(1)创建一个TextToSpeech实例,并实现相应的OnInitListener接口。

(2)然后通过speak()方法来开始播报,通过stop()方法来停止播报。

直接上代码了,ContentActivity.java的代码如下:

public class ContentActivity extends AppCompatActivity implements View.OnClickListener, OnInitListener {

    private static final int LOADING_GONE = 1001;
    private static final int LOADING_VISIBLE = 1002;

    private Context mContext;

    private EditText etContent;
    private Button[] arrayBtnFunc;
    private TextToSpeech textToSpeech;
    private LinearLayout lLayoutLoading;

    private ScheduledExecutorService scheduledExecutorService;

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

        baseDataInit();
        bindViews();
        viewsAddListener();
        autoCheckSpeakState();
    }

    @Override
    protected void onDestroy() {
        if (textToSpeech != null) {
            textToSpeech.stop();
            textToSpeech.shutdown();
        }
        scheduledExecutorService.shutdown();
        super.onDestroy();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LOADING_GONE: {
                    lLayoutLoading.setVisibility(View.GONE);
                    break;
                }
                case LOADING_VISIBLE: {
                    lLayoutLoading.setVisibility(View.VISIBLE);
                    break;
                }
                default:break;
            }
        }
    };

    private void baseDataInit() {
        mContext = this;
        scheduledExecutorService = Executors.newScheduledThreadPool(1);
    }

    private void bindViews() {
        etContent = findViewById(R.id.Content_etContent);
        arrayBtnFunc = new Button[] {
                findViewById(R.id.Content_btnStart),
                findViewById(R.id.Content_btnStop)
        };
        lLayoutLoading = findViewById(R.id.LoadingLayout);
        textToSpeech = new TextToSpeech(mContext, this::onInit);
    }

    private void viewsAddListener() {
        for (int i = 0; i < arrayBtnFunc.length; i ++) {
            arrayBtnFunc[i].setOnClickListener(this::onClick);
        }
    }

    /**
     * 检测是否播报完成(定时)
     */
    private void autoCheckSpeakState() {
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if (textToSpeech != null && textToSpeech.isSpeaking()) {
                    mHandler.sendEmptyMessage(LOADING_VISIBLE);
                } else {
                    mHandler.sendEmptyMessage(LOADING_GONE);
                }
            }
        }, 1, 200, TimeUnit.MILLISECONDS);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.Content_btnStart: {
                lLayoutLoading.setVisibility(View.VISIBLE);
                String content = etContent.getText().toString().trim();
                if (!content.equals("")) {
                    textToSpeech.speak(etContent.getText().toString(), TextToSpeech.QUEUE_FLUSH, null);
                } else {
                    Toast.makeText(mContext, "请输入内容!", Toast.LENGTH_SHORT).show();
                }
                break;
            }
            case R.id.Content_btnStop: {
                textToSpeech.stop();
                break;
            }
            default:break;
        }
    }

    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            //默认设定语言为中文,原生的android貌似不支持中文。
            int result = textToSpeech.setLanguage(Locale.CHINESE);
            if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
                Toast.makeText(mContext, "目前不支持中文!", Toast.LENGTH_SHORT).show();
            }else{
                //不支持中文就将语言设置为英文
                textToSpeech.setLanguage(Locale.US);
            }
        }
    }

特别注意:一定要注意权限问题!!!





相应的Demo地址为:https://download.csdn.net/download/lpcrazyboy/11195714

你可能感兴趣的:(Android开发)