Selaa lähdekoodia

增加media3音频播放

zk 1 vuosi sitten
vanhempi
commit
e6a1704e53

+ 2 - 1
app/build.gradle

@@ -158,5 +158,6 @@ dependencies {
     //字符串加密算法
     implementation "com.github.megatronking.stringfog:xor:$rootProject.stringfog_verstion"
 
-
+    //音频播放
+    implementation "androidx.media3:media3-exoplayer:1.3.1"
 }

+ 3 - 0
app/src/main/java/com/atmob/voiceai/data/api/bean/VoiceListBean.java

@@ -1,5 +1,6 @@
 package com.atmob.voiceai.data.api.bean;
 
+import androidx.annotation.IntDef;
 import androidx.databinding.BaseObservable;
 import androidx.databinding.Bindable;
 
@@ -31,6 +32,7 @@ public class VoiceListBean extends BaseObservable {
     @VoicePlayState
     private int voicePlayState;
 
+    @IntDef({VoicePlayState.INITIAL, VoicePlayState.LOADING, VoicePlayState.PLAYING})
     public @interface VoicePlayState {
 
         int INITIAL = 0;
@@ -134,4 +136,5 @@ public class VoiceListBean extends BaseObservable {
     public void setHasPro(boolean hasPro) {
         this.hasPro = hasPro;
     }
+
 }

+ 1 - 1
app/src/main/java/com/atmob/voiceai/di/NetworkModule.java

@@ -42,7 +42,7 @@ public class NetworkModule {
     @Provides
     public static GenerateApi provideGenerateApi(Gson gson) {
         OkHttpClient okHttpClient = AtmobOkHttpClient.newInstance(ATMOB_TAG, BuildConfig.DEBUG).newBuilder()
-                .connectTimeout(30, TimeUnit.SECONDS)
+                .connectTimeout(25, TimeUnit.SECONDS)
                 .readTimeout(15, TimeUnit.SECONDS)
                 .writeTimeout(15, TimeUnit.SECONDS)
                 .build();

+ 12 - 0
app/src/main/java/com/atmob/voiceai/helper/VoicePlayHelper.java

@@ -0,0 +1,12 @@
+package com.atmob.voiceai.helper;
+
+
+import androidx.annotation.NonNull;
+
+public class VoicePlayHelper {
+
+
+    private static String getFileName(@NonNull String url) {
+        return url.substring(url.lastIndexOf("/") + 1);
+    }
+}

+ 57 - 1
app/src/main/java/com/atmob/voiceai/module/voiceai/VoiceAIFragment.java

@@ -2,15 +2,22 @@ package com.atmob.voiceai.module.voiceai;
 
 import android.annotation.SuppressLint;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.Bundle;
 import android.view.View;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.media3.common.MediaItem;
+import androidx.media3.common.PlaybackException;
+import androidx.media3.common.Player;
+import androidx.media3.exoplayer.ExoPlaybackException;
+import androidx.media3.exoplayer.ExoPlayer;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.atmob.app.lib.base.BaseFragment;
+import com.atmob.common.logging.AtmobLog;
 import com.atmob.voiceai.R;
 import com.atmob.voiceai.data.api.bean.TypeListBean;
 import com.atmob.voiceai.data.api.bean.VoiceListBean;
@@ -19,6 +26,7 @@ import com.atmob.voiceai.databinding.ItemVoiceAiTabBinding;
 import com.atmob.voiceai.module.clonevoice.CloneVoiceFragment;
 import com.atmob.voiceai.module.main.MainActivity;
 import com.atmob.voiceai.utils.GridLayoutItemDecoration;
+import com.atmob.voiceai.utils.ToastUtil;
 import com.google.android.material.tabs.TabLayout;
 import com.gyf.immersionbar.ImmersionBar;
 
@@ -34,6 +42,8 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
     private VoiceAIViewModel voiceViewModel;
     private VoiceAIListAdapter voiceAIListAdapter;
 
+    private ExoPlayer player;
+
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
@@ -64,6 +74,7 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
                 binding.voiceTab.addTab(tab);
                 itemBinding.getRoot().setOnClickListener(v -> {
                     tab.select();
+
                     voiceViewModel.refreshVoiceList(typeListBean.getId());
                 });
                 if (i == 0) {
@@ -74,10 +85,15 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
     }
 
     private void initView() {
+        initExoPlayer();
         initTabLayout();
         initVoiceList();
     }
 
+    private void initExoPlayer() {
+        player = new ExoPlayer.Builder(requireContext()).build();
+    }
+
     private void initVoiceList() {
         voiceAIListAdapter = new VoiceAIListAdapter(getViewLifecycleOwner());
         voiceAIListAdapter.setActionHandler(new VoiceAIListAdapter.ActionHandler() {
@@ -87,8 +103,9 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
             }
 
             @Override
-            public void choiceItemClick(VoiceListBean voiceListBean) {
+            public void choiceItemClick(@NonNull VoiceListBean voiceListBean) {
                 voiceViewModel.setChoiceVoiceBean(voiceListBean);
+                playExampleVoice(voiceListBean);
             }
         });
         binding.ryVoiceView.setAdapter(voiceAIListAdapter);
@@ -107,6 +124,35 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
         });
     }
 
+    private void playExampleVoice(@NonNull VoiceListBean voiceListBean) {
+        if (player.isPlaying() || player.isLoading()) {
+            player.stop();
+        }
+        Uri videoUri = Uri.parse(voiceListBean.getVoiceUrl());
+        MediaItem mediaItem = MediaItem.fromUri(videoUri);
+        player.setMediaItem(mediaItem);
+        player.prepare();
+        player.setPlayWhenReady(true);
+        voiceListBean.setVoicePlayState(VoiceListBean.VoicePlayState.LOADING);
+        player.addListener(new Player.Listener() {
+
+            @Override
+            public void onPlayerError(PlaybackException error) {
+                AtmobLog.d("zk", "onPlayerError: " + error.getMessage());
+                voiceListBean.setVoicePlayState(VoiceListBean.VoicePlayState.INITIAL);
+                ToastUtil.show(R.string.voice_play_error, ToastUtil.LENGTH_SHORT);
+            }
+
+            @Override
+            public void onPlaybackStateChanged(int state) {
+                AtmobLog.d("zk", "onPlaybackStateChanged: " + state + "  " + voiceListBean.getName() + "  " + voiceListBean.getVoiceUrl());
+                if (Player.STATE_ENDED == state) {
+                    voiceViewModel.setVoicePlayEnd();
+                }
+            }
+        });
+    }
+
     private void initTabLayout() {
         binding.voiceTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
             @SuppressLint("UseCompatLoadingForDrawables")
@@ -165,4 +211,14 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
         super.configImmersion(immersionBar);
         immersionBar.statusBarDarkFont(false);
     }
+
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (player != null) {
+            player.stop();
+            player.release();
+        }
+    }
 }

