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 在设置添加开关菜单,这个不写了,菜单添加在设置/电池下, 还有控制的系统变量添加,到此成功跑起来了,灭屏后也可以唤醒了
中间主要问题处理报错和灭屏后唤醒