Java tutorial
/* * Copyright (c) 2014 Amahi * * This file is part of Amahi. * * Amahi is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Amahi is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Amahi. If not, see <http ://www.gnu.org/licenses/>. */ package org.amahi.anywhere.util; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Environment; import android.support.v4.content.FileProvider; import android.util.Log; import org.amahi.anywhere.bus.BusProvider; import org.amahi.anywhere.bus.FileDownloadFailedEvent; import org.amahi.anywhere.bus.FileDownloadedEvent; import org.amahi.anywhere.model.FileOption; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import javax.inject.Inject; import javax.inject.Singleton; /** * File downloader. Uses system {@link android.app.DownloadManager} * for downloads placing and cancelling. */ @Singleton public class Downloader extends BroadcastReceiver { public static final String OFFLINE_PATH = "offline_files"; private final Context context; private long downloadId; private DownloadCallbacks downloadCallbacks; private ProgressTask downloadProgressTask; @Inject public Downloader(Context context) { this.context = context.getApplicationContext(); this.downloadId = Integer.MIN_VALUE; } public void startFileDownloading(Uri fileUri, String fileName, @FileOption.Types int fileOption) { setUpDownloadReceiver(); startDownloading(fileUri, fileName, fileOption); } private void setUpDownloadReceiver() { IntentFilter downloadActionsFilter = new IntentFilter(); downloadActionsFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE); context.registerReceiver(this, downloadActionsFilter); } private void startDownloading(Uri downloadUri, String downloadName, @FileOption.Types int fileOption) { File file; DownloadManager.Request downloadRequest = new DownloadManager.Request(downloadUri); if (fileOption == FileOption.DOWNLOAD) { // download in public directory file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), downloadName); downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, downloadName); } else { // download in App directory file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), downloadName); downloadRequest.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, downloadName); } //code to delete the file if it already exists if (file.exists()) file.delete(); downloadRequest.setVisibleInDownloadsUi(true) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); this.downloadId = getDownloadManager(context).enqueue(downloadRequest); } private DownloadManager getDownloadManager(Context context) { return (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); } @Override public void onReceive(Context context, Intent intent) { if (isDownloadCurrent(intent)) { finishDownloading(); tearDownDownloadReceiver(); } } private boolean isDownloadCurrent(Intent intent) { return downloadId == intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0); } public long startDownloadingForOfflineMode(Uri downloadUri, String downloadName) { File file = new File(context.getExternalFilesDir(OFFLINE_PATH), downloadName); if (file.exists()) file.delete(); DownloadManager.Request downloadRequest = new DownloadManager.Request(downloadUri); downloadRequest.setDestinationInExternalFilesDir(context, OFFLINE_PATH, downloadName) .setVisibleInDownloadsUi(false) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); long id = getDownloadManager(context).enqueue(downloadRequest); downloadCallbacks.downloadStarted((int) id, downloadName); startProgressCount(id); return id; } private void startProgressCount(long id) { if (downloadProgressTask != null) { downloadProgressTask.shutDown(); } downloadProgressTask = new ProgressTask(id); Thread thread = new Thread(downloadProgressTask); thread.start(); } public void resumeProgressCount(long id) { startProgressCount(id); } private void finishDownloading() { DownloadManager.Query downloadQuery = new DownloadManager.Query().setFilterById(downloadId); Cursor downloadInformation = getDownloadManager(context).query(downloadQuery); downloadInformation.moveToFirst(); int downloadStatus = downloadInformation .getInt(downloadInformation.getColumnIndex(DownloadManager.COLUMN_STATUS)); if (downloadStatus == DownloadManager.STATUS_SUCCESSFUL) { String downloadUri = downloadInformation .getString(downloadInformation.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); if (downloadUri.substring(0, 7).matches("file://")) { downloadUri = downloadUri.substring(7); } try { URI uri = new URI(downloadUri); downloadUri = uri.getPath(); } catch (URISyntaxException e) { Log.e("Downloader", "Invalid Uri: " + downloadUri); } File file = new File(downloadUri); Uri contentUri = FileProvider.getUriForFile(context, "org.amahi.anywhere.fileprovider", file); BusProvider.getBus().post(new FileDownloadedEvent(contentUri)); } else { BusProvider.getBus().post(new FileDownloadFailedEvent()); } downloadInformation.close(); } private void tearDownDownloadReceiver() { try { context.unregisterReceiver(this); } catch (IllegalArgumentException e) { // False alarm, no need to unregister. } } public void finishFileDownloading() { getDownloadManager(context).remove(downloadId); tearDownDownloadReceiver(); } public void setDownloadCallbacks(DownloadCallbacks downloadCallbacks) { this.downloadCallbacks = downloadCallbacks; } private boolean isNetworkAvailable() { NetworkUtils networkUtils = new NetworkUtils(context); return networkUtils.isNetworkAvailable(); } public interface DownloadCallbacks { void downloadStarted(int id, String fileName); void downloadProgress(int id, int progress); void downloadSuccess(long id); void downloadError(long id); void downloadPaused(long id, int progress); } private class ProgressTask implements Runnable { private boolean isDownloading; private long id; ProgressTask(long id) { this.id = id; } @Override public void run() { isDownloading = true; while (isDownloading) { DownloadManager.Query q = new DownloadManager.Query(); q.setFilterById(id); Cursor cursor = getDownloadManager(context).query(q); if (cursor != null && cursor.moveToFirst()) { cursor.moveToFirst(); long bytes_downloaded = cursor .getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); long bytes_total = cursor .getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); long progress = bytes_total != 0 ? (100 * bytes_downloaded) / bytes_total : 0; downloadCallbacks.downloadProgress((int) id, (int) progress); int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); switch (status) { case DownloadManager.STATUS_PAUSED: if (!(isNetworkAvailable())) { isDownloading = false; downloadCallbacks.downloadPaused(id, (int) progress); } else { downloadCallbacks.downloadError(id); isDownloading = false; } break; case DownloadManager.STATUS_SUCCESSFUL: isDownloading = false; downloadCallbacks.downloadSuccess((int) id); break; case DownloadManager.STATUS_FAILED: isDownloading = false; downloadCallbacks.downloadError((int) id); break; } cursor.close(); } else { isDownloading = false; } } } void shutDown() { isDownloading = false; } } }