package vandy.mooc.utils;
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 android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.util.Base64;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
/**
* Utils contains helper methods that properly format the WeatherData
* POJO and display it to the user.
*/
public class Utils {
/**
* Logging tag.
*/
private final static String TAG =
Utils.class.getCanonicalName();
/**
* Show a toast message.
*/
public static void showToast(Context context,
String message) {
Toast.makeText(context,
message,
Toast.LENGTH_SHORT).show();
}
/**
* This method is used to hide a keyboard after a user has
* finished typing the url.
*/
public static void hideKeyboard(Activity activity,
IBinder windowToken) {
InputMethodManager mgr =
(InputMethodManager) activity.getSystemService
(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(windowToken,
0);
}
/**
* Download the song located at the provided Internet url using
* the URL class, store it on the android file system using a
* FileOutputStream, and return the path to the song file on disk.
*
* @param context
* The context in which to write the file.
* @param url
* The URL of the song to download.
* @param directoryPathname
* Pathname of the directory to write the file.
*
* @return Absolute path to the downloaded song file on the file
* system.
*/
public static Uri downloadSong(Context context,
Uri url,
Uri directoryPathname) {
try {
if (!isExternalStorageWritable()) {
Log.d(TAG, "external storage is not writable");
return null;
}
Log.d(TAG, "starting download of song at "
+ url.toString()
+ " into directory "
+ directoryPathname);
// Check to see if this thread has been interrupted.
if (!Thread.currentThread().isInterrupted()) {
// Create an output file and save the song referenced
// at the URL into it.
return Utils.downloadAndSaveFile
(context,
new URL(url.toString()),
Uri.parse(url.getLastPathSegment()),
directoryPathname);
} else
return null;
} catch (Exception e) {
Log.e(TAG,
"Exception while downloading -- returning null."
+ e.toString());
return null;
}
}
/**
* Returns a open File if @a directoryPath points to a valid
* directory, else null.
*/
private static File openDirectory(Uri directoryPathname) {
File d = new File(directoryPathname.toString());
if (!d.exists()
&& !d.mkdir())
return null;
else
return d;
}
/**
* Download store a song into a file on the device.
*
* @param context
* The context in which to write the file.
* @param url
* URL to the resource (e.g., local or remote file).
* @param fileName
* Name of the file.
* @param directoryPathname
* Pathname of the directory to write the file.
*
* @return Absolute path to the downloaded song file on the file
* system.
*/
private static Uri downloadAndSaveFile(Context context,
URL url,
Uri fileName,
Uri directoryPathname) {
try {
// Bail out of we get an invalid bitmap.
if (url == null
|| fileName == null)
return null;
// Create a directory path.
File directoryPath =
new File(directoryPathname.toString());
// If the directory doesn't exist already then create it.
if (!directoryPath.exists())
directoryPath.mkdirs();
// Create a filePath within the directoryPath.
File file =
new File(directoryPath,
Utils.getUniqueFilename(fileName));
// Delete the file if it already exists.
if (file.exists())
file.delete();
// Get the content of the resource at the url and save it
// to an output file.
try (InputStream is = (InputStream) url.getContent();
OutputStream os = new FileOutputStream(file)) {
// Copy input to output.
copy(is, os);
// Set the modified date to enable cancellation.
file.setLastModified(System.currentTimeMillis());
} catch (Exception e) {
return null; // Indicate a failure.
}
// Get the absolute path of the song.
final String absolutePathToSong = file.getAbsolutePath();
return Uri.parse(absolutePathToSong);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* This method checks if we can write song to external storage.
*
* @return true if an song can be written, and false otherwise
*/
private static boolean isExternalStorageWritable() {
return Environment.MEDIA_MOUNTED.equals
(Environment.getExternalStorageState());
}
/**
* Create a filename that contains a timestamp which makes it
* unique.
*
* @param filename
* The name of a file that we'd like to make unique.
* @return String containing the unique temporary filename.
*/
static private String getUniqueFilename(final Uri filename) {
return Base64.encodeToString((filename.toString()
+ System.currentTimeMillis()
+ Thread.currentThread().getName()).getBytes(),
Base64.NO_WRAP);
// Use this implementation if you don't want to keep filling
// up your file system with temp files..
//
// return Base64.encodeToString(filename.getBytes(),
// Base64.NO_WRAP);
}
/**
* Copy the contents of the @a inputStream to the @a outputStream.
*
* @throws IOException
*/
private static void copy(InputStream inputStream,
OutputStream outputStream)
throws IOException {
// Size of each file I/O operation.
final int BUFLEN = 1024;
byte[] buffer = new byte[BUFLEN];
// Keep looping until the input stream is finished or the
// thread is interrupted.
for (int n;
(n = inputStream.read(buffer)) >= 0
&& !Thread.currentThread().isInterrupted();
)
// Write the bytes to the output stream.
outputStream.write(buffer,
0,
n);
// Flush the contents of the output stream.
outputStream.flush();
}
/**
* Make UtilGUI a utility class by preventing instantiation.
*/
private Utils() {
throw new AssertionError();
}
}