編輯:關於Android編程
不管你多麼仔細,程序總是會出錯,下面方法是個全局的異常捕獲方法!希望對大家有幫助!
1.用的時候,需要在applicaion裡面調用,代碼如下:
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
2. 下面是主要的功能類:
package com.google.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
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.util.Log;
import android.widget.Toast;
/**
* UncaughtException處理類,當程序發生Uncaught異常的時候,由該類來接管程序,並記錄發送錯誤報告.
*/
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private Thread.UncaughtExceptionHandler mDefaultHandler;// 系統默認的UncaughtException處理類
private static CrashHandler INSTANCE = new CrashHandler();// CrashHandler實例
private Context mContext;// 程序的Context對象
private Map<String, String> info = new HashMap<String, String>();// 用來存儲設備信息和異常信息
private SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd-HH-mm-ss");// 用於格式化日期,作為日志文件名的一部分
/** 保證只有一個CrashHandler實例 */
private CrashHandler() {}
/** 獲取CrashHandler實例 ,單例模式 */
public static CrashHandler getInstance() {
return INSTANCE;
}
//初始化
public void init(Context context) {
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 獲取系統默認的UncaughtException處理器
Thread.setDefaultUncaughtExceptionHandler(this);// 設置該CrashHandler為程序的默認處理器
}
/**
* 當UncaughtException發生時會轉入該重寫的方法來處理
*/
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果自定義的沒有處理則讓系統默認的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);// 如果處理了,讓程序繼續運行3秒再退出,保證文件保存並上傳到服務器
} catch (InterruptedException e) {
e.printStackTrace();
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定義錯誤處理,收集錯誤信息 發送錯誤報告等操作均在此完成.
* @param ex 異常信息
× @ true 如果處理了該異常信息;否則返回false.
*/
public boolean handleException(Throwable ex) {
Log.e("lixp", "ex ===========" + ex);
if (ex == null)
return false;
new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(mContext, "異常退出。。。", 0).show();
Looper.loop();
}
}.start();
// 收集設備參數信息
collectDeviceInfo(mContext);
// 保存日志文件
saveCrashInfo2File(ex);
return true;
}
/**
* 收集設備參數信息
* @param context
*/
public void collectDeviceInfo(Context context) {
try {
PackageManager pm = context.getPackageManager();// 獲得包管理器
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);// 得到該應用的信息,即主Activity
if (pi != null) {
String versionName = pi.versionName == null ? "null"
: pi.versionName;
String versionCode = pi.versionCode + "";
info.put("versionName", versionName);
info.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
// 反射機制
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
info.put(field.getName(), field.get("").toString());
Log.d(TAG, field.getName() + ":" + field.get(""));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//用文件保存異常信息
private String saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : info.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
// 循環著把所有的異常信息寫入writer中
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();// 記得關閉
String result = writer.toString();
sb.append(result);
// 保存文件
long timetamp = System.currentTimeMillis();
String time = format.format(new Date());
String fileName = "crash-" + time + "-" + timetamp + ".log";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Exception");
Log.d("CrashHandler", dir.toString());
if (!dir.exists())
dir.mkdir();
FileOutputStream fos = new FileOutputStream(new File(dir,
fileName));
fos.write(sb.toString().getBytes());
fos.close();
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
好不容易用臉萌做了一個萌萌的卡通頭像,點擊“存儲”按鈕之後卻不知道剛才制作的卡通頭像文件保存到哪裡去了?難道要白做了啊?當然不是的,
廢話不多說,咱們第一篇文章就是模仿“知乎”的回答詳情頁的動畫效果,先上個原版的效果圖,咱們就是要做出這個效果 在實現之前,
Android中的動畫分為視圖動畫(View Animation)、屬性動畫(Property Animation)以及Drawable動畫。Android從最初的版本就
任何程序都是靜態代碼,我們把這些靜態代碼打包好,然後放到運行環境當中,通過事件流的驅動使這些代碼運行起來。Android的環境也不例外。靜態的代碼,在動態事件的驅動下,才