Android
Uitzonderingen
Zoeken…
NetworkOnMainThreadException
Uit de documentatie :
De uitzondering die wordt gegenereerd wanneer een toepassing een netwerkbewerking op de hoofdthread probeert uit te voeren.
Dit wordt alleen gegenereerd voor toepassingen die zijn gericht op de Honeycomb SDK of hoger. Toepassingen die zijn getarget op eerdere SDK-versies mogen netwerken op hun hoofdgebeurtenislusjes, maar dit wordt sterk afgeraden.
Hier is een voorbeeld van een codefragment dat die uitzondering kan veroorzaken:
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);
}
}
}
}
}
Bovenstaande code werpt NetworkOnMainThreadException
voor toepassingen die zijn gericht op Honeycomb SDK (Android v3.0) of hoger, omdat de toepassing een netwerkbewerking op de NetworkOnMainThreadException
probeert uit te voeren.
Om deze uitzondering te voorkomen, moeten uw netwerkactiviteiten altijd in een achtergrondtaak worden uitgevoerd via een AsyncTask
, Thread
, IntentService
, enz.
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
Dit is een veel voorkomende Exception
. Het zorgt ervoor dat uw applicatie stopt tijdens het starten of uitvoeren van uw app. In de LogCat
ziet u het bericht:
android.content.ActivityNotFoundException : Unable to find explicit activity class;
have you declared this activity in your AndroidManifest.xml?
Controleer in dit geval of u uw activiteit in het bestand AndroidManifest.xml
hebt aangegeven.
De eenvoudigste manier om uw Activity
in AndroidManifest.xml
is:
<activity android:name="com.yourdomain.YourStoppedActivity" />
Onvoldoende geheugen fout
Dit is een runtime-fout die optreedt wanneer u een grote hoeveelheid geheugen op de heap aanvraagt. Dit is gebruikelijk bij het laden van een bitmap in een ImageView.
Je hebt een aantal opties:
- Gebruik een grote applicatieheap
Voeg de optie "largeHeap" toe aan de toepassingstag in uw AndroidManifest.xml. Hierdoor wordt meer geheugen beschikbaar voor uw app, maar wordt het rootprobleem waarschijnlijk niet opgelost.
<application largeHeap="true" ... >
- Recycle uw bitmaps
Na het laden van een bitmap, moet u deze recyclen en geheugen vrijmaken:
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
- Laad gesamplede bitmaps in het geheugen
Laad niet de hele bitmap in het geheugen door steekproeven van een kleinere grootte te nemen, met BitmapOptions en inSampleSize.
Zie bijvoorbeeld Android-documentatie
DexException
com.android.dex.DexException: Multiple dex files define Lcom/example/lib/Class;
Deze fout treedt op omdat de app bij het verpakken twee .dex
bestanden vindt die dezelfde set methoden definiëren.
Meestal gebeurt dit omdat de app per ongeluk 2 verschillende afhankelijkheden van dezelfde bibliotheek heeft verkregen.
Stel bijvoorbeeld dat u een project hebt en dat u op twee bibliotheken wilt vertrouwen: A
en B
, die elk hun eigen afhankelijkheden hebben. Als bibliotheek B
al afhankelijk is van bibliotheek A
, wordt deze fout gegenereerd als bibliotheek A
aan het project wordt toegevoegd. Het compileren van bibliotheek B
gaf al de set code van A
, dus wanneer de compiler naar bundelbibliotheek A
, vindt het de methoden van bibliotheek A
al verpakt.
Om dit op te lossen, moet u ervoor zorgen dat geen van uw afhankelijkheden per ongeluk tweemaal op een dergelijke manier kan worden toegevoegd
UncaughtException
Als je niet-gevangen uitzonderingen wilt verwerken, probeer ze dan allemaal te vangen in de onCreate-methode van je toepassingsklasse:
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();
}
}
Eigen Handler registreren voor onverwachte uitzonderingen
Dit is hoe u kunt reageren op niet-opgevangen uitzonderingen, vergelijkbaar met de standaard "Toepassing XYZ is gecrasht"
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
}
}
Registreer vervolgens deze toepassingsklasse in uw AndroidManifest.xml:
<application android:name="de.ioxp.arkmobile.MyApplication" >