Android
Des exceptions
Recherche…
NetworkOnMainThreadException
De la documentation :
Exception levée lorsqu'une application tente d'effectuer une opération de mise en réseau sur son thread principal.
Ceci est seulement lancé pour les applications ciblant le SDK Honeycomb ou supérieur. Les applications ciblant les versions antérieures du SDK sont autorisées à faire du réseautage sur leurs principaux threads de boucle d'événement, mais elles sont fortement déconseillées.
Voici un exemple de fragment de code qui peut provoquer cette exception:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uri.Builder builder = new Uri.Builder().scheme("http").authority("www.google.com");
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
URL url;
try {
url = new URL(builder.build().toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
} catch (IOException e) {
Log.e("TAG","Connection error", e);
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("TAG", "Error closing stream", e);
}
}
}
}
}
Le code ci-dessus lancera NetworkOnMainThreadException
pour les applications ciblant Honeycomb SDK (Android v3.0) ou supérieur car l'application tente d'effectuer une opération réseau sur le thread principal.
Pour éviter cette exception, vos opérations réseau doivent toujours s'exécuter dans une tâche en arrière-plan via une tâche AsyncTask
, Thread
, IntentService
, etc.
private class MyAsyncTask extends AsyncTask<String, Integer, Void> {
@Override
protected Void doInBackground(String[] params) {
Uri.Builder builder = new Uri.Builder().scheme("http").authority("www.google.com");
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
URL url;
try {
url = new URL(builder.build().toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
} catch (IOException e) {
Log.e("TAG","Connection error", e);
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("TAG", "Error closing stream", e);
}
}
}
return null;
}
}
ActivityNotFoundException
C'est une Exception
très commune. Cela provoque l'arrêt de votre application pendant le démarrage ou l'exécution de votre application. Dans le LogCat
vous voyez le message:
android.content.ActivityNotFoundException : Unable to find explicit activity class;
have you declared this activity in your AndroidManifest.xml?
Dans ce cas, vérifiez si vous avez déclaré votre activité dans le fichier AndroidManifest.xml
.
La manière la plus simple de déclarer votre Activity
dans AndroidManifest.xml
est la suivante:
<activity android:name="com.yourdomain.YourStoppedActivity" />
OutOfMemoryError
Ceci est une erreur d'exécution qui se produit lorsque vous demandez une grande quantité de mémoire sur le tas. Ceci est courant lors du chargement d'un bitmap dans un ImageView.
Vous avez des options:
- Utilisez un grand tas d'applications
Ajoutez l'option "largeHeap" à la balise d'application dans votre fichier AndroidManifest.xml. Cela rendra plus de mémoire disponible pour votre application, mais ne résoudra probablement pas le problème.
<application largeHeap="true" ... >
- Recyclez vos bitmaps
Après avoir chargé un bitmap, assurez-vous de le recycler et de libérer de la mémoire:
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
- Charger des bitmaps échantillonnés en mémoire
Évitez de charger l'intégralité du bitmap en mémoire en échantillonnant une taille réduite, en utilisant BitmapOptions et inSampleSize.
Voir la documentation Android par exemple
DexException
com.android.dex.DexException: Multiple dex files define Lcom/example/lib/Class;
Cette erreur se produit car l'application, lors de la mise en package, trouve deux fichiers .dex
qui définissent le même ensemble de méthodes.
Cela se produit généralement parce que l'application a accidentellement acquis 2 dépendances distinctes sur la même bibliothèque.
Par exemple, supposons que vous ayez un projet et que vous souhaitiez vous appuyer sur deux bibliothèques: A
et B
, chacune ayant ses propres dépendances. Si la bibliothèque B
déjà une dépendance à la bibliothèque A
, cette erreur sera renvoyée si la bibliothèque A
est ajoutée au projet par elle-même. La bibliothèque de compilation B
donnait déjà le jeu de code de A
, donc lorsque le compilateur va regrouper la bibliothèque A
, il trouve les méthodes de la bibliothèque A
déjà empaquetées.
Pour résoudre ce problème, assurez-vous qu'aucune de vos dépendances ne soit ajoutée accidentellement deux fois de cette manière.
Exception non interceptée
Si vous souhaitez gérer des exceptions non interceptées, essayez de les récupérer toutes avec la méthode onCreate de votre classe Application:
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
Thread
.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable e) {
Log.e(TAG,
"Uncaught Exception thread: "+thread.getName()+"
"+e.getStackTrace());
handleUncaughtException (thread, e);
}
});
} catch (SecurityException e) {
Log.e(TAG,
"Could not set the Default Uncaught Exception Handler:"
+e.getStackTrace());
}
}
private void handleUncaughtException (Thread thread, Throwable e){
Log.e(TAG, "uncaughtException:");
e.printStackTrace();
}
}
Enregistrement de votre propre gestionnaire pour des exceptions inattendues
Voici comment vous pouvez réagir aux exceptions qui n'ont pas été détectées, comme le système standard "Application XYZ a planté"
import android.app.Application;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Application class writing unexpected exceptions to a crash file before crashing.
*/
public class MyApplication extends Application {
private static final String TAG = "ExceptionHandler";
@Override
public void onCreate() {
super.onCreate();
// Setup handler for uncaught exceptions.
final Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable e) {
try {
handleUncaughtException(e);
System.exit(1);
} catch (Throwable e2) {
Log.e(TAG, "Exception in custom exception handler", e2);
defaultHandler.uncaughtException(thread, e);
}
}
});
}
private void handleUncaughtException(Throwable e) throws IOException {
Log.e(TAG, "Uncaught exception logged to local file", e);
// Create a new unique file
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US);
String timestamp;
File file = null;
while (file == null || file.exists()) {
timestamp = dateFormat.format(new Date());
file = new File(getFilesDir(), "crashLog_" + timestamp + ".txt");
}
Log.i(TAG, "Trying to create log file " + file.getPath());
file.createNewFile();
// Write the stacktrace to the file
FileWriter writer = null;
try {
writer = new FileWriter(file, true);
for (StackTraceElement element : e.getStackTrace()) {
writer.write(element.toString());
}
} finally {
if (writer != null) writer.close();
}
// You can (and probably should) also display a dialog to notify the user
}
}
Enregistrez ensuite cette classe d'application dans votre fichier AndroidManifest.xml:
<application android:name="de.ioxp.arkmobile.MyApplication" >