2011-12-19 130 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);