語音識別,語義理解一站式解決(android平臺&olami sdk)
olami sdk實現了把錄音或者文字轉化為使用者可以理解的json字串從而實現語義理解,使用者可以定義自己的語義,是不是很強大?本文講述怎麼自定義語義,以及如何解析自定義語義。 本文使用olami sdk做了一個線上聽書的demo,使用者只需類似“我想聽***”就能實現聽書的線上查詢並播放。用的是喜馬拉雅的線上聽書sdk.基於eclipse開發環境,libs目錄下jar和so檔案如下: olami-android-sdk.jar //olami sdk 的jar afinal_0.5.1_bin.jar litepal.jar gson-2.2.4.jar okhttp-2.4.0.jar okhttp-urlconnection-2.2.0.jar okio-1.4.0.jar opensdk.jar //上面這幾個都是喜馬拉雅需要的jar libspeex.so //olami sdk 需要用到speex壓縮功能 libxmediaplayer.so // 喜馬拉雅so libxmediaplayer_x.so // 喜馬拉雅so
概述:
VoiceSdkService中定義了OlamiVoiceRecognizer語音識別引擎,通過點選MusicActivity的開始button啟動錄音,錄音結果在VoiceSdkService中的onResult()回撥中拿到識別的Json字串,在processServiceMessage()函式中處理後找到要聽書的名稱,然後進入BookUtil進行搜尋,搜尋到結果後通知VoiceSdkService進行播放,並通知MusicActivity更新播放進度等資訊。
1.AndroidManifest.xml配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.olami.musicdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name="com.olami.musicdemo.OlamiApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!--喜馬拉雅聽書測試賬號app_key-->
<meta-data
android:name="app_key"
android:value="b617866c20482d133d5de66fceb37da3" />
<!--喜馬拉雅聽書測試賬號包名-->
<meta-data
android:name="pack_id"
android:value="com.app.test.android" />
<activity
android:name=".MusicActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--註冊olami sdk service-->
<service
android:name=".VoiceSdkService"
android:exported="true" >
</service>
<!--註冊喜馬拉雅聽書service-->
<service
android:name=
"com.ximalaya.ting.android.opensdk.player.service.XmPlayerService"
/>
</application>
</manifest>
2.layout佈局檔案
layout_musicview.xml
TextView 有兩個,tv_name顯示聽書的名稱, tv_totoal_time顯示聽書的總時間。
ProgressBar 實時重新整理顯示聽書的進度
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<TextView
android:text="name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_centerHorizontal="true"
android:id="@+id/tv_name"/>
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_name"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="@+id/progressbar_music"/>
<TextView
android:text="total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/progressbar_music"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:id="@+id/tv_total_time"/>
</RelativeLayout>
activity_music.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
tools:context="com.olami.musicdemo.MusicActivity" >
<TextView
android:id="@+id/tv_inputText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="輸入:" />
<TextView
android:id="@+id/tv_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tv_inputText"
android:layout_below="@+id/tv_inputText"
android:layout_marginTop="40dp"
android:text="音量:" />
<TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_volume"
android:layout_marginTop="20dp"
android:maxLines="15"
android:ellipsize="end"
android:text="伺服器返回sentence:"
android:visibility="visible" />
<com.olami.musicdemo.MusicView
android:id="@+id/music_view"
android:layout_width="fill_parent"
android:layout_height="80dp"
android:layout_centerInParent="true"
>
</com.olami.musicdemo.MusicView>
<EditText
android:id="@+id/et_content"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_above="@+id/btn_stop"
android:layout_alignLeft="@+id/tv_inputText"
android:layout_marginBottom="10dp"
android:layout_toLeftOf="@+id/btn_send"
android:background="#E7E7E7"
android:singleLine="true"
android:text="上海的天氣" />
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/et_content"
android:layout_alignBottom="@+id/et_content"
android:layout_alignParentRight="true"
android:text="提交" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="開始" />
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/et_content"
android:layout_alignParentBottom="true"
android:text="停止" />
<Button
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/et_content"
android:text="取消" />
</RelativeLayout>
自定義MusicView比較簡單,程式碼如下:
public class MusicView extends RelativeLayout{
private Context mContext;
private Handler mHandler;
private TextView mTextViewName;
private TextView mTextViewTotalTime;
private ProgressBar mProgressBar;
public MusicView(Context context,AttributeSet attrs) {
super(context,attrs);
LayoutInflater inflater =(LayoutInflater) context.getSystemService(
context.LAYOUT_INFLATER_SERVICE);
RelativeLayout view = (RelativeLayout) inflater.inflate(R.layout.layout_musicview, this,true);
mTextViewName = (TextView) view.findViewById(R.id.tv_name);
mTextViewTotalTime = (TextView) view.findViewById(R.id.tv_total_time);
mProgressBar = (ProgressBar)view.findViewById(R.id.progressbar_music);
}
public void initMusicView(Context context,Handler handler)
{
mContext = context;
mHandler = handler;
}
public void setMusicName(String name)
{//設定播放名稱
mTextViewName.setText(name);
}
public void setProgress(int progress)
{//設定播放進度
mProgressBar.setProgress(progress);
}
public void setTotalTime(String time)
{//設定播放總時間
mTextViewTotalTime.setText(time);
}
}
佈局效果圖如下:
3.MusicActivity和VoiceSdkService通訊
本文沒有用bind service的方式實現activity和service的訊息通訊。
MusicAcitity 和 VoiceSdkService中分別實現了一個CommunicationAssist的介面
public interface CommunicationAssist {
public void callBack(int what, int arg1, int arg2,Bundle data, Object obj);
}
然後把他們分別實現CommunicationAssist介面的變數註冊到OlamiApplication,這樣通過OlamiApplication實現了MusicAcitity 和 VoiceSdkService橋接。
3.1OlamiApplication
1) 註冊MusicActivity到VoiceSdkService的回撥
public void setActivityToServiceListener(CommunicationAssist listener)
{
ActivityToServiceListener = listener;
}
這個是在VoiceSdkService中呼叫setActivityToServiceListener(),把VoiceSdkService中的VoiceSdkComAssist註冊到application中,MusicActivity中可以通過getActivityToServiceListener
這個函式回撥向VoiceSdkService傳送訊息。
2) 註冊 VoiceSdkService到MusicActivity回撥
public void setServiceToActivityListener(CommunicationAssist listener)
{
mServiceToActivityListener = listener;
}
這個是在MusicAcitivity中呼叫setServiceToActivityListener(),這樣在VoiceSdkService中就可以通過getServiceToActivityListener()獲得回撥向MusciActivity傳送訊息。
3.2 MusicActivity
public class MusicActivity extends Activity {
private Handler mHandler;
private Handler mInComingHandler;
private ActivityComAssist mActivityComAssist;
private Button mBtnStart;
private Button mBtnStop;
private Button mBtnCancel;
private Button mBtnSend;
private EditText mEditText;
private TextView mTextView;
private TextView mInputTextView;
private TextView mTextViewVolume;
private BookUtil mBookUtil = null;
private MusicView mMusicView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music);
initHandler();//初始化handler用於內部訊息處理
initInComingHandler();//用於處理來自VoiceSdkService的訊息
initCommunicationAssist();//向application註冊訊息回撥,VoiceSdkSerive可以
//通過getServiceToActivityListener()獲得回撥向MusicActivity傳送訊息
initView();//初始化view控制元件
Intent intent = new Intent();
intent.setClass(MusicActivity.this, VoiceSdkService.class);
startService(intent);//啟動後臺服務
}
private void initView()
{
mBtnStart = (Button) findViewById(R.id.btn_start);
mBtnStop = (Button) findViewById(R.id.btn_stop);
mBtnCancel = (Button) findViewById(R.id.btn_cancel);
mBtnSend = (Button) findViewById(R.id.btn_send);
mInputTextView = (TextView) findViewById(R.id.tv_inputText);
mEditText = (EditText) findViewById(R.id.et_content);
mTextView = (TextView) findViewById(R.id.tv_result);
mTextViewVolume = (TextView) findViewById(R.id.tv_volume);
mBtnStart.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
sendMessageToService(MessageConst.CLIENT_ACTION_START_RECORED,0,0,null,null);
}
});
mBtnStop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
sendMessageToService(MessageConst.CLIENT_ACTION_STOP_RECORED,0,0,null,null);
mBtnStart.setText("開始");
Log.i("led","MusicActivity mBtnStop onclick 開始");
}
});
mBtnCancel.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
sendMessageToService(MessageConst.CLIENT_ACTION_CANCEL_RECORED,0,0,null,null);
}
});
mBtnSend.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
sendMessageToService(
MessageConst.CLIENT_ACTION_SENT_TEXT,0,0,null,mEditText.getText());
mInputTextView.setText("文字: "+mEditText.getText());
}
});
mMusicView = (MusicView) findViewById(R.id.music_view);
//if(mMusicView != null)
//mMusicView.initMusicView(MusicActivity.this,mHandler);
}
private void initHandler()
{
mHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
switch (msg.what){
case MessageConst.CLIENT_ACTION_START_RECORED:
break;
default:
break;
}
}
};
}
//InComingHandler 收到來自VoiceSdkService的訊息用於更新介面,
//包括開始錄音,結束錄音,播放的書的名稱和進度,音量等資訊。
private void initInComingHandler()
{
mInComingHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
switch (msg.what){
case MessageConst.CLIENT_ACTION_START_RECORED:
mBtnStart.setText("錄音中");
Log.i("led","MusicActivity 錄音中");
break;
case MessageConst.CLIENT_ACTION_STOP_RECORED:
mBtnStart.setText("識別中");
Log.i("led","MusicActivity 識別中");
break;
case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
mBtnStart.setText("開始");
mTextView.setText("已取消");
break;
case MessageConst.CLIENT_ACTION_ON_ERROR:
mTextView.setText("錯誤程式碼:"+msg.arg1);
mBtnStart.setText("開始");
break;
case MessageConst.CLIENT_ACTION_UPDATA_VOLUME:
mTextViewVolume.setText("音量: "+msg.arg1);
break;
case MessageConst.SERVER_ACTION_RETURN_RESULT:
//mTextView.setText(msg.obj.toString());
mBtnStart.setText("開始");
break;
case MessageConst.CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH:
mBtnStart.setText("開始");
mBookUtil = BookUtil.getInstance();
mBookUtil.play(msg.arg1);
break;
case MessageConst.CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME:
mMusicView.setMusicName(msg.obj.toString());
break;
case MessageConst.CLIENT_ACTION_UPDATE_BOOK_PROGRESS:
int current = msg.arg1;
int duration = msg.arg2;
mMusicView.setProgress(current*100/duration);
float time = duration/1000/60;
mMusicView.setTotalTime("總時間:"+time);
break;
case MessageConst.CLIENT_ACTION_UPDATA_INPUT_TEXT:
if(msg.obj != null)
mInputTextView.setText("文字: "+msg.obj.toString());
break;
case MessageConst.CLIENT_ACTION_UPDATA_SERVER_MESSAGE:
if(msg.obj != null)
mTextView.setText("伺服器返回sentence: "+msg.obj.toString());
break;
default:
break;
}
}
};
}
private void initCommunicationAssist()
{//向Application註冊VoiceSdkService到MusicActivity的回撥
mActivityComAssist = new ActivityComAssist();
OlamiApplication.getInstance().setServiceToActivityListener(mActivityComAssist);
}
private void sendMessageToService(int what, int arg1, int arg2, Bundle data, Object obj)
{//向VoiceSdkService傳送訊息
if(OlamiApplication.getInstance().getActivityToServiceListener() != null)
OlamiApplication.getInstance().getActivityToServiceListener().callBack
(what, arg1, arg2, data, obj);
}
private class ActivityComAssist implements CommunicationAssist{
//實現CommunicationAssist藉口,用於回撥VoiceSdkService傳送過來的訊息
@Override
public void callBack(int what, int arg1, int arg2, Bundle data,Object obj) {
Message msg = Message.obtain(null, what);
msg.arg1 = arg1;
msg.arg2 = arg2;
if (data != null)
msg.setData(data);
if (obj != null)
msg.obj = obj;
mInComingHandler.sendMessage(msg);
}
}
@Override
public void onDestroy() {
//退出應用,停止VoiceSdkService,會進行資源的釋放
super.onDestroy();
Intent intent = new Intent();
intent.setClass(MusicActivity.this, VoiceSdkService.class);
stopService(intent);
}
}
3.3 VoiceSdkService
@Override
public void onCreate() {
initHandler();//用於內部訊息處理
initInComingHandler();//用於處理來自MusicActivity的訊息
initCommunicationAssist();//向application註冊訊息回撥,這樣MusicActivity可
//以通過getActivityToServiceListener()回撥向VoiceSdkService傳送訊息
initViaVoiceRecognizerListener();//初始化錄音識別回撥listener
init();//olami錄音識別引擎初始化
initXmly();//喜馬拉雅初始化
}
public void init()
{
initHandler();
mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(VoiceSdkService.this);
TelephonyManager telephonyManager=(TelephonyManager) this.getSystemService(
(this.getBaseContext().TELEPHONY_SERVICE);
String imei=telephonyManager.getDeviceId();
mOlamiVoiceRecognizer.init(imei);//設定身份標識,可以填null
mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener);//設定識別結果回撥listener
mOlamiVoiceRecognizer.setLocalization(
OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);//設定支援的語音型別,優先選擇中文簡體
mOlamiVoiceRecognizer.setAuthorization("51a4bb56ba954655a4fc834bfdc46af1",
"asr","68bff251789b426896e70e888f919a6d","nli");
//註冊Appkey,在olami官網註冊應用後生成的appkey
//註冊api,請直接填寫“asr”,標識語音識別型別
//註冊secret,在olami官網註冊應用後生成的secret
//註冊seq ,請填寫“nli”
mOlamiVoiceRecognizer.setVADTailTimeout(2000);//錄音時尾音結束時間,建議填//2000ms
//設定經緯度資訊,不願上傳位置資訊,可以填0
mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009);
}
定義OlamiVoiceRecognizerListener
onError(int errCode)//出錯回撥,可以對比官方文件錯誤碼看是什麼錯誤
onEndOfSpeech()//錄音結束
onBeginningOfSpeech()//錄音開始
onResult(String result, int type)//result是識別結果JSON字串
onCancel()//取消識別,不會再返回識別結果
onUpdateVolume(int volume)//錄音時的音量,1-12個級別大小音量
下面是VoiceSdkService完整程式碼:
public class VoiceSdkService extends Service{
private Handler mHandler;
private Handler mInComingHandler;
private VoiceSdkComAssist mVoiceSdkComAssist;
private OlamiVoiceRecognizer mOlamiVoiceRecognizer;
private OlamiVoiceRecognizerListener mOlamiVoiceRecognizerListener;
private BookUtil mBookUtil = null;
private boolean mIsRecordPause = false;
@Override
public void onCreate() {
initHandler();
initInComingHandler();
initCommunicationAssist();
initViaVoiceRecognizerListener();
init();
initXmly();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void init()
{
initHandler();
mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(VoiceSdkService.this);
TelephonyManager telephonyManager=(TelephonyManager) this.getSystemService(
this.getBaseContext().TELEPHONY_SERVICE);
String imei=telephonyManager.getDeviceId();
mOlamiVoiceRecognizer.init(imei);//set null if you do not want to notify olami server.
mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener);
mOlamiVoiceRecognizer.setLocalization(
OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE);
mOlamiVoiceRecognizer.setAuthorization(
"51a4bb56ba954655a4fc834bfdc46af1",
"asr","68bff251789b426896e70e888f919a6d","nli");
mOlamiVoiceRecognizer.setVADTailTimeout(2000);
mOlamiVoiceRecognizer.setLatitudeAndLongitude(31.155364678184498,121.34882432933009);
}
private void initHandler()
{
mHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
switch (msg.what){
case MessageConst.CLIENT_ACTION_START_RECORED:
sendMessageToActivity(MessageConst.CLIENT_ACTION_START_RECORED,0,0,null,null);
break;
case MessageConst.CLIENT_ACTION_STOP_RECORED:
sendMessageToActivity(MessageConst.CLIENT_ACTION_STOP_RECORED,0,0,null,null);
break;
case MessageConst.CLIENT_ACTION_ON_ERROR:
sendMessageToActivity(MessageConst.CLIENT_ACTION_ON_ERROR,msg.arg1,0,null,null);
break;
case MessageConst.CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH:
sendMessageToActivity(MessageConst.
CLIENT_ACTION_PLAY_BOOK_AFTER_SEARCH, msg.arg1, 0, null, msg.obj);
break;
case MessageConst.CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME:
sendMessageToActivity(MessageConst.
CLIENT_ACTION_UPDATA_PLAYING_BOOK_NAME, msg.arg1, 0, null, msg.obj);
break;
case MessageConst.CLIENT_ACTION_UPDATE_BOOK_PROGRESS:
sendMessageToActivity(MessageConst.
CLIENT_ACTION_UPDATE_BOOK_PROGRESS, msg.arg1, msg.arg2, null, null);
break;
case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
sendMessageToActivity(MessageConst.
CLIENT_ACTION_CANCEL_RECORED, msg.arg1, msg.arg2, null, null);
break;
default:
break;
}
}
};
}
private void initInComingHandler()
{
mInComingHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
switch (msg.what){
case MessageConst.CLIENT_ACTION_START_RECORED:
if(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer.start();
break;
case MessageConst.CLIENT_ACTION_STOP_RECORED:
if(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer.stop();
break;
case MessageConst.CLIENT_ACTION_CANCEL_RECORED:
if(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer.cancel();
break;
case MessageConst.CLIENT_ACTION_SENT_TEXT:
if(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer.sendText(msg.obj.toString());
break;
}
}
};
}
private void initViaVoiceRecognizerListener()
{
mOlamiVoiceRecognizerListener = new OlamiVoiceRecognizerListener();
}
private class OlamiVoiceRecognizerListener implements IOlamiVoiceRecognizerListener{
@Override
public void onError(int errCode) {
mHandler.sendMessage(mHandler.obtainMessage(
MessageConst.CLIENT_ACTION_ON_ERROR,errCode,0));
}
@Override
public void onEndOfSpeech() {
mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_STOP_RECORED);
if(mIsRecordPause)
{
mIsRecordPause = false;
mBookUtil.resumePlay();
}
}
@Override
public void onBeginningOfSpeech() {
if(mBookUtil.isPlaying())
{
mBookUtil.pause();
mIsRecordPause = true;
}
mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_START_RECORED);
}
@Override
public void onResult(String result, int type) {
sendMessageToActivity(MessageConst.SERVER_ACTION_RETURN_RESULT,type,0,null,result);
processServiceMessage(result);
}
@Override
public void onCancel() {
mHandler.sendEmptyMessage(MessageConst.CLIENT_ACTION_CANCEL_RECORED);
}
@Override
public void onUpdateVolume(int volume) {
sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_VOLUME,volume,0,null,null);
}
}
private void initCommunicationAssist()
{
mVoiceSdkComAssist = new VoiceSdkComAssist();
OlamiApplication.getInstance().setActivityToServiceListener(mVoiceSdkComAssist);
}
private void initXmly()
{
if(mBookUtil == null)
{
mBookUtil = BookUtil.getInstance();
mBookUtil.init(VoiceSdkService.this);
mBookUtil.setHandler(mHandler);
}
}
private void processServiceMessage(String message)
{
String input = null;
String serverMessage = null;
try{
JSONObject jsonObject = new JSONObject(message);
JSONArray jArrayNli = jsonObject.optJSONObject("data").optJSONArray("nli");
JSONObject jObj = jArrayNli.optJSONObject(0);
JSONArray jArraySemantic = null;
if(message.contains("semantic"))
jArraySemantic = jObj.getJSONArray("semantic");
else{
input = jsonObject.optJSONObject("data").optJSONObject("asr").
optString("result");
sendMessageToActivity(MessageConst.
CLIENT_ACTION_UPDATA_INPUT_TEXT, 0, 0, null, input);
serverMessage = jObj.optJSONObject("desc_obj").opt("result").toString();
sendMessageToActivity(MessageConst.
CLIENT_ACTION_UPDATA_SERVER_MESSAGE, 0, 0, null, serverMessage);
return;
}
JSONObject jObjSemantic;
JSONArray jArraySlots;
JSONArray jArrayModifier;
String type = null;
String songName = null;
String singer = null;
if(jObj != null) {
type = jObj.optString("type");
if("musiccontrol".equals(type))
{
jObjSemantic = jArraySemantic.optJSONObject(0);
input = jObjSemantic.optString("input");
jArraySlots = jObjSemantic.optJSONArray("slots");
jArrayModifier = jObjSemantic.optJSONArray("modifier");
String modifier = (String)jArrayModifier.opt(0);
if((jArrayModifier != null) && ("play".equals(modifier)))
{
if(jArraySlots != null)
for(int i=0,k=jArraySlots.length(); i<k; i++)
{
JSONObject obj = jArraySlots.getJSONObject(i);
String name = obj.optString("name");
if("singer".equals(name))
singer = obj.optString("value");
else if("songname".equals(name))
songName = obj.optString("value");
}
}else if((modifier != null) && ("stop".equals(modifier)))
{
if(mBookUtil != null)
if(mBookUtil.isPlaying())
mBookUtil.stop();
}else if((modifier != null) && ("pause".equals(modifier)))
{
if(mBookUtil != null)
if(mBookUtil.isPlaying())
mBookUtil.pause();
}else if((modifier != null) && ("resume_play".equals(modifier)))
{
if(mBookUtil != null)
mBookUtil.resumePlay();
}else if((modifier != null) && ("add_volume".equals(modifier)))
{
if(mBookUtil != null)
mBookUtil.addVolume();
}else if((modifier != null) && ("del_volume".equals(modifier)))
{
if(mBookUtil != null)
mBookUtil.delVolume();
}else if((modifier != null) && ("next".equals(modifier)))
{
if(mBookUtil != null)
mBookUtil.next();
}else if((modifier != null) && ("previous".equals(modifier)))
{
if(mBookUtil != null)
mBookUtil.prev();
}else if((modifier != null) && ("play_index".equals(modifier)))
{
int position = 0;
if(jArraySlots != null)
for(int i=0,k=jArraySlots.length(); i<k; i++)
{
JSONObject obj = jArraySlots.getJSONObject(i);
JSONObject jNumDetial = obj.getJSONObject("num_detail");
String index = jNumDetial.optString("recommend_value");
position = Integer.parseInt(index) - 1;
}
if(mBookUtil != null)
mBookUtil.skipTo(position);
}
}
}
if(songName != null)
{
if(singer != null)
{
}else{
mBookUtil.searchBookAndPlay(songName,0,0);
}
}else if(singer != null)
{
mBookUtil.searchBookAndPlay(songName,0,0);
}
serverMessage = jObj.optJSONObject("desc_obj").opt("result").toString();
}
catch (Exception e)
{
e.printStackTrace();
}
//傳送訊息更新語音識別的文字
sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_INPUT_TEXT, 0, 0, null, input);
//傳送訊息更新伺服器返回的結果字串
sendMessageToActivity(MessageConst.CLIENT_ACTION_UPDATA_SERVER_MESSAGE,
0, 0, null, serverMessage);
}
private void sendMessageToActivity(int what, int arg1, int arg2, Bundle data, Object obj)
{
if(OlamiApplication.getInstance().getServiceToActivityListener() != null)
OlamiApplication.getInstance().getServiceToActivityListener().
callBack(what, arg1, arg2, data, obj);
}
private class VoiceSdkComAssist implements CommunicationAssist{
@Override
public void callBack(int what, int arg1, int arg2, Bundle data,Object obj) {
Message msg = Message.obtain(null, what);
msg.arg1 = arg1;
msg.arg2 = arg2;
if (data != null)
msg.setData(data);
if (obj != null)
msg.obj = obj;
mInComingHandler.sendMessage(msg);
}
}
@Override
public void onDestroy(){
super.onDestroy();
if(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer.destroy();
if(mBookUtil != null)
{
mBookUtil.destroy();
}
}
}