保存在 sdcard 中的图像不会出现在 Android 的 Gallery 应用程序中

我将一个图像保存到 sdcard,直到我取出 sdcard 并返回它,它才会出现在 Gallery 应用程序中。

你知道为什么吗?

看起来像画廊应用程序有一些缓存,没有更新文件保存..。

实际上,我还想在 Gallery 应用程序中打开刚刚保存的映像,但是没有成功,因为关于这个问题,我的问题是 < br/> 这个

132866 次浏览

The system scans the SD card when it is mounted to find any new image (and other) files. If you are programmatically adding a file, then you can use this class:

http://developer.android.com/reference/android/media/MediaScannerConnection.html

Here is the code for the MediaScannerConnection:

MyMediaConnectorClient client = new MyMediaConnectorClient(newfile);
MediaScannerConnection scanner = new MediaScannerConnection(context, client);
client.setScanner(scanner);
scanner.connect();

newfile is the File object of your new/saved file.

My answer to the original question and to anyone else that may have this problem:

I was having this same problem, images in my app that people saved to the SD card were not showing up in their Gallery immediately. After some searching I found this one line of code inserted after my 'save to sdcard' code that fixed the problem:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

You can also add an Image to the Media Gallery by intent, have a look at the example code to see how it is done:

ContentValues image = new ContentValues();


image.put(Images.Media.TITLE, imageTitle);
image.put(Images.Media.DISPLAY_NAME, imageDisplayName);
image.put(Images.Media.DESCRIPTION, imageDescription);
image.put(Images.Media.DATE_ADDED, dateTaken);
image.put(Images.Media.DATE_TAKEN, dateTaken);
image.put(Images.Media.DATE_MODIFIED, dateTaken);
image.put(Images.Media.MIME_TYPE, "image/png");
image.put(Images.Media.ORIENTATION, 0);


File parent = imageFile.getParentFile();
String path = parent.toString().toLowerCase();
String name = parent.getName().toLowerCase();
image.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
image.put(Images.Media.SIZE, imageFile.length());


image.put(Images.Media.DATA, imageFile.getAbsolutePath());


Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);

there is an app in the emulator that says - ' Dev Tools'

click on that and select ' Media Scanning'.. all the images ll get scanned

My code for MyMediaConnectorClient:

public class MyMediaConnectorClient implements MediaScannerConnectionClient {


String _fisier;
MediaScannerConnection MEDIA_SCANNER_CONNECTION;


public MyMediaConnectorClient(String nume) {
_fisier = nume;
}


public void setScanner(MediaScannerConnection msc){
MEDIA_SCANNER_CONNECTION = msc;
}


@Override
public void onMediaScannerConnected() {
MEDIA_SCANNER_CONNECTION.scanFile(_fisier, null);
}


@Override
public void onScanCompleted(String path, Uri uri) {
if(path.equals(_fisier))
MEDIA_SCANNER_CONNECTION.disconnect();
}
}

Let your activity implement 'MediaScannerConnectionClient' and add this to your activity:

private void startScan()
{
if(conn!=null) conn.disconnect();
conn = new MediaScannerConnection(YourActivity.this,YourActivity.this);
conn.connect();
}


@Override
public void onMediaScannerConnected() {
try{
conn.scanFile(yourImagePath, "image/*");
} catch (java.lang.IllegalStateException e){
}
}


@Override
public void onScanCompleted(String path, Uri uri) {
conn.disconnect();
}

Use this after saving the image

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Here I am sharing code that can load image in form of bitmap from and save that image on sdcard gallery in app name folder. You should follow these steps

  1. Download Image Bitmap first





private Bitmap loadBitmap(String url) {
try {
InputStream in = new java.net.URL(url).openStream();
return BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}



  1. Please also provide following permission in your AndroidManifest.xml file.



uses-permission android:name="android.permission.INTERNET"
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"



  1. Here is whole code that is written in Activty in which we want to perform this task.





void saveMyImage(String appName, String imageUrl, String imageName) {


Bitmap bmImg = loadBitmap(imageUrl);
File filename;
try {
String path1 = android.os.Environment.getExternalStorageDirectory()
.toString();
File file = new File(path1 + "/" + appName);
if (!file.exists())
file.mkdirs();
filename = new File(file.getAbsolutePath() + "/" + imageName
+ ".jpg");
FileOutputStream out = new FileOutputStream(filename);
bmImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, appName);
image.put(Images.Media.DISPLAY_NAME, imageName);
image.put(Images.Media.DESCRIPTION, "App Image");
image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
image.put(Images.Media.MIME_TYPE, "image/jpg");
image.put(Images.Media.ORIENTATION, 0);
File parent = filename.getParentFile();
image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
.toLowerCase().hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
.toLowerCase());
image.put(Images.Media.SIZE, filename.length());
image.put(Images.Media.DATA, filename.getAbsolutePath());
Uri result = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
Toast.makeText(getApplicationContext(),
"File is Saved in  " + filename, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}


}



  1. Hope that it can solve your whole problem.

A simpler solution is to use the static convenience method scanFile():

File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);

where this is your activity (or whatever context), the mime-type is only necessary if you are using non-standard file extensions and the null is for the optional callback (which we don't need for such a simple case).

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Does not seem to work on KITKAT. It throws permission denial exception and crashes the app. So for this, I have done the following,

String path = mediaStorageDir.getPath() + File.separator
+ "IMG_Some_name.jpg";
CameraActivity.this.sendBroadcast(new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
.parse("file://" + path)));

Hope it helps.

Gallery refresh including Android KITKAT

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}

this work with me

File file = ..... // Save file


context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
 File folderGIF = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/newgif2");    //path where gif will be stored
success = folderGIF.mkdir();    //make directory
String finalPath = folderGIF + "/test1.gif";  //path of file
.....
/* changes in gallery app if any changes in done*/
MediaScannerConnection.scanFile(this,
new String[]{finalPath}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});

You need to give permissions to the Gallery app. Just long press the gallery app icon in the home screen and tap on 'APP INFO' that pops up at the top of the screen. Doing it will show the gallery app settings. Now go in Permissions tab and enable the storage, camera permissions by toggling it. Now go to your native gallery app and you will get the your saved images.

This will aslo solve your problem if your image in gallery are not showing instead they might showing a 404 type bitmap in midle. please add a the tags that are in my code with your image because there must some meta data in order to show image in gallery.

      String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+
getString(R.string.directory) + System.currentTimeMillis() + ".jpg";


new File(resultPath).getParentFile().mkdir();


try {
OutputStream fileOutputStream = new FileOutputStream(resultPath);
savedBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e2) {
e2.printStackTrace();
}
savedBitmap.recycle();


File file = new File(resultPath);
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Photo");
values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis ());
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
values.put("_data", resultPath);


ContentResolver cr = getContentResolver();
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);








return  resultPath;

Try this one, it will broadcast about a new image created, so your image visible. inside a gallery. photoFile replace with actual file path of the newly created image

private void galleryAddPicBroadCast() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(photoFile);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}