【问题标题】:Upload large video file use Retrofit(Android) have OutOfMemoryError上传大视频文件使用 Retrofit(Android) 有 OutOfMemoryError
【发布时间】:2019-02-15 15:35:42
【问题描述】:

对不起我的英语。我尝试在服务器上上传大型视频文件,这个文件超过 50 mb。当我上传小文件时,一切正常。在清单中我设置了android:largeHeap="true"android:hardwareAccelerated="false" 它对我没有帮助。以下是我的代码:

界面

@Multipart
@POST("/api/upload")
Observable<UploadVideoResponse> uploadVideo(@Header("Authorization") String userToken,
                                            @Part MultipartBody.Part video);

方法返回文件:

public static MultipartBody.Part getMultipartVideoBody(String pathVideo) {
    try {
        File videoFile = getFile(pathVideo);
        RequestBody videoBody = RequestBody.create(MediaType.parse("video/*"), videoFile);
        String fileName = videoFile.getName();
        return MultipartBody.Part.createFormData("video", fileName, videoBody);
    }catch (Exception e){
        Log.e("File ", e.getMessage());
        return null;
    }
}

方法上传到服务器

new DefaultApi().uploadVideo(
                Utils.getHeaderToken(),
                Utils.getMultipartVideoBody(pathVideo)
        ).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(videoView::showLoading)
                .doOnTerminate(videoView::hideLoading)
                .subscribe(data -> {
                            videoView.setData(data);
                        }
                        , throwable -> {

                        }
                );
    }

错误:

抛出 OutOfMemoryError "未能分配 100390006 字节 分配 16777216 个空闲字节和 92MB 直到 OOM"

完整的堆栈跟踪

09-11 03:53:00.571 6724-6976/des.brain.ga E/art:投掷 OutOfMemoryError“无法分配 100390006 字节分配 16777216 可用字节和 92MB 直到 OOM" 09-11 03:53:00.573 6724-6976/des.brain.ga E/AndroidRuntime:致命异常: RxIoScheduler-3 进程:des.brain.ga,PID:6724 java.lang.IllegalStateException:在 Scheduler.Worker 线程上抛出致命异常。 在 rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 在 java.util.concurrent.FutureTask.run(FutureTask.java:237) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 在 java.lang.Thread.run(Thread.java:818) 原因:java.lang.OutOfMemoryError:无法分配 100390006 字节分配,16777216 个空闲字节和 92MB 直到 OOM 在 java.lang.String.(String.java:332) 在 java.lang.String.(String.java:371) 在 okio.Buffer.readString(Buffer.java:620) 在 okio.Buffer.readString(Buffer.java:603) 在 okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:199) 在 des.brain.ga.api.base.LoggingInterceptor.intercept(LoggingInterceptor.java:31) 在 okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) 在 okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) 在 okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200) 在 okhttp3.RealCall.execute(RealCall.java:77) 在改造 2.OkHttpCall.execute(OkHttpCall.java:180) 在 retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:40) 在 retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:24) 在 retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:36) 在 retrofit2.adapter.rxjava.BodyOnSubscribe.call(BodyOnSubscribe.java:28) 在 rx.Observable.unsafeSubscribe(Observable.java:10256) 在 rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48) 在 rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33) 在 rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) 在 rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) 在 rx.Observable.unsafeSubscribe(Observable.java:10256) 在 rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100) 在 rx.internal.scheduler.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230) 在 rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 在 java.util.concurrent.FutureTask.run(FutureTask.java:237) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 在 java.lang.Thread.run(Thread.java:818) 09-11 03:53:02.159 6724-6724/des.brain.ga E/WindowManager: android.view.WindowLeaked: Activity des.brain.ga.ui.main.HomeActivity 已泄露窗口 com.android.internal.policy.impl.PhoneWindow$DecorView{2ccb16a1 V.ED.... R.....ID 0,0-144,144} 最初添加在这里 在 android.view.ViewRootImpl.(ViewRootImpl.java:363) 在 android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:261) 在 android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 在 android.app.Dialog.show(Dialog.java:298) 在 com.kaopiz.kprogresshud.KProgressHUD.show(KProgressHUD.java:233) 在 des.brain.ga.ui.video.UploadVideoFragment.showLoading(UploadVideoFragment.java:150) 在 des.brain.ga.ui.video.VideoPresenter$$Lambda$4.call(未知来源) 在 rx.internal.operators.OperatorDoOnSubscribe.call(OperatorDoOnSubscribe.java:40) 在 rx.internal.operators.OperatorDoOnSubscribe.call(OperatorDoOnSubscribe.java:27) 在 rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:44) 在 rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) 在 rx.Observable.unsafeSubscribe(Observable.java:10256) 在 rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) 在 rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) 在 rx.Observable.subscribe(Observable.java:10352) 在 rx.Observable.subscribe(Observable.java:10319) 在 rx.Observable.subscribe(Observable.java:10159) 在 des.brain.ga.ui.video.VideoPresenter.uploadVideo(VideoPresenter.java:65) 在 des.brain.ga.ui.video.UploadVideoFragment.lambda$uploadVideo$0$UploadVideoFragment(UploadVideoFragment.java:127) 在 des.brain.ga.ui.video.UploadVideoFragment$$Lambda$0.onClick(未知 资源) 在 com.afollestad.materialdialogs.MaterialDialog.onClick(MaterialDialog.java:410) 在 android.view.View.performClick(View.java:4756) 在 android.view.View$PerformClick.run(View.java:19749) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:135) 在 android.app.ActivityThread.main(ActivityThread.java:5221) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

