usamazf
usamazf

Reputation: 3205

Saving and Reading Bitmaps/Images from Internal memory in Android

What I want to do, is to save an image to the internal memory of the phone (Not The SD Card).

How can I do it?

I have got the image directly from the camera to the image view in my app its all working fine.

Now what I want is to save this image from Image View to the Internal memory of my android device and also access it when required.

Can anyone please guide me how to do this?

I am a little new to android so please, I would appreciate if I can have a detailed procedure.

Upvotes: 197

Views: 318250

Answers (8)

Amit Kundu
Amit Kundu

Reputation: 119

This code will support up Upto Android 11+.

Declare a permission result on Fragment / Activity I am using a fragment

private val askPermissions =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
        val isGranted = permissions.entries.all {
            it.value == true
        }

        if (isGranted) {
            viewModel.saveImageToGallery(requireContext().contentResolver,
                getString(R.string.my_deshi_qr_code),
                bitmap)
        } else {
            askForWritePermission()
        }
    }

Trigger event

bindingView.downloadQrButton.setOnClickListener {
        requestPermission()
    }
private fun requestPermission() {
    val minSDK = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
    val isWritePermissionGranted = (ContextCompat.checkSelfPermission(requireContext(),
        Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) || minSDK

    if (!isWritePermissionGranted) {
        askForWritePermission()
    } else {
        viewModel.saveImageToGallery(requireContext().contentResolver,
            getString(R.string.my_deshi_qr_code),
            bitmap)
    }
}


private fun askForWritePermission() {
    askPermissions.launch(listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE).toTypedArray())
}

Viewmodel

fun saveImageToGallery(contentResolver: ContentResolver, imageName: String, bitmap: Bitmap?) {
    val imageUri: Uri?
    val contentValues = ContentValues().apply {
        put(MediaStore.MediaColumns.DISPLAY_NAME, "$imageName.jpg")
        put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
        bitmap?.let {
            put(MediaStore.Images.Media.WIDTH, bitmap.width)
            put(MediaStore.Images.Media.HEIGHT, bitmap.height)
        }
    }

    imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,
            Environment.DIRECTORY_PICTURES + File.separator.toString() + "YourFolderName")
        MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    } else {
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    }

    try {
        val uri = contentResolver.insert(imageUri, contentValues)
        val fos = uri?.let { contentResolver.openOutputStream(it) }
        bitmap?.compress(Bitmap.CompressFormat.JPEG, 100, fos)
        Objects.requireNonNull(fos)
        _showMessage.postValue(Event("Image Saved"))
    } catch (e: Exception) {
        _showMessage.postValue(Event("Image Not Saved \n$e"))
    }
}

Upvotes: 1

Jim Ovejera
Jim Ovejera

Reputation: 876

Make sure to use WEBP as your media format to save more space with same quality:

fun saveImage(context: Context, bitmap: Bitmap, name: String): String {
        context.openFileOutput(name, Context.MODE_PRIVATE).use { fos ->
            bitmap.compress(Bitmap.CompressFormat.WEBP, 25, fos)
        }
    return context.filesDir.absolutePath
 }

Upvotes: 1

Amin Keshavarzian
Amin Keshavarzian

Reputation: 3943

if you want to follow Android 10 practices to write in storage, check here and if you only want the images to be app specific, here for example if you want to store an image just to be used by your app:

viewModelScope.launch(Dispatchers.IO) {
            getApplication<Application>().openFileOutput(filename, Context.MODE_PRIVATE).use {
                bitmap.compress(Bitmap.CompressFormat.PNG, 50, it)
            }
        }

getApplication is a method to give you context for ViewModel and it's part of AndroidViewModel later if you want to read it:

viewModelScope.launch(Dispatchers.IO) {
            val savedBitmap = BitmapFactory.decodeStream(
                getApplication<App>().openFileInput(filename).readBytes().inputStream()
            )
        }

Upvotes: 0

Meet
Meet

Reputation: 895

