Browse Source

优化先下载后给播放器加载,每次加载前从本地取

zk 1 year ago
parent
commit
e1aa323bb2

+ 44 - 25
app/src/main/java/com/atmob/voiceai/data/repositories/VoiceAIRepository.java

@@ -27,15 +27,22 @@ import com.atmob.voiceai.data.consts.ErrorCode;
 import com.atmob.voiceai.handlers.EventHandler;
 import com.atmob.voiceai.handlers.EventHandler;
 import com.atmob.voiceai.sdk.firebase.FirebaseHelper;
 import com.atmob.voiceai.sdk.firebase.FirebaseHelper;
 import com.atmob.voiceai.utils.BoxingUtil;
 import com.atmob.voiceai.utils.BoxingUtil;
+import com.atmob.voiceai.utils.DownloadUtils;
 import com.atmob.voiceai.utils.ThreePair;
 import com.atmob.voiceai.utils.ThreePair;
+import com.atmob.voiceai.utils.VoiceFileUtil;
 
 
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 
 
+import atmob.okhttp3.OkHttpClient;
+import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
 import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.annotations.NonNull;
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.reactivex.rxjava3.core.Single;
 import atmob.reactivex.rxjava3.core.SingleObserver;
 import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.core.SingleSource;
 import atmob.reactivex.rxjava3.disposables.Disposable;
 import atmob.reactivex.rxjava3.disposables.Disposable;
+import atmob.reactivex.rxjava3.functions.Function;
+import atmob.reactivex.rxjava3.schedulers.Schedulers;
 import atmob.rxjava.utils.RxJavaUtil;
 import atmob.rxjava.utils.RxJavaUtil;
 import dagger.hilt.EntryPoint;
 import dagger.hilt.EntryPoint;
 import dagger.hilt.InstallIn;
 import dagger.hilt.InstallIn;
@@ -51,6 +58,7 @@ public class VoiceAIRepository {
     private final MemberRepository memberRepository;
     private final MemberRepository memberRepository;
 
 
     private final SingleLiveEvent<?> cloneExecuteSuccess = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> cloneExecuteSuccess = new SingleLiveEvent<>();
+    private final OkHttpClient okHttpClient;
     private boolean textToSpeechRequest;
     private boolean textToSpeechRequest;
     private final MutableLiveData<Integer> adFreeGenerateNumber = new MutableLiveData<>();
     private final MutableLiveData<Integer> adFreeGenerateNumber = new MutableLiveData<>();
 
 
@@ -73,9 +81,10 @@ public class VoiceAIRepository {
     }
     }
 
 
     @Inject
     @Inject
-    public VoiceAIRepository(AtmobApi atmobApi, MemberRepository memberRepository, HistoryRepository historyRepository) {
+    public VoiceAIRepository(AtmobApi atmobApi, MemberRepository memberRepository, HistoryRepository historyRepository, OkHttpClient okHttpClient) {
         this.atmobApi = atmobApi;
         this.atmobApi = atmobApi;
         this.memberRepository = memberRepository;
         this.memberRepository = memberRepository;
+        this.okHttpClient = okHttpClient;
         this.historyRepository = historyRepository;
         this.historyRepository = historyRepository;
     }
     }
 
 
