今天公司拿来一台大型的安卓电视过来要把手机端的APP适配上去,当时心想只是适配唯一屏幕尺寸的设备而已,so easy!结果发现那台设备不管是通过OTG转USB还是abd直接调试都不行,那好吧,只能通过笨办法用QQ调一下发过去看看情况,然后接着改,结果竟然在设备上面发现了手机上没有闪退情况,这又没法调试,苦逼的程序员只能想到苦逼的办法:把错误LOG写入TXT,然后查看,好了直接上代码:
public class CrashManager implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
private Map<String, String> infos;
private MyApplication application;
public CrashManager(MyApplication application){
//获取系统默认的UncaughtExceptionHandler
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
}
private boolean handleException(final Throwable exc){
if (exc == null) {
return false;
}
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Log.i("tbcash","崩溃正在写入日志");
flushBufferedUrlsAndReturn();
//处理崩溃
collectDeviceAndUserInfo(application);
writeCrash(exc);
Looper.loop();
}
}).start();
return true;
}
/**
* 把未存盘的url和返回数据写入日志文件
*/
private void flushBufferedUrlsAndReturn(){
//TODO 可以在请求网络时把url和返回xml或json数据缓存在队列中,崩溃时先写入以便查明原因
}
/**
* 采集设备和用户信息
* @param context 上下文
*/
private void collectDeviceAndUserInfo(Context context){
PackageManager pm = context.getPackageManager();
infos = new HashMap<String, String>();
try {
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null?"null":pi.versionName;
String versionCode = pi.versionCode + "";
infos.put("versionName",versionName);
infos.put("versionCode",versionCode);
infos.put("crashTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("tbcash",e.getMessage());
}
Field[] fields = Build.class.getDeclaredFields();
try {
for (Field field : fields) {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
}
} catch (IllegalAccessException e) {
Log.e("tbcash",e.getMessage());
}
}
/**
* 采集崩溃原因
* @param exc 异常
*/
private void writeCrash(Throwable exc){
StringBuffer sb = new StringBuffer();
sb.append("------------------crash----------------------");
sb.append("\r\n");
for (Map.Entry<String,String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key+"="+value+"\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
exc.printStackTrace(pw);
Throwable excCause = exc.getCause();
while (excCause != null) {
excCause.printStackTrace(pw);
excCause = excCause.getCause();
}
pw.close();
String result = writer.toString();
sb.append(result);
sb.append("\r\n");
sb.append("-------------------end-----------------------");
sb.append("\r\n");
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
String sdcardPath = Environment.getExternalStorageDirectory().getPath();
String filePath = sdcardPath + "//tbcash/crash/";
writeLog(sb.toString(), filePath);
}
}
/**
*
* @param log 文件内容
* @param name 文件路径
* @return 返回写入的文件路径
* 写入Log信息的方法,写入到SD卡里面
*/
private String writeLog(String log, String name)
{
String filename = name + "tbcash"+ ".txt";
File file =new File(filename);
if(!file.getParentFile().exists()){
Log.i("tbcash","新建文件");
file.getParentFile().mkdirs();
}
if (file != null && file.exists() && file.length() + log.length() >= 64 * 1024) {
//控制日志文件大小
file.delete();
}
try
{
file.createNewFile();
FileWriter fw=new FileWriter(file,true);
BufferedWriter bw = new BufferedWriter(fw);
//写入相关Log到文件
bw.write(log);
bw.newLine();
bw.close();
fw.close();
return filename;
}
catch(IOException e)
{
Log.w("tbcash",e.getMessage());
return null;
}
}
@Override
public void uncaughtException(Thread thread, Throwable exc) {
if(!handleException(exc) && mDefaultHandler != null){
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, exc);
}else{
try{
Thread.sleep(2000);
}catch (InterruptedException e){
Log.w("tbcash",e.getMessage());
}
Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(
application.getApplicationContext(), 0, intent,
0);
//退出程序
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
//1秒后重启应用
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
restartIntent);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
}
创建一个CrashManager ,然后在Application里:
@Override
public void onCreate() {
super.onCreate();
initRongCloud();
init();
CrashManager crashHandler = new CrashManager(this);
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
if (Build.VERSION.SDK_INT >= 18){
builder.detectFileUriExposure();
}
StrictMode.setVmPolicy(builder.build());
}
这样就可以了!