我有一个带有图片库的应用程序,我希望用户可以将其保存到自己的图库中。 我创建了一个带有单个声音“保存”的选项菜单,但问题是......我怎样才能将图像保存到图库中?
这是我的代码:
@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 :(得分:157)
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);
以前的代码会在图库的末尾添加图片。如果您想要修改日期以显示在开头或任何其他元数据,请参阅下面的代码(S-K的Cortesy, samkirton ):
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;
}
}
}
答案 1 :(得分:44)
实际上,您可以在任何地方保存图片。如果要保存在公共空间中,任何其他应用程序都可以访问,请使用以下代码:
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
找到更多信息答案 2 :(得分:16)
我已经尝试过很多东西让它在Marshmallow和Lollipop上运作。 最后,我最终将保存的图片移动到DCIM文件夹(新的Google Photo应用程序扫描图像只有当它们显然位于此文件夹内时)
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);
}
请记住,此文件夹无法存在于世界上的每个设备中,并且从Marshmallow(API 23)开始,您需要向用户请求WRITE_EXTERNAL_STORAGE的权限。
答案 3 :(得分:11)
根据this course,正确的方法是:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
)
这将为您提供图库目录的根路径。
答案 4 :(得分:11)
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);
}
答案 5 :(得分:5)
您可以在相机文件夹中创建目录并保存。完成后扫描一下。它会立即在图库中显示您的图像。干杯!!
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);
答案 6 :(得分:1)
我带着同样的疑问来到这里但是对于Android的Xamarin,我在保存文件后使用了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的这个问题,我希望它可以帮助其他人。
答案 7 :(得分:1)
在我的情况下,上述解决方案不起作用我必须执行以下操作:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
答案 8 :(得分:1)
这对我有用:
private fun saveBitmapAsImageToDevice(bitmap: Bitmap?) {
// Add a specific media item.
val resolver = this.contentResolver
val imageStorageAddress = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val imageDetails = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "my_app_${System.currentTimeMillis()}.jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis())
}
try {
// Save the image.
val contentUri: Uri? = resolver.insert(imageStorageAddress, imageDetails)
contentUri?.let { uri ->
// Don't leave an orphan entry in the MediaStore
if (bitmap == null) resolver.delete(contentUri, null, null)
val outputStream: OutputStream? = resolver.openOutputStream(uri)
outputStream?.let { outStream ->
val isBitmapCompressed =
bitmap?.compress(Bitmap.CompressFormat.JPEG, 95, outStream)
if (isBitmapCompressed == true) {
outStream.flush()
outStream.close()
}
} ?: throw IOException("Failed to get output stream.")
} ?: throw IOException("Failed to create new MediaStore record.")
} catch (e: IOException) {
throw e
}
}
答案 9 :(得分:0)
String filePath="/storage/emulated/0/DCIM"+app_name;
File dir=new File(filePath);
if(!dir.exists()){
dir.mkdir();
}
此代码位于onCreate方法中。此代码用于创建app_name目录。 现在,可以使用android中的默认文件管理器应用程序访问此目录。 在需要的地方使用此字符串filePath来设置目标文件夹。 我确信这个方法也可以在Android 7上运行,因为我测试了它。因此,它也适用于其他版本的android。
答案 10 :(得分:0)
只需在保存完成后扫描您的媒体即可。
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
File filepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File dir = new File(filepath.getAbsolutePath()+"/Pro Scanner/");
if(!dir.exists()){
dir.mkdir();
}
File file = new File(dir,System.currentTimeMillis()+"_Pro_Scanner.png");
try {
outputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
downloadQRCode.setVisibility(View.VISIBLE);
loadingBar.setVisibility(View.INVISIBLE);
}
bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
Toast.makeText(GenerateQRCodeActivity.this, "QR image saved successfully", Toast.LENGTH_SHORT).show();
try {
outputStream.flush();
outputStream.close();
loadingBar.setVisibility(View.INVISIBLE);
downloadDone.setVisibility(View.VISIBLE);
downloadDone.setAnimation(bottomAnimation);
} catch (IOException e) {
downloadQRCode.setVisibility(View.VISIBLE);
loadingBar.setVisibility(View.INVISIBLE);
e.printStackTrace();
}
MediaScannerConnection.scanFile(GenerateQRCodeActivity.this,new String[]{file.getPath()},new String[] {"image/jpeg"},null);
这些代码和大家一样。如果你在这之后尝试下面的代码,它会起作用。你只需要这一行代码:
MediaScannerConnection.scanFile(GenerateQRCodeActivity.this,new String[]{file.getPath()},new String[] {"image/jpeg"},null);
轰隆隆!!!您现在可以在图库中获取您保存的图片。