2012-09-10 63 views
0

以下代码将图像从Amazon S3下载到设备中,然后尝试将图像加载到图库中。 我的问题是不同的设备(Nexus 7)和模拟器。 我在下面的代码是通过阅读通过stackoverflow答案累积。Android - 无法显示在图库中下载的图像

1)在模拟器DDMS中,我在设备下的/data/data/myprojectname/file/test.jpg中找到文件test.jpg文件的大小是正确的。 但是,当我尝试使用下面的intent方法加载图像时,它显示“不幸相机已停止工作”。

2)对于Nexus 7,图库仅显示图像。我无法真正使用Astro文件管理器找到图像“test.jpg”,为什么这样呢?

此外,为什么模拟器和设备的行为不同?

这让我发疯,在此先感谢您的帮助。

码头。

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()); 
      } 
     } 
    }); 
+0

保存图像文件在SD卡,如果你想显示它,而不是在你的应用程序的文件夹中! – hardartcore

+0

这是一个愚蠢的问题,但nexus 7没有SD卡。它是否仍然有“虚拟”SD卡?如果我想展示下载的文件在SD卡中是否也是标准做法? – lppier

+0

我宁愿将它们存储在SD卡中,如果您只下载几张图像就没问题,但如果它们更多,我更愿意将它们存储在SD卡中。是的,在银河系和更多设备中,没有物理SD卡,但您仍然有权在那里读写。 – hardartcore

回答

1

您应该考虑使用惰性加载而是 看一看这个项目:

https://github.com/thest1/LazyList

+0

看起来很有用,特别是图片加载器类,我来看看,谢谢! – lppier

+0

虽然不是直接的答案,但这对我很有用。我会接受这个答案。 – lppier

0

我不得不修改ImageLoader的在LazyList,以满足我的使用。 以下代码调用Amazon S3,并且由于签名不同,该url与每次调用都不同。

 // 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); 

因此,这是我如何修改ImageLoader的,基本上截断的URL JPEG(假设所有来电都是JPEG文件),并把它和内存缓存中检索时丢弃其余。希望这可以帮助别人:)

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(); 
} 

}