LoggingInterceptor

public final class LoggingInterceptor implements Interceptor {

    private final Interceptor mLoggingInterceptor;

    private LoggingInterceptor() {
        mLoggingInterceptor = new HttpLoggingInterceptor()
                //.setLogLevel(RestAdapter.LogLevel.FULL)
                .setLevel(BuildConfig.DEBUG ? Level.BODY : Level.NONE);
    }

    @NonNull
    public static Interceptor create() {
        return new LoggingInterceptor();
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        return mLoggingInterceptor.intercept(chain);
    }

}

我像这样使用LoggingInterceptor

return new OkHttpClient.Builder()
                .connectTimeout(300, TimeUnit.SECONDS)
                .addInterceptor(LoggingInterceptor.create())
                .addInterceptor(logging)
                .build();

【问题讨论】:

  • 完整的堆栈跟踪是什么?
  • @pskink 我更新了我的问题
  • des.brain.ga.api.base.LoggingInterceptor是你的吗?
  • 删除,只是为了测试,创建 OkHttpClient.Builder 时的那些 .addInterceptor() 方法 - 如果它有效,则只删除一个并检查哪一个会导致您的问题
  • 哪一个会出问题? .addInterceptor(LoggingInterceptor.create())?还是另一个?

标签: android upload retrofit


【解决方案1】:

我在使用改造上传大型视频时遇到了同样的错误,但是 正在删除
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
或设置为NONE 为我工作。

【讨论】:

  • 您的解决方案效果很好,我可以看到,现在如果您调试应用程序,您将看不到请求和响应中的所有日志,对吧?
  • 是的,因为我们将日志级别设置为 NONE。
  • 删除此拦截器后,我仍然遇到问题
  • 请提供您的错误和代码 sn-p 的更多详细信息?@ParthPatel
  • 我搜索并看到在这种情况下没有选项可以让 OkHttp 中的日志具有 BODY 级别。库实现者说您可以分叉库并根据需要进行更改。是的,不幸的是,您不会像以前那样拥有 BODY 日志。
猜你喜欢
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 2017-06-30
  • 1970-01-01
  • 1970-01-01
  • 2016-09-04
相关资源
最近更新 更多