Ich versuche, Retrofit-Bibliothek zu verwenden, um eine Datei (apk: 2mB) von URL in einem getrennten Thread herunterzuladen.Android: NetworkOnMainThreadException tritt auf, wenn Retrofit in einem neuen Thread verwendet wird?
mein Code Hier ist (siehe 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;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
Der Code meines Dienstes:
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);
}
ich das Herunterladen Aufgabe in einem neuen Thread gestartet, aber ich habe diese:
android.os.NetworkOnMainThreadException
Wenn ich ein Bild von 3kB herunterladen, funktioniert das Programm gut. Wenn ich Folgendes hinzufügen Code:
StrictMode policy violation; ~duration=1342 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=23 violation=2
Hier ist der Stacktrace:
Process: com.testapp.yiyuanguo.apkinstall, PID: 25788
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249)
at libcore.io.IoBridge.recvfrom(IoBridge.java:553)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at okio.Okio$2.read(Okio.java:139)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.read(RealBufferedSource.java:50)
at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:381)
at okhttp3.internal.Util.skipAll(Util.java:178)
at okhttp3.internal.Util.discard(Util.java:160)
at okhttp3.internal.http.Http1xStream$FixedLengthSource.close(Http1xStream.java:397)
at okio.RealBufferedSource.close(RealBufferedSource.java:396)
at okio.ForwardingSource.close(ForwardingSource.java:43)
at okio.RealBufferedSource.close(RealBufferedSource.java:396)
at okio.RealBufferedSource$1.close(RealBufferedSource.java:384)
at com.testapp.apkinstall.MainActivity.writeResponseBodyToDisk(MainActivity.java:87)
at com.testapp.apkinstall.MainActivity.access$000(MainActivity.java:24)
at com.testapp.apkinstall.MainActivity$1$1.onResponse(MainActivity.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
Post den gesamten StackTrace. Entfernen Sie die 'StrictMode.ThreadPolicy' – Blackbelt
Sie erkennen, dass' execute() 'den Netzwerkaufruf synchron ausführt, aber' enqueue() 'ist ** bereits asynchron ** und Sie müssen *** nicht starten neuer Thread() ***, oder? – EpicPandaForce
@Blackbelt siehe mein update, danke! – programforjoy