2015-01-30 6 views
5

갤러리에 새 이미지를 추가하려고합니다. 인 텐트를 통해 이미 존재하는 이미지를 선택하고 크기를 조정하고 압축합니다.이미지를 미디어 갤러리에 추가 - 안드로이드

는 다음 나는 결과 비트 맵 저장 :

public static File compressAndSaveImage(Context ctx, Uri imageUri) throws FileNotFoundException { 
    File file = null; 

    if (imageUri != null) { 
     ContextWrapper cw = new ContextWrapper(ctx); 
     File directory = cw.getDir("imageDir", Context.MODE_PRIVATE); 
     file = new File(directory, imageUri.getLastPathSegment()); 
     System.out.println("storing to " + file); 

     InputStream input = ctx.getContentResolver().openInputStream(imageUri); 
     Bitmap b = ImageManager.resize(BitmapFactory.decodeStream(input), 
       ctx.getResources().getDimension(R.dimen.player_thumb_w), 
       ctx.getResources().getDimension(R.dimen.player_thumb_h)); 

     FileOutputStream fos = new FileOutputStream(file); 
     if (b.compress(Bitmap.CompressFormat.PNG, 100, fos)) { 
      System.out.println("Compression success");// bmp is your Bitmap instance 
     } 
     addPictureToGallery(ctx, file); 
    } 
    return file; 
} 

을하지만 갤러리에 이미지를 추가하려고하면, 나는 오류를 얻을 이미지가 추가되지 않습니다. 나는 시도 모두 방법을 아래에있다 :

file /data/data/test.myapps.appname/app_imageDir/6045564126748266738 was scanned successfully: content://media/external/file/7838 

내가 놓친 게 무엇 :

private static void addPictureToGallery(Context ctx, File filepath) { 
//  Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
//  System.out.println("Publish: " + filepath.exists()); 
//  System.out.println("Publish: " + filepath.getAbsolutePath()); 
//  Uri contentUri = Uri.fromFile(filepath); 
//  mediaScanIntent.setData(contentUri); 
//  ctx.sendBroadcast(mediaScanIntent); 
    MediaScannerConnection.scanFile(
      ctx, 
      new String[]{filepath.getAbsolutePath()}, 
      null, 
      new MediaScannerConnection.OnScanCompletedListener() { 
       @Override 
       public void onScanCompleted(String path, Uri uri) { 
        Log.w("mydebug", "file " + path + " was scanned successfully: " + uri); 
       } 
      }); 
    } 
} 

콜백은 다음 줄을 인쇄?

답변

2

나는 물건에 대해 세부적으로 들어가는 시간이 없기 때문에 이것을 주석으로 달았지만 분명히 너무 길다. 이런 식으로 해보십시오 (갤러리에 비트 맵을 저장하기 위해 이것을 사용합니다). 참고로 이미지를 스캔하는 것 외에는 아무 것도하지 않는 것 같습니다. 지금은 파일을 내부 저장소에 저장하고 휴대 전화 콘텐츠 (갤러리)에 저장하지 않는 것 같습니다.

우리가 활동을 zgc7009 @

/** 
* Will save our card (currently set as a bitmap) as a jpeg and save it into our devices 
* native photo gallery. Unfortunately, the default method for this will add the image to the bottom 
* of the gallery by default, that is no good. This more complex method that utilizes Android's 
* native methods will allow us to store the bitmap at the top of the gallery by setting it's 
* meta data to today's date. 
*/ 
public class SaveBitmapToDevice extends AsyncTask<Bitmap, Void, String>{ 

    private final ShareType type; 

    public SaveBitmapToDevice(ShareType type){ 
     this.type = type; 
    } 

    @Override 
    protected String doInBackground(Bitmap... cards) { 
     return insertImageIntoGallery(getContentResolver(), cards[0], getString(R.string.card_gallery_title), 
       getString(R.string.card_gallery_label)); 
    } 

