Added Android code
[wl-app.git] / Android / app / src / main / java / com / moiseum / wolnelektury / connection / downloads / FileCacheUtils.java
diff --git a/Android/app/src/main/java/com/moiseum/wolnelektury/connection/downloads/FileCacheUtils.java b/Android/app/src/main/java/com/moiseum/wolnelektury/connection/downloads/FileCacheUtils.java
new file mode 100644 (file)
index 0000000..dc14253
--- /dev/null
@@ -0,0 +1,180 @@
+package com.moiseum.wolnelektury.connection.downloads;
+
+import android.os.Environment;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import com.moiseum.wolnelektury.base.WLApplication;
+import com.moiseum.wolnelektury.connection.models.MediaModel;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+import io.reactivex.Completable;
+import okhttp3.ResponseBody;
+
+import static android.os.Environment.isExternalStorageRemovable;
+
+/**
+ * Created by Piotr Ostrowski on 10.05.2017.
+ */
+
+public class FileCacheUtils {
+
+       private static final String FILES_CACHE = "FilesCache";
+       private static final int BUFFER_SIZE = 4096;
+       private static final long PROGRESS_UPDATE_RATE = 10;
+       private static final String TAG = FileCacheUtils.class.getSimpleName();
+
+       private FileCacheUtils() {
+               // nop.
+       }
+
+       public static String getCachedFileForUrl(String url) {
+               File cachedFile = new File(getCurrentCachePath() + File.separator + url.hashCode());
+               if (cachedFile.exists()) {
+                       return cachedFile.getAbsolutePath();
+               } else {
+                       return null;
+               }
+       }
+
+       public static boolean deleteFileForUrl(String url) {
+               File cachedFile = new File(getCurrentCachePath() + File.separator + url.hashCode());
+               if (cachedFile.exists()) {
+                       return cachedFile.delete();
+               } else {
+                       Log.e(TAG, "There is no file to be removed: " + url);
+                       return false;
+               }
+       }
+
+       public static boolean writeResponseBodyToDiskCache(ResponseBody body, String fileUrl) {
+               try {
+                       String cachePath = getCurrentCachePath();
+                       File fileCacheDir = new File(cachePath);
+                       File downloadFile = new File(cachePath + File.separator + fileUrl.hashCode() + ".download");
+                       createCacheFolderAndFile(cachePath, fileCacheDir, downloadFile);
+
+                       InputStream inputStream = null;
+                       OutputStream outputStream = null;
+
+                       try {
+                               byte[] fileReader = new byte[BUFFER_SIZE];
+                               long fileSize = body.contentLength();
+                               long fileSizeDownloaded = 0;
+
+                               inputStream = body.byteStream();
+                               outputStream = new FileOutputStream(downloadFile);
+
+                               int updateRate = 0;
+                               while (true) {
+                                       int read = inputStream.read(fileReader);
+                                       if (read == -1) {
+                                               break;
+                                       }
+
+                                       outputStream.write(fileReader, 0, read);
+                                       fileSizeDownloaded += read;
+                                       if (updateRate++ % PROGRESS_UPDATE_RATE == 0) {
+                                               EventBus.getDefault().post(new DownloadProgressEvent(fileUrl, fileSizeDownloaded, fileSize));
+                                       }
+                               }
+                               outputStream.flush();
+
+                               File audioFileDest = new File(cachePath + File.separator + fileUrl.hashCode());
+                               boolean renamed = downloadFile.renameTo(audioFileDest);
+                               if (!renamed) {
+                                       throw new IOException("Failed to rename downloaded file: " + audioFileDest.getAbsolutePath());
+                               }
+                               return true;
+                       } catch (IOException e) {
+                               Log.e(TAG, "Failed to save file to cache: " + fileUrl, e);
+                               downloadFile.delete();
+                               return false;
+                       } finally {
+                               if (inputStream != null) {
+                                       inputStream.close();
+                               }
+                               if (outputStream != null) {
+                                       outputStream.close();
+                               }
+                       }
+               } catch (IOException e) {
+                       Log.e(TAG, "File creation or streaming closure failed", e);
+                       return false;
+               }
+       }
+
+       private static void createCacheFolderAndFile(String cachePath, File audioCacheDir, File audioFile) throws IOException {
+               if (!audioCacheDir.exists()) {
+                       boolean result = audioCacheDir.mkdir();
+                       if (!result) {
+                               throw new IOException("Failed to create AudioCache Dir.");
+                       }
+               }
+               if (!audioFile.exists()) {
+                       boolean result = audioFile.createNewFile();
+                       if (!result) {
+                               throw new IOException("Failed to create file in path: " + audioFile.getAbsolutePath());
+                       }
+               }
+       }
+
+       @NonNull
+       private static String getCurrentCachePath() {
+               File externalCacheDir = WLApplication.getInstance().getApplicationContext().getExternalCacheDir();
+               String cachePath = (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !isExternalStorageRemovable()) &&
+                               externalCacheDir != null ? externalCacheDir.getPath() : WLApplication.getInstance().getCacheDir().getPath();
+               return cachePath + File.separator + FILES_CACHE;
+       }
+
+       public static Completable deleteAudiobookFiles(List<String> fileUrls) {
+               return Completable.fromAction(() -> {
+                       for (String fileUrl : fileUrls) {
+                               boolean deleted = deleteFileForUrl(fileUrl);
+                               if (!deleted) {
+                                       Log.e(TAG, "Failed to delete file " + FileCacheUtils.getCachedFileForUrl(fileUrl));
+                               }
+                       }
+               });
+       }
+
+       public static Completable deleteEbookFile(final String epubUrl) {
+               return Completable.fromAction(() -> deleteFileForUrl(epubUrl));
+       }
+
+       /**
+        * Event indicating progress.
+        */
+       public static class DownloadProgressEvent {
+
+               private String fileUrl;
+               private long downloaded;
+               private long total;
+
+               public DownloadProgressEvent(String fileUrl, long downloaded, long total) {
+                       this.fileUrl = fileUrl;
+                       this.downloaded = downloaded;
+                       this.total = total;
+               }
+
+               public String getFileUrl() {
+                       return fileUrl;
+               }
+
+               public long getDownloaded() {
+                       return downloaded;
+               }
+
+               public long getTotal() {
+                       return total;
+               }
+       }
+}