5

When my app first starts, it lets the user select a profile picture. This can be done taking a photo at the moment, or selecting it from the gallery.

After the user gets a picture, this must be saved in the device's internal storage and will be used in the app as user's profile picture.

This process works fine, the user gets the picture and this is shown in an imageview before it's saved. But to save the image in the internal storage, I'm having some trouble. I have tried several ways to do it, and most of them seem to work. But when I try them, the picture is not being saved or at least I don't find the folder where it is being saved.

I have tried in these 3 ways:

First:

File directory = getDir("profile", Context.MODE_PRIVATE); File mypath = new File(directory, "thumbnail.png"); FileOutputStream fos = null; try { fos = new FileOutputStream(mypath); mybitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); } catch (Exception e) { e.printStackTrace(); } 

Second:

ByteArrayOutputStream bytes = new ByteArrayOutputStream(); mybitmap.compress(Bitmap.CompressFormat.PNG, 90, bytes); FileOutputStream fos = null; try { fos = openFileOutput("thumbnail.png", Context.MODE_PRIVATE); fos.write(bytes.toByteArray()); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } 

Third:

ByteArrayOutputStream bytes = new ByteArrayOutputStream(); mybitmap.compress(Bitmap.CompressFormat.PNG, 90, bytes); File fileWithinMyDir = new File(getFilesDir(), "thumbnail.png"); try { FileOutputStream fos = new FileOutputStream(fileWithinMyDir); fos.write(bytes.toByteArray()); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } 

Suposedly, the image gets saved in the path: android/data/AppName/app_data/ but there is no folder created there. Anyway I have looked in other folders, but nothing.

EDIT-

In the first method, I've seen that is throwing an exception:

E/SAVE_IMAGE﹕ /data/data/com.example.myapp/app_profile/thumbnail.png: open failed: EISDIR (Is a directory) java.io.FileNotFoundException: /data/data/com.example.myapp/app_profile/thumbnail.png: open failed: EISDIR (Is a directory) Caused by: libcore.io.ErrnoException: open failed: EISDIR (Is a directory) 
2
  • did u add write external storage permission ? Commented May 27, 2015 at 11:46
  • 1
    @quicklearner I don't need to write on external storage Commented May 27, 2015 at 12:41

6 Answers 6

9

After trying several things, this is what finally has worked for me:

ContextWrapper cw = new ContextWrapper(getApplicationContext()); File directory = cw.getDir("profile", Context.MODE_PRIVATE); if (!directory.exists()) { directory.mkdir(); } File mypath = new File(directory, "thumbnail.png"); FileOutputStream fos = null; try { fos = new FileOutputStream(mypath); resizedbitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); } catch (Exception e) { Log.e("SAVE_IMAGE", e.getMessage(), e); } 

Basically the thing is to check if the directory (not the file) exists, and if not, create it with mkdir().

Sign up to request clarification or add additional context in comments.

3 Comments

Context#getDir() creates the folder if it doesn't exist, so calling mkdir() is redundant (source: Context.java documentation)
How did you put together all these methods to make the whole thing work? Did you copy some pieces of the code from this and that person? I have always been copying people's code. I cannot never put together a working code.
One question. I saved it but now where do I find it?
4

You can use this ImageSaver class for save bitmap image to your app folder. The image saver class code is given below:

public class ImageSaver { private String directoryName = "images"; private String fileName = "image.png"; private Context context; private File dir; private boolean external=false; public ImageSaver(Context context) { this.context = context; } public ImageSaver setFileName(String fileName) { this.fileName = fileName; return this; } public ImageSaver setExternal(boolean external) { this.external = external; return this; } public ImageSaver setDirectory(String directoryName) { this.directoryName = directoryName; return this; } public void save(Bitmap bitmapImage) { FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(createFile()); bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } @NonNull private File createFile() { File directory; if (external) { directory = getAlbumStorageDir(directoryName); if (!directory.exists()){ directory.mkdir(); } } else { directory = new File(context.getFilesDir()+"/"+directoryName); if (!directory.exists()){ directory.mkdir(); } } 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; } public static boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); return Environment.MEDIA_MOUNTED.equals(state); } public static boolean isExternalStorageReadable() { String state = Environment.getExternalStorageState(); return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state); } public Bitmap load() { FileInputStream inputStream = null; try { inputStream = new FileInputStream(createFile()); return BitmapFactory.decodeStream(inputStream); } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return null; } public boolean deleteFile() { File file = createFile(); return file.delete(); } } 

Then, in your activity where you are getting the bitmap from the server—by using Glide or Picasso, but you can use any method—you should set setExternal before you call .setDirectory:

Bitmap bitmap=........//bitmap from code new ImageSaver(this) .setFileName("filename.jpg") .setExternal(false)//image save in external directory or app folder default value is false .setDirectory("dir_name") .save(bitmap); //Bitmap from your code 