    /** 
    * A copy of the Android internals insertImage method, this method populates the 
    * meta data with DATE_ADDED and DATE_TAKEN. This fixes a common problem where media 
    * that is inserted manually gets saved at the end of the gallery (because date is not populated). 
    * @see android.provider.MediaStore.Images.Media#insertImage(android.content.ContentResolver, Bitmap, String, String). 
    * If the MediaStore not available, we will redirect the file to our alternative source, the SD card. 
    */ 
    public String insertImageIntoGallery(ContentResolver cr, Bitmap source, String title, String description) { 

     ContentValues values = new ContentValues(); 
     values.put(MediaStore.Images.Media.TITLE, title); 
     values.put(MediaStore.Images.Media.DISPLAY_NAME, title); 
     values.put(MediaStore.Images.Media.DESCRIPTION, description); 
     values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); 
     // Add the date meta data to ensure the image is added at the front of the gallery 
     values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 
     values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 

     Uri url = null; 
     String stringUrl = null; /* value to be returned */ 

     try { 
      url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 

      if (source != null) { 
       OutputStream imageOut = cr.openOutputStream(url); 
       try { 
        source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut); 
       } finally { 
        imageOut.close(); 
       } 

       long id = ContentUris.parseId(url); 
       // Wait until MINI_KIND thumbnail is generated. 
       Bitmap miniThumb = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MINI_KIND, null); 
       // This is for backward compatibility. 
       storeThumbnail(cr, miniThumb, id, 50F, 50F, MediaStore.Images.Thumbnails.MICRO_KIND); 
      } else { 
       cr.delete(url, null, null); 
       return storeToAlternateSd(source, title); 
       // url = null; 
      } 
     } catch (Exception e) { 
      if (url != null) { 
       cr.delete(url, null, null); 
       return storeToAlternateSd(source, title); 
       // url = null; 
      } 
     } 

     savedOnSD = false; 
     if (url != null) { 
      stringUrl = url.toString(); 
     } 

     return stringUrl; 
    } 

    /** 
    * A copy of the Android internals StoreThumbnail method, it used with the insertImage to 
    * populate the android.provider.MediaStore.Images.Media#insertImage with all the correct 
    * meta data. The StoreThumbnail method is private so it must be duplicated here. 
    * @see android.provider.MediaStore.Images.Media (StoreThumbnail private method). 
    */ 
    private Bitmap storeThumbnail(
      ContentResolver cr, 
      Bitmap source, 
      long id, 
      float width, 
      float height, 
      int kind) { 

     // create the matrix to scale it 
     Matrix matrix = new Matrix(); 

     float scaleX = width/source.getWidth(); 
     float scaleY = height/source.getHeight(); 

     matrix.setScale(scaleX, scaleY); 

     Bitmap thumb = Bitmap.createBitmap(source, 0, 0, 
       source.getWidth(), 
       source.getHeight(), matrix, 
       true 
     ); 

     ContentValues values = new ContentValues(4); 
     values.put(MediaStore.Images.Thumbnails.KIND,kind); 
     values.put(MediaStore.Images.Thumbnails.IMAGE_ID,(int)id); 
     values.put(MediaStore.Images.Thumbnails.HEIGHT,thumb.getHeight()); 
     values.put(MediaStore.Images.Thumbnails.WIDTH,thumb.getWidth()); 

     Uri url = cr.insert(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, values); 

     try { 
      OutputStream thumbOut = cr.openOutputStream(url); 
      thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut); 
      thumbOut.close(); 
      return thumb; 
     } catch (FileNotFoundException ex) { 
      Log.e("IMAGE_COMPRESSION_ERROR", "File not found"); 
      ex.printStackTrace(); 
      return null; 
     } catch (IOException ex) { 
      Log.e("IMAGE_COMPRESSION_ERROR", "IO Exception"); 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    /** 
    * If we have issues saving into our MediaStore, save it directly to our SD card. We can then interact with this file 
    * directly, opposed to pulling from the MediaStore. Again, this is a backup method if things don't work out as we 
    * would expect (seeing as most devices will have a MediaStore). 
    * 
    * @param src 
    * @param title 
    * @return - the file's path 
    */ 
    private String storeToAlternateSd(Bitmap src, String title){ 
     if(src == null) 
      return null; 

     File sdCardDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "My Cards"); 
     if(!sdCardDirectory.exists()) 
      sdCardDirectory.mkdir(); 

     SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy - (hh.mm.a)", Locale.US); 
     File image = new File(sdCardDirectory, title + " -- [" + sdf.format(new Date()) + "].jpg"); 
     try { 
      FileOutputStream imageOut = new FileOutputStream(image); 
      src.compress(Bitmap.CompressFormat.JPEG, 100, imageOut); 
      imageOut.close(); 
      savedOnSD = true; 
      return image.getAbsolutePath(); 
     } catch (FileNotFoundException ex) { 
      ex.printStackTrace(); 
      return null; 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    @Override 
    public void onPostExecute(String url){ 
     if(url != null){ 
      Intent intent = new Intent(); 
      intent.setAction(Intent.ACTION_VIEW); 
      if(savedOnSD){ 
       File file = new File(url); 
       if(file.exists()) 
        intent.setDataAndType(Uri.fromFile(file), "image/jpeg"); 
       else 
        return; 
      } 
      else 
       intent.setDataAndType(Uri.parse(url), "image/jpeg"); 

      ActivityA.this.startActivity(intent); 
     } 
     else 
      Toast.makeText(ActivityA.this, getString(R.string.error_compressing), Toast.LENGTH_SHORT).show(); 
    } 

} 
+0

유용한 코드를 보내 주셔서 감사합니다. "imageUrl"이 결국에는 무엇인지 알아낼 수는 없지만 ... – rommex

+0

환영받을 것입니다. 그냥 URL이되어야합니다. 응답을 수정하십시오. 아래 parakmiakos 답을 살펴보십시오. 최종 해결책 인 것 같습니다. – zgc7009

7

감사를 확장하는 ActivityA.class에서이 작업을 실행하는 가정, 당신은 바른 길에 저를 설정합니다. 나는 당신의 코드 중 일부를 사용했고, 이것은 해결하고자하는 다른 누군가를위한 최종 결과이다.

문제는 실제로 응용 프로그램의 로컬 저장소에 이미지를 저장하는 것이 었습니다.

File storedImagePath = generateImagePath("player", "png"); 
if (!compressAndSaveImage(storedImagePath, bitmap)) { 
    return null; 
} 
Uri url = addImageToGallery(context.getContentResolver(), "png", storedImagePath); 

사용되는 세 가지 방법은 여기서

이 경로

private static File getImagesDirectory() { 
    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + IMAGE_DIR);//Environment.getExternalStorageDirectory() 
    if (!file.mkdirs() && !file.isDirectory()) { 
     Log.e("mkdir", "Directory not created"); 
    } 
    return file; 
} 

