2011-12-19 112 views
61

我有一個圖像庫的應用程序,我希望用戶可以將它保存到他自己的畫廊。 我已經創建了一個單一的聲音「保存」的選項菜單,以允許但問題是...我如何將圖像保存到畫廊?android - 將圖像保存到圖庫

這是我的代碼:

@Override 
     public boolean onOptionsItemSelected(MenuItem item) { 
      // Handle item selection 
      switch (item.getItemId()) { 
      case R.id.menuFinale: 

       imgView.setDrawingCacheEnabled(true); 
       Bitmap bitmap = imgView.getDrawingCache(); 
       File root = Environment.getExternalStorageDirectory(); 
       File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg"); 
       try 
       { 
        file.createNewFile(); 
        FileOutputStream ostream = new FileOutputStream(file); 
        bitmap.compress(CompressFormat.JPEG, 100, ostream); 
        ostream.close(); 
       } 
       catch (Exception e) 
       { 
        e.printStackTrace(); 
       } 



       return true; 
      default: 
       return super.onOptionsItemSelected(item); 
      } 
     } 

我不知道這部分代碼的:

File root = Environment.getExternalStorageDirectory(); 
       File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg"); 

是正確的保存到庫中? 不幸的是,代碼不工作:(

+0

你解決了這個問題嗎?可以請你與我分享 – user3233280 2014-02-22 09:53:05

+0

我也有同樣的問題http://stackoverflow.com/questions/21951558/failed-to-save-image-from-app-assets-folder-to-gallery-folder-in-android/21951643?noredirect = 1#21951643 – user3233280 2014-02-22 09:54:25

+0

對於那些仍然有問題保存文件,這可能是因爲你的url包含非法字符,如「?」,「:」和「 - 」刪除這些,它應該工作。這是外國設備和android模擬器中的常見錯誤。在這裏看到更多關於它:http://stackoverflow.com/questions/11394616/java-io-ioexception-open-failed-einval-invalid-argument-when-saving-a-image – ChallengeAccepted 2014-11-25 21:58:50

回答

137
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription); 

前面的代碼會將圖片添加到圖庫的末尾。如果您想修改日期以使其出現在開頭或任何其他元數據中,請參閱下面的代碼(SK,samkirton)的Cortesy:

https://gist.github.com/samkirton/0242ba81d7ca00b475b9

/** 
* Android internals have been modified to store images in the media folder with 
* the correct date meta data 
* @author samuelkirton 
*/ 
public class CapturePhotoUtils { 

    /** 
    * 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(ContentResolver, Bitmap, String, String) 
    */ 
    public static final String insertImage(ContentResolver cr, 
      Bitmap source, 
      String title, 
      String description) { 

     ContentValues values = new ContentValues(); 
     values.put(Images.Media.TITLE, title); 
     values.put(Images.Media.DISPLAY_NAME, title); 
     values.put(Images.Media.DESCRIPTION, description); 
     values.put(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(Images.Media.DATE_ADDED, System.currentTimeMillis()); 
     values.put(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 = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null); 
       // This is for backward compatibility. 
       storeThumbnail(cr, miniThumb, id, 50F, 50F,Images.Thumbnails.MICRO_KIND); 
      } else { 
       cr.delete(url, null, null); 
       url = null; 
      } 
     } catch (Exception e) { 
      if (url != null) { 
       cr.delete(url, null, null); 
       url = null; 
      } 
     } 

     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 static final 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(Images.Thumbnails.KIND,kind); 
     values.put(Images.Thumbnails.IMAGE_ID,(int)id); 
     values.put(Images.Thumbnails.HEIGHT,thumb.getHeight()); 
     values.put(Images.Thumbnails.WIDTH,thumb.getWidth()); 

     Uri url = cr.insert(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) { 
      return null; 
     } catch (IOException ex) { 
      return null; 
     } 
    } 
} 
+22

這可以保存圖像,但可以保存到圖庫的盡頭,但是當您使用相機拍攝照片時,它會保存在頂部。我如何將圖像保存到圖庫頂部? – 2012-06-12 16:23:37

+25

人們應該總是解釋他們爲什麼downvote – sfratini 2012-07-29 18:02:52

+15

請注意,您還必須將添加到您的manifext.xml中。 – 2012-12-28 22:43:06

9

this course,要做到這一點,正確的做法是:

Environment.getExternalStoragePublicDirectory(
     Environment.DIRECTORY_PICTURES 
    ) 

thios會給你的根路徑爲畫廊目錄

+0

我試過這個新的代碼,但它崩潰了 java.lang.NoSuchFieldError:android.os.Environment.DIRECTORY_PICTURES – 2011-12-19 13:11:39

+0

@Christian:此代碼只適用於android> = 2.2 – 2011-12-19 13:13:27

+0

好的謝謝,所以沒有辦法將圖像放在android <2.2的圖庫上? – 2012-01-03 17:49:09

38

其實,你可以保存你的照片在任何地方。如果你想在一個公共空間來保存,所以任何其他應用程序可以訪問,使用此代碼:

