I have this weird problem that seems to only happen on one of my tablets that runs android 6.
I have this chunk of code to add a photo taken from the camera to a recycler view
1) I create a file object onto device (this is the photo)
2) I get the uri from that file
3) I create an intent passing in that uri as such
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getActivity().getPackageManager()) != null)
// this is done in a fragment, everything else below is in the if statement
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(take_photo_intent, option_int);
I know MediaStore.EXTRA_OUTPUT does NOT return anything to onActivityResult, but instead writes to the uri you pass in.
now inside of onActivityResult I have
Log.i("PHOTO", "path--->" + uri.getPath());
So I want to mention, when the program works or DOESN'T work, the uri ALWAYS has a path, one example of one of the paths is
/storage/emulated/0/data/20161212_175150797715155.jpg
so to continue on in the onActivityResult
5) create bitmap based on uri path to use it later on
BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inPreferredConfig = Bitmap.Config.ARGB_8888;
*************** problem here ****************
Bitmap temp = BitmapFactory.decodeFile(uri.getPath());
the temp bitmap returns null SOME of the time, let me explain
when I take the photo, the asus android 6 tablet shows two buttons when you take the photo, one button to discard the photo, another to keep the photo.. here is the weird part, ON THAT screen, if I wait like 5-15 seconds before pressing the button to keep the photo, the bitmap will NOT be null, but if I take a photo and immediately accept it, the a bitmap is null.
now as said before, does not matter how i do it, if the bitmap comes out null, or it does not come out null, it always has a path before passing it into the bitmapdecode function (which is weird)
I have no clue if it is the camera software, the physical camera hardware, an android 6 bug....
I also want to say, I am not sure if this is the best code but it has worked on 4 other android devices ( phones, tablets) it is just this ONE tablet that is a asus and only one with android 6, it works fine with everything else
EDIT:
I tried this as suggested
Bitmap TEMP = null;
try {
TEMP = BitmapFactory.decodeStream(getContext().getContentResolver().openInputStream(uri));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
with no luck
EDIT 2:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap TEMP = BitmapFactory.decodeFile(uri.getPath());
Bitmap bitmap_image = ThumbnailUtils.extractThumbnail(TEMP, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
if (bitmap_image == null)
Log.i("PHOTO", "BITMAP THUMBNAIL NULL");
setAdapterBitmap(bitmap_image, uri.getPath(), 1);
}
}
SOLUTION:
I had this method to create a File object and turn it into a URI Object
private File createFileForImage() throws IOException {
String file_creation_time = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String image_file_name = DIR_NAME + "_" + file_creation_time;
File storage_dir = new File(String.valueOf(Environment.getExternalStorageDirectory()), DIR_NAME);
if (!storage_dir.exists())
{
if(!storage_dir.mkdir())
{
return null;
}
}
return File.createTempFile(image_file_name, ".jpg", storage_dir);
}
then I used this after it was return
uri = Uri.fromFile(image_file);
but for some reason this was working but it had a slight delay that cause bizarre behavior as stated in the original post
Jan Kaufmann suggestion seem to work, to i made some small modifications
private Uri getOutputMediaUriFromFile()
{
File photo_storage_dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), DIR_NAME);
if (!photo_storage_dir.exists())
{
if (!photo_storage_dir.mkdirs())
{
return null;
}
}
String file_creation_time = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String image_file_name = "ipr" + "_" + file_creation_time;
File photo = new File(photo_storage_dir.getPath() + File.separator + image_file_name + ".jpg");
return Uri.fromFile(photo);
}
It does essentially the same thing, but for some reason this doesn't cause the issue I was having, at least not with my testing.
I am glad this now works but can anyone explain why this worked?
Make sure the image size is not too big. If needed,subsample the original image to save memory
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize = 8;
Make sure you have permission for
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Or try constructing your URI into something like this:
Uri uri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE, "myimage"); where getOutputMediaFileUri is :
private File getOutputMediaFile(int type, String imgname) {
// External sdcard location
//public static String DIRECTORY_PICTURES = "Pictures";
File mediaStorageDir = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + imgname + ".jpg");
} else {
return null;
}
return mediaFile;
}
Try this dude:
TEMP = MediaStore.Images.Media.getBitmap(context.getContentResolver(), YOUR_URL);
If this is not work, I guess that you didn't create a temp file to save the image.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try{
GEY_FILE;
}catch (Exception ex){
Log.i(TAG, "run: " + ex);
}
}
}, 15000);
Related
I'm building an app that require method to take picture from in-app camera, but for some Android devices (old device or low ram), it's quite freeze when taking picture triggered. Is there any code i can modify or optimize to make user experience feels better?
//this function trigger to take picture (or screenshot) from user screen
private void captureImage() {
mPreview.setDrawingCacheEnabled(true);
final Bitmap[] drawingCache = {Bitmap.createBitmap(mPreview.getDrawingCache())};
mPreview.setDrawingCacheEnabled(false);
mCameraSource.takePicture(null, bytes -> {
int orientation = Exif.getOrientation(bytes);
Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap picture = rotateImage(temp, orientation);
assert picture != null;
Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(), mGraphicOverlay.getHeight(), picture.getConfig());
Canvas canvas = new Canvas(overlay);
Matrix matrix = new Matrix();
matrix.setScale((float) overlay.getWidth() / (float) picture.getWidth(), (float) overlay.getHeight() / (float) picture.getHeight());
// mirror by inverting scale and translating
matrix.preScale(-1, 1);
matrix.postTranslate(canvas.getWidth(), 0);
Paint paint = new Paint();
canvas.drawBitmap(picture, matrix, paint);
canvas.drawBitmap(drawingCache[0], 0, 0, paint);
//this function to save picture taken and put it on app storage cache
try {
String mainpath = getApplicationContext().getFilesDir().getPath() + separator + "e-Presensi" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success" : "Failed");
//this function to get directory path of saved photo
String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
String namafotoo = "photo_" + getPhotoTime() + ".jpg";
filePath = path;
namafoto = namafotoo;
SessionManager.createNamaFoto(namafoto);
File captureFile = new File(path);
boolean sucess = captureFile.createNewFile();
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", sucess ? "Success" : "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
overlay.compress(Bitmap.CompressFormat.WEBP, 60, stream);
stream.flush();
stream.close();
if (!picture.isRecycled()) {
picture.recycle();
}
if (drawingCache[0] != null && !drawingCache[0].isRecycled()) {
drawingCache[0].recycle();
drawingCache[0] = null;
}
mPreview.setDrawingCacheEnabled(false);
uploadPicture();
finish();
} catch (IOException e) {
e.printStackTrace();
}
});
}
Thanks for your help.
In general, I would advise you to step through your code and look at large memory resources you're generating on each line and consider setting those to null aggressively as you move throughout the method if you're done.
For example, you have a variable called temp which is size "Y" bytes that you appear to rotate and then never use temp after that. If picture is a rotated copy of temp then you have now used 2Y bytes of memory to keep temp and picture. I suspect if you simply set temp to null after creating picture, you might free up half that memory that your older/slower phones are going to badly need.
Take that same concept and follow through with the rest of your method to see if you can find other optimizations. Basically anywhere you're creating a copy of the image data you're not going to use, you should immediately set it to null so the garbage collector can throw it away aggressively.
Firt you need some variables:
byte[] byteArray_IMG;
String currentPhotoPath;
static final int REQUEST_TAKE_PHOTO = 1;
ImageView imageView; // maybe you need show the photo before send it
Then define the method to take the photo:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(),Error takin the photo",Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
path_img = photoFile.toString();
Uri photoURI = FileProvider.getUriForFile(this,"com.app.yournmamepackage.fileprovider" , photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Create the method to create the file image
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
Override the activity result to:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
/* Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byteArray_IMG = stream.toByteArray();*/
MediaScannerConnection.scanFile(this, new String[]{path_img}, null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.i("path",""+path);
}
});
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap imageBitmap = BitmapFactory.decodeFile(path_img);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 14, stream);
imageView.setImageBitmap(imageBitmap);
byteArray_IMG = stream.toByteArray();
}
}
Remember this is very important
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 25, stream)
// 25 is photo quality 0-100
Then you can upload the picture usin an asynchronous process
Firstly Initialize these variables above onCreate() method in your activity/fragment
val FILE_NAME:String="photo.jpg" //give any name with.jpg extension
private var imageuri: Uri?=null
val REQUEST_IMAGE=111
Now open camera
val intent: Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
photofile = getphotofile(FILE_NAME)
imageuri = activity?.let { it1 -> FileProvider.getUriForFile(it1, "//your package name here//.fileprovider", photofile) } //put your package name
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri)
startActivityForResult(int, REQUEST_IMAGE)
onActivityResult() method
if(requestCode==REQUEST_IMAGE && resultCode == Activity.RESULT_OK){
val progressdialog: ProgressDialog = ProgressDialog(activity)
progressdialog.setTitle("Sending Image....")
progressdialog.show() //start your progressdialog
val ref= FirebaseDatabase.getInstance().reference
val messagekey=ref.push().key //create a key to store image in firebase
var bmp: Bitmap?=null
try {
bmp=MediaStore.Images.Media.getBitmap(activity?.contentResolver,imageuri) //get image in bitmap
} catch (e: IOException) {
e.printStackTrace();
}
val baos= ByteArrayOutputStream()
bmp!!.compress(Bitmap.CompressFormat.JPEG,50,baos) //compress the quality of image to 50 from 100
val fileinBytes: ByteArray =baos.toByteArray()
val store: StorageReference = FirebaseStorage.getInstance().reference.child("Chat Images/") //create a child reference in firebase
val path=store.child("$messagekey.jpg") //store a message in above reference with the unique key created above with .jpg extension
val uploadTask: StorageTask<*>
uploadTask=path.putBytes(fileinBytes) //it will upload the image to firebase at given path
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot, Task<Uri>> { task ->
if (!task.isSuccessful) {
task.exception?.let {
throw it
}
Toast.makeText(activity, "Upload Failed", Toast.LENGTH_SHORT).show()
}
return#Continuation path.downloadUrl
}).addOnCompleteListener { task->
if(task.isSuccessful){
url=task.result.toString() //get the url of uploaded image
//Do what you want with the url of your image
progressdialog.dismiss()
Toast.makeText(activity, "Image Uploaded", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener { e->
progressdialog.dismiss()
Toast.makeText(activity, "Failed " + e.message, Toast.LENGTH_SHORT)
.show();
}
uploadTask.addOnProgressListener { task->
var progress:Double=(100.0*task.bytesTransferred)/task.totalByteCount
progressdialog.setMessage("Sending ${progress.toInt()}%") //this will show the progress in progress bar 0-100%
}
}
I'm making a simple notebook app, in which a note can have an image attached to it. I can take a photo just fine, and after the photo has been taken, it is correctly displayed in an imageview inside the note. After the note has been saved, the path to the photo is saved in a database. The path is correctly saved. Next, when the user opens the note, the path is correctly found in the database -- however, I am not able to load it into the imageview. Rather, the imageview turns white. As I manually take a look into the folder where the image is supposed to be saved, I see that the image isn't being saved to the phone or SD card at all, and I have no idea how to save it. I've been looking all over the internet and StackOverflow, but haven't found a solution.
public void onIcTakePhotoClick(View icon) {
File imageFile = null;
Intent takePictureIntent;
try {
imageFile = ImageHelper.createImageFile(this);
} catch (IOException e) {
e.printStackTrace();
}
if (imageFile != null) {
mImagePath = imageFile.getAbsolutePath();
//mImagePath = ImageHelper.getImagePath(imageFile);
takePictureIntent = ImageHelper.dispatchTakePictureIntent(this, imageFile);
startActivityForResult(takePictureIntent, ImageHelper.REQUEST_IMAGE_CAPTURE);
} else {
// error message
}
}
All of the above (creating a file, a path, and an intent) work well:
public static File createImageFile(Context context) throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return image;
}
public static Intent dispatchTakePictureIntent(Context context, File photoFile) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
// Continue only if the File was successfully created
Uri photoURI = FileProvider.getUriForFile(context,
"com.bergdahl.notebook.fileprovider",
photoFile);
//takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
return takePictureIntent;
}
return null;
}
The filepath ends up looking like this: "/storage/emulated/0/Android/data/com.myname.notebook/files/Pictures/JPEG_20160824_213643_135920553.jpg". Next I get the result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ImageHelper.REQUEST_IMAGE_CAPTURE: {
if (resultCode == RESULT_OK) {
ImageHelper.handleCameraPhoto(this, imageView, mImagePath);
}
break;
}
}
}
In which I use methods created by the Android team (https://developer.android.com/training/camera/photobasics.html):
public static void handleCameraPhoto(Activity context, ImageView imageView, String imagePath) {
if (imagePath != null) {
ImageHelper.setPic(imagePath, imageView);
ImageHelper.galleryAddPic(context, imagePath);
}
}
public static void setPic(String imagePath, ImageView imageView) {
/* There isn't enough memory to open up more than a couple camera photos */
/* So pre-scale the target bitmap into which the file is decoded */
/* Get the size of the ImageView */
int targetW = imageView.getWidth();
int targetH = imageView.getHeight();
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/* Figure out which way needs to be reduced less */
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
/* Associate the Bitmap to the ImageView */
imageView.setImageBitmap(bitmap);
imageView.setVisibility(View.VISIBLE);
}
public static void galleryAddPic(Activity context, String imagePath) {
Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
File f = new File(imagePath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
context.sendBroadcast(mediaScanIntent);
}
And finally, the code for opening up the note later:
if (mNote.getFilePath() != null) {
mImagePath = mNote.getFilePath();
//ImageHelper.handleCameraPhoto(this, imageView, mNote.getFilePath());
//File file = new File(mImagePath);
//imageView.setImageDrawable(Drawable.createFromPath(mImagePath));
//Uri uri = Uri.parse("file:" + mNote.getFilePath());
//imageView.setImageURI(uri);
}
In the manifest, I've specified the permission for writing to external storage. So, to reiterate, I need help figuring out how to save the image that I've taken onto the device, so that I can later load it into an imageview next time the user opens the note. Thank you in advance for the help!
EDIT: I tried the image.createNewFile()-method, but the outcome is sadly the same. The boolean test is true.
public static File createImageFile(Context context) throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
/*
File image = File.createTempFile(
imageFileName,
".jpg",
storageDir
);
*/
File image = new File(storageDir, imageFileName + ".jpg");
if (!image.exists()) {
try {
boolean test = image.createNewFile();
Log.d("createImageFile", test + "");
} catch (IOException e) {
e.printStackTrace();
}
}
return image;
}
EDIT again: The image now correctly shows up on an emulator, but it doesn't work on my actual device. The emulator runs 6.0, my device 6.0.1. My device has granted permissions and has external storage. I've been trying to change the directory, but to no success.
Try to replace
mImagePath = imageFile.getAbsolutePath();
with
mImagePath = "file:" + imageFile.getAbsolutePath();
With Android 6 you won't have the read/write permission after installing even if you have declared it in your manifest. You have to ask for it first at runtime:
https://developer.android.com/training/permissions/requesting.html
For testing purposes you can give your app the permissions in the app settings menu without implementing the query.
add the Permission runtime..
if (Build.VERSION.SDK_INT >= 23)
{
if (checkPermission())
{
// Code for above or equal 23 API Oriented Device
// Create a common Method for both
///take camera caputure code
} else {
requestPermission();
}
}
else
{
// Code for Below 23 API Oriented Device
// Create a common Method for both
}
Now adding checkPermission() and requestPermission()
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(Your_Activity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void requestPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(Your_Activity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(Your_Activity.this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(Your_Activity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("value", "Permission Granted, Now you can use local drive .");
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
break;
}
}
I am following Google's Taking Photos Simply tutorial, but it is failing on the temp file creation with an java.io.IOException: open failed: EACCES (Permission denied).
Here is my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pricez.fastshop_android" >
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<uses-feature android:required="true" android:name="android.hardware.camera"/>
<!-- Rest of file... -->
</manifest>
So, I guess that at least this is correct.
Here is the relevant code of my activity:
private String mCurrentPhotoPath;
private static final int REQUEST_TAKE_PHOTO = 1;
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "/JPEG_" + timeStamp + "_"; // I forgot from where I got this, but it was from some SO question that tried to deal with a similar problem
File absoluteFileDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsoluteFile(); // Same as above
Log.i("createImageFile", "absoluteFileDir.getAbsolutePath(): " + absoluteFileDir.getAbsolutePath()); // I/createImageFile﹕ absoluteFileDir.getAbsolutePath(): /storage/sdcard/Android/data/-redacted-/files/Pictures
File image = File.createTempFile(imageFileName, ".jpg", absoluteFileDir);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
public void takePhoto(View view) {
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Toast.makeText(this, "External SD card not mounted", Toast.LENGTH_LONG).show();
return;
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile;
try {
photoFile = createImageFile();
} catch (IOException e) {
Log.e("takePhoto", "IOException", e);
return;
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
// Get the dimensions of the View
ImageView imgv = (ImageView)findViewById(R.id.imgPreview);
int targetW = imgv.getWidth();
int targetH = imgv.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
//
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
imgv.setImageBitmap(bitmap);
}
}
EDIT 1:
I'm running this on a emulator, with SDK level 19.
EDIT 2:
If I delete the folders by hand, the getExternalStorageDirectory starts working fine. I'm leaving this question open because it's not really a fix. If everything keeps working in my code, I'm going to close in a few days.
I have no idea why (my guess is that something in the file locks has silently gone horribly wrong), but it started working when I deleted and recreated the folder (Kudos to #greenapps, would upvote if I could). What I can do at this point is to think how to recover somehow.
I don't think deleting the folder is the actual solution, but I have to move on at this point.
Plus, the situation might not present itself in an actual device.
How know that subject is well documented and I have read a lot on that issue, but I still have the following problem: when I take a picture with my app and click on "validate" button, nothing occur. The aime of what I am doing: passing to onActivityReult function not only the thumbnail, but the "whole" picture taken by the camera.
Here is the listener as defined for the "take a picture" button:
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "CameraTest");
mediaStorageDir.mkdir(); // make sure you got this folder
Log.i("Report",mediaStorageDir.toString());
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
try
{
//create directories and the file
mediaFile.getParentFile().mkdirs();
mediaFile.createNewFile();
} catch (IOException e) {
Log.e("Report", "create error for file "+mediaFile);
e.printStackTrace();
}
mFileUri = Uri.fromFile(mediaFile);
Log.i("Report","Uri: "+mFileUri);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);// this line causes issue - onActivityResult not called...
startActivityForResult(intent, CAMERA_PIC_REQUEST);
}
});
and here is the onActivityResult method... that is never called (and that is not declared in the onClickListener method):
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("Report", "1");
if (resultCode == Activity.RESULT_OK) {
if (requestCode == CAMERA_PIC_REQUEST) {
try {
String[] projection = {
MediaStore.Images.Thumbnails._ID, // The columns we want
MediaStore.Images.Thumbnails.IMAGE_ID,
MediaStore.Images.Thumbnails.KIND,
MediaStore.Images.Thumbnails.DATA };
String selection = MediaStore.Images.Thumbnails.KIND + "=" +
MediaStore.Images.Thumbnails.MINI_KIND;
String sort = MediaStore.Images.Thumbnails._ID + " DESC";
Cursor myCursor = this.managedQuery(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, selection, null, sort);
Log.d("Report", "3");
long imageId = 0l;
long thumbnailImageId = 0l;
String thumbnailPath = "";
try {
myCursor.moveToFirst();
imageId = myCursor
.getLong(myCursor
.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
thumbnailImageId = myCursor
.getLong(myCursor
.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
thumbnailPath = myCursor
.getString(myCursor
.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
} finally {
myCursor.close();
}
String[] largeFileProjection = {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA };
String largeFileSort = MediaStore.Images.ImageColumns._ID
+ " DESC";
myCursor = this.managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
largeFileProjection, null, null, largeFileSort);
String largeImagePath = "";
try {
myCursor.moveToFirst();
// This will actually give yo uthe file path location of the
// image.
largeImagePath = myCursor
.getString(myCursor
.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
mImageCaptureUri = Uri.fromFile(new File(
largeImagePath));
} finally {
// myCursor.close();
}
Uri uriLargeImage = Uri.withAppendedPath(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
String.valueOf(imageId));
Uri uriThumbnailImage = Uri.withAppendedPath(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
String.valueOf(thumbnailImageId));
Bitmap thumbnail = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uriThumbnailImage);
Bitmap image = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uriLargeImage);
But, as said in the title, onActivityResult is not called. Could you please find out why? Because I have tried almost everything I have found on that subject but I should have missed something.
Thanks !
check if you have declared the right permissions in the AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
and be sure the file you want to write into exists:
add this below puc_img = new File(photo,"Puc_Img.jpg");
try
{
//create directories and the file
puc_file.getParentFile().mkdirs();
puc_file.createNewFile();
} catch (IOException e) { }
It's not clear from your code but you could be declaring onActivityResult within your onClickListener. If that's true you need to move it.
Take a look at this answer:
OnActivityResult ()
Ok, to solve that issue, I used some "trick" detailed here:
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "CameraTest");
mediaStorageDir.mkdir(); // make sure you got this folder
Log.i("Report",mediaStorageDir.toString());
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
try
{
//create directories and the file
mediaFile.getParentFile().mkdirs();
mediaFile.createNewFile();
} catch (IOException e) {
Log.e("Report", "create error for file "+mediaFile);
e.printStackTrace();
}
tmpFilePath = mediaFile.getPath();
mFileUri = Uri.fromFile(mediaFile);
Log.i("Report","Uri: "+mFileUri);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
}
});
So then, I am recovering the file stored in the tmpFilePath, by using that method in the onActivityResult function:
Bitmap image = BitmapFactory.decodeFile(this.tmpFilePath);
And... It's working fine. I still have some issues when sending the file to the WS but that very question have been solved by that piece of code. Thanks for the help, you put me on the track :)
i have an app with a gallery of images and i want that the user can save it into his own gallery.
I've created an option menu with a single voice "save" to allow that but the problem is...how can i save the image into the gallery?
this is my code:
#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);
}
}
i'm not sure of this part of code:
File root = Environment.getExternalStorageDirectory();
File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");
is it correct to save into the gallery?
unfortunately the code doesn't work :(
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);
The former code will add the image at the end of the gallery. If you want to modify the date so it appears at the beginning or any other metadata, see the code below (Cortesy of S-K, 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;
}
}
}
Actually, you can save you picture at any place. If you want to save in a public space, so any other application can access, use this code:
storageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
),
getAlbumName()
);
The picture doesn't go to the album. To do this, you need to call a scan:
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);
}
You can found more info at https://developer.android.com/training/camera/photobasics.html#TaskGallery
I've tried a lot of things to let this work on Marshmallow and Lollipop.
Finally i ended up moving the saved picture to the DCIM folder (new Google Photo app scan images only if they are inside this folder apparently)
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;
}
And then the standard code for scanning files which you can find in the 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);
}
Please remember that this folder could not be present in every device in the world and that starting from Marshmallow (API 23), you need to request the permission to WRITE_EXTERNAL_STORAGE to the user.
According to this course, the correct way to do this is:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
)
This will give you the root path for the gallery directory.
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);
}
You can create a directory inside the camera folder and save the image. After that, you can simply perform your scan. It will instantly show your image in the gallery.
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);
Here's what worked for me:
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
}
}
Note: For Build.VERSION.SDK_INT < 29, the image has to be saved locally on disk first, which will increase the app size as the user saves more images. The user can delete the image later, in the Files app, but the local image has to sync with Google Photos or Amazon Photos in the cloud.
Saving the image to the cloud is accomplished by having the user open their Google Photos or Amazon Photos app after exporting and before deleting your app APK. If the user of < 29 deletes your APK before opening Google Photos or Amazon Photos, the photo will be lost.
This is a bug with Android Builds before Q (Level 29). Level 29 and later save directly to the Photo Library.
Android Manifest XML
<!-- Adding Read External Storage Permission -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Save Function
// - Save Image -
#Throws(FileNotFoundException::class)
private fun saveImage(
bitmap: Bitmap,
context: Context,
folderName: String
) {
if (Build.VERSION.SDK_INT >= 29) {
val values = ContentValues()
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/$folderName")
values.put(MediaStore.Images.Media.IS_PENDING, true)
// RELATIVE_PATH and IS_PENDING are introduced in API 29.
val uri: Uri? = context.contentResolver
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
if (uri != null) {
saveImageToStream(bitmap, context.contentResolver.openOutputStream(uri))
values.put(MediaStore.Images.Media.IS_PENDING, false)
context.contentResolver.update(uri, values, null, null)
}
} else {
var dir = File(
applicationContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
""
)
// getExternalStorageDirectory is deprecated in API 29
if (!dir.exists()) {
dir.mkdirs()
}
val date = Date()
val fullFileName = "myFileName.jpeg"
val fileName = fullFileName?.substring(0, fullFileName.lastIndexOf("."))
val extension = fullFileName?.substring(fullFileName.lastIndexOf("."))
var imageFile = File(
dir.absolutePath
.toString() + File.separator
+ fileName + "_" + Timestamp(date.time).toString()
+ ".jpg"
)
println("imageFile: $imageFile")
saveImageToStream(bitmap, FileOutputStream(imageFile))
if (imageFile.getAbsolutePath() != null) {
val values = ContentValues()
values.put(MediaStore.Images.Media.DATA, imageFile.absolutePath)
// .DATA is deprecated in API 29
context.contentResolver
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
}
}
}
private fun contentValues(): ContentValues? {
val values = ContentValues()
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
return values
}
private fun saveImageToStream(bitmap: Bitmap, outputStream: OutputStream?) {
println("saveImageToStream")
if (outputStream != null) {
try {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
outputStream.close()
// success dialog
runOnUiThread {
val successDialog = SuccessDialog.getInstance(null)
successDialog.show(supportFragmentManager, SuccessDialog.TAG)
}
} catch (e: Exception) {
e.printStackTrace()
// warning dialog
runOnUiThread {
val warningDialog = WarningDialog.getInstance(null)
warningDialog.show(supportFragmentManager, WarningDialog.TAG)
}
}
}
}
I come here with the same doubt but for Xamarin for Android, I have used the Sigrist answer to do this method after save my file:
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);
}
and it solved my problem, Thx Sigrist. I put it here becouse i did not found an answare about this for Xamarin and i hope it can help other people.
In my case the solutions above did not work I had to do the following:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
String filePath="/storage/emulated/0/DCIM"+app_name;
File dir=new File(filePath);
if(!dir.exists()){
dir.mkdir();
}
This code is in onCreate method.This code is for creating a directory of app_name.
Now,this directory can be accessed using default file manager app in android.
Use this string filePath wherever required to set your destination folder.
I am sure this method works on Android 7 too because I tested on it.Hence,it can work on other versions of android too.
Just you need to scan your Media After Saving finished.
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);
These code are same as everyone .If you try the bellow code after this it will work. You just need these one line of code:
MediaScannerConnection.scanFile(GenerateQRCodeActivity.this,new String[]{file.getPath()},new String[] {"image/jpeg"},null);
Boom!!! Yo can now get your saved image on your Gallery.