讯飞语音唤醒集成过程

1 讯飞平台注册下载sdk包

2 看下sdk包中的demo, 然后跑起来看下效果, 中间主要是导入AS各种报错, 主要集中在修改build.gradle文件,文件如下, 改了好几个地方,记不得了,对比下文件就知道了

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28



    defaultConfig {
        applicationId "com.example.ifytekwakeupdemo"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

3 集成到系统launcher中, 添加ziflytekSevice.java

/*
* Copyright (C) 2014 MediaTek Inc.
* Modification based on code covered by the mentioned copyright
* and/or permission notice(s).
*/
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher3;

import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.*;
import android.util.Log;
import android.util.LongSparseArray;

import java.util.ArrayList;
import java.util.List;

//iflytek add
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.RequestListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
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 org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
// iflytek end
import android.widget.Toast;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.app.KeyguardManager;
//wakeup setting
import android.provider.Settings;
import android.database.ContentObserver;

public class ziflytekSevice extends Service {
    public static final String TAG = ziflytekSevice.class.getSimpleName();
    public static final String ACTION_START_TRACKING = "com.android.launcher3.action.START_TRACKING";

    private final boolean et_is_add_iflytek = true;

    private static final int MSG_START = 1;
    private static final int MSG_STOP = 2;
    private static final int MSG_UPDATE = 3;
    private static final int MSG_RESTART = 4;
    
    private ScreenStatusReceiver mScreenStatusReceiver;
    private boolean isUnlockScreenDisable=false;

    private boolean mWakeupEnable;

    @Override
    public void onCreate() {

            if(et_is_add_iflytek){
                //iflytekInit();//iflytek add
                //iflytekWakeUpHandle();

                mWakeupEnable = 0 != Settings.System.getInt(
                    getApplicationContext().getContentResolver(), Settings.System.IFLYTEK_VOICE_WAKEUP_ENABLE, 0);

                Message msg = mHandler.obtainMessage(MSG_START);
                mHandler.sendMessageDelayed(msg,1000);
                registerBroadcast();
                registerStopSleep();
                registerSettingChange();
            }

    }
    
//setting handle
    private void registerSettingChange(){
        getApplicationContext().getContentResolver().registerContentObserver(
                Settings.System.getUriFor(Settings.System.IFLYTEK_VOICE_WAKEUP_ENABLE), true,
                mSettingsObserver);
        mSettingsObserver.onChange(false);
    }

    private ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
         public void onChange(boolean selfChange) {
             mWakeupEnable = 0 != Settings.System.getInt(
                    getApplicationContext().getContentResolver(), Settings.System.IFLYTEK_VOICE_WAKEUP_ENABLE, 0);

            Log.d(TAG, "ssss iflytek wakeup setting change enable="+mWakeupEnable);

            if(mWakeupEnable)
            {
                registerStopSleep();
            }
            else {
                unregisterStopSleep();
            }        
        };
    };
//end setting handle

        private class ScreenStatusReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if("android.intent.action.SCREEN_ON".equals(intent.getAction())) {
                    if(mWakeupEnable)
                        iflyteWakeupEnable(false);
                    Log.d(TAG, "ssss message SCREEN_ON mWakeupEnable="+mWakeupEnable);
            } else if("android.intent.action.SCREEN_OFF".equals(intent.getAction())) {
                    Log.d(TAG, "ssss message SCREEN_OFF isUnlockScreenDisable="+isUnlockScreenDisable+" mWakeupEnable="+mWakeupEnable);
                    mHandler.removeMessages(MSG_RESTART);
                    if(mWakeupEnable){
                        Message msg = mHandler.obtainMessage(MSG_RESTART);
                        mHandler.sendMessageDelayed(msg,1000);    
                    }
                    if(isUnlockScreenDisable)
                        ziflytekSevice.this.setDisableKeyguard(false);                                
            }
        }
    }    

        private void registerBroadcast(){
              mScreenStatusReceiver = new ScreenStatusReceiver();
              IntentFilter filterIF = new IntentFilter();//new一个intent过滤器
              filterIF.addAction("android.intent.action.SCREEN_ON");//增加亮屏操作
              filterIF.addAction("android.intent.action.SCREEN_OFF");//增加灭屏操作
                registerReceiver(mScreenStatusReceiver, filterIF);//注册监听            
        }    
        
        private void unregisterBroadcast(){
                unregisterReceiver(mScreenStatusReceiver);        
        }            

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message m) {
            switch (m.what) {
                case MSG_START:
                        iflytekInit();//iflytek add
                        iflytekWakeUpHandle();    
                        Log.d(TAG, "ssss message MSG_START");
                    break;
                case MSG_RESTART:
                        Log.d(TAG, "ssss message MSG_RESTART mIvw="+mIvw);
                        mHandler.removeMessages(MSG_RESTART);
                        iflyteWakeupEnable(true);
                    break;
                case MSG_UPDATE:

                    break;
            }
        }
    };

      private void iflyteWakeupEnable(boolean isEnable){
                        mIvw = VoiceWakeuper.getWakeuper();
                        if(mIvw!=null){
                            if(isEnable==false)
                                mIvw.stopListening();
                            else{
                                mIvw.stopListening();
                                mIvw.startListening(mWakeuperListener);
                            }
                        }          
      }
      

    //iflytek add    
            PowerManager mPowerManager=null;
        // 语音唤醒对象
            private VoiceWakeuper mIvw=null;
            // 唤醒结果内容
            private String resultString;
            
            private final static int MAX = 3000;
            private final static int MIN = 0;
            private int curThresh = 1450;
            private String threshStr = "门限值:";
            private String keep_alive = "1";
            private String ivwNetMode = "0";
    
    private void iflytekInit(){

            Log.d(TAG, "ssss iflytekInit");

            StringBuffer param = new StringBuffer();
            param.append("appid="+getString(R.string.app_id));
            param.append(",");
            // 设置使用v5+
            param.append("engine_mode"+"="+"msc");
            SpeechUtility.createUtility(getApplicationContext(), param.toString());
            
    }    
    
    private void iflytekDestory(){
            // 销毁合成对象
            mIvw = VoiceWakeuper.getWakeuper();
            if (mIvw != null) {
                mIvw.destroy();
            }            
        
        unregisterBroadcast();    
    }        
    
    private void iflytekWakeUpHandle(){
    
        mIvw = VoiceWakeuper.createWakeuper(this, null);
        
            mIvw = VoiceWakeuper.getWakeuper();
            Log.d(TAG, "ssss mIvw="+mIvw);
            if(mIvw != null) {
            
                // 清空参数
                mIvw.setParameter(SpeechConstant.PARAMS, null);
                // 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
                mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:"+ curThresh);
                // 设置唤醒模式
                mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
                // 设置持续进行唤醒
                mIvw.setParameter(SpeechConstant.KEEP_ALIVE, keep_alive);
                // 设置闭环优化网络模式
                mIvw.setParameter(SpeechConstant.IVW_NET_MODE, ivwNetMode);
                // 设置唤醒资源路径
                mIvw.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
                // 设置唤醒录音保存路径,保存最近一分钟的音频
                mIvw.setParameter( SpeechConstant.IVW_AUDIO_PATH, Environment.getExternalStorageDirectory().getPath()+"/msc/ivw.wav" );
                mIvw.setParameter( SpeechConstant.AUDIO_FORMAT, "wav" );
                // 如有需要,设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
                //mIvw.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
                // 启动唤醒
            /*    mIvw.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");*/

                mIvw.startListening(mWakeuperListener);
                /*File file = new File(Environment.getExternalStorageDirectory().getPath() + "/msc/ivw1.wav");
                byte[] byetsFromFile = getByetsFromFile(file);
                mIvw.writeAudio(byetsFromFile,0,byetsFromFile.length);*/
                mIvw.stopListening();
            } else {
                ;//showTip("唤醒未初始化");
            }        
    }
    
        KeyguardManager.KeyguardLock kl=null;
        KeyguardManager km=null;
        private void setDisableKeyguard(boolean isDisable){
            if(km==null)
             km = (KeyguardManager)getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);  
            if(kl==null)
                kl = km.newKeyguardLock("unlock");
            if(isDisable)
                kl.disableKeyguard();  
            else
                kl.reenableKeyguard();    
            isUnlockScreenDisable=isDisable;            
        }        
    
    private WakeuperListener mWakeuperListener = new WakeuperListener() {

        @Override
        public void onResult(WakeuperResult result) {
            Log.d(TAG, "onResult");
            if(!"1".equalsIgnoreCase(keep_alive)) {
                ;//setRadioEnable(true);
            }
            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();
            } catch (JSONException e) {
                resultString = "结果解析出错";
                e.printStackTrace();
            }
            //textView.setText(resultString);
            Log.d(TAG, "ssssjj"+ resultString);
            Toast.makeText(getApplicationContext(), "wake up", Toast.LENGTH_LONG).show();
            wakeUp();
        }

        private void wakeUp(){
            PowerManager pm = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);  
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.FULL_WAKE_LOCK, "bright");  
            wl.acquire();  
            wl.release();              
            
            ziflytekSevice.this.setDisableKeyguard(true);
            
        }    

        @Override
        public void onError(SpeechError error) {
            //showTip(error.getPlainDescription(true));
            //setRadioEnable(true);
        }

        @Override
        public void onBeginOfSpeech() {
        }

        @Override
        public void onEvent(int eventType, int isLast, int arg2, Bundle obj) {
            switch( eventType ){
            // EVENT_RECORD_DATA 事件仅在 NOTIFY_RECORD_DATA 参数值为 真 时返回
            case SpeechEvent.EVENT_RECORD_DATA:
                final byte[] audio = obj.getByteArray( SpeechEvent.KEY_EVENT_RECORD_DATA );
                Log.i( TAG, "ivw audio length: "+audio.length );
                break;
            }
        }

        @Override
        public void onVolumeChanged(int volume) {
            
        }
    };
        
        private String getResource() {
            final String resPath = ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "ivw/"+getString(R.string.app_id)+".jet");
            Log.d( TAG, "resPath: "+resPath );
            return resPath;
        }        
     //end iflytek       
    
    private PowerManager.WakeLock mWakeLock=null;
    private void registerStopSleep(){
            PowerManager pm = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);
            if (mWakeLock == null)
            {
                mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"battery service");
                mWakeLock.acquire();
            }
    }

    private void unregisterStopSleep(){
            if (mWakeLock != null){
                mWakeLock.release();
                mWakeLock=null;
            }
    }

    @Override
    public void onDestroy() {
        
        if(et_is_add_iflytek){
            iflytekDestory();
            unregisterStopSleep();
        }

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(TAG, "Received start id " + startId + ": " + intent);

        return START_STICKY;
    }

    public class ziflytekSeviceInterface extends Binder {
        ziflytekSevice getService() {
            return ziflytekSevice.this;
        }
    }

    private final IBinder mBinder = new ziflytekSeviceInterface();

    public IBinder onBind(Intent intent) {

        return mBinder;
    }
}