storageDir = new File(
    Environment.getExternalStoragePublicDirectory(
     Environment.DIRECTORY_PICTURES 
    ), 
    getAlbumName() 
); 

圖片不走的專輯。要做到這一點,你需要調用掃描:

private void galleryAddPic() { 
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
    File f = new File(mCurrentPhotoPath); 
    Uri contentUri = Uri.fromFile(f); 
    mediaScanIntent.setData(contentUri); 
    this.sendBroadcast(mediaScanIntent); 
} 

你可以找到更多信息在https://developer.android.com/training/camera/photobasics.html#TaskGallery

+0

這是一個很好的簡單解決方案因爲我們不需要改變整個實現,我們可以爲應用程序創建一個自定義文件夾。 – 2015-10-07 12:48:03

+1

當您只能掃描文件時,發送廣播可能會浪費資源:http://stackoverflow.com/a/5814533/43051。 – 2016-02-03 07:19:04

+0

這是最好的解決方案,謝謝先生! – 2017-02-13 16:44:11

8
private void galleryAddPic() { 
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
    File f = new File(mCurrentPhotoPath); 
    Uri contentUri = Uri.fromFile(f); 
    mediaScanIntent.setData(contentUri); 
    this.sendBroadcast(mediaScanIntent); 
} 
+1

爲我完美工作。 – KNU 2013-12-12 20:41:24

8

我已經嘗試了很多東西,讓在棉花糖和棒棒糖這項工作。 最後我結束了保存的圖像移動到DCIM文件夾中(新的谷歌照片應用程序掃描圖像,只有當他們在這個文件夾顯然裏面)

public static File createImageFile() throws IOException { 
    // Create an image file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") 
     .format(System.currentTimeInMillis()); 
    File storageDir = new File(Environment 
     .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/Camera/"); 
    if (!storageDir.exists()) 
     storageDir.mkdirs(); 
    File image = File.createTempFile(
      timeStamp,     /* prefix */ 
      ".jpeg",      /* suffix */ 
      storageDir     /* directory */ 
    ); 
    return image; 
} 

然後掃描文件,你可以在找到標準代碼Google Developers site too

public static void addPicToGallery(Context context, String photoPath) { 
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
    File f = new File(photoPath); 
    Uri contentUri = Uri.fromFile(f); 
    mediaScanIntent.setData(contentUri); 
    context.sendBroadcast(mediaScanIntent); 
} 

請記住,世界上每一個設備,並從棉花糖開始(API 23),則需要請求WRITE_EXTERNAL_STORAGE給用戶的權限在此文件夾可能不存在。

+1

感謝有關Google相冊的信息。 – 2016-02-03 07:06:41

+1

這是唯一的解決方案。 沒有人提到該文件必須在DCIM文件夾中。 謝謝!!! – 2016-06-28 21:19:18

+0

'Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)'爲我做了詭計。謝謝! – saltandpepper 2017-11-17 11:51:06

1

我來到這裏同樣毋庸置疑的,但對於Xamarin的Android,我已經使用了SIGRIST答案做這個方法救我的文件之後:

private void UpdateGallery() 
{ 
    Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile); 
    Java.IO.File file = new Java.IO.File(_path); 
    Android.Net.Uri contentUri = Android.Net.Uri.FromFile(file); 
    mediaScanIntent.SetData(contentUri); 
    Application.Context.SendBroadcast(mediaScanIntent); 
} 

,它解決了我的問題,THX SIGRIST。我把它放在這裏,因爲我沒有找到Xamarin的這個answare,我希望它可以幫助其他人。

1

在我的情況下,上述的解決方案沒有工作,我必須做到以下幾點:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f))); 
+0

其真的很瞭解這個選項,但不幸的是不適用於一些使用android 6的設備,所以'ContentProvider'更好的解決方案 – user5599807 2017-04-19 21:03:28

0
String filePath="/storage/emulated/0/DCIM"+app_name; 
    File dir=new File(filePath); 
    if(!dir.exists()){ 
     dir.mkdir(); 
    } 

此代碼是的onCreate method.This代碼是用於創建APP_NAME的目錄。 現在,可以使用android中的默認文件管理器應用程序訪問此目錄。 使用此字符串filePath來設置您的目標文件夾。 我相信這種方法也適用於Android 7,因爲我測試過它。因此,它也可以在其他版本的Android上工作。

1

您可以在相機文件夾內創建一個目錄並保存。一旦你完成掃描。它會立即在畫廊中展示你的形象。乾杯!!

  String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()+ "/Camera/Your_Directory_Name"; 
      File myDir = new File(root); 
      myDir.mkdirs(); 
      String fname = "Image-" + image_name + ".png"; 
      File file = new File(myDir, fname); 
      System.out.println(file.getAbsolutePath()); 
      if (file.exists()) file.delete(); 
      Log.i("LOAD", root + fname); 
      try { 
       FileOutputStream out = new FileOutputStream(file); 
       finalBitmap.compress(Bitmap.CompressFormat.PNG, 90, out); 
       out.flush(); 
       out.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      MediaScannerConnection.scanFile(context, new String[]{file.getPath()}, new String[]{"image/jpeg"}, null);