最近的音频播放项目要求应用内支持语音控制
用的是讯飞的,大概整理一下作为笔记:
首先在lib目录下引入:XiriScene.jar和XiriFeedback.jar
然后在bulid.gradle文件中加入:
implementation files('libs\xiriScene.jar')
implementation files('libs\xiriFeedback.jar')
接下来是代码:
1.XiriISceneListener.java
package com.mychtech.himalayajs.service;
import android.content.Intent;
public interface XiriISceneListener {
String onQuery();
void onExecute(Intent var1);
}
2.XiriManager.java
package com.mychtech.himalayajs.service;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.iflytek.xiri.Feedback;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class XiriManager implements XiriISceneListener {
private static XiriManager mInstance = null;
private XiriScene mScene;
private Feedback mFeedback;
private String mSceneJson;
private Context mContext = null;
private IXiriManager mIXiriManager = null;
public static XiriManager getInstance() {
synchronized (XiriManager.class) {
if (mInstance == null) {
mInstance = new XiriManager();
}
}
return mInstance;
}
public void onCreate(Context context, IXiriManager iXiriManager) {
mIXiriManager = iXiriManager;
mContext = context;
mScene = new XiriScene(context);
mFeedback = new Feedback(context);
mScene.init(this);
Log.i("XiriManager", "XiriManager add XiriManager oncreate....");
}
public void onResume() {
//初始化Scene,在界面显示的时候才可调用
mScene.init(this);
Log.i("XiriManager", "XiriManager add XiriManager onResume....");
}
public void onPause() {
//释放Scene,在界面消失的时候调用
mScene.release();
Log.i("XiriManager", "XiriManager add XiriManager onPause....");
}
@Override
public String onQuery() {
return regiestScene();
}
@Override
public void onExecute(Intent intent) {
mFeedback.begin(intent);
//判断是否有注册的场景
Log.i("XiriManager", "XiriManager add _scene = " + intent.hasExtra("_scene"));
if (intent.hasExtra("_scene") && intent.getStringExtra("_scene")
.equals("com.mychtech.himalayajs.activity.AudioDetailActivity")) {
if (intent.hasExtra("_command")) { //需注意,此处是_command,不是场景注册时候的_commands,千万别搞错了!
String commands = intent.getStringExtra("_command");
Log.i("XiriManager", "XiriManager add commands:" + commands);
JSonObject params = new JSonObject();
if ("key1".equals(commands)) {
//key1--> 固定命令(打开,退出)
mFeedback.feedback("打开", Feedback.SILENCE);
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("打开", "", params.toString());
}
} else if ("key2".equals(commands)) {
//key2--> 预定于语义$P(_PLAY)
String action = intent.getStringExtra("_action");
Log.i("XiriManager", "onExecute___key2__action: "+action);
if("SEEK".equals(action)) {
int position = intent.getIntExtra("position", -1);
try {
params.put("position", position);
} catch (JSonException e) {
e.printStackTrace();
}
} else if("FORWARD".equals(action) || "BACKWARD".equals(action)) {
int position = intent.getIntExtra("offset", -1);
try {
params.put("offset", position);
} catch (JSonException e) {
e.printStackTrace();
}
}
mFeedback.feedback(action, Feedback.SILENCE);
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("$P(_PLAY)", action, params.toString());
}
} else if ("key3".equals(commands)) {
//ke3-->预定义槽 $P(_PAGE)
String action = intent.getStringExtra("_action");
if ("PREV".equals(action))
{
mFeedback.feedback("上一页", Feedback.SILENCE);
}
else if ("NEXT".equals(action))
{
mFeedback.feedback("下一页", Feedback.SILENCE);
}
else if ("INDEX".equals(action))
{
String index = intent.getStringExtra("index");
mFeedback.feedback("第" + index + "页", Feedback.SILENCE);
try {
params.put("index", index);
} catch (JSonException e) {
e.printStackTrace();
}
}
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("$W(video)", action, params.toString());
}
} else if ("key4".equals(commands)) {
//key3-->自定义槽$W(video)
String video = intent.getStringExtra("video");
mFeedback.feedback(video, Feedback.SILENCE);
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("$W(video)", "", params.toString());
}
} else if("key5".equals(commands)) {
//$P(_EPISODE)
String action = intent.getStringExtra("_action");
if ("PREV".equals(action))
{
//mFeedback.feedback("上一集", Feedback.SILENCE);
}
else if ("NEXT".equals(action))
{
//mFeedback.feedback("下一集", Feedback.SILENCE);
}
else if ("INDEX".equals(action))
{
int index = intent.getIntExtra("index",0);
///mFeedback.feedback("第" + index + "集", Feedback.SILENCE);
try {
params.put("index", index);
} catch (JSonException e) {
e.printStackTrace();
}
}
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("$P(_EPISODE)", action, params.toString());
}
} else if("key6".equals(commands)) {
//$P(_SELECt)
try {
params.put("row", intent.getIntExtra("row", -1));
params.put("index", intent.getIntExtra("index", -1));
} catch (JSonException e) {
e.printStackTrace();
}
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("$P(_SELECT)", "", params.toString());
}
} else if("key7".equals(commands)) {
//退出应用
if(mIXiriManager != null) {
mIXiriManager.setXiriToJs("退出", "", params.toString());
}
}
}
}
}
public String getSceneText(InputStream is) {
StringBuilder builder = new StringBuilder();
if (is != null) {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
builder.append(line);
}
br.close();
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return builder.toString();
}
public String regiestScene() {
try {
mSceneJson = getSceneText(mContext.getAssets().open("XiriSceneText.json"));
} catch (IOException e) {
e.printStackTrace();
}
return mSceneJson;
}
public interface IXiriManager {
void setXiriToJs(String key, String action, String params);
}
}
3. XiriScene.java
package com.mychtech.himalayajs.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.util.Log;
import org.json.JSONObject;
public class XiriScene {
private Context mContext;
IntentFilter mIntentFilter;
private XiriISceneListener mISceneListenner;
public static final String ADDSCENECOMMAND_ACTION = "com.iflytek.xiri2.topActivity.QUERY";
public static final String FUZZY_SCENE_SERVICE_ACTION = "com.iflytek.xiri2.scenes.EXECUTE";
public static final String COMMIT_ACTION = "com.iflytek.xiri2.topActivity.COMMIT";
public static final String NEW_COMMIT_ACTION = "tv.yuyin.topActivity.COMMIT";
private int token;
BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String sceneId;
Log.i("XiriScene", "onReceive__intent.getAction(): "+intent.getAction());
if ("com.iflytek.xiri2.topActivity.QUERY".equals(intent.getAction())) {
Log.d("XiriScene", "ADDSCENECOMMAND_ACTION 1 onReceive " + Uri.decode(intent.toURI()));
sceneId = intent.getStringExtra("pkgname") == null ? "com.iflytek.xiri" : intent.getStringExtra("pkgname");
//intent.putExtra("topActivity", "com.mychtech.himalayajs.ximalaya.");
if ("com.iflytek.xiri".equals(sceneId)) {
intent.setAction("com.iflytek.xiri2.topActivity.COMMIT");
intent.putExtra("_scene", mISceneListenner.onQuery());
//intent.putExtra("_package", XiriScene.this.mContext.getPackageName());
//intent.putExtra("sw_caller_packagename", "com.mychtech.himalayajs.ximalaya");
intent.putExtra("_package", "com.mychtech.himalayajs.ximalaya");
intent.putExtra("_objhash", XiriScene.this.token);
intent.setPackage(sceneId);
XiriScene.this.mContext.startService(intent);
} else {
intent.setAction("tv.yuyin.topActivity.COMMIT");
intent.putExtra("_scene", XiriScene.this.mISceneListenner.onQuery());
//intent.putExtra("_package", XiriScene.this.mContext.getPackageName());
//intent.putExtra("sw_caller_packagename", "com.mychtech.himalayajs.ximalaya");
intent.putExtra("_package", "com.mychtech.himalayajs.ximalaya");
intent.putExtra("_objhash", XiriScene.this.token);
intent.setPackage(sceneId);
XiriScene.this.mContext.startService(intent);
}
Log.d("XiriScene", "ADDSCENECOMMAND_ACTION startService " + Uri.decode(intent.toURI()));
} else if ("com.iflytek.xiri2.scenes.EXECUTE".equals(intent.getAction())) {
Log.d("XiriScene", "FUZZY_SCENE_SERVICE_ACTION " + Uri.decode(intent.toURI()));
Log.d("SCENE_TIME", "StartTime " + System.currentTimeMillis());
Log.d("XiriScene", "mContext getPackagename " + XiriScene.this.mContext.getPackageName());
if (intent.hasExtra("_objhash") && intent.getStringExtra("_objhash").equals(XiriScene.this.token + "")) {
if (intent.hasExtra("_scene")) {
sceneId = intent.getStringExtra("_scene");
Log.d("SCENE_TIME", "fromIntent sceneId " + sceneId);
try {
JSonObject mJsonObject = new JSonObject(XiriScene.this.mISceneListenner.onQuery());
String userSceneId = mJsonObject.getString("_scene");
Log.d("SCENE_TIME", "userSceneId " + sceneId);
if (userSceneId.equals(sceneId)) {
XiriScene.this.mISceneListenner.onExecute(intent);
Log.d("SCENE_TIME", "EndTime " + System.currentTimeMillis());
Log.d("XiriScene", "FUZZY_SCENE_SERVICE_ACTION exe " + Uri.decode(intent.toURI()));
}
} catch (Exception var6) {
}
} else {
XiriScene.this.mISceneListenner.onExecute(intent);
Log.d("XiriScene", "else Scene exe " + Uri.decode(intent.toURI()));
}
}
}
}
};
public XiriScene(Context context) {
this.mContext = context;
this.token = this.hashCode();
this.mIntentFilter = new IntentFilter();
this.mIntentFilter.addAction("com.iflytek.xiri2.scenes.EXECUTE");
this.mIntentFilter.addAction("com.iflytek.xiri2.topActivity.QUERY");
}
public void init(XiriISceneListener listenner) {
this.mContext.registerReceiver(this.mReceiver, this.mIntentFilter);
this.mISceneListenner = listenner;
}
public void release() {
this.mContext.unregisterReceiver(this.mReceiver);
}
}
然后在 main目录下新建一个名为“XiriSceneText.json”的文件
XiriSceneText.json的内容如下:
{
"_commands": {
"key1": [
"打开",
"打开详情"
],
"key2": [
"$P(_PLAY)"
],
"key3": [
"$P(_PAGE)"
],
"key4": [
"$W(video)"
],
"key5":[
"$P(_EPISODE)"
],
"key6":[
"$P(_SELECT)"
],
"key7":[
"退出当前页面"
]
},
"_fuzzy_words": {
"video": [
]
},
"_scene": "com.mychtech.himalayajs.activity.AudioDetailActivity"
}
然后在AudioDetailActivity的onCreate方法里面调用:
XiriManager.getInstance().onCreate(this, new XiriManager.IXiriManager() {
@Override
public void setXiriToJs(String key, String action, String params) {
//预定义槽 $P(_PLAY) $P(_PAGE) $P(_EPISODE) $P(_SELECT)
mKey = key;
Log.i(TAG, "setXiriToJs--key:" + key + "---action:" + action + "---param:" + params);
if (null != mMediaPlayer) {
switch (key) {
case "$P(_PLAY)":// 播放控制
if ("PAUSE".equals(action)) {
if (mMediaPlayer.isPlaying()) {
ivPlay.setImageResource(R.drawable.bg_play_slt);
mMediaPlayer.pause();
}
} else if ("PLAY".equals(action)) {
ivPlay.setImageResource(R.drawable.bg_pause_slt);
mMediaPlayer.start();
mHandler.sendEmptyMessage(123);
mAudioChapterAdapter.setPlay(false);
} else if ("RESUME".equals(action)) {
mMediaPlayer.start();
ivPlay.setImageResource(R.drawable.bg_pause_slt);
} else if ("RESTART".equals(action)) {
mMediaPlayer.seekTo(0);
mMediaPlayer.start();
} else if ("SEEK".equals(action)) {//跳到指定位置 例如:跳到1分30秒播放
if (!TextUtils.isEmpty(params)) {
if (params.contains("position")) {
int position = JSONUtils.getInt(params, "position", 0);
Log.i(TAG, "setXiriToJs--position: " + position);
mMediaPlayer.seekTo(position * 1000);
}
}
} else if ("FORWARD".equals(action)) {//快进指定时间 例如:快进30秒
if (!TextUtils.isEmpty(params)) {
if (params.contains("offset")) {
int offset = JSONUtils.getInt(params, "offset", 0);
Log.i(TAG, "setXiriToJs--offset: " + offset);
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() + offset * 1000);
} else {
Log.i(TAG, "setXiriToJs--offset: " + "not contain offset");
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() + 3000);//快进
}
} else {
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() + 3000);//快进
}
} else if ("BACKWARD".equals(action)) {//后退指定时间 例如:快退30秒
if (!TextUtils.isEmpty(params)) {
if (params.contains("offset")) {
int offset = JSONUtils.getInt(params, "offset", 0);
Log.i(TAG, "setXiriToJs--offset: " + offset);
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() - offset * 1000);
} else {
Log.i(TAG, "setXiriToJs--offset: " + "not contain offset");
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() - 3000);//快进
}
} else {
mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() - 3000);//快进
}
} else if ("EXIT".equals(action)) {//退出
exitAudioActivity();
}
break;
case "$P(_PAGE)"://翻页控制
//TODO
if ("NEXT".equals(action)) {//跳到下一页
} else if ("PREV".equals(action)) {//跳到上一页
} else if ("INDEX".equals(action)) {//index 页号(整数值型,负数表示倒数)
}
break;
case "$P(_EPISODE)"://选集控制
if ("NEXT".equals(action)) {//跳到下一集/期
isNext = true;
nextMusic();
} else if ("PREV".equals(action)) {//跳到上一集/期
previousEpisode();
} else if ("INDEX".equals(action)) {//跳到指定集/期 index 集/期号(整数值型,负数表示倒数)
if (!TextUtils.isEmpty(params)) {
if (params.contains("index")) {
int index = JSONUtils.getInt(params, "index", 0);
Log.i(TAG, "setXiriToJs--index: " + index);
changeMusicForIndex(index - 1);
}
}
} else {
}
break;
case "$P(_SELECT)"://选择 例如:第二行第三个
//row:第 x 行(整数值型,负数表示倒数)可选
//index:第 x 个(整数值型,负数表示倒数)
break;
case "退出":
exitAudioActivity();
finish();
break;
}
}
}
});
在对应的OnDestory里面调用:
XiriManager.getInstance().onPause();
以上!



