Android开发这么久你竟然还不知道Dropbox?
Android?DropBox 是 Android 用來持續化存儲系統數據的一個管理類,主要用于記錄 Android 運行過程中, 內核, 系統進程, 用戶進程等出現嚴重問題時的 log, 可以認為這是一個可持續存儲的系統級別的 logcat。
本文主要從以下幾個方面闡述Android?Dropbox。
1.什么是Android?Dropbox
Android Dropbox 是 Android 在 Froyo(API level 8) 引入的用來持續化存儲系統數據的機制。主要用于記錄 Android 運行過程中, 內核, 系統進程, 用戶進程等出現嚴重問題時的 log, 可以認為這是一個可持續存儲的系統級別的 logcat。
相關文件記錄存儲目錄:/data/system/dropbox
2.Dropbox源碼
主要源碼(基于N版本代碼:http://androidxref.com/7.0.0_r1/):
/frameworks/base/core/java/android/os/DropBoxManager.java
/frameworks/base/services/core/java/com/android/server/DropBoxManagerService.java
接下來對源碼進行初步分析。(備注:因為篇幅原因,源碼中...是我省略無關代碼)
a.Dropbox的啟動流程
作為android系統服務,其啟動方式和其他android服務基本一致。
系統啟動過程中SystemServer.java中的startOtherServices()方法中啟動 private void startOtherServices() {... mSystemServiceManager.startService(DropBoxManagerService.class);...}DropBoxManagerService的構造函數:
public DropBoxManagerService(final Context context) { this(context, new File("/data/system/dropbox"));}可以看出dropbox文件存儲的目錄是:/data/system/dropbox
再就是需要關注DropBoxManagerService中add和dump方法:
private final IDropBoxManagerService.Stub mStub = new IDropBoxManagerService.Stub() { @Override public void add(DropBoxManager.Entry entry) { DropBoxManagerService.this.add(entry); } ... @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { DropBoxManagerService.this.dump(fd, pw, args); } };DropBoxManager進程通訊時寫數據都是通過這個add方法將數據寫入到存儲目錄,通過dump來采集記錄數據的。
這里重點提下add方法:
public void add(DropBoxManager.Entry entry) { ...? final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag); dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time); if (!mBooted) { dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } // Call sendBroadcast after returning from this call to avoid deadlock. In particular // the caller may be holding the WindowManagerService lock but sendBroadcast requires a // lock in ActivityManagerService. ActivityManagerService has been caught holding that // very lock while waiting for the WindowManagerService lock. mHandler.sendMessage(mHandler.obtainMessage(MSG_SEND_BROADCAST, dropboxIntent)); ...}可以發現:在dropbox在日志存儲時會發送系統廣播:
DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED
所以我們可以針對這個做一些系統定制,如獲取dropbox中的日志以確認相關問題。
另外,DropBoxManagerService中數據dump和add的一些控制數據需了解下:
private static final int DEFAULT_AGE_SECONDS = 3 * 86400;private static final int DEFAULT_MAX_FILES = 1000;private static final int DEFAULT_QUOTA_KB = 5 * 1024;private static final int DEFAULT_QUOTA_PERCENT = 10;private static final int DEFAULT_RESERVE_PERCENT = 10;private static final int QUOTA_RESCAN_MILLIS = 5000;DEFAULT_AGE_SECONDS = 3 * 86400:文件最長可存活時長為3天?
DEFAULT_MAX_FILES = 1000:最大dropbox文件個數為1000?
DEFAULT_QUOTA_KB = 5 * 1024:分配dropbox空間的最大值5M
DEFAULT_QUOTA_PERCENT = 10:是指dropbox目錄最多可占用空間比例10%?
DEFAULT_RESERVE_PERCENT = 10:是指dropbox不可使用的存儲空間比例10%?
QUOTA_RESCAN_MILLIS = 5000:重新掃描retrim時長為5s
上面這些都是默認值,完全可以通過設置content://settings/global數據庫對應項來修改。
DropBoxManager是可以供其系統服務直接調用的類。
final DropBoxManager dbox = (DropBoxManager)mContext.getSystemService(Context.DROPBOX_SERVICE);例如,拿ActivityManagerService中,設備應用出現crash時,報錯信息棧就會記錄到dropbox目錄,下面詳細介紹下應用出現crash后日志記錄到dropbox的過程。
首先:應用在crash后,ActivityManagerService會處理對應的消息:
HANDLE_APPLICATION_CRASH_TRANSACTION
case HANDLE_APPLICATION_CRASH_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder app = data.readStrongBinder(); ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data); handleApplicationCrash(app, ci); reply.writeNoException(); return true; }handleApplicationCrash實現了處理appcrash的流程:
可以看到?addErrorToDropBox方法:
public void addErrorToDropBox(String eventType, ProcessRecord process, String processName, ActivityRecord activity, ActivityRecord parent, String subject, final String report, final File dataFile, final ApplicationErrorReport.CrashInfo crashInfo) { ... dbox.addText(dropboxTag, sb.toString()); ...}代碼:dbox.addText(dropboxTag, sb.toString()); 就是調用的DropBoxManager中的addText方法
public void addText(String tag, String data) { try { mService.add(new Entry(tag, 0, data)); } catch (RemoteException e) { if (e instanceof TransactionTooLargeException && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { Log.e(TAG, "App sent too much data, so it was ignored", e); return; } throw e.rethrowFromSystemServer(); }}addText實際是調用DropBoxManagerService中add方法最終將crash的trace信息寫入dropbox目錄。
3.dropbox中記錄的文件有哪些呢?
下圖是項目中從dropbox目錄pull出來的一個目錄截圖:
可以看到每個文件格式命名都是:processClass _ eventType@時間戳[.txt|txt.gz].
processClass列舉:system_server, system_app, data_app;?
eventType列舉:分為crash anr watchdog wtf strict_mode lowmem
netstats_error Kernel Panic SYSTEM_BOOT SYSTEM_RESTART?
BATTERY_DISCHARGE_INFO SYSTEM_TOMBSTONE;
其中@前面部分及dropbox寫入的tag。
如列舉部分tag含義:?
system_app_anr:系統app無響應?
system_app_crash:系統app進程崩潰?
system_server_native_crash system進程native出現崩潰?
system_server_wtf:system進程發生嚴重錯誤?
system_server_lowmem:system進程內存不足?
?
4.如何利用DropboxManager
a.利用 DropBoxManager 來記錄需要相對持久化存儲的錯誤日志信息
優點:自動抓錯, 避免人為因素而產生的錯誤遺漏
b.錯誤自動上報
可以利用dropbox每生成新的記錄, Dropbox 就會發送廣播:
DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED
app可以接收監聽改廣播獲取指定的數據文件內容,內容發送到指定的服務器或郵箱完成錯誤自動上報。
利用前提:app要具有系統權限??因為:DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED是保護性廣播,且讀取系統日志也需要android.Manifest.permission.READ_LOGS權限
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?
總結
以上是生活随笔為你收集整理的Android开发这么久你竟然还不知道Dropbox?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 斯托曼与林纳斯的恩怨纠葛,天才往往都很固
- 下一篇: SSM+Mysql实现的共享单车管理系统