package vandy.mooc.common;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import vandy.mooc.R;
import android.content.Context;
import android.net.Uri;
import android.util.Base64;
import android.util.Log;
/**
* @class DownloadUtils
*
* @brief This class encapsulates several static methods so that all
* Services can access them without redefining them in each
* Service.
*/
public class DownloadUtils {
/**
* Used for debugging.
*/
static final String TAG =
DownloadUtils.class.getSimpleName();
/**
* If you have access to a stable Internet connection for testing
* purposes, feel free to change this variable to false so it
* actually downloads the image from a remote server.
*/
static final boolean DOWNLOAD_OFFLINE = false;
/**
* The resource that we write to the file system in offline
* mode. Note that this must be the same image that the testing
* project expects. (found in res/drawable-nodpi and Options.java)
*/
static final int OFFLINE_TEST_IMAGE = R.raw.dougs;
/**
* The file name that we should use to store the image in offline mode
*/
static final String OFFLINE_FILENAME = "dougs.jpg";
/**
* Download the file located at the provided internet url using
* the URL class, store it on the android file system using
* openFileOutput(), and return the path to the file on disk.
*
* @param context the context in which to write the file
* @param uri the web url
*
* @return the path to the downloaded file on the file system
*/
public static Uri downloadFile(Context context,
Uri uri) {
// If we're offline, write the image in our resources to disk,
// then return that pathname.
if (DOWNLOAD_OFFLINE) {
// Store the image on the file system. We can store it as
// private since the test project runs in the same process
// as the target project.
try (FileOutputStream out =
context.openFileOutput(OFFLINE_FILENAME, 0);
InputStream in =
context.getResources().openRawResource(OFFLINE_TEST_IMAGE)) {
// Write the resource to disk.
copy(in,
out);
} catch (Exception e) {
Log.e(TAG,
"Exception while downloading. Returning null.");
Log.e(TAG,
e.toString());
e.printStackTrace();
return null;
}
return Uri.parse(context.getFilesDir().toString()
+ File.separator
+ OFFLINE_FILENAME);
}
// Otherwise, go ahead and download the file
else {
// Create a temp file.
final File file = getTemporaryFile(context,
uri.toString());
Log.d(TAG,
" downloading to "
+ file);
// Download the contents at the URL, which should
// reference an image.
try (final InputStream in = (InputStream)
new URL(uri.toString()).getContent();
final OutputStream os =
new FileOutputStream(file)) {
// Copy the contents of the downloaded image to the
// temp file.
copy(in,
os);
} catch (Exception e) {
Log.e(TAG,
"Exception while downloading. Returning null.");
Log.e(TAG,
e.toString());
e.printStackTrace();
return null;
}
// Return the pathname of the temp file.
return Uri.parse(file.getAbsolutePath());
}
}
/**
* Create a temp file to store the result of a download.
*
* @param context
* @param url
* @return
* @throws IOException
*/
static private File getTemporaryFile(Context context,
String url) {
// This is what you'd normally call to get a unique temporary
// file, but for testing purposes we always name the file the
// same to avoid filling up student phones with numerous
// files!
// return context.getFileStreamPath(Base64.encodeToString(url.getBytes(),
// Base64.NO_WRAP)
// + System.currentTimeMillis());
return context.getFileStreamPath(Base64.encodeToString(url.getBytes(),
Base64.NO_WRAP));
}
/**
* Copy the contents of an InputStream into an OutputStream.
*
* @param in
* @param out
* @return
* @throws IOException
*/
static public int copy(final InputStream in,
final OutputStream out) throws IOException {
final int BUFFER_LENGTH = 1024;
final byte[] buffer = new byte[BUFFER_LENGTH];
int totalRead = 0;
int read = 0;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
totalRead += read;
}
return totalRead;
}
}