حتما برای دولاپر های عزیز اندروید پیش اومده که بعد از آماده سازی اولیه اپ و نصب روی گوشی ، در حالی که به نظر میاد همه چیز داره خوب کار میکنه اپ کرش می کنه و یه سوال بسیار بزرگ عین شاخ از سرشون بیرون میزنه ! اگر مثل من دسترسی به محیط دیباگ android studio به سرعت در اختیارتون نیست و یا نمیدونید کجا خطا اتفاق افتاده تا سریع برید همون خط رو دیباگ دوباره کنید و میخواید که خطا روی خود گوشی بهتون نمایش داده بشه ، این روش کارایی خوبی خواهد داشت .
Android Global Exception Handler
اینکار به سادگی با java.lang.Thread.UncaughtExceptionHandler قابل انجامه ولی باید یکی از دو روش زیر رو انتخاب کنید :
1.خطایابی در سطح Application که در این صورت نمی توانید dialog باز کنید و یا اکتیویتی جدیدی اجرا کنید با این حال هر نوع خطایابی قابل اجرا خواهد شد
2.خطایابی در سطح Activity که به راحتی میتوان dialog یا اکتیویتی دیگری باز کرد ولی باید در یک کلاس ارث بری شده توسط اکتیویتی ها نوشته شود ( مثلا BaseActivity )
خطایابی در سطح Application
در این روش log ایرور بصورت فایل روی دستگاه ذخیره خواهد شد تا در اجرای دوباره اپ بتوان از آن استفاده کرده و متن خطا را نمایش داد
public class LoggingExceptionHandler implements Thread.UncaughtExceptionHandler { private final static String TAG = LoggingExceptionHandler.class.getSimpleName(); private final static String ERROR_FILE = MyAuthException.class.getSimpleName() + ".error"; private final Context context; private final Thread.UncaughtExceptionHandler rootHandler; public LoggingExceptionHandler(Context context) { this.context = context; // we should store the current exception handler -- to invoke it for all not handled exceptions ... rootHandler = Thread.getDefaultUncaughtExceptionHandler(); // we replace the exception handler now with us -- we will properly dispatch the exceptions ... Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(final Thread thread, final Throwable ex) { try { Log.d(TAG, "called for " + ex.getClass()); // assume we would write each error in one file ... File f = new File(context.getFilesDir(), ERROR_FILE); // log this exception ... FileUtils.writeStringToFile(f, ex.getClass().getSimpleName() + " " + System.currentTimeMillis() + "\n", true); } catch (Exception e) { Log.e(TAG, "Exception Logger failed!", e); } public static final List<String> readExceptions(Context context) { List<String> exceptions = new ArrayList<>(); File f = new File(context.getFilesDir(), ERROR_FILE); if (f.exists()) { try { exceptions = FileUtils.readLines(f); } catch (IOException e) { Log.e(TAG, "readExceptions failed!", e); } } return exceptions; } }
حالا باید ان را به سطح Application ضمیمه کنیم
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); new LoggingExceptionHandler(this); } }
یادتان نرود که در فایل AndroidManifest نیز تغییرات زیر را انجام دهید
<application android:name=".MyApp"
خطایابی در سطح Activity
public class MyExceptionHandler implements Thread.UncaughtExceptionHandler { public static final String EXTRA_MY_EXCEPTION_HANDLER = "EXTRA_MY_EXCEPTION_HANDLER"; private final Activity context; private final Thread.UncaughtExceptionHandler rootHandler; public MyExceptionHandler(Activity context) { this.context = context; // we should store the current exception handler -- to invoke it for all not handled exceptions ... rootHandler = Thread.getDefaultUncaughtExceptionHandler(); // we replace the exception handler now with us -- we will properly dispatch the exceptions ... Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(final Thread thread, final Throwable ex) { if (ex instanceof MyAuthException) { // note we can't just open in Android an dialog etc. we have to use Intents here // http://stackoverflow.com/questions/13416879/show-a-dialog-in-thread-setdefaultuncaughtexceptionhandler Intent registerActivity = new Intent(context, AuthActivity.class); registerActivity.putExtra(EXTRA_MY_EXCEPTION_HANDLER, MyExceptionHandler.class.getName()); registerActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); registerActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); context.startActivity(registerActivity); // make sure we die, otherwise the app will hang ... android.os.Process.killProcess(android.os.Process.myPid()); System.exit(0); } else { rootHandler.uncaughtException(thread, ex); } } }
public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new MyExceptionHandler(BaseActivity.this); } }