+ 1 - 0
app/src/main/java/com/atmob/voiceai/module/voiceai/VoiceAIListAdapter.java

@@ -135,6 +135,7 @@ public class VoiceAIListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
             binding.setChoiceClick(v -> {
                 VoiceListBean viewBean = binding.getBean();
                 if (checkBean != null) {
+                    checkBean.setVoicePlayState(VoiceListBean.VoicePlayState.INITIAL);
                     checkBean.setCheck(false);
                 }
                 viewBean.setCheck(true);

+ 8 - 0
app/src/main/java/com/atmob/voiceai/module/voiceai/VoiceAIViewModel.java

@@ -246,6 +246,7 @@ public class VoiceAIViewModel extends BaseViewModel {
                 voiceDetailList.setValue(voiceList);
                 VoiceListBean choiceBean = choiceVoiceBean.getValue();
                 if (choiceBean != null) {
+                    choiceBean.setVoicePlayState(VoiceListBean.VoicePlayState.INITIAL);
                     choiceBean.setCheck(false);
                 }
                 choiceVoiceBean.setValue(null);
@@ -280,4 +281,11 @@ public class VoiceAIViewModel extends BaseViewModel {
         }
         requestGenerateVoice(bean);
     }
+
+    public void setVoicePlayEnd() {
+        VoiceListBean bean = choiceVoiceBean.getValue();
+        if (bean != null) {
+            bean.setVoicePlayState(VoiceListBean.VoicePlayState.INITIAL);
+        }
+    }
 }

+ 13 - 0
app/src/main/res/layout/item_voice_ai_list.xml

@@ -16,6 +16,9 @@
         <variable
             name="addClick"
             type="android.view.View.OnClickListener" />
+
+        <import type="com.atmob.voiceai.data.api.bean.VoiceListBean.VoicePlayState" />
+
     </data>
 
     <androidx.constraintlayout.widget.ConstraintLayout
@@ -52,6 +55,16 @@
             app:layout_constraintTop_toTopOf="parent" />
 
         <View
+            isGone="@{bean.voicePlayState == VoicePlayState.INITIAL}"
+            android:background="@color/colorPrimaryVariant"
+            app:layout_constraintBottom_toBottomOf="@+id/iv_avatar"
+            app:layout_constraintEnd_toEndOf="@+id/iv_avatar"
+            app:layout_constraintStart_toStartOf="@+id/iv_avatar"
+            app:layout_constraintTop_toTopOf="@+id/iv_avatar"
+            android:layout_width="0dp"
+            android:layout_height="0dp" />
+
+        <View
             android:background="@drawable/bg_voice_ai_list_check"
             isGone="@{!bean.check}"
             android:layout_width="0dp"

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -16,4 +16,5 @@
     <string name="add_voice">Add Voice</string>
     <string name="voice_new">New</string>
     <string name="voice_ai_no_choice">Please choose</string>
+    <string name="voice_play_error">Play Error</string>
 </resources>

+ 1 - 1
build.gradle

@@ -1,7 +1,7 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 buildscript {
     ext {
-        compileSdkVersion = 33
+        compileSdkVersion = 34
         applicationId = "com.atmob.vioceai"
         minSdkVersion = 21
         targetSdkVersion = 32