Android
eccezioni
Ricerca…
NetworkOnMainThreadException
Dalla documentazione :
L'eccezione che viene generata quando un'applicazione tenta di eseguire un'operazione di rete sul thread principale.
Questo viene lanciato solo per applicazioni che hanno come target l'SDK Honeycomb o superiore. Le applicazioni che hanno come target versioni precedenti dell'SDK sono autorizzate a fare networking sui loro thread del ciclo degli eventi principali, ma sono fortemente scoraggiate.
Ecco un esempio di un frammento di codice che può causare quell'eccezione:
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);
}
}
}
}
}
Sopra il codice verrà NetworkOnMainThreadException
per le applicazioni di targeting Honeycomb SDK (Android v3.0) o superiore poiché l'applicazione sta tentando di eseguire un'operazione di rete sul thread principale.
Per evitare questa eccezione, le operazioni di rete devono sempre essere eseguite in un'attività in background tramite AsyncTask
, Thread
, IntentService
, ecc.
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
Questo è un molto comune Exception
. Fa fermare la tua applicazione durante l'avvio o l'esecuzione della tua app. Nel LogCat
vedi il messaggio:
android.content.ActivityNotFoundException : Unable to find explicit activity class;
have you declared this activity in your AndroidManifest.xml?
In questo caso, controlla se hai dichiarato la tua attività nel file AndroidManifest.xml
.
Il modo più semplice per dichiarare la tua Activity
in AndroidManifest.xml
è:
<activity android:name="com.yourdomain.YourStoppedActivity" />
OutOfMemoryError
Questo è un errore di runtime che si verifica quando si richiede una grande quantità di memoria nell'heap. Questo è comune quando si carica un Bitmap in un ImageView.
Hai alcune opzioni:
- Utilizzare un heap di applicazioni di grandi dimensioni
Aggiungi l'opzione "largeHeap" al tag dell'applicazione nel tuo AndroidManifest.xml. Ciò renderà disponibile più memoria per la tua app, ma probabilmente non risolverà il problema di root.
<application largeHeap="true" ... >
- Ricicla i tuoi bitmap
Dopo aver caricato una bitmap, assicurati di riciclarla e liberare memoria:
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
- Carica bitmap campionati in memoria
Evita di caricare l'intera bitmap in memoria in una sola volta campionando una dimensione ridotta, utilizzando BitmapOptions e inSampleSize.
Vedi la documentazione di Android, per esempio
DexException
com.android.dex.DexException: Multiple dex files define Lcom/example/lib/Class;
Questo errore si verifica perché l'app, in fase di pacchettizzazione, trova due file .dex
che definiscono lo stesso insieme di metodi.
Solitamente ciò accade perché l'app ha accidentalmente acquisito 2 dipendenze separate sulla stessa libreria.
Ad esempio, supponiamo di avere un progetto e di affidarti a due librerie: A
e B
, ciascuna delle quali ha le sue dipendenze. Se la libreria B
ha già una dipendenza dalla libreria A
, questo errore verrà generato se la libreria A
viene aggiunta al progetto da sola. Compilare la libreria B
fornisce già il set di codice da A
, quindi quando il compilatore va a raggruppare la libreria A
, trova i metodi della libreria A
già impacchettati.
Per risolvere, assicurati che nessuna delle tue dipendenze possa essere accidentalmente aggiunta due volte in questo modo
Eccezione non rilevata
Se vuoi gestire le eccezioni non rilevate prova a catturarle tutte nel metodo onCreate della tua 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();
}
}
Registrazione del proprio gestore per eccezioni impreviste
È così che puoi reagire alle eccezioni che non sono state rilevate, in modo simile allo standard del sistema "L'applicazione XYZ si è bloccata"
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
}
}
Quindi registra questa classe di applicazione nel tuo AndroidManifest.xml:
<application android:name="de.ioxp.arkmobile.MyApplication" >