日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Log保存文件-Android

發(fā)布時(shí)間:2023/12/20 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Log保存文件-Android 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

前言

在開發(fā)過程中尤其是項(xiàng)目進(jìn)入測(cè)試后,為了方便定位問題,經(jīng)常需要將log保存下來,當(dāng)然你可以自己寫個(gè)log輔助類又或者直接使用第三方的jar包,這里多多少少需要對(duì)系統(tǒng)的log類進(jìn)行一些包裝,調(diào)用也不再是系統(tǒng)的log類,如果你只希望調(diào)用系統(tǒng)的log類又想打印的log能按自己的規(guī)則保存到文件那么請(qǐng)繼續(xù)往下看。

原理

首先啟動(dòng)模擬器或者用手機(jī)連接電腦,進(jìn)入命令行并且輸入如下命令

C:\Users\Administrator>adb shell root[@pisces](https://my.oschina.net/lazydomino):/ # logcat -v time *:W 05-01 17:10:48.619 W/PushService( 2216): 2015-05-01 17:10:48,620 - [WARN::PushService] - [Process:2216][Thread:1] Service called on timer 05-01 17:10:48.622 W/PushService( 2216): 2015-05-01 17:10:48,623 - [WARN::PushService] - [Process:2216][Thread:31] SMACK 05:10:48 下午 SENT (1122316296): <iq to='xiaomi.com' id='0' chid='0' type='get'><ping xmlns='urn:xmpp:ping'><pf><p>t:69</p></pf></ping></iq> 05-01 17:10:48.622 W/PushService( 2216): 05-01 17:10:48.701 W/PushService( 2216): 2015-05-01 17:10:48,701 - [WARN::PushService] - [Process:2216][Thread:428] SMACK 05:10:48 下午 RCV (1122316296): <iq chid='0' id='0' type='result'/> 05-01 17:11:03.638 W/PushService( 2216): 2015-05-01 17:11:03,637 - [WARN::PushService] - [Process:2216][Thread:31] JOB: check the ping-pong. 05-01 17:11:08.384 W/MountService( 960): getVolumeState(/storage/emulated/0/external_sd): Unknown volume 05-01 17:11:08.385 W/MountService( 960): getVolumeState(/mnt/sdcard-ext): Unknown volume 05-01 17:11:08.386 W/MountService( 960): getVolumeState(/mnt/ext_sdcard): Unknown volume 05-01 17:11:08.387 W/MountService( 960): getVolumeState(/mnt/sdcard2): Unknown volume

上面的命令過濾出了所有的w以及w優(yōu)先級(jí)以上的log(本人D等級(jí)打印太多所以選用W),按“Ctrl + c”終止剛才的命令,然后再執(zhí)行如下命令

C:\Users\Administrator>adb shell root[@pisces](https://my.oschina.net/lazydomino):/ # logcat -v time *:W >> /sdcard/log.log logcat -v time *:W > sdcard/log.log

這時(shí)候你再去設(shè)備的sd卡根目錄看看,是不是多出來個(gè)“l(fā)og.log”文件,打開看看里面的內(nèi)容是不是我們保存的log。

是的,這里我們要用到的就是上面的方式,既然命令行中的log可以保存的文件中,那我們只需要在程序中執(zhí)行命令行即可

logcat

關(guān)于logcat的用法可以通過如下命令查看

C:\Users\Administrator>adb shell root[@pisces](https://my.oschina.net/lazydomino):/ # logcat --help logcat --help Usage: logcat [options] [filterspecs] options include:-s Set default filter to silent.Like specifying filterspec '*:s'-f <filename> Log to file. Default to stdout-r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f-n <count> Sets max number of rotated logs to <count>, default 4-v <format> Sets the log print format, where <format> is one of:brief process tag thread raw time threadtime long-c clear (flush) the entire log and exit-d dump the log and then exit (don't block)-t <count> print only the most recent <count> lines (implies -d)-g get the size of the log's ring buffer and exit-b <buffer> Request alternate ring buffer, 'main', 'system', 'radio'or 'events'. Multiple -b parameters are allowed and theresults are interleaved. The default is -b main -b system.-B output the log in binary filterspecs are a series of<tag>[:priority]where <tag> is a log component tag (or * for all) and priority is:V VerboseD DebugI InfoW WarnE ErrorF FatalS Silent (supress all output)'*' means '*:d' and <tag> by itself means <tag>:vIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS. If no filterspec is found, filter defaults to '*:I'If not specified with -v, format is set from ANDROID_PRINTF_LOG or defaults to "brief"

從logcat help可以看出,logcat本身就提供了保存文件的參數(shù)“-f <filename>”,你可能要問為什么不用直接這個(gè)保存,主要是logcat也有它的局限性,從上面可以看出,logcat提供了根據(jù)tag和priority的過濾器,但如果我們想把項(xiàng)目中的所有l(wèi)og都保存到文件中,那我們就不得不將所有的tag都添加到過濾器中,這時(shí)候如果可以根據(jù)應(yīng)用程序的包名或者進(jìn)程ID過濾就省事多了,所以我們有用到了grep命令。

grep

grep命令的用法如下

root[@pisces](https://my.oschina.net/lazydomino):/ # grep grep usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]][-e pattern] [-f file] [--binary-files=value] [--color=when][-e pattern] [-f file] [--binary-files=value] [--color=when][--context[=num]] [--directories=action] [--label] [--line-buffered][pattern] [file ...]

grep命令不僅支持關(guān)鍵字過濾還支持正則,這里我們要用到的就是他的正則過濾。

使用方法

再試試如下命令

logcat -v time *:W | grep '( 960):' >> /sdcard/log.txt

注: 關(guān)鍵字"'( 960):'"中的進(jìn)程ID請(qǐng)修改為你系統(tǒng)中存在的ID號(hào),最好直接從“l(fā)ogcat -v time *:W”命令輸出的log中復(fù)制粘貼,另外“()”中有五個(gè)字符,進(jìn)程ID長度不夠在前面補(bǔ)空格

對(duì)比下SD中的log.log和log.txt你會(huì)發(fā)現(xiàn)log.log中包含了所有進(jìn)程warn和warn以上優(yōu)先級(jí)的log而log.txt中只包含了指定關(guān)鍵字的log。所以我們只需根據(jù)“l(fā)ogcat -v time *:W”打印的log的規(guī)則再配合grep命令的正則表達(dá)式是可以根據(jù)進(jìn)程ID過濾的。遺憾的是本人嘗試了很多次始終由于grep無法完全支持正則表達(dá)式而未能得到一個(gè)完全匹配的正則表達(dá)式,目前只得到以下表達(dá)式,雖然不能做到百分百的過濾但也算比較靠譜,如果你寫出來了麻煩也告訴我一下yxmsw2007@gmail.com

logcat -v time *:W | grep '^.*\/.*( 960):' >> /sdcard/log.log

LogService

package com.example.service;import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.List;import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Environment; import android.os.IBinder; import android.os.PowerManager; import android.os.StatFs; import android.os.PowerManager.WakeLock; import android.os.StrictMode; import android.util.Log;/*** @project SampleAndroid * @class LogService * @description * 日志服務(wù),日志默認(rèn)會(huì)存儲(chǔ)在內(nèi)存中的安裝目錄下面并且系統(tǒng)每隔一段時(shí)間就會(huì)檢測(cè)一下log文件的大小,* 如果log文件超過指定的大小則會(huì)執(zhí)行如下動(dòng)作:* 1.SD卡不可用,所有l(wèi)og文件都保存在內(nèi)存中,當(dāng)log文件數(shù)超出指定的數(shù)量就會(huì)刪除較早的log* 2.SD卡可用而且存儲(chǔ)空間足夠則將文件移動(dòng)SD卡中,并檢測(cè)SD中保存的文件是否都在指定時(shí)間日期內(nèi),如果不是則刪除* 3.SD卡可用但存儲(chǔ)空間小于指定的大小,在操作log前會(huì)先刪除SD卡中的所有l(wèi)og并重新檢測(cè)空間,如果空間仍不足則按1操作否則按2進(jìn)行* @author yxmsw2007* @version 1.0* @email yxmsw2007@gmail.com * @data 2015-5-1 下午8:18:27 */ public class LogService extends Service {private static final String TAG = LogService.class.getSimpleName();private static final int MEMORY_LOG_FILE_MAX_SIZE = 10 * 1024 * 1024; // 內(nèi)存中日志文件最大值,10Mprivate static final int MEMORY_LOG_FILE_MONITOR_INTERVAL = 10 * 60 * 1000; // 內(nèi)存中的日志文件大小監(jiān)控時(shí)間間隔,10分鐘private static final int MEMORY_LOG_FILE_MAX_NUMBER = 2; // 內(nèi)存中允許保存的最大文件個(gè)數(shù)private static final int SDCARD_LOG_FILE_SAVE_DAYS = 7; // sd卡中日志文件的最多保存天數(shù)private static final String LOG_FOLDER = "Log"; //日志文件夾private static final String MONITOR_LOG_PRIORITY = "D"; // 監(jiān)聽日志的最低優(yōu)先級(jí)private static final String MONITOR_LOG_SIZE_ACTION = "MONITOR_LOG_SIZE"; // 日志文件大小監(jiān)測(cè)action/*** logcat -v time *:D | grep -n '^.*\/.*( 828):' >> /sdcard/download/Log.log*/private static String LOG_FILTER_COMMAND_FORMAT = "logcat -v time *:%s | grep '^.*\\/.*(%s):' >> %s";private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmmss");// 日志名稱格式private String mLogFileDirMemory; // 日志文件在內(nèi)存中的路徑(日志文件在安裝目錄中的路徑)private String mLogFileDirSdcard; // 日志文件在sdcard中的路徑private String mCurrLogFileName; // 如果當(dāng)前的日志寫在內(nèi)存中,記錄當(dāng)前的日志文件名稱private Process process;private WakeLock wakeLock;private PendingIntent mMemoryLogFileSizeMonitor; private AlarmManager mAlarmManager;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "-- onCreate() --");if (android.os.Build.VERSION.SDK_INT > 9) {StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();StrictMode.setThreadPolicy(policy);} // 注冊(cè)SD卡狀態(tài)監(jiān)聽廣播IntentFilter sdCarMonitorFilter = new IntentFilter();sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);sdCarMonitorFilter.addDataScheme("file");registerReceiver(mSDStateReceiver, sdCarMonitorFilter);IntentFilter logTaskFilter = new IntentFilter();logTaskFilter.addAction(MONITOR_LOG_SIZE_ACTION); //注冊(cè)日志大小監(jiān)聽廣播logTaskFilter.addAction(Intent.ACTION_TIME_CHANGED); //如果時(shí)間被重新設(shè)置,要判斷當(dāng)前時(shí)間是否在有效時(shí)間內(nèi),//如果超出了范圍需要將日志保存到新文件中,否則會(huì)被清除registerReceiver(mLogTaskReceiver, logTaskFilter);// 部署日志大小監(jiān)控任務(wù)Intent intent = new Intent(MONITOR_LOG_SIZE_ACTION);mMemoryLogFileSizeMonitor = PendingIntent.getBroadcast(this, 0, intent, 0);mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),MEMORY_LOG_FILE_MONITOR_INTERVAL, mMemoryLogFileSizeMonitor);PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);new LogCollectorThread().start();}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "-- onDestroy() --");if (process != null) {process.destroy();}// 取消日志大小監(jiān)控任務(wù)mAlarmManager.cancel(mMemoryLogFileSizeMonitor);unregisterReceiver(mSDStateReceiver);unregisterReceiver(mLogTaskReceiver);}/*** 日志收集 * 1.清除日志緩存 * 2.殺死應(yīng)用程序已開啟的Logcat進(jìn)程防止多個(gè)進(jìn)程寫入一個(gè)日志文件 * 3.開啟日志收集進(jìn)程 * 4.處理日志文件 移動(dòng) OR 刪除*/class LogCollectorThread extends Thread {public LogCollectorThread() {super("LogCollectorThread");Log.d(TAG, "LogCollectorThread is create");}@Overridepublic void run() {try {wakeLock.acquire(); // 喚醒手機(jī)clearLogCache();List<String> orgProcessList = getAllProcess();List<ProcessInfo> processInfoList = getProcessInfoList(orgProcessList);killLogcatProc(processInfoList);mCurrLogFileName = dateToFileName(new Date());//獲取新的日志文件名稱createLogCollector(getMemoryFilePath(mCurrLogFileName));Thread.sleep(1000);// 休眠,創(chuàng)建文件,然后處理文件,不然該文件還沒創(chuàng)建,會(huì)影響文件刪除handleLog(mCurrLogFileName);wakeLock.release(); // 釋放} catch (Exception e) {e.printStackTrace();}}}/*** 每次記錄日志之前先清除日志的緩存, 不然會(huì)在兩個(gè)日志文件中記錄重復(fù)的日志*/private void clearLogCache() {Log.d(TAG, "-- clearLogCache() --");Process proc = null;List<String> commandList = new ArrayList<String>();commandList.add("logcat");commandList.add("-c");try {proc = Runtime.getRuntime().exec(commandList.toArray(new String[commandList.size()]));StreamConsumer errorGobbler = new StreamConsumer(proc.getErrorStream());StreamConsumer outputGobbler = new StreamConsumer(proc.getInputStream());errorGobbler.start();outputGobbler.start();if (proc.waitFor() != 0) {Log.e(TAG, " clearLogCache proc.waitFor() != 0");}} catch (Exception e) {Log.e(TAG, "clearLogCache failed", e);} finally {try {proc.destroy();} catch (Exception e) {Log.e(TAG, "clearLogCache failed", e);}}}/*** 關(guān)閉由本程序開啟的logcat進(jìn)程: 根據(jù)用戶名稱殺死進(jìn)程(如果是本程序進(jìn)程開啟的Logcat收集進(jìn)程那么兩者的USER一致)* 如果不關(guān)閉會(huì)有多個(gè)進(jìn)程讀取logcat日志緩存信息寫入日志文件* @param allProcList* @return*/private void killLogcatProc(List<ProcessInfo> allProcList) {Log.d(TAG, "-- killLogcatProc() --");if (process != null) {process.destroy();}String packName = this.getPackageName();String myUser = getAppUser(packName, allProcList);for (ProcessInfo processInfo : allProcList) {if (processInfo.name.toLowerCase().equals("logcat")&& processInfo.user.equals(myUser)) {android.os.Process.killProcess(Integer.parseInt(processInfo.pid));}}}/*** 獲取本程序的用戶名稱* @param packName* @param allProcList* @return*/private String getAppUser(String packName, List<ProcessInfo> allProcList) {for (ProcessInfo processInfo : allProcList) {if (processInfo.name.equals(packName)) {return processInfo.user;}}return null;}/*** 根據(jù)ps命令得到的內(nèi)容獲取PID,User,name等信息* @param orgProcessList* @return*/private List<ProcessInfo> getProcessInfoList(List<String> orgProcessList) {List<ProcessInfo> procInfoList = new ArrayList<ProcessInfo>();for (int i = 1; i < orgProcessList.size(); i++) {String processInfo = orgProcessList.get(i);String[] proStr = processInfo.split(" ");// USER PID PPID VSIZE RSS WCHAN PC NAME// root 1 0 416 300 c00d4b28 0000cd5c S /initList<String> orgInfo = new ArrayList<String>();for (String str : proStr) {if (!"".equals(str)) {orgInfo.add(str);}}if (orgInfo.size() == 9) {ProcessInfo pInfo = new ProcessInfo();pInfo.user = orgInfo.get(0);pInfo.pid = orgInfo.get(1);pInfo.ppid = orgInfo.get(2);pInfo.name = orgInfo.get(8);procInfoList.add(pInfo);}}return procInfoList;}/*** 運(yùn)行PS命令得到進(jìn)程信息* @return USER PID PPID VSIZE RSS WCHAN PC NAME * root 1 0 416 300 c00d4b28 0000cd5c S /init*/private List<String> getAllProcess() {List<String> orgProcList = new ArrayList<String>();Process proc = null;try {proc = Runtime.getRuntime().exec("ps");StreamConsumer errorConsumer = new StreamConsumer(proc.getErrorStream());StreamConsumer outputConsumer = new StreamConsumer(proc.getInputStream(), orgProcList);errorConsumer.start();outputConsumer.start();if (proc.waitFor() != 0) {Log.e(TAG, "getAllProcess proc.waitFor() != 0");}} catch (Exception e) {Log.e(TAG, "getAllProcess failed", e);} finally {try {proc.destroy();} catch (Exception e) {Log.e(TAG, "getAllProcess failed", e);}}return orgProcList;}/*** eg: logcat -v time *:D | grep -n '^.*\/.*( 828):' >> /sdcard/download/Log.log* @param priority* @param path* @return*/private String getLogFilterCommand(String priority, String path) {Log.d(TAG, "-- getLogFilterCommand() --");String sid = "" + android.os.Process.myPid();for (int i = sid.length(); i < 5; i++) {sid = " " + sid;}return String.format(LOG_FILTER_COMMAND_FORMAT, priority, sid, path);}/*** 開始收集日志信息*/public void createLogCollector(String path) {Log.d(TAG, "-- createLogCollector() --");String command = getLogFilterCommand(MONITOR_LOG_PRIORITY, path.replace(" ", "\\ "));//獲取命令Log.d(TAG, command);List<String> commandList = new ArrayList<String>();commandList.add("sh");commandList.add("-c");commandList.add(command);try {process = Runtime.getRuntime().exec(commandList.toArray(new String[commandList.size()]));// process.waitFor();} catch (Exception e) {Log.e(TAG, "CollectorThread == >" + e.getMessage(), e);}}/*** 處理日志文件 */public void handleLog(String currFileName) {Log.d(TAG, "-- handleLog() --");moveLogfile(currFileName);//將內(nèi)存中日志文件轉(zhuǎn)移到SD中,當(dāng)前正在記錄的日志文件除外deleteSdcardExpiredLog(SDCARD_LOG_FILE_SAVE_DAYS);//刪除SD中過期的日志文件deleteMemoryExpiredLog(MEMORY_LOG_FILE_MAX_NUMBER, currFileName);//刪除內(nèi)存中過期的日志文件}/*** 檢查日志文件大小是否超過了規(guī)定大小 如果超過了重新開啟一個(gè)日志收集進(jìn)程*/private void checkLogSize() {Log.d(TAG, "-- checkLogSize() --");if (mCurrLogFileName != null && !"".equals(mCurrLogFileName)) {String path = getMemoryFilePath(mCurrLogFileName);File file = new File(path);if (!file.exists()) {return;}if (file.length() >= MEMORY_LOG_FILE_MAX_SIZE) {Log.d(TAG, "The log's size is too big!");new LogCollectorThread().start();}}}/*** 將日志文件轉(zhuǎn)移到SD卡下面*/private void moveLogfile(String currFileName) {Log.d(TAG, "-- moveLogfile() --");if (!isSdcardAvailable()) {return;}File file = new File(getMemoryDirPath());if (!file.isDirectory()) {return;}File[] allFiles = file.listFiles();for (File logFile : allFiles) {String fileName = logFile.getName();if (currFileName.equals(fileName)) {continue;}if (logFile.length() >= getSdcardAvailableSize()) {deleteSdcardAllLog();}if (logFile.length() >= getSdcardAvailableSize()) {return;}if (copy(logFile, new File(getSdcardFilePath(fileName)))) {logFile.delete();Log.d(TAG, "move file success, log name is:" + fileName);}}}/*** 刪除SD卡中所有日志文件*/private void deleteSdcardAllLog() {Log.d(TAG, "-- deleteSdcardAllLog() --");if (isSdcardAvailable()) {File file = new File(getSdcardDirPath());if (file.isDirectory()) {File[] allFiles = file.listFiles();for (File logFile : allFiles) {logFile.delete();Log.d(TAG, "delete file success, file name is:" + logFile.getName());}}}}/*** 刪除SD內(nèi)過期的日志*/private void deleteSdcardExpiredLog(int days) {Log.d(TAG, "-- deleteSdcardExpiredLog() --");if (isSdcardAvailable()) {File file = new File(getSdcardDirPath());File[] allFiles = file.listFiles();for (File logFile : allFiles) {if (canDeleteSDLog(logFile.getName(), days)) {logFile.delete();Log.d(TAG, "delete file success, file name is:" + logFile.getName());}}}}/*** * @param createDateStr* @return*//*** 判斷sdcard上的日志文件是否可以刪除,規(guī)則:文件創(chuàng)建時(shí)間是否在days天數(shù)內(nèi)* @param fileName 文件名* @param days 天數(shù)* @return*/public boolean canDeleteSDLog(String fileName, int days) {Calendar calendar = Calendar.getInstance();calendar.add(Calendar.DAY_OF_MONTH, -1 * days);// 刪除7天之前日志Date expiredDate = calendar.getTime();try {Date createDate = fileNameToDate(fileName);return createDate.before(expiredDate);} catch (ParseException e) {Log.e(TAG, e.getMessage(), e);}return false;}/*** 刪除內(nèi)存中的過期日志,刪除規(guī)則: 保存最近的number個(gè)日志文件* @param number 保留的文件個(gè)數(shù)*/private void deleteMemoryExpiredLog(int number, String currFileName) {Log.d(TAG, "-- deleteMemoryExpiredLog() --");File file = new File(getMemoryDirPath());if (file.isDirectory()) {File[] allFiles = file.listFiles();Arrays.sort(allFiles, new FileComparator());for (int i = 0; i < allFiles.length - number; i++) {File f = allFiles[i];if (f.getName().equals(currFileName)) {continue;}f.delete();Log.d(TAG, "delete file success, file name is:" + f.getName());}}}/*** 拷貝文件* @param source* @param target* @return*/private boolean copy(File source, File target) {FileInputStream in = null;FileOutputStream out = null;try {if (!target.exists()) {boolean createSucc = target.createNewFile();if (!createSucc) {return false;}}in = new FileInputStream(source);out = new FileOutputStream(target);byte[] buffer = new byte[8 * 1024];int count;while ((count = in.read(buffer)) != -1) {out.write(buffer, 0, count);}return true;} catch (Exception e) {Log.e(TAG, e.getMessage(), e);return false;} finally {try {if (in != null) {in.close();}if (out != null) {out.close();}} catch (IOException e) {Log.e(TAG, e.getMessage(), e);return false;}}}class ProcessInfo {public String user;public String pid;public String ppid;public String name;@Overridepublic String toString() {return "user=" + user + " pid=" + pid + " ppid=" + ppid + " name=" + name;}}class StreamConsumer extends Thread {InputStream is;List<String> list;StreamConsumer(InputStream is) {this.is = is;}StreamConsumer(InputStream is, List<String> list) {this.is = is;this.list = list;}public void run() {try {InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String line = null;while ((line = br.readLine()) != null) {if (list != null) {list.add(line);}}} catch (IOException ioe) {ioe.printStackTrace();}}}/*** 監(jiān)控SD卡狀態(tài)*/private BroadcastReceiver mSDStateReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();Log.d(TAG, "mLogTaskReceiver: " + action);if (Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction())) { // 存儲(chǔ)卡被卸載} else { // 存儲(chǔ)卡被掛載}}};/*** 監(jiān)控日志大小*/private BroadcastReceiver mLogTaskReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();Log.d(TAG, "mLogTaskReceiver: " + action);if (MONITOR_LOG_SIZE_ACTION.equals(action)) {checkLogSize();} else if (Intent.ACTION_TIME_CHANGED.equals(action)) {if (canDeleteSDLog(mCurrLogFileName, SDCARD_LOG_FILE_SAVE_DAYS)) {Log.d(TAG, "The log is out of date !");new LogCollectorThread().start();}}}};private class FileComparator implements Comparator<File> {public int compare(File file1, File file2) {try {Date create1 = fileNameToDate(file1.getName());Date create2 = fileNameToDate(file2.getName());if (create1.before(create2)) {return -1;} else {return 1;}} catch (ParseException e) {return 0;}}}/*** SD卡是否可用* @return*/private boolean isSdcardAvailable() {return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);}/*** SD卡剩余空間* @return*/private long getSdcardAvailableSize() {if (isSdcardAvailable()) {String path = Environment.getExternalStorageDirectory().getAbsolutePath();StatFs fileStats = new StatFs(path);fileStats.restat(path);return fileStats.getAvailableBlocksLong() * fileStats.getBlockSizeLong();}return 0;}public boolean creatDir(String path) {File f = new File(path);return f.exists() && f.isDirectory() || f.mkdirs();}public boolean creatFile(String path) {if (path != null && path.contains(File.separator) && creatDir(path.substring(0, path.lastIndexOf(File.separator)))) {File f = new File(path);try {return f.exists() && f.isFile() || f.createNewFile();} catch (IOException e) {Log.w(TAG, e);}}return false;}/*** 日志文件名轉(zhuǎn)日期* @param fileName* @return* @throws ParseException*/private Date fileNameToDate(String fileName) throws ParseException {fileName = fileName.substring(0, fileName.indexOf("."));//去除文件的擴(kuò)展類型(.log)return sdf.parse(fileName);}/*** 日期轉(zhuǎn)日志文件名* @param date* @return*/private String dateToFileName(Date date) {return sdf.format(date) + ".log";//日志文件名稱}/*** 文件在內(nèi)存中的路徑* @param fileName* @return*/private String getMemoryFilePath(String fileName) {return getMemoryDirPath() + File.separator + fileName;}/*** 內(nèi)存中日志文件保存目錄* @return*/private String getMemoryDirPath() {if (mLogFileDirMemory == null) {mLogFileDirMemory = getFilesDir().getAbsolutePath() + File.separator + LOG_FOLDER;creatDir(mLogFileDirMemory);}return mLogFileDirMemory;}/*** 文件在SD中的路徑* @param fileName* @return*/private String getSdcardFilePath(String fileName) {return getSdcardDirPath() + File.separator + fileName;}/*** SD卡中日志文件保存目錄* @return*/private String getSdcardDirPath() {if (mLogFileDirSdcard == null && isSdcardAvailable()) {mLogFileDirSdcard = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator+ getString(R.string.app_name)+ File.separator+ LOG_FOLDER;creatDir(mLogFileDirSdcard);}return mLogFileDirSdcard;}}

源碼下載

SampleAndroid

參考資料

android 寫log到文件

轉(zhuǎn)載于:https://my.oschina.net/noke/blog/1506859

總結(jié)

以上是生活随笔為你收集整理的Log保存文件-Android的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。