我正在使用android 4.0.4,内核3.0.8 +
BitmapFactory.decodeFile经常返回一个空位图。
请注意,如果位图工厂无法加载位图,我会立即再次尝试,最多4次,这通常有效(!)
有很多人抱怨这个。大多数问题的答案涉及位图的放置位置,或者刷新的输入流/ http连接的性质等等。我已经排除了这些 - 事实上,我已经将我的问题简化为一个如此荒谬的简单的Android应用程序,它可以被称为测试用例。
我的应用程序有一个活动,其中包含一个按钮,当按下该按钮时,会启动一个循环通过外部文件目录的线程,尝试将其中的所有内容加载到位图中。我不使用位图,或保留它,或任何东西,我只是加载并忘记:
public class MainActivity extends Activity {
private static final String TAG = "bmpbash";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onGo(View view) {
view.setVisibility(View.GONE);
start();
}
/**
* Start the thread.
*/
public void start() {
Runnable r = new Runnable() {
@Override
public void run() {
mainLoop();
}
};
Thread thread = new Thread(r);
thread.start();
}
public void mainLoop() {
int index = 0;
File top = getExternalFilesDir(null);
while (true) {
File[] files = top.listFiles();
if (files.length < 1) {
Log.e(TAG, "no files found");
} else {
if (files.length <= index) {
index = 0;
}
File file = files[index];
//byte[] data = readFile(file);
try {
boolean ok = false;
for (int i = 0; i < 4 && !ok; ++i) {
//Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
if (bitmap == null) {
Log.e(TAG, file.getName() + "[" + i + "] - NULL bitmap");
} else {
ok = true;
Log.w(TAG, file.getName() + "[" + i + "] - OK");
}
}
} catch (Exception e) {
Log.e(TAG, file.getName() + " - DIED", e);
} catch (OutOfMemoryError oom) {
Log.e(TAG, file.getName() + " - OOM");
}
++index;
}
}
}
}
我会看到这样的输出:
10-22 17:27:57.688: W/bmpbash(1131): translucent.png[0] - OK
10-22 17:27:57.698: W/bmpbash(1131): fearthecow.png[0] - OK
10-22 17:27:57.798: W/bmpbash(1131): gui2.png[0] - OK
10-22 17:27:57.888: W/bmpbash(1131): gui.png[0] - OK
10-22 17:27:58.058: W/bmpbash(1131): boot.png[0] - OK
10-22 17:27:58.218: E/bmpbash(1131): trainer2.png[0] - NULL bitmap
10-22 17:27:58.378: W/bmpbash(1131): trainer2.png[1] - OK
您将在上面的代码中看到一个注释掉的替代加载序列,其中而不是使用decodeFile我将文件加载到byte []然后使用decodeByteArray。这具有相同的效果(decodeByteArray失败,然后立即在完全相同的字节数组上成功!),但我注意到失败不太常见。
在decodeFile的情况下,10次尝试中可能有1次返回null。在decodeByteArray的情况下,也许只有100中的1个。它并不总是同一个文件失败,但有些文件似乎比其他文件更频繁地失败。
我最好的预感是png解码器出现故障,如果它运行的时间较长,则更容易发生,但之后我有点迷失了。如果有人对这个问题有所了解,或者加载png文件的其他方法,我真的很感激!
答案 0 :(得分:2)
进一步的实验表明,这种情况发生在我拥有的每台设备上(我有很多),它运行4.0.4的特殊风味,但即使在4.1.1设备上过夜运行也不会发生。考虑到代码的简单性,以及后来的Android版本没有复制它,我倾向于将此标记为Android中的一个错误,在某些时候已修复。有了这些信息可以提供帮助,我将假设这是SKIA中的一个错误,这个错误在这个主题中被认为是nth degree:
http://code.google.com/p/android/issues/detail?id=6066
我的总体看法是,这是一个很少发生的错误,其存在被大量未充分处理其输入流的人所掩盖。我在这个问题的任何地方看到的唯一答案是尝试在循环(OMG)中加载位图。但是,如果因为他们有这些症状而找到这个问题的数百人可以100%确定他们使用可行的刷新输入流然后再诉诸这种邪恶的黑客,那么我认为我们我们都很感激!
由于
P.S。将这称为“答案”感到内疚是否可以?
答案 1 :(得分:0)
我的问题很相似,但我只是通过向外部存储添加访问权限来解决它:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
希望这有帮助。