public static File generateImagePath(String title, String imgType) { 
    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss"); 
    return new File(getImagesDirectory(), title + "_" + sdf.format(new Date()) + "." + imgType); 
} 

압축을 생성하고

public boolean compressAndSaveImage(File file, Bitmap bitmap) { 
    boolean result = false; 
    try { 
     FileOutputStream fos = new FileOutputStream(file); 
     if (result = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)) { 
      Log.w("image manager", "Compression success"); 
     } 
     fos.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return result; 
} 

는 갈레에 추가 저장 StringinsertImage에서 반환

public String addImageToGallery(ContentResolver cr, File filepath) { 
    try { 
     retrun MediaStore.Images.Media.insertImage(cr, filepath.toString(), 
                filepath.getName(), "Image Description"); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 

공예

public Uri addImageToGallery(ContentResolver cr, String imgType, File filepath) { 
    ContentValues values = new ContentValues(); 
    values.put(MediaStore.Images.Media.TITLE, "player"); 
    values.put(MediaStore.Images.Media.DISPLAY_NAME, "player"); 
    values.put(MediaStore.Images.Media.DESCRIPTION, ""); 
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/" + imgType); 
    values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 
    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 
    values.put(MediaStore.Images.Media.DATA, filepath.toString()); 

    return cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 
} 
0

또한 미디어 스토어 MediaStore의 정적 메소드를 사용할 수는 ... 허용 대답에 Uri 객체에 toString()를 호출 한 것과 같은 상태가된다.

나는 이것이 오래된 게시물 인 것을 알고 있지만, 여전히이 방법을 찾는 다른 사람들에게 도움이되기를 바랍니다.