package ar.rulosoft.mimanganu.services; import android.util.Log; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.TimeUnit; import ar.rulosoft.navegadores.Navigator; import ar.rulosoft.navegadores.RefererInterceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class SingleDownload implements Runnable { public static int RETRY = 3; public boolean referer; public Status status = Status.QUEUED; int index, cid; ChapterDownload cd; private String fromURL; private String toFile; private StateChangeListener changeListener = null; private int retry = RETRY; public SingleDownload(String fromURL, String toFile, int index, int cid, ChapterDownload cd, boolean referer) { super(); this.fromURL = fromURL; this.toFile = toFile; this.index = index; this.cid = cid; this.referer = referer; this.cd = cd; } public int getIndex() { return index; } @Override public void run() { changeStatus(Status.INIT); while (status != Status.DOWNLOAD_OK && retry > 0) { File o = new File(toFile); File ot = new File(toFile + ".temp"); if (ot.exists()) { ot.delete(); } if (o.length() == 0) { InputStream input; OutputStream output; Response response; long contentLength; try { OkHttpClient copy; if(referer){ copy = Navigator.navigator.getHttpClient().newBuilder() .connectTimeout(3, TimeUnit.SECONDS) .readTimeout(3, TimeUnit.SECONDS) .addNetworkInterceptor(new RefererInterceptor(cd.chapter.getPath())) .build(); } else { copy = Navigator.navigator.getHttpClient().newBuilder() .connectTimeout(3, TimeUnit.SECONDS) .readTimeout(3, TimeUnit.SECONDS) .build(); } response = copy.newCall(new Request.Builder().url(fromURL).build()).execute(); if (!response.isSuccessful()) { if (response.code() == 404) { changeStatus(Status.ERROR_404); } else { changeStatus(Status.ERROR_CONNECTION); } retry = 0; ot.delete(); writeErrorImage(ot); ot.renameTo(o); break; } contentLength = response.body().contentLength(); input = response.body().byteStream(); output = new FileOutputStream(ot); } catch (FileNotFoundException e) { Log.e("SingleDownload", "ERROR_WRITING_FILE"); retry--; if (retry > 0) { changeStatus(Status.RETRY); try { Thread.sleep(3000); } catch (InterruptedException e1) {} continue; } else { changeStatus(Status.ERROR_WRITING_FILE); break; } } catch (IOException e) { Log.e("SingleDownload", "ERROR_OPENING_FILE"); retry--; if (retry > 0) { changeStatus(Status.RETRY); try { Thread.sleep(3000); } catch (InterruptedException e1) {} continue; } else { changeStatus(Status.ERROR_OPENING_FILE); break; } } catch (Exception e) { retry = 0; Log.e("SingleDownload", "ERROR_CONNECTION " + e.getMessage()); e.printStackTrace(); changeStatus(Status.ERROR_CONNECTION); break; } try { changeStatus(Status.DOWNLOADING); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, bytesRead); } } catch (Exception e) { retry--; if (retry > 0) { changeStatus(Status.RETRY); } else { changeStatus(Status.ERROR_TIMEOUT); } try { Thread.sleep(3000); } catch (InterruptedException e1) {} Log.e("SingleDownload", "ERROR_TIMEOUT"); } finally { boolean flaggedOk = false; if (status != Status.RETRY) { if (contentLength > ot.length()) { Log.e("SingleDownload", "content length = " + contentLength + " size = " + o.length() + " on = " + o.getPath()); ot.delete(); retry--; changeStatus(Status.RETRY); } else { flaggedOk = true; } } try { output.flush(); output.close(); input.close(); response.body().close(); if (flaggedOk) { if (ot.length() > 0) { ot.renameTo(o); } else { ot.delete(); writeErrorImage(ot); ot.renameTo(o); } // Log.i("SingleDownload", "download ok =" + o.getPath()); changeStatus(Status.DOWNLOAD_OK); } } catch (IOException e) { e.printStackTrace(); } } } else { changeStatus(Status.DOWNLOAD_OK); } } } private void writeErrorImage(File ot) throws IOException { if (DownloadPoolService.actual != null) { InputStream ims = DownloadPoolService.actual.getAssets().open("error_image.jpg"); FileOutputStream output = new FileOutputStream(ot); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = ims.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, bytesRead); } ims.close(); output.flush(); output.close(); } } private void changeStatus(Status status) { this.status = status; if (changeListener != null && status.ordinal() > Status.POSTPONED.ordinal()) { changeListener.onChange(this); } } public void setChangeListener(StateChangeListener changeListener) { this.changeListener = changeListener; } public enum Status { QUEUED, INIT, DOWNLOADING, RETRY, POSTPONED, DOWNLOAD_OK, ERROR_CONNECTION, ERROR_404, ERROR_TIMEOUT, ERROR_ON_UPLOAD, ERROR_INVALID_URL, ERROR_WRITING_FILE, ERROR_OPENING_FILE } }