7 Comments

Please explain your lines of code so other users can understand its functionality. Thanks!
I liked this solution, but I dont undestand this part: * directory = new File(context.getFilesDir()+"/"+directoryName); *
@LeandroPortnoy its for save the file in the phone directory.
nice solution but i am not able to open the image
@AndroidDeveloper You can use the same class to open the saved image by calling load() function
|
1

Well, you need to create the folder if it doesn't exist.

try running this code and see if it fixes your issue:

File parentDestination = saveFile.getParentFile(); if (!parentDestination.exists()) { parentDestination.mkdirs(); //make all the directory structures needed } 

5 Comments

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Do I need to have that permission to write in the INTERNAL storage?
YES you need permission
Excuse me but I think you are wrong. I have finally achieved to write it in the internal storage without adding that permission. That permission just applies to write in the external storage (SD card), no in device's memory. The permission needed in this case is: WRITE_INTERNAL_STORAGE
aw "INTERNAL", yes, I was wrong. sorry if i miss led you, i mixed it up.
1

understand your requirement. Below pasting some piece of code which i tested and working.Basically get the image from camera and save it in app storage.please go through it. Hope this helps.Cheers..

//For saving image...

private String saveToInternalSorage(Bitmap bitmapImage) { ContextWrapper cw = new ContextWrapper(getApplicationContext()); File directory = cw.getDir("imageDir", Context.MODE_PRIVATE); // Create imageDir File mypath = new File(directory, "profile.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); fos.close(); Editor editor = sharedpreferences.edit(); editor.putString("saved", "na"); editor.commit(); } catch (Exception e) { e.printStackTrace(); } return directory.getAbsolutePath(); } 

//..To load image from storage

private void loadImageFromStorage(String path) { try { ContextWrapper cw = new ContextWrapper(getApplicationContext()); File path1 = cw.getDir("imageDir", Context.MODE_PRIVATE); File f = new File(path1, "profile.jpg"); Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f)); ImageView img = (ImageView) findViewById(R.id.viewImage); img.setImageBitmap(b); } catch (FileNotFoundException e) { e.printStackTrace(); } } 

2 Comments

If you have a look to my code, thats the first method I have used
could you point how you created an instance of sharedpreferences in order to access it's edit method?
0

Try this ...

You should use the Bitmap.compress() method to save a Bitmap as a file. It will compress (if the format used allows it) your picture and push it into an OutputStream.

Here is an example of a Bitmap instance obtained through getImageBitmap(myurl) that can be compressed as a JPEG with a compression rate of 85% :

String path = Environment.getExternalStorageDirectory().toString(); OutputStream fOut = null; File file = new File(path, "FitnessGirl"+Contador+".jpg"); // the File to save to fOut = new FileOutputStream(file); Bitmap pictureBitmap = getImageBitmap(myurl); // obtaining the Bitmap pictureBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // saving the Bitmap to a file compressed as a JPEG with 85% compression rate fOut.flush(); fOut.close(); // do not forget to close the stream MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName()); 

1 Comment

your path refers to the external storage and I need to save it in the internal storage
0

First Thanks @masmic. I use it to make some search in github repos and made my own way. Note that I use kotlin, coroutines and crashlitics you can get rid of all that with Java, posting a thread to a Handler and send data to your custom sever with okhttp.

My code can Save bitmap to app folder i.e. local store. and read load it is:.

