Je suis sous Android 4.0.4, kernel 3.0.8+
De temps en temps BitmapFactory.decodeFile retourne un bitmap nul.
Notez que si l'usine de bitmaps échoue à charger le bitmap, j'essaie immédiatement à nouveau, jusqu'à 4 fois, et cela fonctionne souvent (!)
Beaucoup de personnes se plaignent de cela. La plupart des réponses aux questions impliquent l'endroit où le bitmap est placé, ou la nature du flux d'entrée effacé / connexion HTTP / autre. J'ai exclu ces causes - en fait, j'ai réduit mon problème à une application android d'une simplicité ridicule qui pourrait être appelée un cas de test.
Mon application a une seule activité, qui contient un seul bouton, qui lorsqu'il est pressé lance un thread qui parcourt le répertoire des fichiers externes en essayant de charger tout ce qui s'y trouve en bitmaps. Je n'utilise pas le bitmap, ni ne le garde, ni rien, je charge simplement et oublie :
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;
}
}
}
}
Je verrai une sortie comme ceci :
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
Vous remarquerez dans le code ci-dessus qu'il y a une séquence de chargement alternative mise en commentaire, dans laquelle au lieu d'utiliser decodeFile, je charge le fichier dans un byte[] et utilise ensuite decodeByteArray. Cela a le même effet (decodeByteArray échoue puis réussit immédiatement sur exactement le même tableau de bytes!), mais je note que les échecs sont beaucoup moins fréquents.
Dans le cas de decodeFile, peut-être 1 tentative sur 10 renvoie null. Dans le cas de decodeByteArray, peut-être seulement 1 sur 100. Ce n'est pas toujours le même fichier qui échoue, mais certains fichiers semblent échouer plus souvent que d'autres.
Mon meilleur soupçon est que le décodeur png a une défaillance qui est plus susceptible de se produire s'il fonctionne sur une plus longue période, mais après cela, je suis un peu perdu. Si quelqu'un peut éclairer le problème, ou proposer des approches alternatives pour charger des fichiers png, je vous en serais très reconnaissant !