// mutiple image retrieve

 File folPath = new File(getIntent().getStringExtra("folder_path"));
 File[] imagep = folPath.listFiles();

 for (int i = 0; i < imagep.length ; i++) {
     imageModelList.add(new ImageModel(imagep[i].getAbsolutePath(), Uri.parse(imagep[i].getAbsolutePath())));
 }
 imagesAdapter.notifyDataSetChanged();

Upvotes: 0

Anurag
Anurag

Reputation: 1531

Came across this question today and this is how I do it. Just call this function with the required parameters

public void saveImage(Context context, Bitmap bitmap, String name, String extension){
    name = name + "." + extension;
    FileOutputStream fileOutputStream;
    try {
        fileOutputStream = context.openFileOutput(name, Context.MODE_PRIVATE);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream);
        fileOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Similarly, for reading the same, use this

public Bitmap loadImageBitmap(Context context,String name,String extension){
    name = name + "." + extension
    FileInputStream fileInputStream
    Bitmap bitmap = null;
    try{
        fileInputStream = context.openFileInput(name);
        bitmap = BitmapFactory.decodeStream(fileInputStream);
        fileInputStream.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
     return bitmap;
}

Upvotes: 33

Amiraslan
Amiraslan

Reputation: 812

For Kotlin users, I created a ImageStorageManager class which will handle save, get and delete actions for images easily:

class ImageStorageManager {
    companion object {
        fun saveToInternalStorage(context: Context, bitmapImage: Bitmap, imageFileName: String): String {
            context.openFileOutput(imageFileName, Context.MODE_PRIVATE).use { fos ->
                bitmapImage.compress(Bitmap.CompressFormat.PNG, 25, fos)
            }
            return context.filesDir.absolutePath
        }

        fun getImageFromInternalStorage(context: Context, imageFileName: String): Bitmap? {
            val directory = context.filesDir
            val file = File(directory, imageFileName)
            return BitmapFactory.decodeStream(FileInputStream(file))
        }

        fun deleteImageFromInternalStorage(context: Context, imageFileName: String): Boolean {
            val dir = context.filesDir
            val file = File(dir, imageFileName)
            return file.delete()
        }
    }
}

Read more here

Upvotes: 17

Ilya Gazman
Ilya Gazman

Reputation: 32226

/**
 * Created by Ilya Gazman on 3/6/2016.
 */
public class ImageSaver {

    private String directoryName = "images";
    private String fileName = "image.png";
    private Context context;
    private boolean external;

    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 setDirectoryName(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);
        }
        else {
            directory = context.getDir(directoryName, Context.MODE_PRIVATE);
        }
        if(!directory.exists() && !directory.mkdirs()){
            Log.e("ImageSaver","Error creating directory " + directory);
        }

        return new File(directory, fileName);
    }

    private File getAlbumStorageDir(String albumName) {
        return new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), albumName);
    }

    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;
    }
}

Usage

  • To save:

    new ImageSaver(context).
            setFileName("myImage.png").
            setDirectoryName("images").
            save(bitmap);
    
  • To load:

    Bitmap bitmap = new ImageSaver(context).
            setFileName("myImage.png").
            setDirectoryName("images").
            load();
    

Edit:

Added ImageSaver.setExternal(boolean) to support saving to external storage based on googles example.

Upvotes: 81

Brijesh Thakur
Brijesh Thakur

Reputation: 6788

Use the below code to save the image to internal directory.

private String saveToInternalStorage(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
        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);
        } catch (Exception e) {
              e.printStackTrace();
        } finally {
            try {
              fos.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
        } 
        return directory.getAbsolutePath();
    }

Explanation :

1.The Directory will be created with the given name. Javadocs is for to tell where exactly it will create the directory.

2.You will have to give the image name by which you want to save it.

To Read the file from internal memory. Use below code

private void loadImageFromStorage(String path)
{

    try {
        File f=new File(path, "profile.jpg");
        Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
            ImageView img=(ImageView)findViewById(R.id.imgPicker);
        img.setImageBitmap(b);
    } 
    catch (FileNotFoundException e) 
    {
        e.printStackTrace();
    }

}

Upvotes: 379

Related Questions