4 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" />
    
<user-permission android:name="android.permission.DEVICE_POWER"/>  


        <service android:name="com.android.launcher3.ziflytekSevice">
        </service>

4 launcher.java  oncreate中添加启动

// iflytek end
import com.android.launcher3.ziflytekSevice;

            if(et_is_add_iflytek){
                Intent intent = new Intent(this, ziflytekSevice.class);
                startService(intent);                
            }

5 另外在lancher中接收android.intent.action.BOOT_COMPLETED 广播的地方添加 服务启动,这一步是因为开机后launcher没有起来而是直接进了锁屏,这样就唤醒不了了,

        <receiver android:name="com.android.launcher3.StartupReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

package com.android.launcher3;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartupReceiver extends BroadcastReceiver {

    static final String SYSTEM_READY = "com.android.launcher3.SYSTEM_READY";

    private final boolean et_is_add_iflytek = true;    

    @Override
    public void onReceive(Context context, Intent intent) {

        if(et_is_add_iflytek){
             Intent intent1 = new Intent(context, ziflytekSevice.class);
             context.startService(intent1);                
        }
    }
}

5 android.mk 中添加

LOCAL_STATIC_JAVA_LIBRARIES += \
                Msc.jar

LOCAL_JNI_SHARED_LIBRARIES := libmsc libw_ivw


include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := libs/armeabi-v7a/libmsc.so \
                        libs/armeabi-v7a/libw_ivw.so
include $(BUILD_MULTI_PREBUILT)

include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := Msc.jar:libs/Msc.jar
include $(BUILD_MULTI_PREBUILT)

6 \assets 下资源文件添加

7 编译过程报找不到lib,  system/core/libnativeloader/native_loader.cpp 中修改

static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand:/system/lib"; //songjian add :/system/lib 20191216

8 报找不到类,且有乱码,去掉混淆 launcher下这个文件 proguard.flags 添加

-keep public class com.iflytek.thirdparty.* { *; }

9  在设置添加开关菜单,这个不写了,菜单添加在设置/电池下, 还有控制的系统变量添加,到此成功跑起来了,灭屏后也可以唤醒了

中间主要问题处理报错和灭屏后唤醒

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值