I'm trying to save bitmap to gallery to open it again from ImagePicker intent.
The problem is - if I'm saving it on external storage, it will not work on devices without it, and when I'm writing it on internal storage - it won't shown in gallery, so i can not pick that image.
Tried so many ways of resolving it, but no success this far.
I mean, is it possible to save bitmap in internal storage and open it from activity, which called to choose image from gallery?
edit: added code
private String saveToInternalStorage(Bitmap bitmapImage, String filename){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,filename + ".jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
With that procedure it's seems like saving bitmap is ok, but i can't find that file in gallery.
Related
I cannot seem to delete a picture from the local storage. What I want to happen is: delete the old picture, add a new picture with the same name.
When I change the picture name it has no problem loading it as a new one. But when I don't change its name it shows the old picture.
I tried context.deleteFile(filename). file.exists returns false after deletion but the picture is still there.
A solution with overwriting can be helpful.
I also have external storage permissions in the manifest.
Thanks!
The deletion:
void deleteOldPicture(String filename, Context context){
File file = new ImageSaver(context).setFileName(filename).setDirectoryName("images").createFile();
file.delete();
}
Creating the file
File createFile() {
File directory;
if(external){
directory = getAlbumStorageDir(directoryName);
}
else {
directory = context.getDir(directoryName, Context.MODE_PRIVATE);
}
return new File(directory, fileName);
}
private File getAlbumStorageDir(String albumName) {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e("ImageSaver", "Directory not created");
}
return file;
}
Saving the file:
private String saveFileInSD(String name, ImageView image){
String filename = name+parentId+".png";
Log.e("Filename is", filename);
new ImageSaver(getApplicationContext()).setFileName(filename).setDirectoryName("images").save(((BitmapDrawable) image.getDrawable()).getBitmap());
return filename;
}
add this library to your Gradle, it will help clean up your code a little bit :
implementation 'org.apache.commons:commons-io:1.3.2'
the do the following to save the picture :
//Compress the Bitmap
ByteArrayOutputStream stream = new ByteArrayOutputStream();
yourBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
//save Bitmap to file and get it form preview activity and especially to avoid TransactionTooLargeException
File imageFile = new File(getExternalCacheDir(), "image.png");
try {
FileOutputStream imageFileStream = new FileOutputStream(imageFile);
IOUtils.copyLarge(new ByteArrayInputStream(stream.toByteArray()), imageFileStream);
IOUtils.closeQuietly(imageFileStream);
} catch (Exception e) {
e.printStackTrace();
}
to get the path of your saved bitmap just use the following method :
imageFile.getAbsolutePath()
I wasn't sure how to word this, but in iOS terms, if I download an image, and save it in the documents directory, it saves it in the Apps Container, which is not visible to other apps, and camera roll etc.
The way I have it in Android currently, all of these images are visible in the File Explorer and Gallery.
I was wondering how I could save these images in a similar way to iOS and have them hidden in the Apps own container.
Is there a way to create a folder, with context.MODE_PRIVATE or something similiar?
This is what I have currently, does it do the trick?
public static Boolean saveToInternalStorage(Context context, Bitmap bitmap, String filename) {
ContextWrapper cw = new ContextWrapper(context);
//Path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
//Create imageDir
File mypath = new File(directory, filename);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
//Use the compress method on the BitMap object to write image to the OutputStream
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
public static Bitmap loadImageFromStorage(Context context, String filename) {
ContextWrapper cw = new ContextWrapper(context);
//Path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
try {
File f = new File(directory, filename);
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
return b;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Read this article. This will help..
You can save files directly on the device's internal storage. By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
I was wondering how I could save these images in a similar way to iOS and have them hidden in the Apps own container.
Write them to getFilesDir(), getCacheDir(), or another location on internal storage.
This is what I have currently, does it do the trick?
The ContextWrapper is useless. If you are downloading an image, I do not know why you have a Bitmap that you are trying to write to storage — download straight to storage.
But, with respect to keeping the images private to your app, getDir() also points to locations in internal storage.
When I save a bitmap with this function, I get an unreadable file, bigger than the original image(using Root explorer on my phone) what is wrong?
The bitmap is set by the user using the stock image picker.
Here is the call:
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
saveToInternalSorage(bitmap);
Here the saveToInternalSorage method (from here Saving and Reading Bitmaps/Images from Internal memory in Android )
private String saveToInternalSorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
String filename = randomString();
System.out.println(filename);
File mypath=new File(directory,filename);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return directory.getAbsolutePath();
}
I can pass sdcard location to my adb command using
file:///sdcard/Android/screen.bmp
What is the equivalent string, if my file is saved in phone memory instead of sdcard, will it be
file:///phone/Android/screen.bmp
That isn't necessarily how you access things saved internally on your phone.
Keep in mind how you save an image to internal storage:
Bitmap bitmap = ______; //get your bitmap however
try {
FileOutputStream fos = context.openFileOutput("desiredFilename.png", Context.MODE_PRIVATE);
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
Log.e("saveToInternalStorage()", e.getMessage());
Log.e("Saving the bitmap",e.getMessage());
}
Now, to go read it, we just get the context, and call getFileStreamPath(filename) on it.
Bitmap retrievedImage;
String filename = "desiredFilename.png";
try {
File filePath = context.getFileStreamPath(filename);
FileInputStream fi = new FileInputStream(filePath);
retrievedImage = BitmapFactory.decodeStream(fi);
} catch (Exception e) {
Log.e("Retrieving the image", e.getMessage());
}
You can read more about this here.
I'm trying to capture a photo with the camera and save it (to be previewed later) and it seems to work with the emulator but when I use it on my GalaxyS - it doesn't save the file (I use RootExplorer to check) and there's no preview.
What am I doing wrong?
Code for saving the file:
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
// Write to SD Card
String filename = "captured_image.jpg";
Log.d("##--File name--##", filename);
outStream = openFileOutput(filename, Context.MODE_WORLD_READABLE); // <9>
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) { // <10>
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d(TAG, "onPictureTaken - jpeg");
}
Code for displaying:
ImageView imagePrev = (ImageView) findViewById(R.id.image_capturedimagepreview_preview);
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeStream(openFileInput("captured_image.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imagePrev.setImageBitmap(bmp);
i think i found the problem.
instead of outStream = openFileOutput(filename, Context.MODE_WORLD_READABLE); i should use outStream = getApplicationContext().openFileOutput(filename, Context.MODE_WORLD_READABLE);
but now i'm facing a new one - the file seems to be corrupted cause when i open it with the Android's viewer it's just black and its size is always 18474 bytes.
any ideas?
Where are you storing the image? Have you tried using an absolute path? Do you have the read/write external permission in the manifest?
I used something like this in my program to store an image in a directory the same as my package name.
File path = new File(Environment.getExternalStorageDirectory(), context.getPackageName() );
File imagePath = new File(path,"capture_image.jpg");
EDIT:
If its your first time using the sd card for your given package name you will need to create the directory before trying to write to it.