package com.roboo.like.google.commons;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnKeyListener;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.Process;
import android.view.KeyEvent;
import android.widget.Toast;
import com.roboo.like.google.GoogleApplication;
import com.roboo.like.google.R;
/**
* 处理未捕获的异常, 并且把错误信息保存到文件中 , 如果可以的话,再上传到服务器上进行错误分析
* @author bo.li
*
* 2014-8-7 下午12:57:49
*
* TODO
*/
public class CrashException implements UncaughtExceptionHandler
{
private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/crash/";
private static final String FILE_NAME = "crash";
// log文件的后缀名
private static final String FILE_NAME_SUFFIX = ".trace";
private Activity activity;
public CrashException(Activity activity)
{
this.activity = activity;
}
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
System.out.println("程序出现异常!");
System.out.println("线程Id = " + thread.getId() + " 线程名称 = " + thread.getName() + " 错误原因 = " + ex.toString());
ex.printStackTrace();
saveExceptionToSDCard(ex);
showExceptionDialog();
}
/***
* 保存异常信息到sd卡,如果存在的话
*
* @param ex
*/
@SuppressLint("SimpleDateFormat")
private void saveExceptionToSDCard(Throwable ex)
{
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
return;
}
File dir = new File(PATH);
if (!dir.exists())
{
dir.mkdirs();
}
deleteCrashFile(dir);
long currentTime = System.currentTimeMillis();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(currentTime));
String fileName = time + "_" + System.currentTimeMillis();
// 以当前时间创建log文件
File file = new File(PATH + FILE_NAME + fileName + FILE_NAME_SUFFIX);
try
{
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
// 导出发生异常的时间
pw.println(time);
// 导出手机信息
getPhoneInfo(pw);
pw.println();
// 导出异常的调用栈信息
ex.printStackTrace(pw);
pw.flush();
pw.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* 删除以前记录的异常文件
*
* @param dir
*/
private void deleteCrashFile(File dir)
{
if (dir != null)
{
for (File file : dir.listFiles())
{
file.delete();
}
System.out.println("清空所以的异常文件成功");
}
}
/**
* 获取发生异常的手机信息
*
* @param pw
* @throws NameNotFoundException
*/
private void getPhoneInfo(PrintWriter pw) throws NameNotFoundException
{
// 应用的版本名称和版本号
PackageManager pm = activity.getPackageManager();
PackageInfo pi = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_ACTIVITIES);
pw.print("App Version: ");
pw.print(pi.versionName);
pw.print('_');
pw.println(pi.versionCode);
// android版本号
pw.print("OS Version: ");
pw.print(Build.VERSION.RELEASE);
pw.print("_");
pw.println(Build.VERSION.SDK_INT);
// 手机制造商
pw.print("Vendor: ");
pw.println(Build.MANUFACTURER);
// 手机型号
pw.print("Model: ");
pw.println(Build.MODEL);
// cpu架构
pw.print("CPU ABI: ");
pw.println(Build.CPU_ABI);
System.out.println("获取手机信息完毕");
}
/**
* 弹出异常对话框
*/
private void showExceptionDialog()
{
Runnable runnable = new Runnable()
{
public void run()
{
Looper.prepare();
final AlertDialog dialog = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setTitle("很抱歉").setMessage("程序崩溃了...,我也崩溃了...").setNegativeButton("退出吧", new OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
GoogleApplication.getInstance().exitClient();
Process.killProcess(Process.myPid());
System.exit(10);
}
}).setPositiveButton("重新打开", new OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setAction(Intent.ACTION_MAIN);
intent.setClassName(activity.getPackageName(), activity.getPackageName() + ".StartActivity");
activity.startActivity(intent);
dialog.dismiss();
GoogleApplication.getInstance().exitClient();
}
}).create();
dialog.setCanceledOnTouchOutside(false);
if (!activity.isFinishing())
{
dialog.show();
}
dialog.setOnKeyListener(new OnKeyListener()
{
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
dialog.dismiss();
Toast.makeText(activity, "返回", Toast.LENGTH_SHORT).show();
GoogleApplication.getInstance().exitClient();
Process.killProcess(Process.myPid());
System.exit(10);
return true;
}
return false;
}
});
Looper.loop();
}
};
new Thread(runnable).start();
}
public static CrashException getInstance(Activity activity)
{
return new CrashException(activity);
}
}