网站维护工作内容有什么,wordpress推广,溧阳市建设网站,ppt制作入门教程程序员最头疼的事情就是bug和debug。这次debug长达20天#xff0c;搞的我心力交瘁。累#xff0c;因为Android兼容性#xff0c;不同手机会有不同的bug出来#xff0c;而且很难复现#xff0c;所以就上网找了下类似保存错误log到文件再上传到服务器#xff0c;现把源码也…程序员最头疼的事情就是bug和debug。这次debug长达20天搞的我心力交瘁。累因为Android兼容性不同手机会有不同的bug出来而且很难复现所以就上网找了下类似保存错误log到文件再上传到服务器现把源码也共享出来。上传至服务器的代码我没加。相信大家都有现成的代码了。先讲下原理跟JavaEE的自定义异常捕获一样将错误一直向上抛然后在最上层统一处理。这里就可以获得Exception Message进行保存操作异常捕获类如下/*** author Stay* 在Application中统一捕获异常保存到文件中下次再打开时上传*/public class CrashHandler implements UncaughtExceptionHandler {/** 是否开启日志输出,在Debug状态下开启,* 在Release状态下关闭以提示程序性能* */public static final boolean DEBUG true;/** 系统默认的UncaughtException处理类 */private Thread.UncaughtExceptionHandler mDefaultHandler;/** CrashHandler实例 */private static CrashHandler INSTANCE;/** 程序的Context对象 */// private Context mContext;/** 保证只有一个CrashHandler实例 */private CrashHandler() {}/** 获取CrashHandler实例 ,单例模式*/public static CrashHandler getInstance() {if (INSTANCE null) {INSTANCE new CrashHandler();}return INSTANCE;}/*** 初始化,注册Context对象,* 获取系统默认的UncaughtException处理器,* 设置该CrashHandler为程序的默认处理器** param ctx*/public void init(Context ctx) {// mContext ctx;mDefaultHandler Thread.getDefaultUncaughtExceptionHandler();Thread.setDefaultUncaughtExceptionHandler(this);}/*** 当UncaughtException发生时会转入该函数来处理*/Overridepublic void uncaughtException(Thread thread, Throwable ex) {if (!handleException(ex) mDefaultHandler ! null) {//如果用户没有处理则让系统默认的异常处理器来处理mDefaultHandler.uncaughtException(thread, ex);} else { //如果自己处理了异常则不会弹出错误对话框则需要手动退出apptry {Thread.sleep(3000);} catch (InterruptedException e) {}android.os.Process.killProcess(android.os.Process.myPid());System.exit(10);}}/*** 自定义错误处理,收集错误信息* 发送错误报告等操作均在此完成.* 开发者可以根据自己的情况来自定义异常处理逻辑* return* true代表处理该异常不再向上抛异常* false代表不处理该异常(可以将该log信息存储起来)然后交给上层(这里就到了系统的异常处理)去处理* 简单来说就是true不会弹出那个错误提示框false就会弹出*/private boolean handleException(final Throwable ex) {if (ex null) {return false;}// final String msg ex.getLocalizedMessage();final StackTraceElement[] stack ex.getStackTrace();final String message ex.getMessage();//使用Toast来显示异常信息new Thread() {Overridepublic void run() {Looper.prepare();// Toast.makeText(mContext, 程序出错啦: message, Toast.LENGTH_LONG).show();// 可以只创建一个文件以后全部往里面append然后发送这样就会有重复的信息个人不推荐String fileName crash- System.currentTimeMillis() .log;File file new File(Environment.getExternalStorageDirectory(), fileName);try {FileOutputStream fos new FileOutputStream(file,true);fos.write(message.getBytes());for (int i 0; i stack.length; i) {fos.write(stack[i].toString().getBytes());}fos.flush();fos.close();} catch (Exception e) {}Looper.loop();}}.start();return false;}// TODO 使用HTTP Post 发送错误报告到服务器 这里不再赘述// private void postReport(File file) {// 在上传的时候还可以将该app的version该手机的机型等信息一并发送的服务器// Android的兼容性众所周知所以可能错误不是每个手机都会报错还是有针对性的去debug比较好// }}在Application onCreate时就注册ExceptionHandler此后只要程序在抛异常后就能捕获到。public class App extends Application{Overridepublic void onCreate() {super.onCreate();CrashHandler crashHandler CrashHandler.getInstance();//注册crashHandlercrashHandler.init(getApplicationContext());}}?public class LogActivity extends Activity {Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);try {//制造bugFile file new File(Environment.getExternalStorageState() ,crash.bin);FileInputStream fis new FileInputStream(file);byte[] buffer new byte[1024];fis.read(buffer);} catch (Exception e) {//这里不能再向上抛异常如果想要将log信息保存起来则抛出runtime异常// 让自定义的handler来捕获统一将文件保存起来上传throw new RuntimeException(e);}}}注意如果catch后不throw就默认是自己处理了ExceptionHandler不会捕获异常了。再分享一个Log的封装类只要在这里设置DEBUG的值就能让控制台是否打印出logpublic class DebugUtil {public static final String TAG ICON;public static final boolean DEBUG true;public static void toast(Context context,String content){Toast.makeText(context, content, Toast.LENGTH_SHORT).show();}public static void debug(String tag,String msg){if (DEBUG) {Log.d(tag, msg);}}public static void debug(String msg){if (DEBUG) {Log.d(TAG, msg);}}public static void error(String tag,String error){Log.e(tag, error);}public static void error(String error){Log.e(TAG, error);}}