2013年8月11日 星期日

Saving & loading bitmaps to the Android device storage (internal & external)

Saving & loading bitmaps to the Android device storage (internal & external)

In this tutorial I will show how to save a bitmap file to the external and internal storage of an Android device. It’s actually quite easy and only requires a few lines of code for the basic feature. As the source I am using a Bitmap object. If you want to use a image file from your drawable folder you can get it with this line of code:
Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
If you want to save a thumbnail of an image you can easily change the size of the image with this line of code:
Bitmap thumbnail = Bitmap.createScaledBitmap(originalBitmap, width, height, false);
This will return a new Bitmap object with the desired width and height.

Saving the bitmap to the external storage

To save the Bitmap to the external storage (for example a SD card) use this code:
public final static String APP_PATH_SD_CARD = "/DesiredSubfolderName/";
public final static String APP_THUMBNAIL_PATH_SD_CARD = "thumbnails";

public boolean saveImageToExternalStorage(Bitmap image) {
String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + APP_PATH_SD_CARD + APP_THUMBNAIL_PATH_SD_CARD;

try {
File dir = new File(fullPath);
if (!dir.exists()) {
dir.mkdirs();
}

OutputStream fOut = null;
File file = new File(fullPath, "desiredFilename.png");
file.createNewFile();
fOut = new FileOutputStream(file);

// 100 means no compression, the lower you go, the stronger the compression
image.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();

MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());

return true;

} catch (Exception e) {
Log.e("saveToExternalStorage()", e.getMessage());
return false;
}
}

Note that we have to pass the context to this variable. Otherwise we will not be able to use the getContentResolver() method. If you are using this method in an Activity class you can just delete “context”. Otherwise you can pass the context from an Activity class with “this”.
With the variable APP_PATH_SD_CARD you can set to which sub folder the file shall be saved. The root folder is the root folder of the SD card in the phone. You should name the sub folder with the name of your application so the user can easily find the proper folder of the saved files from your app.

Saving the bitmap to the internal storage

Alternatively you can also save the Bitmap to the internal storage in case the SD card is not available or for whatever other reasons you may have. Files saved to the internal storage are only accessible by the application which saved the files. Neither the user nor other applications can access those files. Also, all these files will be deleted once the application was uninstalled by the user.
public boolean saveImageToInternalStorage(Bitmap image) {

try {
// Use the compress method on the Bitmap object to write image to
// the OutputStream
FileOutputStream fos = context.openFileOutput("desiredFilename.png", Context.MODE_PRIVATE);

// Writing the bitmap to the output stream
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();

return true;
} catch (Exception e) {
Log.e("saveToInternalStorage()", e.getMessage());
return false;
}
}

Note that we have to pass the context to this variable. Otherwise we will not be able to use the openFileOutput() method. If you are using this method in an Activity class you can just delete “context”. Otherwise you can pass the context from an Activity class with “this”.
You can change the value of Context.MODE_PRIVATE to Context.MODE_WORLD_READABLE so that other applications will be able to access those files.

 Reading a bitmap from the storage

With this method you can read a file from the storage. The method first checks for the file in the external storage. If the file is not there or there is no external storage it will look for the file in the internal storage.
First I made a method which checks if the external storage is readable.
public boolean isSdReadable() {

boolean mExternalStorageAvailable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = true;
Log.i("isSdReadable", "External storage card is readable.");
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
Log.i("isSdReadable", "External storage card is readable.");
mExternalStorageAvailable = true;
} else {
// Something else is wrong. It may be one of many other
// states, but all we need to know is we can neither read nor write
mExternalStorageAvailable = false;
}

return mExternalStorageAvailable;
}

We will be using the above method in this following method:
public Bitmap getThumbnail(String filename) {

String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + APP_PATH_SD_CARD + APP_THUMBNAIL_PATH_SD_CARD;
Bitmap thumbnail = null;

// Look for the file on the external storage
try {
if (tools.isSdReadable() == true) {
thumbnail = BitmapFactory.decodeFile(fullPath + "/" + filename);
}
} catch (Exception e) {
Log.e("getThumbnail() on external storage", e.getMessage());
}

// If no file on external storage, look in internal storage
if (thumbnail == null) {
try {
File filePath = context.getFileStreamPath(filename);
FileInputStream fi = new FileInputStream(filePath);
thumbnail = BitmapFactory.decodeStream(fi);
} catch (Exception ex) {
Log.e("getThumbnail() on internal storage", ex.getMessage());
}
}
return thumbnail;
}

Note that we have to pass the context to this variable. Otherwise we will not be able to use the getFileStreamPath() method. If you are using this method in an Activity class you can just delete “context”. Otherwise you can pass the context from an Activity class with “this”.
So basically this method only needs the filename and returns a Bitmap object of this image for further use. If you want to use this Bitmap object for your ImageView in your activity you can set the bitmap to this object with this line of code:
myImageView.setImageBitmap(MyBitmapObject);


Hinterlasse eine Antwort

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...