package xxxx.data import android.content.Context import android.content.ContextWrapper import android.graphics.Bitmap import android.graphics.BitmapFactory import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.ktx.Firebase import java.io.ByteArrayOutputStream import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException import java.io.FileOutputStream import java.io.IOException import java.util.Date interface BitmapDAO { suspend fun insertBitmapAndGetRelativePath(bitmapEntity: PhotoEntity): String? suspend fun getBitmapFromPath(bitmapEntity: PhotoEntity): Bitmap? suspend fun deleteFile(bitmapEntity: PhotoEntity) : Boolean suspend fun updateBitmap(bitmapEntity: PhotoEntity): Boolean } class BitmapDAOImpl(private val mContext: Context): BitmapDAO { companion object{ //private const val MIME_TYPE_IMAGE:String = "image/*" private const val FILE_EXTENSION:String = ".jpeg" private const val FOLDER:String = "images" } private fun convertFromBitMapToByteArray(bitmap: Bitmap) : ByteArray { val byteArrayOutputStream = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG,100,byteArrayOutputStream) return byteArrayOutputStream.toByteArray() } override suspend fun insertBitmapAndGetRelativePath(bitmapEntity: PhotoEntity): String? { val bitmap: Bitmap = bitmapEntity.bitmap.let { bitmap -> return@let bitmap }?: return null val productName: String = bitmapEntity.productName.let { productName -> return@let productName }?: return null // Get the context wrapper val wrapper = ContextWrapper(mContext) val fileName: String = productName + Date().time.toString() + FILE_EXTENSION try { /** * Caution: On devices that run Android 7.0 (API level 24) or higher, * unless you pass the Context.MODE_PRIVATE file mode * into openFileOutput(), a SecurityException occurs. */ return withContext(Dispatchers.IO) { // Initialize a new file instance to save bitmap object var fileDir = wrapper.getDir(FOLDER, Context.MODE_PRIVATE) if (!fileDir.exists()) { fileDir.mkdir() } fileDir = File(fileDir, fileName) //with mContext.openFileOutput It gets: EISDIR (Is a directory) FileOutputStream(fileDir).use { it.write(convertFromBitMapToByteArray(bitmap)) } //Uri.parse(file.absolutePath) return@withContext fileName } } catch (ex: FileNotFoundException) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "insertBitmapAndGetUri") Firebase.crashlytics.setCustomKey("UseCase", "saveImage") Firebase.crashlytics.recordException(ex) Log.e("BitmapDAOImpl FileNotFoundException", ex.message ?: "") Log.e("BitmapDAOImpl FileNotFoundException", ex.stackTrace.toString()) } catch (ex: IOException) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "insertBitmapAndGetUri") Firebase.crashlytics.setCustomKey("UseCase", "saveImage") Firebase.crashlytics.recordException(ex) Log.e("BitmapDAOImpl IOException", ex.message ?: "") Log.e("BitmapDAOImpl IOException", ex.stackTrace.toString()) } //only for Exception case return null } override suspend fun getBitmapFromPath(bitmapEntity: PhotoEntity): Bitmap? { try { val wrapper = ContextWrapper(mContext) return withContext(Dispatchers.IO) { var fileDir = wrapper.getDir(FOLDER, Context.MODE_PRIVATE) if (!fileDir.exists()) { fileDir.mkdir() } fileDir = File(fileDir, bitmapEntity.fileName) var payload : Bitmap? = null if (fileDir.exists()){ FileInputStream(fileDir).use { fileInputStream -> /** * Loading image */ payload = BitmapFactory.decodeStream(fileInputStream) } } return@withContext payload } } catch (ex: FileNotFoundException) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "getBitmapFromUri") Firebase.crashlytics.setCustomKey("UseCase", "readImage") Firebase.crashlytics.recordException(ex) Log.e("BitmapDAOImpl", ex.message ?: "") Log.e("BitmapDAOImpl", ex.stackTrace.toString()) } catch (out: OutOfMemoryError) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "getBitmapFromUri") Firebase.crashlytics.setCustomKey("UseCase", "readImage") Firebase.crashlytics.recordException(out) Log.e("BitmapDAOImpl", out.message ?: "") Log.e("BitmapDAOImpl", out.stackTrace.toString()) } // If an error has occurred or the album ID is null, then return a default artwork image //return BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_launcher_foreground) //only for Exception case return null } override suspend fun deleteFile(bitmapEntity: PhotoEntity) : Boolean { val wrapper = ContextWrapper(mContext) try { return withContext(Dispatchers.IO) { var fileDir = wrapper.getDir(FOLDER, Context.MODE_PRIVATE) if (!fileDir.exists()) { fileDir.mkdir() } fileDir = File(fileDir, bitmapEntity.fileName) if(fileDir.exists()){ return@withContext fileDir.delete() } else { return@withContext false } } } catch (ex: FileNotFoundException) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "deleteFile") Firebase.crashlytics.setCustomKey("UseCase", "deleteImage") Firebase.crashlytics.recordException(ex) Log.e("BitmapDAOImpl", ex.message ?: "") Log.e("BitmapDAOImpl", ex.stackTrace.toString()) } //only for Exception case return false } override suspend fun updateBitmap(bitmapEntity: PhotoEntity):Boolean { val newImage: Bitmap = bitmapEntity.bitmap.let { newImage -> return@let newImage }?: return false val wrapper = ContextWrapper(mContext) try { return withContext(Dispatchers.IO) { var fileDir = wrapper.getDir(FOLDER, Context.MODE_PRIVATE) if (!fileDir.exists()) { fileDir.mkdir() } fileDir = File(fileDir, bitmapEntity.fileName) //if(fileDir.exists()) ?? for both case is the same FileOutputStream(fileDir).use { it.write(convertFromBitMapToByteArray(newImage)) } return@withContext true } } catch (ex: Exception) { //REPORT Firebase.crashlytics.setCustomKey("Class", "BitmapDAOImpl") Firebase.crashlytics.setCustomKey("Method", "updateBitmapAndGetUri") Firebase.crashlytics.setCustomKey("UseCase", "updateImage") Firebase.crashlytics.recordException(ex) Log.e("BitmapDAOImpl", ex.message ?: "") Log.e("BitmapDAOImpl", ex.stackTrace.toString()) } return false } } //End of class 

Thanks. And have a nice day.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.