Android
Wyjątki
Szukaj…
NetworkOnMainThreadException
Z dokumentacji :
Wyjątek zgłaszany, gdy aplikacja próbuje wykonać operację sieciową w swoim głównym wątku.
Jest to generowane tylko w przypadku aplikacji kierowanych na zestaw SDK o strukturze plastra miodu lub nowszy. Aplikacje kierowane na wcześniejsze wersje SDK mogą tworzyć sieci w swoich głównych wątkach pętli zdarzeń, ale jest to bardzo odradzane.
Oto przykład fragmentu kodu, który może powodować ten wyjątek:
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);
}
}
}
}
}
NetworkOnMainThreadException
kod spowoduje NetworkOnMainThreadException
dla aplikacji atakujących pakiet Honeycomb SDK (Android v3.0) lub wyższy, ponieważ aplikacja próbuje wykonać operację sieciową w głównym wątku.
Aby uniknąć tego wyjątku, operacje sieciowe muszą zawsze być wykonywane w zadaniu w tle za pośrednictwem AsyncTask
, Thread
, IntentService
itp.
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
Jest to bardzo powszechny Exception
. Powoduje zatrzymanie aplikacji podczas uruchamiania lub wykonywania aplikacji. W LogCat
zobaczysz komunikat:
android.content.ActivityNotFoundException : Unable to find explicit activity class;
have you declared this activity in your AndroidManifest.xml?
W takim przypadku sprawdź, czy zadeklarowałeś swoją aktywność w pliku AndroidManifest.xml
.
Najprostszym sposobem na zadeklarowanie swojej Activity
w AndroidManifest.xml
jest:
<activity android:name="com.yourdomain.YourStoppedActivity" />
Błąd brak pamięci
Jest to błąd środowiska wykonawczego, który występuje, gdy żądasz dużej ilości pamięci na stercie. Jest to powszechne podczas ładowania mapy bitowej do ImageView.
Masz kilka opcji:
- Użyj dużej sterty aplikacji
Dodaj opcję „largeHeap” do znacznika aplikacji w pliku AndroidManifest.xml. Dzięki temu aplikacja zyska więcej pamięci, ale prawdopodobnie nie usunie problemu z rootem.
<application largeHeap="true" ... >
- Przetwarzaj swoje mapy bitowe
Po załadowaniu mapy bitowej należy ją ponownie przetworzyć i zwolnić pamięć:
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
- Załaduj próbkowane mapy bitowe do pamięci
Unikaj ładowania całej mapy bitowej do pamięci jednocześnie, próbkując zmniejszony rozmiar, używając BitmapOptions i inSampleSize.
Zobacz na przykład dokumentację Androida
DexException
com.android.dex.DexException: Multiple dex files define Lcom/example/lib/Class;
Ten błąd występuje, ponieważ podczas pakowania aplikacja znajduje dwa pliki .dex
, które definiują ten sam zestaw metod.
Zwykle dzieje się tak, ponieważ aplikacja przypadkowo uzyskała 2 oddzielne zależności od tej samej biblioteki.
Załóżmy na przykład, że masz projekt i chcesz polegać na dwóch bibliotekach: A
i B
, z których każda ma swoje zależności. Jeśli biblioteka B
ma już zależność od biblioteki A
, ten błąd zostanie zgłoszony, jeśli sama biblioteka A
zostanie dodana do projektu. Kompilacja biblioteki B
dała już zestaw kodu z A
, więc kiedy kompilator przejdzie do biblioteki pakietów A
, znajdzie metody biblioteki A
już spakowane.
Aby rozwiązać problem, upewnij się, że żadna z twoich zależności nie może zostać przypadkowo dodana dwukrotnie w taki sposób
UncaughtException
Jeśli chcesz obsłużyć nieprzechwycone wyjątki, spróbuj złapać je wszystkie w metodzie onCreate klasy aplikacji:
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();
}
}
Rejestracja własnego modułu obsługi dla nieoczekiwanych wyjątków
W ten sposób możesz zareagować na wyjątki, które nie zostały wychwycone, podobnie jak w przypadku standardowego systemu „Aplikacja XYZ uległa awarii”
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
}
}
Następnie zarejestruj tę klasę aplikacji w pliku AndroidManifest.xml:
<application android:name="de.ioxp.arkmobile.MyApplication" >