multithreading - Android: NetworkOnMainThreadException occurs when using retrofit in a new thread? -


i try use retrofit library download file(apk:2mb)from url in separated thread.

here's code(see tutorial:https://futurestud.io/blog/retrofit-2-how-to-download-files-from-server):

public class mainactivity extends appcompatactivity {     string fileurl = ".....";       @override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);          new thread(new runnable() {             @override             public void run() {                 filedownloadservice downloadservice = servicegenerator.createservice(filedownloadservice.class);                 call<responsebody> call = downloadservice.downloadfilewithdynamicurlsync(fileurl2);                  call.enqueue(new callback<responsebody>() {                     @override                     public void onresponse(call<responsebody> call, response<responsebody> response) {                         if (response.issuccessful()) {                            writeresponsebodytodisk(response.body());                         } else {                             log.d("fail", "server contact failed");                         }                     }                      @override                     public void onfailure(call<responsebody> call, throwable t) {                         log.e("fail", "error");                     }                 });             }         }).start();     }      private boolean writeresponsebodytodisk(responsebody body) {         try {             file apkfile = new file(getexternalfilesdir(null) +                     file.separator + "test.apk");             inputstream inputstream = null;             outputstream outputstream = null;             try {                 byte[] filereader = new byte[4096];                  inputstream = body.bytestream();                 outputstream = new fileoutputstream(apkfile);                  while (true) {                     int read = inputstream.read(filereader);                      if (read == -1) {                         break;                     }                      outputstream.write(filereader, 0, read);                 }                  outputstream.flush();                  return true;             } catch (ioexception e) {                 e.printstacktrace();                 return false;             } {                 if (inputstream != null) {                     inputstream.close();                 }                  if (outputstream != null) {                     outputstream.close();                 }             }         } catch (ioexception e) {             e.printstacktrace();             return false;         }      } } 

the code of service:

public class servicegenerator {      public static final string api_base_url = "https://your.api.url/";      private static okhttpclient.builder httpclient = new okhttpclient.builder();      private static retrofit.builder builder =         new retrofit.builder()                 .baseurl(api_base_url)                 .addconverterfactory(gsonconverterfactory.create());      public static <s> s createservice(class<s> serviceclass) {         retrofit retrofit = builder.client(httpclient.build()).build();         return retrofit.create(serviceclass);     } }  public interface filedownloadservice {     @streaming     @get     call<responsebody> downloadfilewithdynamicurlsync(@url string fileurl); } 

i started downloading task in new thread got this:

    android.os.networkonmainthreadexception 

if choose download image of 3kb,the program works fine.if add following code:

    strictmode.threadpolicy policy = new strictmode.threadpolicy.builder().permitall().build();     strictmode.setthreadpolicy(policy);   

the downloading proceed while , stop information:

    strictmode policy violation; ~duration=1342 ms: android.os.strictmode$strictmodediskreadviolation: policy=23 violation=2 

here's stacktrace:

process: com.testapp.yiyuanguo.apkinstall, pid: 25788 android.os.networkonmainthreadexception    @ android.os.strictmode$androidblockguardpolicy.onnetwork(strictmode.java:1147) @ libcore.io.blockguardos.recvfrom(blockguardos.java:249) @ libcore.io.iobridge.recvfrom(iobridge.java:553) @ java.net.plainsocketimpl.read(plainsocketimpl.java:485) @ java.net.plainsocketimpl.access$000(plainsocketimpl.java:37) @ java.net.plainsocketimpl$plainsocketinputstream.read(plainsocketimpl.java:237) @ okio.okio$2.read(okio.java:139) @ okio.asynctimeout$2.read(asynctimeout.java:211) @ okio.realbufferedsource.read(realbufferedsource.java:50) @ okhttp3.internal.http.http1xstream$fixedlengthsource.read(http1xstream.java:381) @ okhttp3.internal.util.skipall(util.java:178) @ okhttp3.internal.util.discard(util.java:160) @ okhttp3.internal.http.http1xstream$fixedlengthsource.close(http1xstream.java:397) @ okio.realbufferedsource.close(realbufferedsource.java:396) @ okio.forwardingsource.close(forwardingsource.java:43) @ okio.realbufferedsource.close(realbufferedsource.java:396) @ okio.realbufferedsource$1.close(realbufferedsource.java:384) @ com.testapp.apkinstall.mainactivity.writeresponsebodytodisk(mainactivity.java:87) @ com.testapp.apkinstall.mainactivity.access$000(mainactivity.java:24) @ com.testapp.apkinstall.mainactivity$1$1.onresponse(mainactivity.java:42) @ retrofit2.executorcalladapterfactory$executorcallbackcall$1$1.run(executorcalladapterfactory.java:68) @ 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:5254) @ java.lang.reflect.method.invoke(native method) @ java.lang.reflect.method.invoke(method.java:372) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:898) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:693) 

onresponse runs on ui thread, , bytestream() accesses underlaying network connection and, exception states, can't it. @epicpandaforce points out, since using own thread, don't need call enqueue, can call directly execute(), blocking call returns response<t>:

response<responsebody> response = call.execute(); if (response.issuccessful()) {   writeresponsebodytodisk(response.body()); } 

in case runs on context of thread, , not on ui thread. thread allowed access bytestream(), , won't experience networkonmainthreadexception


Comments