package edu.vanderbilt.cs282.feisele.lab05;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.UnknownHostException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.annotation.TargetApi;
import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
/**
* The parent class for performing the work. The child classes implement the
* specific communication mechanism.
*
* @author "Fred Eisele" <phreed@gmail.com>
*/
public abstract class DownloadBoundService extends LifecycleLoggingService {
static private final Logger logger = LoggerFactory
.getLogger("class.service.download.bound");
static protected final int MAXIMUM_SIZE = 100;
/**
* The workhorse for the class. Download the provided image uri. If there is
* a problem an exception is raised and the calling method is expected to
* handle it in an appropriate manner.
* <p>
* Two types of uri are handled, url and content provider uri.
* <p>
* The url is indicated by the
* <p>
* An allowance is made for a uri of a content provider, which have a shema
* of "content".
*
* @param uri
* the thing to download
*/
protected Bitmap downloadBitmap(Uri uri) throws FailedDownload,
FileNotFoundException, IOException {
logger.debug("downloadBitmap:");
final Bitmap bitmap;
try {
final String scheme = uri.getScheme();
if ("http".equals(scheme)) {
final InputStream is = new URL(uri.toString()).openStream();
bitmap = BitmapFactory.decodeStream(is);
} else {
return null;
}
logger.debug("bitmap size [{}:{}]", bitmap.getWidth(),
bitmap.getHeight());
return bitmap;
} catch (UnknownHostException ex) {
logger.warn("download failed bad host", ex);
throw new FailedDownload(this.getResources().getText(
R.string.error_downloading_url));
} catch (IOException ex) {
logger.warn("download failed ?", ex);
throw new FailedDownload(this.getResources().getText(
R.string.error_downloading_url));
}
}
/**
* An exception class used when there is a problem with the download.
*/
public static class FailedDownload extends Exception {
private static final long serialVersionUID = 6673968049922918951L;
final public CharSequence msg;
@Override
public String getMessage() {
return new StringBuilder().append(this.msg).toString();
}
public FailedDownload(CharSequence msg) {
super();
this.msg = msg;
}
}
/**
* In order to preserve security for this object it would be good if only a
* file descriptor were provided (the file being immediately deleted).
* However, I have been unable to properly return a ParcelFileDescriptor,
* therefore this method (and its calling routines) work with the file by
* name. The requesting application is expected to delete the file as
* needed.
*
* @param bitmap
* @return the temporary file by name.
*/
@TargetApi(9)
protected File storeBitmap(Bitmap bitmap) {
final File cacheDir = this.getCacheDir();
File tempFile = null;
try {
tempFile = File.createTempFile("download", "tmp", cacheDir);
final ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, outBytes);
final FileOutputStream fo = new FileOutputStream(tempFile);
fo.write(outBytes.toByteArray());
fo.close();
outBytes.close();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
tempFile.setReadable(true, false);
tempFile.setWritable(true, false);
}
return tempFile;
} catch (IOException ex) {
logger.error("could not write bitmap file {}", tempFile);
}
return null;
}
}