@@ -178,33 +187,43 @@ public class VoiceAIRepository {
 //        userVoiceBean.setVoiceUrl("http://cdn.atmob.com/upload/project_voice/text_to_speech/20240510/986334800900366336.mp3");
 //        userVoiceBean.setVoiceUrl("http://cdn.atmob.com/upload/project_voice/text_to_speech/20240510/986334800900366336.mp3");
 //        textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATED, null, userVoiceBean));
 //        textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATED, null, userVoiceBean));
 //        /********仅测试使用******/
 //        /********仅测试使用******/
-        textToSpeech(bean.getId(), bean.getVoiceType(), content).subscribe(new SingleObserver<TextToSpeechResponse>() {
-            @Override
-            public void onSubscribe(@NonNull Disposable d) {
-                textToSpeechRequest = true;
-                textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATING, null, null));
-            }
+        textToSpeech(bean.getId(), bean.getVoiceType(), content)
+                .flatMap((Function<TextToSpeechResponse, SingleSource<UserVoiceBean>>) textToSpeechResponse -> {
+                    UserVoiceBean userVoice = textToSpeechResponse.getUserVoice();
+                    if (userVoice == null || userVoice.getVoiceUrl() == null) {
+                        throw new Exception("cloneVoice is null");
+                    }
+                    return VoiceFileUtil.getVoiceFile(okHttpClient, userVoice.getVoiceUrl())
+                            .map(file -> userVoice);
+                })
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new SingleObserver<UserVoiceBean>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        textToSpeechRequest = true;
+                        textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATING, null, null));
+                    }
 
 
-            @Override
-            public void onSuccess(@NonNull TextToSpeechResponse textToSpeechResponse) {
-                textToSpeechRequest = false;
-                textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATED, null, textToSpeechResponse.getUserVoice()));
-            }
+                    @Override
+                    public void onSuccess(@NonNull UserVoiceBean userVoiceBean) {
+                        textToSpeechRequest = false;
+                        textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.GENERATED, null, userVoiceBean));
+                    }
 
 
-            @Override
-            public void onError(@NonNull Throwable throwable) {
-                textToSpeechRequest = false;
-                if (throwable instanceof RxHttpHandler.ServerErrorException) {
-                    RxHttpHandler.ServerErrorException serverErrorException = (RxHttpHandler.ServerErrorException) throwable;
-                    textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.ERROR, serverErrorException.getMsg(), null));
-                    if (serverErrorException.getCode() == ErrorCode.ERROR_NOT_SUBSCRIBED) {
-                        memberRepository.refreshUserData();
+                    @Override
+                    public void onError(@NonNull Throwable throwable) {
+                        textToSpeechRequest = false;
+                        if (throwable instanceof RxHttpHandler.ServerErrorException) {
+                            RxHttpHandler.ServerErrorException serverErrorException = (RxHttpHandler.ServerErrorException) throwable;
+                            textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.ERROR, serverErrorException.getMsg(), null));
+                            if (serverErrorException.getCode() == ErrorCode.ERROR_NOT_SUBSCRIBED) {
+                                memberRepository.refreshUserData();
+                            }
+                        } else {
+                            textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.ERROR, ContextUtil.getContext().getString(R.string.generate_error), null));
+                        }
                     }
                     }
-                } else {
-                    textToSpeechState.setValue(new ThreePair<>(TextToSpeechState.ERROR, ContextUtil.getContext().getString(R.string.generate_error), null));
-                }
-            }
-        });
+                });
     }
     }
 
 
     private Single<TextToSpeechResponse> textToSpeech(int id, int voiceType, String content) {
     private Single<TextToSpeechResponse> textToSpeech(int id, int voiceType, String content) {

+ 1 - 1
app/src/main/java/com/atmob/voiceai/module/clonevoice/CloneVoiceViewModel.java

@@ -456,7 +456,7 @@ public class CloneVoiceViewModel extends BaseViewModel {
     }
     }
 
 
     public String getRecordAudioFilePath() {
     public String getRecordAudioFilePath() {
-        File cacheFile = FileUtils.getVoiceDownloadSaveRootFile();
+        File cacheFile = FileUtils.getVoiceCacheFile();
         recordFile = new File(cacheFile, "record_audio.mp3");
         recordFile = new File(cacheFile, "record_audio.mp3");
         return recordFile.getPath();
         return recordFile.getPath();
     }
     }

+ 3 - 4
app/src/main/java/com/atmob/voiceai/module/result/VoiceResultActivity.java

@@ -215,12 +215,11 @@ public class VoiceResultActivity extends BaseActivity<ActivityVoiceResultBinding
             long currentPosition = player.getCurrentPosition();
             long currentPosition = player.getCurrentPosition();
             binding.voiceSeekBar.setProgress((int) currentPosition);
             binding.voiceSeekBar.setProgress((int) currentPosition);
         });
         });
