Después de unos días que luchan para evitar todos los errores OutOfMemory que estaba recibiendo con diferentes dispositivos, creo esto:
private Bitmap getDownsampledBitmap(Context ctx, Uri uri, int targetWidth, int targetHeight) {
Bitmap bitmap = null;
try {
BitmapFactory.Options outDimens = getBitmapDimensions(uri);
int sampleSize = calculateSampleSize(outDimens.outWidth, outDimens.outHeight, targetWidth, targetHeight);
bitmap = downsampleBitmap(uri, sampleSize);
} catch (Exception e) {
//handle the exception(s)
}
return bitmap;
}
private BitmapFactory.Options getBitmapDimensions(Uri uri) throws FileNotFoundException, IOException {
BitmapFactory.Options outDimens = new BitmapFactory.Options();
outDimens.inJustDecodeBounds = true; // the decoder will return null (no bitmap)
InputStream is= getContentResolver().openInputStream(uri);
// if Options requested only the size will be returned
BitmapFactory.decodeStream(is, null, outDimens);
is.close();
return outDimens;
}
private int calculateSampleSize(int width, int height, int targetWidth, int targetHeight) {
int inSampleSize = 1;
if (height > targetHeight || width > targetWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/(float) targetHeight);
final int widthRatio = Math.round((float) width/(float) targetWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
private Bitmap downsampleBitmap(Uri uri, int sampleSize) throws FileNotFoundException, IOException {
Bitmap resizedBitmap;
BitmapFactory.Options outBitmap = new BitmapFactory.Options();
outBitmap.inJustDecodeBounds = false; // the decoder will return a bitmap
outBitmap.inSampleSize = sampleSize;
InputStream is = getContentResolver().openInputStream(uri);
resizedBitmap = BitmapFactory.decodeStream(is, null, outBitmap);
is.close();
return resizedBitmap;
}
Este método funciona con todos los dispositivos que he probado, pero creo que la calidad puede Sería mejor usar otro proceso del que no soy consciente.
Espero que mi código pueda ayudar a otros desarrolladores en la misma situación. También aprecio que un desarrollador experimentado pueda ayudar, dando una sugerencia sobre otro proceso para evitar perder (menos) calidad en el proceso.
El sitio oficial [Android Training] (http://developer.android.com/training/index.html) ahora tiene una clase llamada [Mostrar mapas de bits de manera eficiente] (http://developer.android.com/training/ displaying-bitmaps/index.html) con una lección, [Cargando grandes mapas de bits de manera eficiente] (http://developer.android.com/training/displaying-bitmaps/load-bitmap.html) que repasa esto. La lección [Caching Bitmaps] (http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html) también cubre algo de información sobre el almacenamiento en caché utilizando una memoria caché de referencia de disco duro en lugar de una WeakReference o SoftReference. – AdamK