来自Assets的BitmapFactory.decodeStream有时会在Android 7上失败

时间:2016-10-03 03:30:17

标签: android android-emulator android-7.0-nougat

我刚从androidTargetSdk = 23移到androidTargetSdk = 24。我也使用JDK 1.8和sourceCompatibility =“1.7”,targetCompatibility =“1.7”。

以下现有代码解码资产在Android Studio模拟器Galaxy_S6_API_24和Genymotion API 24模拟器上出现故障(但在运行API 19和21的实际设备上运行良好)。

myInputStream = getActivity().getAssets().open("images/" + imageName);
BitmapFactory.Options opts = new BitmapFactory.Options();

// Find the size of the image
// (http://developer.android.com/training/displaying-bitmaps/load-bitmap.html)
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(myInputStream, null, opts);

// For debugging this issue to keep it simple I've stopped calling calculateInSampleSize()
//opts.inSampleSize = ImageUtils.calculateInSampleSize(opts, width, height);
opts.inSampleSize = 1;
opts.inJustDecodeBounds = false;

bm = BitmapFactory.decodeStream(myInputStream, null, opts);
imageView.setImageBitmap( bm );

调试此代码时, myInputStream 不为null,因此找到资产。方法 decodeStream()返回null。

为了进一步调试,我将代码更改为以下内容。此代码有效 - BitmapFactory.decodeStream()返回一个有效的位图。

myInputStream = getActivity().getAssets().open("images/" + imageName);
BitmapFactory.Options opts = new BitmapFactory.Options();

// Find the size of the image
// (http://developer.android.com/training/displaying-bitmaps/load-bitmap.html)
opts.inJustDecodeBounds = true;
//BitmapFactory.decodeStream(myInputStream, null, opts);

// For debugging this issue to keep it simple I've stopped calling calculateInSampleSize()
//opts.inSampleSize = ImageUtils.calculateInSampleSize(opts, width, height);
opts.inSampleSize = 1;
opts.inJustDecodeBounds = false;

bm = BitmapFactory.decodeStream(myInputStream, null, opts);
imageView.setImageBitmap( bm );

顶部的失败代码和上面正在运行的代码之间的唯一区别是我已经注释掉了对BitmapFactory.decodeStream()的第一次调用。

为了进一步调试,我简化了代码。这有效:

myInputStream = getActivity().getAssets().open("images/" + imageName);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 1;
bm = BitmapFactory.decodeStream(myInputStream, null, opts);
imageView.setImageBitmap( bm );

但这无法显示图像(注意我在下面两次调用decodeStream):

myInputStream = getActivity().getAssets().open("images/" + imageName);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 1;
bm = BitmapFactory.decodeStream(myInputStream, null, opts);
bm = BitmapFactory.decodeStream(myInputStream, null, opts);
imageView.setImageBitmap( bm );

这也失败了:

myInputStream = getActivity().getAssets().open("images/" + imageName);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 1;
bm = BitmapFactory.decodeStream(myInputStream, null, opts);
BitmapFactory.Options opts2 = new BitmapFactory.Options();
opts2.inSampleSize = 1;
bm = BitmapFactory.decodeStream(myInputStream, null, opts2);
imageView.setImageBitmap( bm );

使用调试器,我已经进入了BitMapFactory.decodeStream()的API 24源代码。问题是由于对 nativeDecodeAsset()的调用失败。第二次使用相同的输入资产调用它总是失败。我的猜测是我正在使用正确的本机库,但它有一个错误或者某种程度上我正在使用的库是错误的。

正如我之前提到的,我在运行API 19和21的真实设备上没有看到这个问题。我只在Android Studio的仿真器Galaxy_S6_API_24和Genymotion API 24仿真器上看到它。

我不清楚如何调试这个。我在哪里可以获得与我的构建匹配的本机库的源代码?你能建议一个解决方案或者我应该检查什么来解决这个问题?我想在不必使用真实设备的情况下证明我的代码适用于Android 7.0!

2 个答案:

答案 0 :(得分:1)

这不是android的问题; 在方法decodestream()中使用输入流后,输入流变为null; 如果你想多次使用输入流,你应该每次重置它使用它的.reset()函数。

答案 1 :(得分:0)

一旦您从输入流中读取了内容(例如在BitmapFatory.decodeStream中),就无法再次备份到流的开头。可以将其想象为从字节数组中进行读取,而该数组中的读取索引对您不可用-每次读取时,您都会在上一次读取之后获得字节。

当通过myInputStream = getActivity()。getAssets()。open(“ images /” + imageName)将输入流初始化为资产的开始时,一旦调用BitmapFatory.decodeStream(),输入流就有效了指向资产之外。如果您尝试再次使用它,将无法正常工作。在这种情况下,必须在每次调用BitmapFatory.decodeStream()之前初始化输入流。