-        voiceResultViewModel.getResultBean().observe(this, bean -> {
-            if (bean == null) {
+        voiceResultViewModel.getVoiceUri().observe(this, uri -> {
+            if (uri == null) {
                 return;
                 return;
             }
             }
-            Uri videoUri = Uri.parse(bean.getVoiceUrl());
-            MediaItem mediaItem = MediaItem.fromUri(videoUri);
+            MediaItem mediaItem = MediaItem.fromUri(uri);
             player.setMediaItem(mediaItem);
             player.setMediaItem(mediaItem);
             player.prepare();
             player.prepare();
             player.setPlayWhenReady(false);
             player.setPlayWhenReady(false);

+ 28 - 0
app/src/main/java/com/atmob/voiceai/module/result/VoiceResultViewModel.java

@@ -1,5 +1,6 @@
 package com.atmob.voiceai.module.result;
 package com.atmob.voiceai.module.result;
 
 
+import android.net.Uri;
 import android.os.Parcelable;
 import android.os.Parcelable;
 
 
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.LiveData;
@@ -18,6 +19,7 @@ import com.atmob.voiceai.data.consts.EventId;
 import com.atmob.voiceai.data.repositories.VoiceAIRepository;
 import com.atmob.voiceai.data.repositories.VoiceAIRepository;
 import com.atmob.voiceai.handlers.EventHandler;
 import com.atmob.voiceai.handlers.EventHandler;
 import com.atmob.voiceai.utils.DateUtil;
 import com.atmob.voiceai.utils.DateUtil;
+import com.atmob.voiceai.utils.DownloadUtils;
 import com.atmob.voiceai.utils.MediaStoreHelper;
 import com.atmob.voiceai.utils.MediaStoreHelper;
 import com.atmob.voiceai.utils.ScoringUtils;
 import com.atmob.voiceai.utils.ScoringUtils;
 import com.atmob.voiceai.utils.ShareUtils;
 import com.atmob.voiceai.utils.ShareUtils;
@@ -56,6 +58,7 @@ public class VoiceResultViewModel extends BaseViewModel {
     private final MutableLiveData<List<VoiceListBean>> voiceList = new MutableLiveData<>();
     private final MutableLiveData<List<VoiceListBean>> voiceList = new MutableLiveData<>();
     private final SingleLiveEvent<?> showScoringEvent = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showScoringEvent = new SingleLiveEvent<>();
     private final MutableLiveData<UserVoiceBean> userVoiceBean = new MutableLiveData<>();
     private final MutableLiveData<UserVoiceBean> userVoiceBean = new MutableLiveData<>();
+    private final MutableLiveData<Uri> voiceUri = new MutableLiveData<>();
     private final OkHttpClient okHttpClient;
     private final OkHttpClient okHttpClient;
     private boolean isSeekbarChanging;
     private boolean isSeekbarChanging;
     private Timer timer;
     private Timer timer;
@@ -73,6 +76,10 @@ public class VoiceResultViewModel extends BaseViewModel {
         checkScoring();
         checkScoring();
     }
     }
 
 
+    public LiveData<Uri> getVoiceUri() {
+        return voiceUri;
+    }
+
     public LiveData<List<VoiceListBean>> getVoiceList() {
     public LiveData<List<VoiceListBean>> getVoiceList() {
         return voiceList;
         return voiceList;
     }
     }
@@ -257,6 +264,27 @@ public class VoiceResultViewModel extends BaseViewModel {
 
 
     public void setVoiceBean(UserVoiceBean userVoiceBean) {
     public void setVoiceBean(UserVoiceBean userVoiceBean) {
         this.userVoiceBean.setValue(userVoiceBean);
         this.userVoiceBean.setValue(userVoiceBean);
+        startDownloadVoice(userVoiceBean.getVoiceUrl());
+    }
+
+    private void startDownloadVoice(String voiceUrl) {
+        VoiceFileUtil.getVoiceFile(okHttpClient, voiceUrl)
+                .subscribe(new SingleObserver<File>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        addDisposable(d);
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull File file) {
+                        voiceUri.setValue(Uri.fromFile(file));
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+                        voiceUri.setValue(Uri.parse(voiceUrl));
+                    }
+                });
     }
     }
 
 
 
 

+ 3 - 0
app/src/main/java/com/atmob/voiceai/module/subscription/SubscriptionPageViewModel.java

@@ -5,6 +5,7 @@ import android.os.SystemClock;
 
 
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.MutableLiveData;
+import androidx.media3.common.C;
 
 
 import com.android.billingclient.api.BillingClient;
 import com.android.billingclient.api.BillingClient;
 import com.android.billingclient.api.BillingResult;
 import com.android.billingclient.api.BillingResult;
@@ -189,7 +190,9 @@ public class SubscriptionPageViewModel extends BaseViewModel {
                             return memberBean;
                             return memberBean;
                         })
                         })
                         .subscribeOn(Schedulers.io())
                         .subscribeOn(Schedulers.io())
+                        .onErrorReturn(throwable -> memberBean)
                 )
                 )
