Reputation: 1987
The following code downloads a image from Amazon S3 into the device, and then I try to load the image in gallery. My issue is different for the Device (Nexus 7) and the emulator. My code below is a cumulation of reading through stackoverflow answers.
1) In the emulator DDMS, I find the file test.jpg in the device under /data/data/myprojectname/file/test.jpg The size of the file is correct. However, it says "Unfortunately camera has stopped working" when I try to load the image using the intent method below.
2) For the Nexus 7, gallery simply shows up with no image. I can't really find the image "test.jpg" using Astro file manager, why is this so?
Also, why would the emulator and the device act differently?
This is driving me crazy, thanks in advance for your help.
Pier.
showInGallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// Ensure that the image will be treated as such.
ResponseHeaderOverrides override = new ResponseHeaderOverrides();
override.setContentType( "image/jpeg" );
// Generate the presigned URL.
Date expirationDate = new Date( System.currentTimeMillis() + 3600000 ); // Added an hour's worth of milliseconds to the current time.
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest( Constants.getPictureBucket(), Constants.PICTURE_NAME );
urlRequest.setExpiration( expirationDate );
urlRequest.setResponseHeaders( override );
URL url = s3Client.generatePresignedUrl( urlRequest );
/* Open a connection to that URL. */
File file = new File(PATH + Constants.PICTURE_NAME);
URLConnection ucon = url.openConnection();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
/* Convert the Bytes read to a String. */
String fileName = "test.jpg";
//FileOutputStream fos = new FileOutputStream(fileName);
FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(baf.toByteArray());
fos.close();
/* read the file */
File filePath = getFileStreamPath(fileName);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(filePath.toString()), "image/*");
startActivity(intent);
}
catch ( Exception exception ) {
S3UploaderActivity.this.displayAlert( "Browser Failure", exception.getMessage() );
}
}
});
Upvotes: 0
Views: 1282
Reputation: 1987
I had to modify ImageLoader in LazyList to suit my use. The following code calls Amazon S3, and the url is different with every call due to different signature.
// Generate the presigned URL.
Date expirationDate = new Date( System.currentTimeMillis() + 3600000 ); // Added an hour's worth of milliseconds to the current time.
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest( Constants.PICTURE_BUCKET, menuItemArray[position].getImageFileName() );
urlRequest.setExpiration( expirationDate );
urlRequest.setResponseHeaders( override );
URL url = s3Client.generatePresignedUrl( urlRequest );
imageLoader.DisplayImage(url.toString(), holder.image);
So this was how I modified ImageLoader, basically to truncate the url to the jpeg (assume all your calls are for jpeg files) and discarding the rest when putting it and retrieving from memory cache. Hope this helps someone :)
package com.suite.android.menu;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.OutOfMemoryError;
import java.lang.Runnable;
import java.lang.String;
import java.lang.Throwable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
public class ImageLoader {
MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
public ImageLoader(Context context){
fileCache=new FileCache(context);
executorService=Executors.newFixedThreadPool(5);
}
final int stub_id=R.drawable.stub;
public void DisplayImage(String url, ImageView imageView)
{
String truncURL = truncateJPEG(url); // required as every amazon s3 call slightly different
imageViews.put(imageView, truncURL);
Bitmap bitmap=memoryCache.get(truncURL);
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
private String truncateJPEG(String s)
{
int pos = s.indexOf("jpeg");
String newURL = s.substring(0, pos+4); //account for jpeg
return newURL;
}
private void queuePhoto(String url, ImageView imageView)
{
PhotoToLoad p=new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad=photoToLoad;
}
@java.lang.Override
public void run() {
if(imageViewReused(photoToLoad))
return;
Bitmap bmp=getBitmap(photoToLoad.url);
String newURL = truncateJPEG(photoToLoad.url); // every amazon s3 call different so need to do this
memoryCache.put(newURL, bmp);
if(imageViewReused(photoToLoad))
return;
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
boolean imageViewReused(PhotoToLoad photoToLoad){
String tag=imageViews.get(photoToLoad.imageView);
if(tag==null || !tag.equals(truncateJPEG(photoToLoad.url)))
return true;
return false;
}
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
public void run()
{
if(imageViewReused(photoToLoad))
return;
if(bitmap!=null)
photoToLoad.imageView.setImageBitmap(bitmap);
else
photoToLoad.imageView.setImageResource(stub_id);
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
}
Upvotes: 0
Reputation: 22469
You should consider using lazyloading instead, take a look at this project:
https://github.com/thest1/LazyList
Upvotes: 1