I got a camera application where, after the user takes an image, I save it to the internal storage in a directory I have made.
All that works fine, the image gets saved there and I can load it and show afterwards, but I'm having trouble saving the image to the Android gallery too.
What I want to, is after saving the image to the internal directory, copy it to the gallery.
I have tried this:
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.Images.Media.SIZE, file.length());
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Where the file is the image I saved in internal storage.
With this method all I get is a broken image in the gallery.
copy it to gallery or show it in android gallery?
if you want the image show in android gallery? you can do this by scan media, this is how to scan:
Uri uri = Uri.fromFile(file);
Intent scanFileIntent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
sendBroadcast(scanFileIntent);
if you want just copy the file just do this :
in = new FileInputStream(sourceFile);
out = new FileOutputStream(destFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
You can use this method for saving image:
public void saveToSD(Bitmap outputImage){
File storagePath = new File(Environment.getExternalStorageDirectory() + "/MyPhotos/");
storagePath.mkdirs();
File myImage = new File(storagePath, Long.toString(System.currentTimeMillis()) + ".jpg");
try {
FileOutputStream out = new FileOutputStream(myImage);
outputImage.compress(Bitmap.CompressFormat.JPEG, 80, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
This is what might help :
Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));
After getting the path u can store the image by this :
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.Images.Media.SIZE, file.length());
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
context.getContentResolver().insert(imageFile, values);
Hope this helps.
Related
I am storing video in internal storage but the saved video is not showing up in gallery. To see that first i have to open my file manager then come back to gallery. I stored the same video in android Q using media store but in
ContentResolver contentResolver = getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "videoFileName");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_MOVIES);
Uri finalUriPath = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
File sourceLocation = new File(finalUri.getPath());
InputStream in = new FileInputStream(sourceLocation);
FileOutputStream out = new FileOutputStream(String.valueOf(finalUriPath));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
contentValues.clear();
contentValues.put(MediaStore.Video.Media.IS_PENDING, 0);
StatusShowerActivity.this.getContentResolver().update(finalUriPath, contentValues, null, null);
Toast.makeText(StatusShowerActivity.this, "Saved", Toast.LENGTH_SHORT).show();
Exception got from Catch in android 9
java.io.FileNotFoundException: null (Read-only file system)
I created an example app, which takes pictures and saves them, by following this tutorial. Unfortunately the "Add the photo to a gallery" part is not working. I get no error in logcat. The image is just simply not visible in the gallery. Original code:
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
I tried to solve it, by calling MediaScannerConnection.scanFile:
MediaScannerConnection.scanFile(
getApplicationContext(),
new String[]{f.getAbsolutePath()},
null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.v("MyActivity", "file " + path + " was scanned successfully: " + uri);
}
});
I get this result in logcat:
file /storage/emulated/0/Android/data/com.example.myapplication/files/Pictures/JPEG_20200804_104708_4760605263689075696.jpg was scanned successfully: content://media/external/file/3524
Unfortunately the picture is still not available in the gallery. What do I wrong? How is it possible to debug something like this?
Your link tells you:
Note: If you saved your photo to the directory provided by getExternalFilesDir(), the media scanner cannot access the files because they are private to your app..
Well everybody -until Q- can get access to that dir but apparently the media scanner closes its eyes for it.
But strange that an uri is returned. Try to open it.
You can use this to save the image to the gallery and it will be visible immediately after it is saved
String name = "image_name";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
ContentResolver resolver = getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/" + "App Name");
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream outputStream = resolver.openOutputStream(Objects.requireNonNull(imageUri));
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.PNG, quality, outputStream);
outputStream.flush();
outputStream.close();
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, imageUri));
}catch (Exception e){
e.printStackTrace();
Snackbar.make(v, "Unable to Save image " + e.getMessage(), Snackbar.LENGTH_SHORT).show();
}
}else {
String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/App Name";
File dir = new File(fullPath);
if (!dir.exists()) {
dir.mkdirs();
}
File imageFile = new File(fullPath, name);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.PNG, quality, outputStream);
outputStream.flush();
outputStream.close();
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageFile)));
}
I can currently save an image in my app using the Es File explorer to a shared windows folder.
But what I want to know is, how can I eliminate the process of selecting the folder and specify it in code?
public void SaveToNetwork() {
Intent shareIntent = new Intent(Android.Content.Intent.ActionSend);
shareIntent.SetType("*/*");
shareIntent.PutExtra(Android.Content.Intent.ExtraStream, Android.Net.Uri.FromFile(new File(App._dir, App._file.Name)));
shareIntent.SetPackage("com.estrongs.android.pop");
StartActivity(shareIntent);
}
I don't want to use the file explorer. I just want to directly save it to the folder, or at least change the default selected folder to the correct one.
android provides File class and outpustream class for this purpose following is a sample code which recives the bitmap and save it to specified folder and then add you image to gallery content provider
private String savePic(Bitmap bitmapImage) {
try {
//bitmapImage=drawView.getmCanvasBitmap();
File dir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"youfoldername");
dir.mkdir();
Calendar c = Calendar.getInstance();
if (dir.isDirectory()) {
String path = dir.getAbsolutePath() + "/youfilename"
+ c.getTimeInMillis() + ".Jpg";
FileOutputStream fos = new FileOutputStream(path);
// Use the compress method on the BitMap object to write image
// to
// the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA, path);
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/Jpg");
intent.putExtra(android.content.Intent.EXTRA_STREAM,
Uri.parse("file://" + path));
startActivity(intent);
return path;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
I am writing an app to share image.
I wrote the code but getting problems.
What I am doing
1: Saving the image temporarily in Internal Stoarge
2: Passing the URI to share the image.
Image is successfully saved in internal storage but not getting share on whatsapp.
When I share it on whatsapp, Whatsapp get opens, I select recipient, whatsapp processes it and says "Retry".
Code:
public void shareImage(View V)
{
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.download);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/jpeg");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
icon.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "myDownloadedImage.jpg");
try
{
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
} catch (IOException e) {
Toast.makeText(this, "Some error in Writing"+e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
Uri downloadLocation=Uri.fromFile(file);
share.putExtra(Intent.EXTRA_STREAM, downloadLocation);
startActivity(Intent.createChooser(share, "Share Image"));
}
Image succesfully get saved on internal storage but not getting shared on whatsapp.
The screenshot is below. We can see images are not shared successfully.
Use below code to fetch image and make uri:
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "share_image_" + System.currentTimeMillis() + ".png");
file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = Uri.fromFile(file);
Now pass the bmpUri in:
shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
This should make your image share.
I have a piece of code which basically crops an image selected by the user and is supposed to overwrite the image "CurrentProfilePic.jpg" with the new image.It does so by first deleting the image if it exists and then creating it again.but the image doesnt get deleted.So the no. of times the code is run, that many no. of images are created WITH THE SAME NAME. I used logs to see if the file.delete(); returns true, and it does return true.
public void cropImage(View v) {
bitmap=cropImageView.getCroppedImage();
boolean imageSaved = false;
String imageName="CurrentProfilePic";
//to save current image to directory
if (bitmap != null && !bitmap.isRecycled()) {
File storagePath = new File(
Environment.getExternalStorageDirectory() + "/SimpleMessaging/");
if (!storagePath.exists()) {
storagePath.mkdirs();
}
File temp= new File(Environment.getExternalStorageDirectory() + "/SimpleMessaging/CurrentProfilePic.jpg");
if(temp.exists()){
boolean x= temp.delete();
Log.d("PICS", "Inside if exist of pic");
if(x)
Log.d("bool", "x true");
else
Log.d("bool", "x false");
}
FileOutputStream out = null;
File imageFile = new File(storagePath, String.format("%s.jpg",
imageName));
try {
out = new FileOutputStream(imageFile);
imageSaved = bitmap.compress(Bitmap.CompressFormat.JPEG,
100, out);
out.flush();
out.close();
} catch (Exception e) {
Log.e("SaveToSD ", "Unable to write the image to gallery" + e);
}
ContentValues values = new ContentValues(3);
values.put(Images.Media.TITLE, imageName);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put("_data", imageFile.getAbsolutePath());
getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
}
startActivity(new Intent(getBaseContext(), EditProfilePic.class));
finish();
}
The thing to stress upon is that the latest image is overwritten on each of those files, but their sizes are unchanged, their original sizes.
Delete getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values); and its supporting code. Use MediaScannerConnection or ACTION_MEDIA_SCANNER_SCAN_FILE to index your file.