+                .filter(goodsBean -> goodsBean.getGpProductInfo() != null)
                 .toSortedList()
                 .toSortedList()
                 .observeOn(AndroidSchedulers.mainThread())
                 .observeOn(AndroidSchedulers.mainThread())
                 .subscribe(new SingleObserver<List<GoodsBean>>() {
                 .subscribe(new SingleObserver<List<GoodsBean>>() {

+ 2 - 2
app/src/main/java/com/atmob/voiceai/sdk/billing/operation/QueryDetails.java

@@ -26,13 +26,13 @@ public class QueryDetails {
 
 
     public static Single<GPProductInfo> queryGoodsDetails(BillingClient billingClient, String productType, @NonNull String productId, @Nullable String basePlanId, @Nullable String legacyProductId) {
     public static Single<GPProductInfo> queryGoodsDetails(BillingClient billingClient, String productType, @NonNull String productId, @Nullable String basePlanId, @Nullable String legacyProductId) {
         if (billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS).getResponseCode() == BillingClient.BillingResponseCode.OK) {
         if (billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS).getResponseCode() == BillingClient.BillingResponseCode.OK) {
-            return queryProductDetails(billingClient, productType, productId, basePlanId, legacyProductId);
+            return queryProductDetails(billingClient, productType, productId, basePlanId);
         } else {
         } else {
             return querySkuDetails(billingClient, productType, productId, basePlanId, legacyProductId);
             return querySkuDetails(billingClient, productType, productId, basePlanId, legacyProductId);
         }
         }
     }
     }
 
 
-    private static Single<GPProductInfo> queryProductDetails(BillingClient billingClient, String productType, @NonNull String productId, @Nullable String basePlanId, @Nullable String legacyProductId) {
+    private static Single<GPProductInfo> queryProductDetails(BillingClient billingClient, String productType, @NonNull String productId, @Nullable String basePlanId) {
         AtmobLog.i(TAG, "querySkuDetails() called with: productType = [" + productType + "], productId = [" + productId + "], basePlanId = [" + basePlanId + "]");
         AtmobLog.i(TAG, "querySkuDetails() called with: productType = [" + productType + "], productId = [" + productId + "], basePlanId = [" + basePlanId + "]");
         QueryProductDetailsParams productDetailsParams = QueryProductDetailsParams.newBuilder()
         QueryProductDetailsParams productDetailsParams = QueryProductDetailsParams.newBuilder()
                 .setProductList(Collections.singletonList(QueryProductDetailsParams.Product.newBuilder()
                 .setProductList(Collections.singletonList(QueryProductDetailsParams.Product.newBuilder()

+ 49 - 49
app/src/main/java/com/atmob/voiceai/utils/DownloadUtils.java

@@ -15,14 +15,14 @@ public class DownloadUtils {
 
 
     public static final String FILE_PREFIX = "VoiceAI_";
     public static final String FILE_PREFIX = "VoiceAI_";
 
 
-    public static File voiceFile = FileUtils.getVoiceDownloadSaveRootFile();
+    public static File voiceFile = FileUtils.getVoiceCacheFile();
 
 
     private DownloadUtils() {
     private DownloadUtils() {
 
 
     }
     }
 
 
 
 
-    public static void downLoad(OkHttpClient client, String url, final File rootFile, final String fileName,
+    public static void downLoad(OkHttpClient client, String url, final String filePath, final String fileName,
                                 final FileDownLoadObserver<File> fileDownLoadObserver) {
                                 final FileDownLoadObserver<File> fileDownLoadObserver) {
         Observable.create((ObservableOnSubscribe<ResponseBody>) emitter -> {
         Observable.create((ObservableOnSubscribe<ResponseBody>) emitter -> {
                     Request request = new Request.Builder()
                     Request request = new Request.Builder()
@@ -46,7 +46,7 @@ public class DownloadUtils {
                     }
                     }
                 })
                 })
                 .map(responseBody -> fileDownLoadObserver.saveFile(responseBody,
                 .map(responseBody -> fileDownLoadObserver.saveFile(responseBody,
-                        rootFile.getPath(), fileName))
+                        filePath, fileName))
                 .subscribeOn(Schedulers.io())
                 .subscribeOn(Schedulers.io())
                 .observeOn(Schedulers.io())
                 .observeOn(Schedulers.io())
                 .map(file -> {
                 .map(file -> {
@@ -59,51 +59,51 @@ public class DownloadUtils {
     }
     }
 
 
 
 
-    public static void downLoadCompareBeforeLocal(OkHttpClient client, String url, final File localFile, final File rootFile, final String fileName,
-                                                  final FileDownLoadObserver<File> fileDownLoadObserver) {
-        Observable.create((ObservableOnSubscribe<Object>) emitter -> {
-                    Request request = new Request.Builder()
-                            .url(url)
-                            .build();
-                    try (Response response = client.newCall(request).execute()) {
-                        if (!response.isSuccessful()) {
-                            emitter.onError(new IOException("Failed to download audio: " + response));
-                            return;
-                        }
-                        ResponseBody body = response.body();
-                        if (body == null) {
-                            emitter.onError(new IOException("Response body is null"));
-                            return;
-                        }
-//                        AtmobLog.d("zk", String.format("文件类型为%s,文件大小为%d", response.body().contentType().toString(), response.body().contentLength()));
-                        if (localFile == null || !localFile.exists() || localFile.length() != body.contentLength()) {
-                            emitter.onNext(body);
-                        } else {
-                            emitter.onNext(localFile);
-                        }
-                        emitter.onComplete();
-                    } catch (IOException e) {
-                        emitter.onError(e);
-                    }
-                })
-                .map(data -> {
-                    if (data instanceof File) {
-                        return (File) data;
-                    } else {
-                        ResponseBody responseBody = (ResponseBody) data;
-                        return fileDownLoadObserver.saveFile(responseBody,
-                                rootFile.getPath(), fileName);
-                    }
-                })
-                .subscribeOn(Schedulers.io())
-                .observeOn(Schedulers.io())
-                .map(file -> {
-                    if (file == null) {
-                        throw new IOException("file is null");
-                    }
-                    return file;
-                })
-                .subscribe(fileDownLoadObserver);
-    }
+//    public static void downLoadCompareBeforeLocal(OkHttpClient client, String url, final File localFile, final File rootFile, final String fileName,
+//                                                  final FileDownLoadObserver<File> fileDownLoadObserver) {
+//        Observable.create((ObservableOnSubscribe<Object>) emitter -> {
+//                    Request request = new Request.Builder()
+//                            .url(url)
+//                            .build();
+//                    try (Response response = client.newCall(request).execute()) {
+//                        if (!response.isSuccessful()) {
+//                            emitter.onError(new IOException("Failed to download audio: " + response));
+//                            return;
+//                        }
+//                        ResponseBody body = response.body();
+//                        if (body == null) {
+//                            emitter.onError(new IOException("Response body is null"));
+//                            return;
+//                        }
+////                        AtmobLog.d("zk", String.format("文件类型为%s,文件大小为%d", response.body().contentType().toString(), response.body().contentLength()));
+//                        if (localFile == null || !localFile.exists() || localFile.length() != body.contentLength()) {
+//                            emitter.onNext(body);
+//                        } else {
+//                            emitter.onNext(localFile);
+//                        }
+//                        emitter.onComplete();
+//                    } catch (IOException e) {
+//                        emitter.onError(e);
+//                    }
+//                })
+//                .map(data -> {
+//                    if (data instanceof File) {
+//                        return (File) data;
+//                    } else {
+//                        ResponseBody responseBody = (ResponseBody) data;
+//                        return fileDownLoadObserver.saveFile(responseBody,
+//                                rootFile.getPath(), fileName);
+//                    }
+//                })
+//                .subscribeOn(Schedulers.io())
+//                .observeOn(Schedulers.io())
+//                .map(file -> {
+//                    if (file == null) {
+//                        throw new IOException("file is null");
+//                    }
+//                    return file;
+//                })
+//                .subscribe(fileDownLoadObserver);
+//    }
 
 
 }
 }

+ 21 - 24
app/src/main/java/com/atmob/voiceai/utils/FileDownLoadObserver.java

@@ -1,5 +1,9 @@
 package com.atmob.voiceai.utils;
 package com.atmob.voiceai.utils;
 
 
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
@@ -41,7 +45,7 @@ public abstract class FileDownLoadObserver<T> extends DefaultObserver<T> {
 
 
     }
     }
 
 
-    private void copyStream(InputStream is, OutputStream os) throws Exception {
+    private void copyStream(InputStream is, OutputStream os) throws IOException {
         byte[] buf = new byte[2048];
         byte[] buf = new byte[2048];
         int n;
         int n;
         while ((n = is.read(buf)) > 0) {
         while ((n = is.read(buf)) > 0) {
@@ -50,37 +54,30 @@ public abstract class FileDownLoadObserver<T> extends DefaultObserver<T> {
         os.flush();
         os.flush();
     }
     }
 
 
-    public File saveFile(ResponseBody responseBody, String destFileDir, String destFileName)
-            throws IOException {
-        InputStream is = null;
-        FileOutputStream fos = null;
+
+    public File saveFile(ResponseBody responseBody, String destFileDir, String destFileName) {
         File file = null;
         File file = null;
+        File dir = new File(destFileDir);
+
         try {
         try {
-            is = responseBody.byteStream();
-            File dir = new File(destFileDir);
             if (!dir.exists()) {
             if (!dir.exists()) {
                 dir.mkdirs();
                 dir.mkdirs();
             }
             }
+
             file = new File(dir, destFileName);
             file = new File(dir, destFileName);
-            fos = new FileOutputStream(file);
-            copyStream(is, fos);
-            return file;
-        } catch (Exception e) {
-            if (file != null) {
-                file.delete();
-            }
-        } finally {
-            try {
-                if (is != null) is.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            try {
-                if (fos != null) fos.close();
-            } catch (IOException e) {
-                e.printStackTrace();
+
+            try (
+                    InputStream is = new BufferedInputStream(responseBody.byteStream());
+                    FileOutputStream fos = new FileOutputStream(file);
+                    OutputStream os = new BufferedOutputStream(fos);
+            ) {
+                copyStream(is, os);
             }
             }
+
+        } catch (IOException e) {
+            Log.d("FileDownLoadObserver", "saveFile: " + e.getMessage());
         }
         }
+
         return file;
         return file;
     }
     }
 }
 }

+ 9 - 1
app/src/main/java/com/atmob/voiceai/utils/FileUtils.java

@@ -23,7 +23,15 @@ import atmob.reactivex.rxjava3.annotations.NonNull;
 public class FileUtils {
 public class FileUtils {
 
 
 
 
-    public static File getVoiceDownloadSaveRootFile() {
+    public static File rename(File oldFile, String newFileName) {
+        File newFile = new File(oldFile.getParent(), newFileName);
+        if (oldFile.renameTo(newFile)) {
+            return newFile;
+        }
+        return oldFile;
+    }
+
+    public static File getVoiceCacheFile() {
         File cacheDir;
         File cacheDir;
         if (Objects.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)
         if (Objects.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)
                 && Environment.getExternalStorageDirectory().canWrite()) {
                 && Environment.getExternalStorageDirectory().canWrite()) {

+ 22 - 17
app/src/main/java/com/atmob/voiceai/utils/VoiceFileUtil.java

@@ -25,23 +25,28 @@ public class VoiceFileUtil {
     public static Single<File> getVoiceFile(OkHttpClient okHttpClient, @NonNull String url) {
     public static Single<File> getVoiceFile(OkHttpClient okHttpClient, @NonNull String url) {
         return Single.create((SingleOnSubscribe<File>) emitter -> {
         return Single.create((SingleOnSubscribe<File>) emitter -> {
                     File localFile = net2LocalFile(url);
                     File localFile = net2LocalFile(url);
-                    DownloadUtils.downLoadCompareBeforeLocal(okHttpClient, url, localFile, DownloadUtils.voiceFile, DownloadUtils.FILE_PREFIX + getFileName(url), new FileDownLoadObserver<File>() {
-                        @Override
-                        public void onDownLoadStart() {
-
-                        }
-
-                        @Override
-                        public void onDownLoadSuccess(File file) {
-                            emitter.onSuccess(file);
-                        }
-
-                        @Override
-                        public void onDownLoadFail(Throwable throwable) {
-                            emitter.onError(throwable);
-                        }
-
-                    });
+                    if (localFile.exists()) {
+                        emitter.onSuccess(localFile);
+                    } else {
+                        String fileName = getFileName(url);
+                        DownloadUtils.downLoad(okHttpClient, url, DownloadUtils.voiceFile.getPath(), fileName, new FileDownLoadObserver<File>() {
+                            @Override
+                            public void onDownLoadStart() {
+
+                            }
+
+                            @Override
+                            public void onDownLoadSuccess(File file) {
+                                emitter.onSuccess(FileUtils.rename(file, DownloadUtils.FILE_PREFIX + fileName));
+                            }
+
+                            @Override
+                            public void onDownLoadFail(Throwable throwable) {
+                                emitter.onError(throwable);
+                            }
+
+                        });
+                    }
                 })
                 })
                 .compose(RxJavaUtil.SingleSchedule.io2Main());
                 .compose(RxJavaUtil.SingleSchedule.io2Main());
     }
     }