BitmapFactory.decodeStream de Activos devuelve null en Android 7
Cómo decodificar mapas de bits del directorio de activos en Android 7?
Mi aplicación está funcionando bien en las versiones de Android hasta Marshmallow. Con Android 7 falla al cargar imágenes desde el directorio de activos.
- ¿Cómo puedo especificar el formato de mapa de bits (por ejemplo, RGBA_8888) con BitmapFactory.decode * ()?
- Cargar muchas imágenes de mapa de bits grandes como miniaturas - Android
- Android BitmapFactory devolver null en Base64 decodificó byte matriz
- BitmapFactory.decodeStream devuelve null sin excepción
- Visualización de imágenes de una carpeta específica de la tarjeta SD mediante una vista de cuadrícula
Mi código:
private Bitmap getImage(String imagename) { // Log.dd(logger, "AsyncImageLoader: " + ORDNER_IMAGES + imagename); AssetManager asset = context.getAssets(); InputStream is = null; try { is = asset.open(ORDNER_IMAGES + imagename); } catch (IOException e) { // Log.de(logger, "image konnte nicht gelesen werden: " + ORDNER_IMAGES + imagename); return null; } // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, PW, PH); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; // Lesen des Bitmaps in der optimierten Groesse return BitmapFactory.decodeStream(is, null, options); }
Como resultado (sólo Android 7) BitmapFactory.decodeStream
es nulo. Funciona correctamente una vieja API de Android.
En el modo de depuración, veo el siguiente mensaje:
09-04 10: 10: 50.384 6274-6610 / myapp D / skia: — SkAndroidCodec :: NewFromStream devuelto null
¿Puede alguien decirme la razón y cómo corregir la codificación?
Edit: Mientras tanto, encontré que la eliminación de la primera BitmapFactory.decodeStream con inJustDecodeBounds = true conduce a un BitmapFactory.decodeStream con éxito después con inJustDecodeBounds = false. No sé la razón y no sé cómo sustituir la medida de tamaño de mapa de bits.
- Android - calculateInSampleSize, ¿por qué Math.round se ocupa de height (height / reqHeight) cuando width> height?
- ImageView y el muestreo GIF grande
- Asignación de mapa de bits, utilizando BitmapFactory.Options.inBitmap arroja IllegalArgumentException
- Perder fondo transparente al descargar una imagen PNG externa
- No se puede resolver el símbolo BitmapFactory.decodeResource en InteliJ
- Android: ¿Qué formato de imagen debo utilizar y por qué?
- BitmapFactory.decodeResource y inexplicable Fuera de memoria
- pérdida de memoria debido a llamada bitmapfactory
Creo que estamos en el mismo barco. Mi equipo se quedó en este problema por un tiempo como tú.
Parece ser un problema en BitmapFactory.cpp ( https://android.googlesource.com/platform/frameworks/base.git/+/master/core/jni/android/graphics/BitmapFactory.cpp ) Se ha agregado algún código en Android 7.0 y hecho el problema ocurrió.
// Create the codec. NinePatchPeeker peeker; std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(), &peeker)); if (!codec.get()) { return nullObjectReturn("SkAndroidCodec::NewFromStream returned null"); }
Y descubrí que el método BitmapFactory.decodeStream
no creó el mapa de bits después de establecer inJustDecodeBounds=false
pero cuando intento crear bitmap sin decodificación vinculada. ¡Funciona! El problema es sobre BitmapOptions en que InputStream no se actualiza cuando llamamos a BitmapFactory.decodeStream
nuevo.
Así que restablecer ese InputStream antes de decodificar de nuevo
private Bitmap getBitmapFromAssets(Context context, String fileName, int width, int height) { AssetManager asset = context.getAssets(); InputStream is; try { is = asset.open(fileName); } catch (IOException e) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); try { is.reset(); } catch (IOException e) { return null; } options.inSampleSize = calculateInSampleSize(options, width, height); options.inJustDecodeBounds = false; return BitmapFactory.decodeStream(is, null, options); } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
Parece que tenemos que restablecer InputStream cada vez antes de volver a usarlo.
En caso de que esto ayude a alguien, me estaba topando con un problema similar de actualización de código anterior que había trabajado anteriormente para el cambio de tamaño de las imágenes. Mi problema estaba más arriba en la pila donde estaba leyendo datos del archivo de imagen. Hice uso de IOUtils.toByteArray(Reader)
, que se ha desaprobado. Cambié a la conversión a una matriz de bytes directamente desde el URI y ahora está funcionando bien. Vea las dos primeras líneas de resizeImage()
continuación para el ejemplo de ese nuevo método (El resto del código me permite cambiar el tamaño de la imagen.)
public static Bitmap resizeImage(Uri imageUri, int targetWidth, int targetHeight) { // Convert the image to a byte array java.net.URI tempUri = new URI(uri.toString()); byte[] imageData = IOUtils.toByteArray(tempUri); // First decode with inJustDecodeBounds=true to check dimensions BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; Bitmap reducedBitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options); Bitmap resizedBitmap = Bitmap.createScaledBitmap(reducedBitmap, targetWidth, targetHeight, false); return resizedBitmap; } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a // power of 2 and keeps both height and width larger // than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
- Facebook account kit – Devuelve el error "Lo sentimos, algo salió mal." En android
- ¿Cómo puedo probar multi-touch en Android Emulator?