From: xiewei <892331662@qq.com> Date: Tue, 25 Mar 2025 12:06:27 +0000 (+0800) Subject: 250325:柒牌demo X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=49dc1310e71a88c78c7609315469181a4f9aecb2;p=mirrors%2Fpoly-sdk.git 250325:柒牌demo --- diff --git a/app/build.gradle b/app/build.gradle index 4ba284a..a75864b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,7 +42,7 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'com.google.code.gson:gson:2.10' implementation 'com.github.bumptech.glide:glide:4.0.0-RC1' - + implementation 'com.github.xfans:VoiceWaveView:1.0.2'//音频动效 // implementation "org.java-websocket:Java-WebSocket:1.5.1" implementation 'com.arthenica:mobile-ffmpeg-full:4.4' // implementation 'com.squareup.okhttp3:okhttp:4.9.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9e59667..b9abe25 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,9 +20,18 @@ android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.PolymerizeSdk" + android:theme="@style/AppTheme.NoActionBar" android:usesCleartextTraffic="true" tools:targetApi="31"> + + + + + + + @@ -44,11 +53,11 @@ - + diff --git a/app/src/main/assets/first.pcm b/app/src/main/assets/first.pcm new file mode 100644 index 0000000..361709b Binary files /dev/null and b/app/src/main/assets/first.pcm differ diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java index 5d52b13..6c3d6e3 100644 --- a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java @@ -1,9 +1,9 @@ package com.zhixun.android.sdk.polymerizesdk; + import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; -import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -11,47 +11,79 @@ import android.util.Log; import androidx.annotation.NonNull; -import com.zhixun.android.sdk.polysdk.authentication.AuthMsgSendHandler; +import com.zhixun.android.sdk.polysdk.util.SobLog; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; public class AudioPlayer { private AudioTrack audioTrack; private int bufferSize; private final int MSG_PLAY = 101; + private final int MSG_PLAY_OVER = 102; private String TAG = "AudioPlayer"; private List playList = new ArrayList<>(); + private boolean isPlaying = false; private Handler audioHandler; - private AudioLooperThread audioLooperThread; - class AudioLooperThread extends Thread { + private Queue queueMsg = new ConcurrentLinkedQueue();//线程安全到队列 + private class AudioLooperThread extends Thread { + + @Override public void run() { + super.run(); Looper.prepare(); - audioHandler = new Handler(){ + audioHandler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); - switch (msg.what){ + switch (msg.what) { case MSG_PLAY: - Log.i(TAG,"play---111---"); - byte[] data = (byte[]) msg.obj; + isPlaying = true; + audioHandler.removeMessages(MSG_PLAY_OVER); + Log.i(TAG, "play---111---"); + byte[] data = queueMsg.poll(); + if(data==null){ + audioHandler.sendEmptyMessageDelayed(MSG_PLAY_OVER, 1000); + return; + } if (audioTrack != null) { audioTrack.play(); int length = data.length; - while (length > 0&&audioTrack != null) { - int written = audioTrack.write(data, 0, length); - length -= written; + while (length > 0 && audioTrack != null&&isPlaying) { + try { + int written = audioTrack.write(data, 0, length); + length -= written; + } catch (Exception e) { + Log.e(TAG, "play---Exception---" + e.getMessage()); + } + } - Log.i(TAG,"play---end---"); + Log.i(TAG, "play---end---"); + } + if(isPlaying){ + audioHandler.sendEmptyMessage(MSG_PLAY); + } + break; + case MSG_PLAY_OVER: + isPlaying = false; + if (audioPlayStateChangeListener != null) { + audioPlayStateChangeListener.onStateChange(isPlaying); } - break; } } }; Looper.loop(); - } + + } public AudioPlayer(int sampleRate, int channelConfig, int audioFormat) { @@ -63,12 +95,16 @@ public class AudioPlayer { sampleRate, channelConfig, audioFormat, bufferSize, AudioTrack.MODE_STREAM); } + private AudioLooperThread audioLooperThread; + public AudioPlayer() { - audioLooperThread = new AudioLooperThread(); - audioLooperThread.start(); + init(); + } + + private void init() { int sampleRate = 16000; int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; - int audioFormat = AudioFormat.ENCODING_PCM_8BIT; + int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 初始化buffer size bufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat); // 初始化AudioTrack @@ -78,47 +114,101 @@ public class AudioPlayer { AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM); + audioTrack.setPositionNotificationPeriod(bufferSize); - audioTrack.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { - @Override - public void onMarkerReached(AudioTrack track) { - //播放完成 - Log.i(TAG,"onMarkerReached"); - } + audioLooperThread = new AudioLooperThread(); + audioLooperThread.start(); - @Override - public void onPeriodicNotification(AudioTrack track) { - } - }); +// AudioManager mAm = ( AudioManager ) context.getSystemService(Context.AUDIO_SERVICE); +// mAm.setMode(AudioManager.MODE_IN_CALL); +// mAm.setBluetoothScoOn(true); +// mAm.startBluetoothSco(); + } + + public boolean isPlaying() { + return isPlaying; + } + + public void setPlaying(boolean playing) { + isPlaying = playing; } private byte[] cacheAudio = new byte[0]; - public synchronized void play(byte[] audioData) { - Log.i(TAG,"play---"+cacheAudio.length); -// if(cacheAudio.length<40*1024){ -// cacheAudio = ByteTools.concatAll(cacheAudio,audioData); -// }else { - Message message = new Message(); - message.what = MSG_PLAY; - message.obj = audioData; - audioHandler.sendMessage(message); - cacheAudio = new byte[0]; -// } + public synchronized void play(byte[] audioData) { + if (audioTrack == null) { + init(); + } + queueMsg.add(audioData); + if (!isPlaying) { + isPlaying = true; + if (audioPlayStateChangeListener != null) { + audioPlayStateChangeListener.onStateChange(isPlaying); + } + audioHandler.sendEmptyMessage(MSG_PLAY); + } } + public synchronized void play(String audioPath) { + if (audioTrack == null) { + init(); + } + SobLog.d(TAG,"play--"+audioPath); + try { + InputStream inputStream = new FileInputStream(audioPath); + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + byte[] data = new byte[inputStream.available()]; + bufferedInputStream.read(data); + inputStream.close(); + bufferedInputStream.close(); + queueMsg.add(data); + // do something with the data + } catch (IOException e) { + e.printStackTrace(); + } + SobLog.d(TAG,"play--"+isPlaying); + if (!isPlaying) { + isPlaying = true; + if (audioPlayStateChangeListener != null) { + audioPlayStateChangeListener.onStateChange(isPlaying); + } + + audioHandler.sendEmptyMessage(MSG_PLAY); + } + } public void stop() { + if(!isPlaying)return; + isPlaying = false; if (audioTrack != null) { audioTrack.stop(); audioTrack.release(); audioTrack = null; } + audioHandler.removeMessages(MSG_PLAY); + audioHandler.removeMessages(MSG_PLAY_OVER); + SobLog.d(TAG,"stop--"); + + queueMsg.clear(); + if (audioPlayStateChangeListener != null) { + audioPlayStateChangeListener.onStateChange(isPlaying); + } + } + private AudioPlayStateChangeListener audioPlayStateChangeListener; + + + public void setAudioPlayStateChangeListener(AudioPlayStateChangeListener audioPlayStateChangeListener) { + this.audioPlayStateChangeListener = audioPlayStateChangeListener; + } + + public interface AudioPlayStateChangeListener { + void onStateChange(boolean state); + } } diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java index e25aedd..90e7ac7 100644 --- a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java @@ -15,7 +15,7 @@ public class AudioRecorderMan { private AudioRecord audioRecord; private int bufferSize; private boolean isRecording = false; - + private Thread audioThread; private static AudioRecorderMan sInstance; public static AudioRecorderMan getInstance() { if (sInstance == null) { @@ -39,38 +39,50 @@ public class AudioRecorderMan { Log.d(TAG,"startRecording--no Permission"); return ; } - audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, + audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, sampleRate, channelConfig, audioFormat, bufferSize); if (audioRecord != null) { isRecording = true; Log.d(TAG,"startRecording--"); - new Thread(() -> { - audioRecord.startRecording(); - byte[] buffer = new byte[bufferSize]; - int read = 0; - while (read>=0) { - read = audioRecord.read(buffer, 0, bufferSize); - Log.d(TAG,"startRecording--"+read); - if (read < 0) { - // 处理错误 - } else { - // 处理buffer中的数据,这里你可以将它传输或者保存 - if(onBuffChange!=null){ - onBuffChange.onChange(buffer); - } + doRecord(); + } + } + + private void doRecord() { + audioThread = new Thread(() -> { + audioRecord.startRecording(); + byte[] buffer = new byte[bufferSize]; + int read = 0; + while (read>=0&&audioRecord!=null) { + read = audioRecord.read(buffer, 0, bufferSize); + Log.d(TAG,"startRecording--"+read); + if (read < 0) { + // 处理错误 + } else { + // 处理buffer中的数据,这里你可以将它传输或者保存 + if(onBuffChange!=null){ + onBuffChange.onChange(buffer); } } + } - }, "AudioRecorderThread").start(); - } + }, "AudioRecorderThread"); + audioThread.start(); } + public void stopRecording() { Log.d(TAG,"stopRecording--"); isRecording = false; + if (audioThread != null) { + audioThread.interrupt(); + audioThread = null; + } + if (audioRecord != null) { audioRecord.stop(); audioRecord.release(); + audioRecord = null; } } diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/DoubaoMainActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/DoubaoMainActivity.java new file mode 100644 index 0000000..586f4cc --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/DoubaoMainActivity.java @@ -0,0 +1,416 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.graphics.Color; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.VideoView; + +import com.zhixun.android.sdk.polymerizesdk.adapter.AiMsgAdapter; +import com.zhixun.android.sdk.polymerizesdk.adapter.VcData; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.ai.VoiceChatManager; +import com.zhixun.android.sdk.polysdk.callback.AuthCallback; +import com.zhixun.android.sdk.polysdk.callback.IVoiceChatCallback; +import com.zhixun.android.sdk.polysdk.callback.OnTranscriptionDataChange; +import com.zhixun.android.sdk.polysdk.util.SobLog; +import com.zhixun.android.sdk.polysdk.util.SpUtils; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +import me.xfans.lib.voicewaveview.VoiceWaveView; +import me.xfans.lib.voicewaveview.WaveMode; + +public class DoubaoMainActivity extends AppCompatActivity { + + + private String TAG = "DoubaoMainActivity"; + private VideoView bq_video; + private TextView tv_state,tv_event; + private ImageView startBtn; + private AudioPlayer player = new AudioPlayer(); + private boolean isStartTranscrip; +// private final int MSG_DO_TTS = 101; + private AiMsgAdapter aiMsgAdapter; + private RecyclerView msg_listview; + private VoiceWaveView voiceWaveView; + private LinearLayout layout_msg; + private int msgPosition=-1,chatPosition = -1; + private String responsStr = ""; + private String asrStr = ""; + private boolean shwoList = false; + private long downTime = 0; + private Handler handler = new Handler(Looper.getMainLooper()){ + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + switch (msg.what){ + + case 102: + if(isFirst){ + String uri="android.resource://"+getPackageName()+"/"+R.raw.zhayan; + bq_video.setOnPreparedListener(null); + bq_video.destroyDrawingCache(); + bq_video.suspend(); + playVideo(uri); + handler.sendEmptyMessageDelayed(106,1000); + } + break; + case 103: + Log.i(TAG,"onRspons--103"); + responsStr = ""; + chatPosition = aiMsgAdapter.addData(new VcData(1,responsStr)); + msg_listview.scrollToPosition(chatPosition); + break; + case 104: + Log.i(TAG,"onRspons--104"); + chatPosition = -1; + responsStr = ""; + break; + case 105: + + String text = (String) msg.obj; + if(TextUtils.isEmpty(text))return; + Log.i(TAG,"onRspons--105"+text); + responsStr = responsStr+text; + if(chatPosition==-1){ + chatPosition = aiMsgAdapter.addData(new VcData(1,responsStr)); + }else { + aiMsgAdapter.setData(chatPosition,new VcData(1,responsStr)); + } + aiMsgAdapter.notifyItemChanged(chatPosition); + tv_event.setText(responsStr); + break; + case 106: + tv_event.setVisibility(View.VISIBLE); + break; + } + } + }; + + private boolean isFirst = true; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_doubao_main); + bq_video = findViewById(R.id.bq_video); + tv_state = findViewById(R.id.tv_state); + startBtn = findViewById(R.id.startBtn); + msg_listview = findViewById(R.id.msg_listview); + voiceWaveView = findViewById(R.id.voiceWaveView); + tv_event = findViewById(R.id.tv_event); + String uri="android.resource://"+getPackageName()+"/"+R.raw.delfult; + + playVideo(uri); + PolymerizeAgent.getInstance().getAuthenAPI().setAIChannelKey("huoshan","",null); + goLogin(); + + startBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + player.stop(); + String uri="android.resource://"+getPackageName()+"/"+R.raw.lisening; + if(isStartTranscrip){ + isStartTranscrip = false; + AudioRecorderMan.getInstance().stopRecording(); + PolymerizeAgent.getInstance().getAiAPI().stopTrans(); + uri="android.resource://"+getPackageName()+"/"+R.raw.thinking; + voiceWaveView.stop(); + }else { + isStartTranscrip = true; +// PolymerizeAgent.getInstance().getAiAPI().cancleChat(); + VoiceChatManager.getInstance().cancleChat(); + PolymerizeAgent.getInstance().getAiAPI().startTrans(); + uri="android.resource://"+getPackageName()+"/"+R.raw.lisening; + tv_state.setText("点击或停止说话发送"); + voiceWaveView.start(); + } + playVideo(uri); + + } + }); + AudioRecorderMan.getInstance().setOnBuffChange(new AudioRecorderMan.onBuffChange() { + @Override + public void onChange(byte[] data) { + Log.i(TAG,"Audio-onChange-"+isStartTranscrip); + if(isStartTranscrip){ + Log.i(TAG,"Audio-onChange-"+data.length); + PolymerizeAgent.getInstance().getAiAPI().sendTransByte(data); +// VoiceChatManager.getInstance().sendVoice(data); + } + } + }); + + PolymerizeAgent.getInstance().getAiAPI().setOnTranscriptionDataChange(new OnTranscriptionDataChange() { + @Override + public void onStartChange(int action,boolean state) { + if(state){ + AudioRecorderMan.getInstance().startRecording(DoubaoMainActivity.this); + } + } + + @Override + public void onChange(String state,String text) { + Log.i(TAG,"Transcription-onChange-"+state+"--"+text); + if(state.equals("end")){ + PolymerizeAgent.getInstance().getAiAPI().sendChatMsg(text); + } + runOnUiThread(new Runnable() { + @Override + public void run() { + if(state.equals("start")){ + asrStr = ""; + msgPosition = aiMsgAdapter.addData(new VcData(0,text)); + tv_state.setText("点击结束说话"); + } + else if(state.equals("SentenceEnd")||state.equals("end")){ + asrStr = text; + tv_event.setText(asrStr); + if(msgPosition==-1){ + msgPosition = aiMsgAdapter.addData(new VcData(0,asrStr)); + }else { + aiMsgAdapter.setData(msgPosition,new VcData(0,asrStr)); + } + } + + aiMsgAdapter.notifyItemChanged(msgPosition); + msg_listview.scrollToPosition(msgPosition); + if(state.equals("end")){ + msgPosition = -1; + asrStr = ""; + } + } + }); + } + }); + + PolymerizeAgent.getInstance().getAiAPI().setOnVoiceChatListener(new IVoiceChatCallback() { + @Override + public void OnSpeech(byte[] data) { + player.play(data); + } + + @Override + public void OnRespond(String type, String text) { + Log.d(TAG,"OnRespond--"+type); + doRespons(type,text); + } + }); + + player.setAudioPlayStateChangeListener(new AudioPlayer.AudioPlayStateChangeListener() { + @Override + public void onStateChange(boolean state) { + if(isFirst&&!state){ + isFirst = false; + return; + } + if(isFirst)return; + Log.d(TAG,"setAudioPlayStateChangeListener--"+state); + + runOnUiThread(new Runnable() { + @Override + public void run() { + String uri="android.resource://"+getPackageName()+"/"+R.raw.speek; + + if(state){ + uri="android.resource://"+getPackageName()+"/"+R.raw.speek; + tv_state.setText("点击打断"); + }else { + uri="android.resource://"+getPackageName()+"/"+R.raw.zhayan; + tv_state.setText("点击对话"); +// tv_event.setText("再聊点啥呢..."); + } + playVideo(uri); + } + }); + } + }); + + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + msg_listview.setLayoutManager(layoutManager); + aiMsgAdapter = new AiMsgAdapter(this, new ArrayList<>()); + msg_listview.setAdapter(aiMsgAdapter); + msg_listview.getItemAnimator().setChangeDuration(0);// 通过设置动画执行时间为0来解决闪烁问题 + + + + msg_listview.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + Log.d(TAG,"layout_msg--"+event.getAction()); + switch (event.getAction()){ + case MotionEvent.ACTION_DOWN: + downTime = System.currentTimeMillis(); + break; + case MotionEvent.ACTION_UP: + long time = System.currentTimeMillis()-downTime; + if(time<200){ + msg_listview.setVisibility(View.GONE); + bq_video.setVisibility(View.VISIBLE); + } + break; + } + return false; + } + }); + + bq_video.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + msg_listview.setVisibility(View.VISIBLE); + msg_listview.setFocusable(true); + bq_video.setVisibility(View.GONE); + } + }); + + voiceWaveView.setShowGravity(Gravity.CENTER); + voiceWaveView.setWaveMode(WaveMode.LEFT_RIGHT); + voiceWaveView.setLineWidth(3f); + voiceWaveView.setLineSpace(5f); + voiceWaveView.setLineColor(Color.parseColor("#ffffff")); + voiceWaveView.setDuration(100); +// voiceWaveView.addHeader(4); + voiceWaveView.addHeader(4); + voiceWaveView.addBody(16); + voiceWaveView.addBody(26); + voiceWaveView.addBody(46); + voiceWaveView.addBody(26); + voiceWaveView.addBody(16); +// voiceWaveView.addBody(60); +// voiceWaveView.addBody(38); +// voiceWaveView.addBody(14); +// voiceWaveView.addBody(8); + voiceWaveView.addFooter(4); +// voiceWaveView.addFooter(2); + player.play(readFile()); + + } + + private String pwd = "RTQYOiB3zLAz5AeJSGnEPXea4qPfTY"; + public void goLogin(){ + pwd = SpUtils.getInstance().getStringValue("devicePwd"); + PolymerizeAgent.getInstance().getAuthenAPI().authentication("281106010111" + , pwd, "4EepovakpbqhZUnUDwH42KAADYGv4UUe", new AuthCallback() { + @Override + public void onSuccess(String result) { + Log.i(TAG,"result--"+result); + } + + @Override + public void onFail(int code,String msg) { + Log.i(TAG,"onFail--"+msg+"code-"+code); + goRegiest(); + } + }); + + } + + public void goRegiest(){ + PolymerizeAgent.getInstance().getAuthenAPI().regiest("4EepovakpbqhZUnUDwH42KAADYGv4UUe" + , "281106010111", "Y1DxRdBfnzVZQrXHdrNl", new AuthCallback() { + @Override + public void onSuccess(String result) { + Log.i(TAG,"result--"+result); + pwd = result; + SpUtils.getInstance().saveValue("devicePwd",pwd); + goLogin(); + } + + @Override + public void onFail(int code,String msg) { + Log.i(TAG,"onFail--"+msg+"code-"+code); + } + }); + + + + /*ChatGPTClient.getInstance().checkAIKey("sk-proj-04ogvrZQqyaiv1OWw8OZT3BlbkFJG9Gyr8oFvRdmr3oXQNbX", new IOnKeyCheckCallback() { + @Override + public void OnKeyCheckResult(boolean result) { + Log.d(TAG,"result--"+result); + } + });*/ + } + + + private void playVideo(String path){ + bq_video.setVideoURI(Uri.parse(path)); + bq_video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + Log.i(TAG, "init_vieofile:..main_video1...视频准备完毕,可以进行播放....." + mediaPlayer.isPlaying()); + mediaPlayer.setVolume(0f, 0f); + if (!mediaPlayer.isPlaying()) { + mediaPlayer.start(); + } + Log.i(TAG, "isFirst....." + isFirst); + if(!isFirst){ + mediaPlayer.setLooping(true); + } + + + } + }); + bq_video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + //结束播放 + handler.sendEmptyMessage(102); + } + }); + + + } + + private void doRespons(String state,String text) { + + if(state.equals("start")){ + handler.sendEmptyMessage(103); + }else if(state.equals("end")){ + handler.sendEmptyMessage(104); + }else { + Message message = handler.obtainMessage(105); + message.obj = text; + handler.sendMessage(message); + } + } + + private byte[] readFile() { + try { + InputStream in = getAssets().open("first.pcm"); + byte[] filecontent = new byte[in.available()]; + in.read(filecontent); + + SobLog.show(TAG, "readFile--" + filecontent.length); + in.close(); + return filecontent; + } catch (FileNotFoundException e) { + e.printStackTrace(); + SobLog.show(TAG, "readFile---" + e.getMessage()); + return null; + } catch (IOException e) { + e.printStackTrace(); + SobLog.show(TAG, "readFile---" + e.getMessage()); + return null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MyMediaPlayer.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MyMediaPlayer.java index f869e95..2850ed8 100644 --- a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MyMediaPlayer.java +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MyMediaPlayer.java @@ -28,17 +28,8 @@ public class MyMediaPlayer { private void initMedia() { mediaPlayer = new MediaPlayer(); - mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { - @Override - public void onCompletion(MediaPlayer mp) { - Log.d(TAG,"play over"); - if (sourceList.size() > 0) { - playData(sourceList.get(0)); - sourceList.remove(0); - } - } - }); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM); + } private List sourceList = new ArrayList<>(); @@ -48,43 +39,25 @@ public class MyMediaPlayer { new Thread(new Runnable() { @Override public void run() { - if (mediaPlayer.isPlaying()||sourceList.size()>0) { - try { - File tempMp3 = File.createTempFile("temp_" + System.currentTimeMillis(), ".mp3"); -// tempMp3.deleteOnExit(); - FileOutputStream fos = new FileOutputStream(tempMp3); - fos.write(audioSource); - fos.close(); - FileInputStream fis = new FileInputStream(tempMp3); - sourceList.add(fis); - } catch (IOException ex) { - String s = ex.toString(); - Log.d(TAG, "playData--" + s); - ex.printStackTrace(); - } - - } else { - try { - File tempMp3 = File.createTempFile("temp_" + System.currentTimeMillis(), ".mp3"); - tempMp3.deleteOnExit(); - Log.i(TAG,"playData-11-"); - FileOutputStream fos = new FileOutputStream(tempMp3); - fos.write(audioSource); - fos.close(); - Log.i(TAG,"playData-22-"); - mediaPlayer.reset(); - FileInputStream fis = new FileInputStream(tempMp3); - Log.i(TAG,"playData-33-"); - mediaPlayer.setDataSource(fis.getFD()); - mediaPlayer.prepare(); - mediaPlayer.start(); - Log.i(TAG,"playData-44-"); - } catch (IOException ex) { - String s = ex.toString(); - Log.d(TAG, "playData-1-" + s); - ex.printStackTrace(); - } - + try { + File tempMp3 = File.createTempFile("temp_" + System.currentTimeMillis(), ".m4a"); + Log.i(TAG,"playData-11-"); + FileOutputStream fos = new FileOutputStream(tempMp3); + fos.write(audioSource); + fos.close(); + Log.i(TAG,"playData-22-"); + mediaPlayer.reset(); + FileInputStream fis = new FileInputStream(tempMp3); + Log.i(TAG,"playData-33-"); + mediaPlayer.setDataSource(fis.getFD()); + mediaPlayer.prepare(); + mediaPlayer.start(); +// tempMp3.deleteOnExit(); + Log.i(TAG,"playData-44-"); + } catch (IOException ex) { + String s = ex.toString(); + Log.d(TAG, "playData-1-" + s); + ex.printStackTrace(); } } @@ -106,7 +79,7 @@ public class MyMediaPlayer { } - public void playData(String path) { + public void playData(String path) { stop(); initMedia(); try { diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/AiMsgAdapter.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/AiMsgAdapter.java new file mode 100644 index 0000000..1a5416a --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/AiMsgAdapter.java @@ -0,0 +1,108 @@ +package com.zhixun.android.sdk.polymerizesdk.adapter; + + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + + +import com.zhixun.android.sdk.polymerizesdk.R; + +import java.util.ArrayList; + +public class AiMsgAdapter extends RecyclerView.Adapter { + + private ArrayList msgList ; + private Context mContext; + public AiMsgAdapter(Context context, ArrayList msgList) { + this.mContext = context; + this.msgList = msgList; + } + + @NonNull + @Override + public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = View.inflate(mContext, R.layout.layout_item_ai_msg, null); + MyViewHoder myViewHoder = new MyViewHoder(view); + return myViewHoder; + } + + @Override + public void onBindViewHolder(@NonNull MyViewHoder holder, int position) { + + VcData vcData = msgList.get(position); + String msg = vcData.getMsg(); + if(vcData.getType()==0){ + //问 + holder.tvMsg.setVisibility(View.GONE); + holder.tvInput.setVisibility(View.VISIBLE); + if(!TextUtils.isEmpty(msg)&&!msg.equals("null")){ + holder.tvInput.setText(vcData.getMsg()); + }else { + holder.tvInput.setText(""); + } + + }else { + //回复 + holder.tvMsg.setVisibility(View.VISIBLE); + holder.tvInput.setVisibility(View.GONE); + if(!TextUtils.isEmpty(msg)&&!msg.equals("null")){ + holder.tvMsg.setText(vcData.getMsg()); + }else { + holder.tvMsg.setText(""); + } + } + + + } + + @Override + public int getItemCount() { + return msgList.size(); + } + + + private void addData(ArrayList data){ + msgList.addAll(data); + notifyDataSetChanged(); + } + + public int addData(VcData data){ + msgList.add(data); + notifyDataSetChanged(); + return msgList.size()-1; + } + + public void setData(int position,VcData data){ + msgList.set(position,data); +// notifyItemChanged(position); + } + + public ArrayList getMsgList() { + return msgList; + } + + public class MyViewHoder extends RecyclerView.ViewHolder { + TextView tvMsg,tvInput; + + public MyViewHoder(@NonNull View itemView) { + super(itemView); + tvMsg = itemView.findViewById(R.id.tv_msg); + tvInput = itemView.findViewById(R.id.tv_input); + + + + } + + } + +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/VcData.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/VcData.java new file mode 100644 index 0000000..3be2487 --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/VcData.java @@ -0,0 +1,27 @@ +package com.zhixun.android.sdk.polymerizesdk.adapter; + +public class VcData { + private int type; + private String msg; + + public VcData(int type, String msg) { + this.type = type; + this.msg = msg; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/FullScreenVideoView.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/FullScreenVideoView.java new file mode 100644 index 0000000..f847f04 --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/FullScreenVideoView.java @@ -0,0 +1,32 @@ +package com.zhixun.android.sdk.polymerizesdk.util; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.VideoView; + + +public class FullScreenVideoView extends VideoView{ + + + public FullScreenVideoView(Context context) { + super(context); +// TODO Auto-generated constructor stub + } + public FullScreenVideoView(Context context, AttributeSet attrs) + { + super(context,attrs); + } + public FullScreenVideoView(Context context, AttributeSet attrs, int defStyle) + { + super(context,attrs,defStyle); + } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width , height); + } + + +} diff --git a/app/src/main/res/drawable/ai_input_bg_shape.xml b/app/src/main/res/drawable/ai_input_bg_shape.xml new file mode 100644 index 0000000..5129148 --- /dev/null +++ b/app/src/main/res/drawable/ai_input_bg_shape.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ai_msg_bg_shape.xml b/app/src/main/res/drawable/ai_msg_bg_shape.xml new file mode 100644 index 0000000..fcd3e2f --- /dev/null +++ b/app/src/main/res/drawable/ai_msg_bg_shape.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_doubao_main.xml b/app/src/main/res/layout/activity_doubao_main.xml new file mode 100644 index 0000000..8159269 --- /dev/null +++ b/app/src/main/res/layout/activity_doubao_main.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_item_ai_msg.xml b/app/src/main/res/layout/layout_item_ai_msg.xml new file mode 100644 index 0000000..606537f --- /dev/null +++ b/app/src/main/res/layout/layout_item_ai_msg.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/bg_speek.png b/app/src/main/res/mipmap-xhdpi/bg_speek.png new file mode 100644 index 0000000..cad0ea4 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/bg_speek.png differ diff --git a/app/src/main/res/mipmap-xhdpi/start_icon.png b/app/src/main/res/mipmap-xhdpi/start_icon.png new file mode 100644 index 0000000..f82fca5 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/start_icon.png differ diff --git a/app/src/main/res/raw/delfult.mp4 b/app/src/main/res/raw/delfult.mp4 new file mode 100644 index 0000000..e90872d Binary files /dev/null and b/app/src/main/res/raw/delfult.mp4 differ diff --git a/app/src/main/res/raw/lisening.mp4 b/app/src/main/res/raw/lisening.mp4 new file mode 100644 index 0000000..9e628e8 Binary files /dev/null and b/app/src/main/res/raw/lisening.mp4 differ diff --git a/app/src/main/res/raw/speek.mp4 b/app/src/main/res/raw/speek.mp4 new file mode 100644 index 0000000..cbc6ecb Binary files /dev/null and b/app/src/main/res/raw/speek.mp4 differ diff --git a/app/src/main/res/raw/thinking.mp4 b/app/src/main/res/raw/thinking.mp4 new file mode 100644 index 0000000..22ed409 Binary files /dev/null and b/app/src/main/res/raw/thinking.mp4 differ diff --git a/app/src/main/res/raw/zhayan.mp4 b/app/src/main/res/raw/zhayan.mp4 new file mode 100644 index 0000000..a77476b Binary files /dev/null and b/app/src/main/res/raw/zhayan.mp4 differ diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml new file mode 100644 index 0000000..5877a2c --- /dev/null +++ b/app/src/main/res/values/style.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/TranscriptionManager.java b/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/TranscriptionManager.java index a830e98..155b303 100644 --- a/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/TranscriptionManager.java +++ b/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/TranscriptionManager.java @@ -219,7 +219,9 @@ public class TranscriptionManager { asrMsg = ""; } else if (reply.getEvent().equals("SentenceEnd") && reply.getStatus() == 20000000) { asrMsg = asrMsg+reply.getResult().getResult(); - + if (onTranscriptionDataChange != null) { + onTranscriptionDataChange.onChange("SentenceEnd", asrMsg); + } } else if (reply.getEvent().equals("Changed") && reply.getStatus() == 20000000) { if (onTranscriptionDataChange != null) { String msg = reply.getResult().getResult(); diff --git a/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/VoiceChatManager.java b/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/VoiceChatManager.java index 0c7b7c7..d16c926 100644 --- a/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/VoiceChatManager.java +++ b/polysdk/src/main/java/com/zhixun/android/sdk/polysdk/ai/VoiceChatManager.java @@ -1,6 +1,8 @@ package com.zhixun.android.sdk.polysdk.ai; import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; import android.os.Message; import android.text.TextUtils; @@ -48,34 +50,42 @@ public class VoiceChatManager { return sInstance; } + private MsgLooperThread msgLooperThread; + private class MsgLooperThread extends Thread { + public void run() { + Looper.prepare(); + handler = new Handler(Looper.myLooper()){ + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + switch (msg.what){ + case MSG_RECONNECT: + SobLog.d(TAG, "MSG_RECONNECT"); + if (chatClient != null) { + chatClient.close(); + chatClient = null; + } + isStart = false; + connectChat(); + break; + case MSG_SENDPING: +// SobLog.d(TAG, "MSG_SENDPING"); + if(chatClient!=null&&chatClient.isOpen()){ + chatClient.sendPing(); + } + break; + } + } + }; + Looper.loop(); + } + } private final int MSG_RECONNECT = 101; private final int MSG_SENDPING = 102; - private Handler handler = new Handler(){ - @Override - public void handleMessage(@NonNull Message msg) { - super.handleMessage(msg); - switch (msg.what){ - case MSG_RECONNECT: - SobLog.d(TAG, "MSG_RECONNECT"); - if (chatClient != null) { - chatClient.close(); - chatClient = null; - } - isStart = false; - connectChat(); - break; - case MSG_SENDPING: -// SobLog.d(TAG, "MSG_SENDPING"); - if(chatClient!=null&&chatClient.isOpen()){ - chatClient.sendPing(); - } + private Handler handler; - break; - } - } - }; public VoiceChatManager() { SobLog.d(TAG, "-----VoiceChatManager---creat--"); @@ -91,6 +101,10 @@ public class VoiceChatManager { private String chatType = ""; public void init() { SobLog.d(TAG, "-----VoiceChatManager---init--"); + if(msgLooperThread==null){ + msgLooperThread = new MsgLooperThread(); + msgLooperThread.start(); + } channelMap.put("aliyun","qianwen"); channelMap.put("huoshan","doubao"); channelMap.put("baidu","wenxin"); @@ -110,13 +124,19 @@ public class VoiceChatManager { isReConnect = false; return; } + SobLog.d(TAG, "channel--" + channel); String param = ""; if(channelMap.containsKey(channel)){ param = "&bot_type="+channelMap.get(channel); } String url = MyConfig.URL_VOICE_CHAT+"?is_auth=0"+"&dt="+MyConfig.TOKEN+"&platform=raisound"+param; URI chatRri = URI.create(url); - handler.removeMessages(MSG_RECONNECT); + if(handler!=null){ + handler.removeMessages(MSG_RECONNECT); + }else { + return; + } + SobLog.d(TAG, "url--" + url); chatClient = new JWebSocketClient(chatRri) { @Override @@ -375,14 +395,15 @@ public class VoiceChatManager { * 设置通道 */ public void checkoutChannel(IAIChannelChangeCallback channelChangeCallback) { + if(handler==null)return; this.channelChangeCallback = channelChangeCallback; - if (chatClient != null && chatClient.isOpen()) { ischeckoutChannel = true; close(); } else { ischeckoutChannel = false; isReConnect = true; + handler.removeMessages(MSG_RECONNECT); connectChat(); } @@ -544,9 +565,9 @@ public class VoiceChatManager { if (iVoiceChatCallback != null) { iVoiceChatCallback.OnRespond(chatType, ""); } - if (chatClient != null && chatClient.isOpen()) { - close(); - } + } + if (chatClient != null && chatClient.isOpen()) { + close(); } } diff --git a/settings.gradle b/settings.gradle index b3c3389..a8f1aca 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,6 +3,7 @@ pluginManagement { google() mavenCentral() gradlePluginPortal() + maven { url 'https://jitpack.io' } } } dependencyResolutionManagement { @@ -10,6 +11,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { url 'https://jitpack.io' } } }