2016-09-04 38 views
5

Android 7'deki Asset dizininden bitmapler kodu nasıl çözülür?BitmapFactory.decodeStream öğesinden Gelen Değerler, Android 7'de null değerini döndürüyor

Uygulamam, Android sürümlerinde Marshmallow'a kadar iyi çalışıyor. Android 7 ile, Asset dizinindeki görüntüleri yüklemek başarısız oluyor.

Benim Kod:

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

} 

Sonuç olarak (yalnızca Android 7) BitmapFactory.decodeStream boş. Eski bir Android API'ları doğru şekilde çalışıyor.

09-04 10: 10: --- SkAndroidCodec :: NewFromStream boş

döndürdü: 50,384 6274-6610/myapp D/Skia aşağıdaki Mesaj olmadığını ayıklama modunda

Birisi bana nedenini ve kodlamayı nasıl düzeltebilir?

Düzenleme: Bu arada, ilk BitmapFactory.decodeStream öğesinin inJustDecodeBounds = true ile kaldırılmasının, daha sonra inJustDecodeBounds = false ile başarılı bir BitmapFactory.decodeStream yol açtığını buldum. Nedeni bilmemek ve bitmap boyutunun ölçümünü nasıl değiştireceğinizi bilmemek.

+0

Tahminim, sorununuzun varlığınıza özel olması. Sadece Android 7.0 çalıştıran bir Nexus 9'da [resim kitaplığımdan biri] (https://github.com/commonsguy/cw-omnibus/tree/master/Bitmaps/InSampleSize) testlerini öğelerden yükledim. İyi çalışıyor gibi görünüyor. – CommonsWare

cevap

8

Biz aynı durumda düşünüyorum. Ekibim senin gibi bir süreliğine bu problemde sıkıştı.

BitmapFactory.cpp'de bir sorun var gibi görünüyor (https://android.googlesource.com/platform/frameworks/base.git/+/master/core/jni/android/graphics/BitmapFactory.cpp) Android 7.0'da bazı kodlar eklendi ve sorun oluştu.

// Create the codec. 
NinePatchPeeker peeker; 
std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(), &peeker)); 
if (!codec.get()) { 
    return nullObjectReturn("SkAndroidCodec::NewFromStream returned null"); 
} 

Ve biz inJustDecodeBounds=false set ama sonra bit eşlem yaratmadı BitmapFactory.decodeStream yöntemini öğrendim ben ciltli çözme olmadan bitmap oluşturmak çalıştığınızda. Bu çalışıyor! Sorun, BitmapFactory.decodeStream'u tekrar aradığımızda bu InputStream'in güncellenmediği BitmapOptions ile ilgilidir.

yüzden

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

O var onu yeniden önce InputStream her zaman sıfırlamak zorunda benziyor yine kod çözme önce InputStream sıfırlayın.

+0

Bu hile yaptı. Sadece InputStream'i sıfırlama. Yardımın için teşekkürler. – Savari

+0

Bu hile denedim, ancak dinlenirken "işaretleme/sıfırlama desteklenmiyor" IOException almaya devam ediyorum. Ama ben FileInputStream kullanıyorum, çünkü SD karttan bitmap yüklemeye çalışıyorum. –

+0

Dosyadan depolama yapmak için FileInputStream başka bir yolu var mı? –

0

Bu, herhangi birine yardımcı olursa, görüntülerin yeniden boyutlandırılması için daha önce kullanılmış olan eski kodun güncellenmesiyle benzer bir soruna çarpıyordum. Sorunum, görüntü dosyasından veri okuduğum yığının daha da ötesindeydi. Kullanımdan kaldırılmış olan IOUtils.toByteArray(Reader)'u kullandım. Doğrudan URI'den bir bayt dizisine dönüştürmeye geçtim ve şimdi iyi çalışıyor. Aşağıda bu yeni yöntemin örneğin resizeImage() ilk iki satırını bakın (kod gerisi benim görüntüyü yeniden boyutlandırmak için izin verir.)

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; 
} 
İlgili konular