27 changed files with 636 additions and 415 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,78 @@ |
|||
package qianmu.container.activity; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.core.app.ActivityCompat; |
|||
import androidx.core.content.ContextCompat; |
|||
|
|||
import android.Manifest; |
|||
import android.content.pm.PackageManager; |
|||
import android.os.Bundle; |
|||
import android.util.Log; |
|||
import android.view.View; |
|||
|
|||
import qianmu.container.R; |
|||
import qianmu.container.util.TTSUtil; |
|||
|
|||
public class TestActivity extends AppCompatActivity implements View.OnClickListener { |
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
setContentView(R.layout.activity_test); |
|||
setPermission(); |
|||
addEventListener(); |
|||
TTSUtil.connectLocalSocket(); |
|||
} |
|||
private void addEventListener(){ |
|||
findViewById(R.id.button).setOnClickListener(this); |
|||
findViewById(R.id.button2).setOnClickListener(this); |
|||
findViewById(R.id.button3).setOnClickListener(this); |
|||
findViewById(R.id.button4).setOnClickListener(this); |
|||
} |
|||
/** |
|||
* 检测权限并授权 |
|||
* */ |
|||
private void setPermission(){ |
|||
|
|||
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ |
|||
ActivityCompat.requestPermissions(this,new String[]{ |
|||
Manifest.permission.READ_EXTERNAL_STORAGE, |
|||
Manifest.permission.WRITE_EXTERNAL_STORAGE, |
|||
Manifest.permission.ACCESS_NETWORK_STATE, |
|||
Manifest.permission.CAMERA, |
|||
Manifest.permission.RECORD_AUDIO, |
|||
Manifest.permission.RECEIVE_BOOT_COMPLETED, |
|||
Manifest.permission.SYSTEM_ALERT_WINDOW, |
|||
Manifest.permission.READ_PHONE_STATE, |
|||
Manifest.permission.ACCESS_NETWORK_STATE},998); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { |
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults); |
|||
if(requestCode==998){ |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void onClick(View view) { |
|||
switch (view.getId()){ |
|||
case R.id.button : |
|||
TTSUtil.startAsr(); |
|||
break; |
|||
case R.id.button2 : |
|||
TTSUtil.stopAsr(); |
|||
break; |
|||
case R.id.button3 : |
|||
TTSUtil.startTts("天有不测风云,人有旦夕祸福。蜈蚣百足,行不及蛇;雄鸡两翼,飞不过鸦。"); |
|||
break; |
|||
case R.id.button4 : |
|||
TTSUtil.stopTts(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
package qianmu.container.entity; |
|||
|
|||
public class TTSMessage { |
|||
String jsonrpc; |
|||
String method; |
|||
Params params; |
|||
|
|||
public String getJsonrpc() { |
|||
return jsonrpc; |
|||
} |
|||
|
|||
public void setJsonrpc(String jsonrpc) { |
|||
this.jsonrpc = jsonrpc; |
|||
} |
|||
|
|||
public String getMethod() { |
|||
return method; |
|||
} |
|||
|
|||
public void setMethod(String method) { |
|||
this.method = method; |
|||
} |
|||
|
|||
public Params getParams() { |
|||
return params; |
|||
} |
|||
|
|||
public void setParams(Params params) { |
|||
this.params = params; |
|||
} |
|||
|
|||
public static class Params { |
|||
String text; |
|||
String speakUrl; |
|||
|
|||
public String getText() { |
|||
return text; |
|||
} |
|||
|
|||
public void setText(String text) { |
|||
this.text = text; |
|||
} |
|||
|
|||
public String getSpeakUrl() { |
|||
return speakUrl; |
|||
} |
|||
|
|||
public void setSpeakUrl(String speakUrl) { |
|||
this.speakUrl = speakUrl; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
package qianmu.container.util; |
|||
|
|||
import android.media.AudioAttributes; |
|||
import android.media.MediaPlayer; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
public class AudioPlay { |
|||
|
|||
private static volatile MediaPlayer mediaPlayer; |
|||
|
|||
public static void startPlay(String url){ |
|||
if (mediaPlayer != null) { |
|||
mediaPlayer.release(); |
|||
mediaPlayer = null; |
|||
} |
|||
try { |
|||
mediaPlayer = new MediaPlayer(); |
|||
// 设置音频属性(需在 setDataSource 前调用)
|
|||
AudioAttributes attributes = new AudioAttributes.Builder() |
|||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) |
|||
.setUsage(AudioAttributes.USAGE_MEDIA) |
|||
.build(); |
|||
mediaPlayer.setAudioAttributes(attributes); |
|||
// 设置数据源(确保路径正确,且有读取权限)
|
|||
mediaPlayer.setDataSource(url); |
|||
// 异步准备(避免阻塞主线程)
|
|||
mediaPlayer.prepareAsync(); |
|||
mediaPlayer.setVolume(1.0f, 1.0f); |
|||
mediaPlayer.setOnPreparedListener(mp -> { |
|||
// 准备完成后才能播放
|
|||
mp.start(); |
|||
}); |
|||
|
|||
// 监听错误状态
|
|||
mediaPlayer.setOnErrorListener((mp, what, extra) -> { |
|||
LoggerUtil.e("MediaPlayer", "Error: " + what + ", " + extra); |
|||
// 出错后释放资源
|
|||
mp.release(); |
|||
mediaPlayer = null; |
|||
return true; |
|||
}); |
|||
|
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
// 处理文件读取错误(如路径无效、权限不足)
|
|||
} |
|||
} |
|||
|
|||
public static void stopPlay(){ |
|||
if(mediaPlayer != null){ |
|||
mediaPlayer.stop(); |
|||
mediaPlayer.release(); |
|||
mediaPlayer = null; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,117 @@ |
|||
package qianmu.container.util; |
|||
|
|||
import com.google.gson.Gson; |
|||
|
|||
import org.greenrobot.eventbus.EventBus; |
|||
import org.java_websocket.drafts.Draft_6455; |
|||
import org.java_websocket.enums.ReadyState; |
|||
|
|||
import java.net.URI; |
|||
|
|||
import qianmu.container.entity.TTSMessage; |
|||
import qianmu.container.socket.SocketClient; |
|||
|
|||
/** |
|||
* 思必驰 语音调用 |
|||
*/ |
|||
public class TTSUtil { |
|||
|
|||
private static SocketClient localSocketClient; |
|||
|
|||
|
|||
private static void initLocalSocketClient() { |
|||
try { |
|||
URI localUri = new URI("ws://127.0.0.1:50002"); |
|||
LoggerUtil.e("TTSSocketUri", localUri.toString()); |
|||
localSocketClient = new SocketClient(localUri, new Draft_6455()); |
|||
setLocalSocketListener(); |
|||
} catch (Throwable t) { |
|||
LoggerUtil.e("initSocketClient", StringUtil.getThrowableStr(t)); |
|||
} |
|||
} |
|||
|
|||
public static void connectLocalSocket() { |
|||
try { |
|||
//客户端不存在时 创建客户端设置监听事件
|
|||
if (localSocketClient == null) initLocalSocketClient(); |
|||
//获取客户端当前的连接状态
|
|||
ReadyState state = localSocketClient.getReadyState(); |
|||
LoggerUtil.e("connectLocalSocket", "TTS客户端连接状态:"+ GsonUtil.getGson().toJson(state)); |
|||
boolean open = localSocketClient.isOpen(); |
|||
LoggerUtil.e("connectLocalSocket", "TTS客户端连接状态:open="+open); |
|||
if (open) return; |
|||
//获取客户端当前的连接状态
|
|||
if (localSocketClient.isOpen()) return; |
|||
//未连接状态时 连接服务器
|
|||
if (state.equals(ReadyState.NOT_YET_CONNECTED)) localSocketClient.connect(); |
|||
else if (state.equals(ReadyState.CLOSING) || state.equals(ReadyState.CLOSED)) { |
|||
//正在关闭或者关闭状态时 重新连接服务器
|
|||
localSocketClient.reconnect(); |
|||
} |
|||
} catch (Throwable t) { |
|||
LoggerUtil.e("connectLocalSocket", StringUtil.getThrowableStr(t)); |
|||
destroyLocalSocketClient(); |
|||
} |
|||
} |
|||
// 识别语音
|
|||
public static void startAsr(){ |
|||
localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/start\"}")); |
|||
} |
|||
// 停止语音识别
|
|||
public static void stopAsr(){ |
|||
localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/stop\"}")); |
|||
} |
|||
// 开始语音合成
|
|||
public static void startTts(String txt){ |
|||
localSocketClient.send(StringUtil.strSplice("{\"method\": \"/tts/start\",\"params\": {\"text\":\"", txt, "\", \"mode\":\"autoPlay\"}}")); |
|||
} |
|||
// 停止语音合成
|
|||
public static void stopTts(){ |
|||
localSocketClient.send(StringUtil.strSplice("{\"method\":\"/tts/stop\"}")); |
|||
AudioPlay.stopPlay(); |
|||
} |
|||
|
|||
private static void setLocalSocketListener() { |
|||
localSocketClient.setOnOpenListener((handshakeData) -> { |
|||
LoggerUtil.e("connectLocalSocket", "TTS客户端连接成功"); |
|||
localSocketClient.send(StringUtil.strSplice("{\"id\":123,\"method\":\"/asr/stop\"}")); |
|||
}); |
|||
|
|||
localSocketClient.setOnMessageListener((conn, message) -> { |
|||
try { |
|||
TTSMessage messageBean = new Gson().fromJson(message, TTSMessage.class); |
|||
TTSMessage.Params content = messageBean.getParams(); |
|||
if (content == null) return; |
|||
LoggerUtil.e("ttsSocket:", messageBean.getMethod()); |
|||
if("asr.text".equals(messageBean.getMethod())){ |
|||
LoggerUtil.e("ttsSocket:",content.getText()); |
|||
} |
|||
if("asr.result".equals(messageBean.getMethod())){ |
|||
LoggerUtil.e("ttsSocket:",content.getText()); |
|||
} |
|||
if("tts.result".equals(messageBean.getMethod())){ |
|||
LoggerUtil.e("ttsSocket:",content.getSpeakUrl()); |
|||
} |
|||
} catch (Throwable t) { |
|||
LoggerUtil.e("setOnMessageListener", StringUtil.getThrowableStr(t)); |
|||
} |
|||
}); |
|||
|
|||
localSocketClient.setOnCloseListener((code, reason, remote) -> { |
|||
LoggerUtil.e("LocSocCliManager", "onClose:code="+code); |
|||
if (localSocketClient == null){ |
|||
initLocalSocketClient(); |
|||
}else { |
|||
localSocketClient.reconnect(); |
|||
} |
|||
}); |
|||
localSocketClient.setOnErrorListener((ex) -> LoggerUtil.e("LocSocCliManager", "onError")); |
|||
} |
|||
|
|||
//销毁当前的客户端
|
|||
public static void destroyLocalSocketClient() { |
|||
if (localSocketClient == null) return; |
|||
localSocketClient.close(); |
|||
localSocketClient = null; |
|||
} |
|||
} |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,37 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<LinearLayout 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" |
|||
tools:context=".activity.TestActivity" |
|||
android:orientation="vertical"> |
|||
|
|||
|
|||
<Button |
|||
android:id="@+id/button" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="@dimen/aspect_btn_height" |
|||
android:layout_weight="1" |
|||
android:text="开始语音识别" /> |
|||
|
|||
<Button |
|||
android:id="@+id/button2" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:text="停止语音识别" /> |
|||
|
|||
<Button |
|||
android:id="@+id/button3" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:text="播放语音合成" /> |
|||
|
|||
<Button |
|||
android:id="@+id/button4" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:text="停止语音合成" /> |
|||
</LinearLayout> |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue