編輯:關於Android編程
public void init(Context context) { try { if (context == null) throw new NullPointerException("Application 的Context不能為空"); this.mContext = context; /** * 獲取系統默認的異常處理類 */ mUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); /** * 在獲取系統異常類之前子類可以先做一些初始化的操作 */ initParams(this); /** * 使用當前的類為異常處理類 */ Thread.setDefaultUncaughtExceptionHandler(this); }catch (Exception e){ Log.e(TAG, "init - "+e.getMessage()); } }
/** * 此類是當應用出現異常的時候執行該方法 * @param thread * @param throwable */ @Override public void uncaughtException(Thread thread, Throwable throwable) { try { /** * hanlderException此方法是是否處理異常日志,如果處理那麼就返回tru * e,如果處理遇到問題那麼就返回false,交由系統默認處理 **/ if (!hanlderException(throwable) && mUncaughtExceptionHandler != null) { /** * 如果此異常不處理則由系統自己處理 */ this.mUncaughtExceptionHandler.uncaughtException(thread, throwable); }else{ /** * 可以延遲一秒鐘在退出 */ // Thread.sleep(1000); //如果開發者自己處理一場那麼就自己處理,這裡我處理的是退出進程 android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } }catch (Exception e) { Log.e(TAG, "uncaughtException - "+e.getMessage()); } }
/** * 用戶處理異常日志 * @param throwable * @return */ private boolean hanlderException(Throwable throwable) { try { if (throwable == null) return false; new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Toast.makeText(mContext, "程序崩潰", Toast.LENGTH_SHORT).show(); Looper.loop(); } }).start(); /** * 收集應用信息 */ collectCrashLogInfo(mContext); /** * 將日志寫入文件 */ writerCrashLogToFile(throwable); /** * 限制日子志文件的數量 */ limitAppLogCount(LIMIT_LOG_COUNT); } catch (Exception e) { Log.e(TAG, "hanlderException - " + e.getMessage()); } return false; }
/** * 獲取應用信息 * @param mContext */ private void collectCrashLogInfo(Context mContext) { try { if (mContext == null) return ; PackageManager packageManager = mContext.getPackageManager(); if (packageManager != null) { PackageInfo packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); if (packageInfo != null) { String versionName = packageInfo.versionName; String versionCode = ""+packageInfo.versionCode; String packName = packageInfo.packageName; crashAppLog.put("versionName",versionName); crashAppLog.put("versionCode",versionCode); crashAppLog.put("packName",packName); } } /** * 獲取手機型號,系統版本,以及SDK版本 */ crashAppLog.put("手機型號:", android.os.Build.MODEL); crashAppLog.put("系統版本", ""+android.os.Build.VERSION.SDK); crashAppLog.put("Android版本", android.os.Build.VERSION.RELEASE); Field[] fields = Build.class.getFields(); if (fields != null && fields.length > 0) { for (Field field:fields) { if (field != null) { field.setAccessible(true); crashAppLog.put(field.getName(), field.get(null).toString()); } } } }catch (Exception e) { Log.e(TAG, "collectDeviceInfo - "+e.getMessage()); } }
/** * 寫入文件中 * @param ex */ private void writerCrashLogToFile(Throwable ex) { try { StringBuffer buffer = new StringBuffer(); if (crashAppLog != null && crashAppLog.size() >0) { for (Map.Entryentry:crashAppLog.entrySet()) { buffer.append(entry.getKey()+":"+entry.getValue()+"\n"); } } Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while(cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.flush(); printWriter.close(); String result = writer.toString(); buffer.append("Exception:+\n"); buffer.append(result); writerToFile(buffer.toString()); }catch (Exception e) { Log.e(TAG, "writerCrashLogToFile - "+e.getMessage()); } } //將文件寫入 private void writerToFile(String s) { try { /** * 創建日志文件名稱 */ String curtTimer = ""+System.currentTimeMillis(); if (formate == null) { formate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); } String timer = formate.format(new Date()); String fileName = "crash-"+timer+"-"+curtTimer+".log"; /** * 創建文件夾 */ File folder = new File(CAHCE_CRASH_LOG); if (!folder.exists()) folder.mkdirs(); /** * 創建日志文件 */ File file = new File(folder.getAbsolutePath()+File.separator+fileName); if (!file.exists()) file.createNewFile(); FileWriter fileWriter = new FileWriter(file); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write(s); bufferedWriter.flush(); bufferedWriter.close(); sendCrashLogToServer(folder, file); }catch (Exception e) { Log.e(TAG, "writerToFile - "+e.getMessage()); } }
/** * 最大文件數量 * @param limitLogCount */ private void limitAppLogCount(int limitLogCount) { try { File file = new File(CAHCE_CRASH_LOG); if (file != null && file.isDirectory()) { File[] files = file.listFiles(new CrashLogFliter()); if(files != null && files.length >0) { Arrays.sort(files, comparator); if (files.length > LIMIT_LOG_COUNT) { for (int i = 0 ; i < files.length - LIMIT_LOG_COUNT ;i++) { files[i].delete(); } } } } }catch (Exception e) { Log.e(TAG, "limitAppLogCount - "+e.getMessage()); } } //這裡限制文件的數量我使用的文件類型過濾和排序 /** * 日志文件按日志大小排序 */ private Comparatorcomparator = new Comparator () { @Override public int compare(File l, File r) { if (l.lastModified() > r.lastModified()) return 1; if (l.lastModified() < r.lastModified()) return -1; return 0; } }; /** * 過濾.log的文件 */ public class CrashLogFliter implements FileFilter { @Override public boolean accept(File file) { if (file.getName().endsWith(".log")) return true; return false; } }
/** * 默認放在內存卡的root路徑 */ private String CAHCE_CRASH_LOG = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator; /** * 抽象方法, * 在該類初始化的時候使用 */ public abstract void initParams(CrashAppLog crashAppLog); /** * 發送一場日志文件到服務器 * @param folder 文件路徑 * @param file 文件 */ public abstract void sendCrashLogToServer(File folder, File file); /** * 允許最大日志文件的數量 */ private int LIMIT_LOG_COUNT = 10; //這兩個變量是可以通過父類調用的,比如可以進行對緩存目錄更改和文件數量更改 public int getLIMIT_LOG_COUNT() { return LIMIT_LOG_COUNT; } public void setLIMIT_LOG_COUNT(int LIMIT_LOG_COUNT) { this.LIMIT_LOG_COUNT = LIMIT_LOG_COUNT; } public String getCAHCE_CRASH_LOG() { return CAHCE_CRASH_LOG; } public void setCAHCE_CRASH_LOG(String CAHCE_CRASH_LOG) { this.CAHCE_CRASH_LOG = CAHCE_CRASH_LOG; } //initParams這個抽象方法拋出父類進行一些操作; //sendCrashLogToServer(File folder, File file)這個是在異常日志寫入文件之後進行用開發者進行發送給服務器
package com.base.crash; import android.os.Environment; import android.util.Log; import java.io.File; /** * Created by 東帥 on 2016/9/6. */ public class CrashApphandler extends CrashAppLog { public static CrashApphandler mCrashApphandler = null; //實現單例 private CrashApphandler(){}; public static CrashApphandler getInstance() { if (mCrashApphandler == null) mCrashApphandler = new CrashApphandler(); return mCrashApphandler; } @Override public void initParams(CrashAppLog crashAppLog) { if (crashAppLog != null){ //動態的改變緩存目錄和緩存文件數量 crashAppLog.setCAHCE_CRASH_LOG(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"crashLog"); crashAppLog.setLIMIT_LOG_COUNT(5); } } @Override public void sendCrashLogToServer(File folder, File file) { //發送服務端 Log.e("*********", "文件夾:"+folder.getAbsolutePath()+" - "+file.getAbsolutePath()+""); } }
package com.base.crash; import android.app.Application; /** * Created by 東帥 on 2016/9/6. */ public class App extends Application { @Override public void onCreate() { super.onCreate(); //初始化一下就行了,別忘記了 CrashApphandler.getInstance().init(this); } } // *** 最後加上權限
通知使用權打開方式設置——提示音和通知——通知使用權。詳細界面如圖:存在需要擁有通知使用權應用時:不存在需要擁有通知使用權
引言 本系列適合0基礎的人員,因為我就是從0開始的,此系列記錄我步入Android開發的一些經驗分享,望與君共勉!作為Android隊伍中的一個新人的我,如果有什麼不對
前言:前面幾篇總結一些TV上的小Sample,開源到GitHub:https://github.com/hejunlin2013/TVSample, 點擊鏈接,可以持續關
我們在開發Android上應用程序時,有很多時候會遇到“延時”等待的情況,例如數據加載時,尤其是在聯網的時候,請求網絡會有個等待時間