Android的log保存到文件上查看

http://www.eoeandroid.com/thread-153626-1-1.html


在调试的时候一般都是在logcat中看日志的信息,以便找出BUG和调试信息,但是如果在真机上的话不可能一直连接电脑查看日志,所以生成日志文件并保存,是一个比较普遍的需求,下面就是最近实现的一个例子。欢迎大家讨论并给出别的思路。

 

  1. import java.io.BufferedReader;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.InputStreamReader;  
  8. import java.io.OutputStreamWriter;  
  9. import java.text.ParseException;  
  10. import java.text.SimpleDateFormat;  
  11. import java.util.ArrayList;  
  12. import java.util.Arrays;  
  13. import java.util.Calendar;  
  14. import java.util.Comparator;  
  15. import java.util.Date;  
  16. import java.util.List;  
  17.   
  18. import android.app.AlarmManager;  
  19. import android.app.PendingIntent;  
  20. import android.app.Service;  
  21. import android.content.BroadcastReceiver;  
  22. import android.content.Context;  
  23. import android.content.Intent;  
  24. import android.content.IntentFilter;  
  25. import android.os.Environment;  
  26. import android.os.IBinder;  
  27. import android.os.PowerManager;  
  28. import android.os.PowerManager.WakeLock;  
  29. import android.util.Log;  
  30.   
  31. /** 
  32.  * 日志服务,日志默认会存储在SDcar里如果没有SDcard会存储在内存中的安装目录下面。 1.本服务默认在SDcard中每天生成一个日志文件, 
  33.  * 2.如果有SDCard的话会将之前内存中的文件拷贝到SDCard中 3.如果没有SDCard,在安装目录下只保存当前在写日志 
  34.  * 4.SDcard的装载卸载动作会在步骤2,3中切换 5.SDcard中的日志文件只保存7天 
  35.  *  
  36.  * @author Administrator 
  37.  *  
  38.  */  
  39. public class LogService extends Service {  
  40.     private static final String TAG = "LogService";  
  41.   
  42.     private static final int MEMORY_LOG_FILE_MAX_SIZE = 10 * 1024 * 1024// 内存中日志文件最大值,10M  
  43.     private static final int MEMORY_LOG_FILE_MONITOR_INTERVAL = 10 * 60 * 1000// 内存中的日志文件大小监控时间间隔,10分钟  
  44.     private static final int SDCARD_LOG_FILE_SAVE_DAYS = 7// sd卡中日志文件的最多保存天数  
  45.   
  46.     private String LOG_PATH_MEMORY_DIR; // 日志文件在内存中的路径(日志文件在安装目录中的路径)  
  47.     private String LOG_PATH_SDCARD_DIR; // 日志文件在sdcard中的路径  
  48.     @SuppressWarnings("unused")  
  49.     private String LOG_SERVICE_LOG_PATH; // 本服务产生的日志,记录日志服务开启失败信息  
  50.   
  51.     private final int SDCARD_TYPE = 0// 当前的日志记录类型为存储在SD卡下面  
  52.     private final int MEMORY_TYPE = 1// 当前的日志记录类型为存储在内存中  
  53.     private int CURR_LOG_TYPE = SDCARD_TYPE; // 当前的日志记录类型  
  54.   
  55.     private String CURR_INSTALL_LOG_NAME; // 如果当前的日志写在内存中,记录当前的日志文件名称  
  56.   
  57.     private String logServiceLogName = "Log.log";// 本服务输出的日志文件名称  
  58.     private SimpleDateFormat myLogSdf = new SimpleDateFormat(  
  59.             "yyyy-MM-dd HH:mm:ss");  
  60.     private OutputStreamWriter writer;  
  61.   
  62.     private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmmss");// 日志名称格式  
  63.   
  64.     private Process process;  
  65.   
  66.     private WakeLock wakeLock;  
  67.   
  68.     private SDStateMonitorReceiver sdStateReceiver; // SDcard状态监测  
  69.     private LogTaskReceiver logTaskReceiver;  
  70.   
  71.     /* 
  72.      * 是否正在监测日志文件大小; 如果当前日志记录在SDcard中则为false 如果当前日志记录在内存中则为true 
  73.      */  
  74.     private boolean logSizeMoniting = false;  
  75.   
  76.     private static String MONITOR_LOG_SIZE_ACTION = "MONITOR_LOG_SIZE"// 日志文件监测action  
  77.     private static String SWITCH_LOG_FILE_ACTION = "SWITCH_LOG_FILE_ACTION"// 切换日志文件action  
  78.   
  79.     @Override  
  80.     public IBinder onBind(Intent intent)  
  81.     {  
  82.         return null;  
  83.     }  
  84.   
  85.     @Override  
  86.     public void onCreate()  
  87.     {  
  88.         super.onCreate();  
  89.         init();  
  90.         register();  
  91.         deploySwitchLogFileTask();  
  92.         new LogCollectorThread().start();  
  93.     }  
  94.   
  95.     private void init()  
  96.     {  
  97.         LOG_PATH_MEMORY_DIR = getFilesDir().getAbsolutePath() + File.separator  
  98.                 + "log";  
  99.         LOG_SERVICE_LOG_PATH = LOG_PATH_MEMORY_DIR + File.separator  
  100.                 + logServiceLogName;  
  101.         LOG_PATH_SDCARD_DIR = Environment.getExternalStorageDirectory()  
  102.                 .getAbsolutePath()  
  103.                 + File.separator  
  104.                 + "MyApp"  
  105.                 + File.separator  
  106.                 + "log";  
  107.         createLogDir();  
  108.   
  109.         /* ****************************************************** 
  110.          * try { writer = new OutputStreamWriter(new FileOutputStream( 
  111.          * LOG_SERVICE_LOG_PATH, true)); } catch (FileNotFoundException e) { 
  112.          * Log.e(TAG, e.getMessage(), e); } 
  113.          * ***************************************************** 
  114.          */  
  115.         PowerManager pm = (PowerManager) getApplicationContext()  
  116.                 .getSystemService(Context.POWER_SERVICE);  
  117.         wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);  
  118.   
  119.         CURR_LOG_TYPE = getCurrLogType();  
  120.         Log.i(TAG, "LogService onCreate");  
  121.     }  
  122.   
  123.     private void register()  
  124.     {  
  125.         IntentFilter sdCarMonitorFilter = new IntentFilter();  
  126.         sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  127.         sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  128.         sdCarMonitorFilter.addDataScheme("file");  
  129.         sdStateReceiver = new SDStateMonitorReceiver();  
  130.         registerReceiver(sdStateReceiver, sdCarMonitorFilter);  
  131.   
  132.         IntentFilter logTaskFilter = new IntentFilter();  
  133.         logTaskFilter.addAction(MONITOR_LOG_SIZE_ACTION);  
  134.         logTaskFilter.addAction(SWITCH_LOG_FILE_ACTION);  
  135.         logTaskReceiver = new LogTaskReceiver();  
  136.         registerReceiver(logTaskReceiver, logTaskFilter);  
  137.     }  
  138.   
  139.     /** 
  140.      * 获取当前应存储在内存中还是存储在SDCard中 
  141.      *  
  142.      * @return 
  143.      */  
  144.     public int getCurrLogType()  
  145.     {  
  146.         if (!Environment.getExternalStorageState().equals(  
  147.                 Environment.MEDIA_MOUNTED))  
  148.         {  
  149.             return MEMORY_TYPE;  
  150.         } else  
  151.         {  
  152.             return SDCARD_TYPE;  
  153.         }  
  154.     }  
  155.   
  156.     /** 
  157.      * 部署日志切换任务,每天凌晨切换日志文件 
  158.      */  
  159.     private void deploySwitchLogFileTask()  
  160.     {  
  161.         Intent intent = new Intent(SWITCH_LOG_FILE_ACTION);  
  162.         PendingIntent sender = PendingIntent.getBroadcast(this0, intent, 0);  
  163.         Calendar calendar = Calendar.getInstance();  
  164.         calendar.add(Calendar.DAY_OF_MONTH, 1);  
  165.         calendar.set(Calendar.HOUR_OF_DAY, 0);  
  166.         calendar.set(Calendar.MINUTE, 0);  
  167.         calendar.set(Calendar.SECOND, 0);  
  168.   
  169.         // 部署任务  
  170.         AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);  
  171.         am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),  
  172.                 AlarmManager.INTERVAL_DAY, sender);  
  173.         recordLogServiceLog("deployNextTask succ,next task time is:"  
  174.                 + myLogSdf.format(calendar.getTime()));  
  175.     }  
  176.   
  177.     /** 
  178.      * 日志收集 1.清除日志缓存 2.杀死应用程序已开启的Logcat进程防止多个进程写入一个日志文件 3.开启日志收集进程 4.处理日志文件 移动 
  179.      * OR 删除 
  180.      */  
  181.     class LogCollectorThread extends Thread {  
  182.   
  183.         public LogCollectorThread() {  
  184.             super("LogCollectorThread");  
  185.             Log.d(TAG, "LogCollectorThread is create");  
  186.         }  
  187.   
  188.         @Override  
  189.         public void run()  
  190.         {  
  191.             try  
  192.             {  
  193.                 wakeLock.acquire(); // 唤醒手机  
  194.   
  195.                 clearLogCache();  
  196.   
  197.                 List<String> orgProcessList = getAllProcess();  
  198.                 List<ProcessInfo> processInfoList = getProcessInfoList(orgProcessList);  
  199.                 killLogcatProc(processInfoList);  
  200.   
  201.                 createLogCollector();  
  202.   
  203.                 Thread.sleep(1000);// 休眠,创建文件,然后处理文件,不然该文件还没创建,会影响文件删除  
  204.   
  205.                 handleLog();  
  206.   
  207.                 wakeLock.release(); // 释放  
  208.             } catch (Exception e)  
  209.             {  
  210.                 e.printStackTrace();  
  211.                 recordLogServiceLog(Log.getStackTraceString(e));  
  212.             }  
  213.         }  
  214.     }  
  215.   
  216.     /** 
  217.      * 每次记录日志之前先清除日志的缓存, 不然会在两个日志文件中记录重复的日志 
  218.      */  
  219.     private void clearLogCache()  
  220.     {  
  221.         Process proc = null;  
  222.         List<String> commandList = new ArrayList<String>();  
  223.         commandList.add("logcat");  
  224.         commandList.add("-c");  
  225.         try  
  226.         {  
  227.             proc = Runtime.getRuntime().exec(  
  228.                     commandList.toArray(new String[commandList.size()]));  
  229.             StreamConsumer errorGobbler = new StreamConsumer(  
  230.                     proc.getErrorStream());  
  231.   
  232.             StreamConsumer outputGobbler = new StreamConsumer(  
  233.                     proc.getInputStream());  
  234.   
  235.             errorGobbler.start();  
  236.             outputGobbler.start();  
  237.             if (proc.waitFor() != 0)  
  238.             {  
  239.                 Log.e(TAG, " clearLogCache proc.waitFor() != 0");  
  240.                 recordLogServiceLog("clearLogCache clearLogCache proc.waitFor() != 0");  
  241.             }  
  242.         } catch (Exception e)  
  243.         {  
  244.             Log.e(TAG, "clearLogCache failed", e);  
  245.             recordLogServiceLog("clearLogCache failed");  
  246.         } finally  
  247.         {  
  248.             try  
  249.             {  
  250.                 proc.destroy();  
  251.             } catch (Exception e)  
  252.             {  
  253.                 Log.e(TAG, "clearLogCache failed", e);  
  254.                 recordLogServiceLog("clearLogCache failed");  
  255.             }  
  256.         }  
  257.     }  
  258.   
  259.     /** 
  260.      * 关闭由本程序开启的logcat进程: 根据用户名称杀死进程(如果是本程序进程开启的Logcat收集进程那么两者的USER一致) 
  261.      * 如果不关闭会有多个进程读取logcat日志缓存信息写入日志文件 
  262.      *  
  263.      * @param allProcList 
  264.      * @return 
  265.      */  
  266.     private void killLogcatProc(List<ProcessInfo> allProcList)  
  267.     {  
  268.         if (process != null)  
  269.         {  
  270.             process.destroy();  
  271.         }  
  272.         String packName = this.getPackageName();  
  273.         String myUser = getAppUser(packName, allProcList);  
  274.         /* 
  275.          * recordLogServiceLog("app user is:"+myUser); 
  276.          * recordLogServiceLog("========================"); for (ProcessInfo 
  277.          * processInfo : allProcList) { 
  278.          * recordLogServiceLog(processInfo.toString()); } 
  279.          * recordLogServiceLog("========================"); 
  280.          */  
  281.         for (ProcessInfo processInfo : allProcList)  
  282.         {  
  283.             if (processInfo.name.toLowerCase().equals("logcat")  
  284.                     && processInfo.user.equals(myUser))  
  285.             {  
  286.                 android.os.Process.killProcess(Integer  
  287.                         .parseInt(processInfo.pid));  
  288.                 // recordLogServiceLog("kill another logcat process success,the process info is:"  
  289.                 // + processInfo);  
  290.             }  
  291.         }  
  292.     }  
  293.   
  294.     /** 
  295.      * 获取本程序的用户名称 
  296.      *  
  297.      * @param packName 
  298.      * @param allProcList 
  299.      * @return 
  300.      */  
  301.     private String getAppUser(String packName, List<ProcessInfo> allProcList)  
  302.     {  
  303.         for (ProcessInfo processInfo : allProcList)  
  304.         {  
  305.             if (processInfo.name.equals(packName))  
  306.             {  
  307.                 return processInfo.user;  
  308.             }  
  309.         }  
  310.         return null;  
  311.     }  
  312.   
  313.     /** 
  314.      * 根据ps命令得到的内容获取PID,User,name等信息 
  315.      *  
  316.      * @param orgProcessList 
  317.      * @return 
  318.      */  
  319.     private List<ProcessInfo> getProcessInfoList(List<String> orgProcessList)  
  320.     {  
  321.         List<ProcessInfo> procInfoList = new ArrayList<ProcessInfo>();  
  322.         for (int i = 1; i < orgProcessList.size(); i++)  
  323.         {  
  324.             String processInfo = orgProcessList.get(i);  
  325.             String[] proStr = processInfo.split(" ");  
  326.             // USER PID PPID VSIZE RSS WCHAN PC NAME  
  327.             // root 1 0 416 300 c00d4b28 0000cd5c S /init  
  328.             List<String> orgInfo = new ArrayList<String>();  
  329.             for (String str : proStr)  
  330.             {  
  331.                 if (!"".equals(str))  
  332.                 {  
  333.                     orgInfo.add(str);  
  334.                 }  
  335.             }  
  336.             if (orgInfo.size() == 9)  
  337.             {  
  338.                 ProcessInfo pInfo = new ProcessInfo();  
  339.                 pInfo.user = orgInfo.get(0);  
  340.                 pInfo.pid = orgInfo.get(1);  
  341.                 pInfo.ppid = orgInfo.get(2);  
  342.                 pInfo.name = orgInfo.get(8);  
  343.                 procInfoList.add(pInfo);  
  344.             }  
  345.         }  
  346.         return procInfoList;  
  347.     }  
  348.   
  349.     /** 
  350.      * 运行PS命令得到进程信息 
  351.      *  
  352.      * @return USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 416 300 c00d4b28 
  353.      *         0000cd5c S /init 
  354.      */  
  355.     private List<String> getAllProcess()  
  356.     {  
  357.         List<String> orgProcList = new ArrayList<String>();  
  358.         Process proc = null;  
  359.         try  
  360.         {  
  361.             proc = Runtime.getRuntime().exec("ps");  
  362.             StreamConsumer errorConsumer = new StreamConsumer(  
  363.                     proc.getErrorStream());  
  364.   
  365.             StreamConsumer outputConsumer = new StreamConsumer(  
  366.                     proc.getInputStream(), orgProcList);  
  367.   
  368.             errorConsumer.start();  
  369.             outputConsumer.start();  
  370.             if (proc.waitFor() != 0)  
  371.             {  
  372.                 Log.e(TAG, "getAllProcess proc.waitFor() != 0");  
  373.                 recordLogServiceLog("getAllProcess proc.waitFor() != 0");  
  374.             }  
  375.         } catch (Exception e)  
  376.         {  
  377.             Log.e(TAG, "getAllProcess failed", e);  
  378.             recordLogServiceLog("getAllProcess failed");  
  379.         } finally  
  380.         {  
  381.             try  
  382.             {  
  383.                 proc.destroy();  
  384.             } catch (Exception e)  
  385.             {  
  386.                 Log.e(TAG, "getAllProcess failed", e);  
  387.                 recordLogServiceLog("getAllProcess failed");  
  388.             }  
  389.         }  
  390.         return orgProcList;  
  391.     }  
  392.   
  393.     /** 
  394.      * 开始收集日志信息 
  395.      */  
  396.     public void createLogCollector()  
  397.     {  
  398.         String logFileName = sdf.format(new Date()) + ".log";// 日志文件名称  
  399.         List<String> commandList = new ArrayList<String>();  
  400.         commandList.add("logcat");  
  401.         commandList.add("-f");  
  402.         // commandList.add(LOG_PATH_INSTALL_DIR + File.separator + logFileName);  
  403.         commandList.add(getLogPath());  
  404.         commandList.add("-v");  
  405.         commandList.add("time");  
  406.         commandList.add("*:I");  
  407.   
  408.         // commandList.add("*:E");// 过滤所有的错误信息  
  409.   
  410.         // 过滤指定TAG的信息  
  411.         // commandList.add("MyAPP:V");  
  412.         // commandList.add("*:S");  
  413.         try  
  414.         {  
  415.             process = Runtime.getRuntime().exec(  
  416.                     commandList.toArray(new String[commandList.size()]));  
  417.             recordLogServiceLog("start collecting the log,and log name is:"  
  418.                     + logFileName);  
  419.             // process.waitFor();  
  420.         } catch (Exception e)  
  421.         {  
  422.             Log.e(TAG, "CollectorThread == >" + e.getMessage(), e);  
  423.             recordLogServiceLog("CollectorThread == >" + e.getMessage());  
  424.         }  
  425.     }  
  426.   
  427.     /** 
  428.      * 根据当前的存储位置得到日志的绝对存储路径 
  429.      *  
  430.      * @return 
  431.      */  
  432.     public String getLogPath()  
  433.     {  
  434.         createLogDir();  
  435.         String logFileName = sdf.format(new Date()) + ".log";// 日志文件名称  
  436.         if (CURR_LOG_TYPE == MEMORY_TYPE)  
  437.         {  
  438.             CURR_INSTALL_LOG_NAME = logFileName;  
  439.             Log.d(TAG, "Log stored in memory, the path is:"  
  440.                     + LOG_PATH_MEMORY_DIR + File.separator + logFileName);  
  441.             return LOG_PATH_MEMORY_DIR + File.separator + logFileName;  
  442.         } else  
  443.         {  
  444.             CURR_INSTALL_LOG_NAME = null;  
  445.             Log.d(TAG, "Log stored in SDcard, the path is:"  
  446.                     + LOG_PATH_SDCARD_DIR + File.separator + logFileName);  
  447.             return LOG_PATH_SDCARD_DIR + File.separator + logFileName;  
  448.         }  
  449.     }  
  450.   
  451.     /** 
  452.      * 处理日志文件 1.如果日志文件存储位置切换到内存中,删除除了正在写的日志文件 并且部署日志大小监控任务,控制日志大小不超过规定值 
  453.      * 2.如果日志文件存储位置切换到SDCard中,删除7天之前的日志,移 动所有存储在内存中的日志到SDCard中,并将之前部署的日志大小 监控取消 
  454.      */  
  455.     public void handleLog()  
  456.     {  
  457.         if (CURR_LOG_TYPE == MEMORY_TYPE)  
  458.         {  
  459.             deployLogSizeMonitorTask();  
  460.             deleteMemoryExpiredLog();  
  461.         } else  
  462.         {  
  463.             moveLogfile();  
  464.             cancelLogSizeMonitorTask();  
  465.             deleteSDcardExpiredLog();  
  466.         }  
  467.     }  
  468.   
  469.     /** 
  470.      * 部署日志大小监控任务 
  471.      */  
  472.     private void deployLogSizeMonitorTask()  
  473.     {  
  474.         if (logSizeMoniting)  
  475.         { // 如果当前正在监控着,则不需要继续部署  
  476.             return;  
  477.         }  
  478.         logSizeMoniting = true;  
  479.         Intent intent = new Intent(MONITOR_LOG_SIZE_ACTION);  
  480.         PendingIntent sender = PendingIntent.getBroadcast(this0, intent, 0);  
  481.         AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);  
  482.         am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),  
  483.                 MEMORY_LOG_FILE_MONITOR_INTERVAL, sender);  
  484.         Log.d(TAG, "deployLogSizeMonitorTask() succ !");  
  485.         // recordLogServiceLog("deployLogSizeMonitorTask() succ ,start time is "  
  486.         // + calendar.getTime().toLocaleString());  
  487.     }  
  488.   
  489.     /** 
  490.      * 取消部署日志大小监控任务 
  491.      */  
  492.     private void cancelLogSizeMonitorTask()  
  493.     {  
  494.         logSizeMoniting = false;  
  495.         AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);  
  496.         Intent intent = new Intent(MONITOR_LOG_SIZE_ACTION);  
  497.         PendingIntent sender = PendingIntent.getBroadcast(this0, intent, 0);  
  498.         am.cancel(sender);  
  499.   
  500.         Log.d(TAG, "canelLogSizeMonitorTask() succ");  
  501.     }  
  502.   
  503.     /** 
  504.      * 检查日志文件大小是否超过了规定大小 如果超过了重新开启一个日志收集进程 
  505.      */  
  506.     private void checkLogSize()  
  507.     {  
  508.         if (CURR_INSTALL_LOG_NAME != null && !"".equals(CURR_INSTALL_LOG_NAME))  
  509.         {  
  510.             String path = LOG_PATH_MEMORY_DIR + File.separator  
  511.                     + CURR_INSTALL_LOG_NAME;  
  512.             File file = new File(path);  
  513.             if (!file.exists())  
  514.             {  
  515.                 return;  
  516.             }  
  517.             Log.d(TAG, "checkLog() ==> The size of the log is too big?");  
  518.             if (file.length() >= MEMORY_LOG_FILE_MAX_SIZE)  
  519.             {  
  520.                 Log.d(TAG, "The log's size is too big!");  
  521.                 new LogCollectorThread().start();  
  522.             }  
  523.         }  
  524.     }  
  525.   
  526.     /** 
  527.      * 创建日志目录 
  528.      */  
  529.     private void createLogDir()  
  530.     {  
  531.         File file = new File(LOG_PATH_MEMORY_DIR);  
  532.         boolean mkOk;  
  533.         if (!file.isDirectory())  
  534.         {  
  535.             mkOk = file.mkdirs();  
  536.             if (!mkOk)  
  537.             {  
  538.                 mkOk = file.mkdirs();  
  539.             }  
  540.         }  
  541.   
  542.         /* ************************************ 
  543.          * file = new File(LOG_SERVICE_LOG_PATH); if (!file.exists()) { try { 
  544.          * mkOk = file.createNewFile(); if (!mkOk) { file.createNewFile(); } } 
  545.          * catch (IOException e) { Log.e(TAG, e.getMessage(), e); } } 
  546.          * *********************************** 
  547.          */  
  548.   
  549.         if (Environment.getExternalStorageState().equals(  
  550.                 Environment.MEDIA_MOUNTED))  
  551.         {  
  552.             file = new File(LOG_PATH_SDCARD_DIR);  
  553.             if (!file.isDirectory())  
  554.             {  
  555.                 mkOk = file.mkdirs();  
  556.                 if (!mkOk)  
  557.                 {  
  558.                     recordLogServiceLog("move file failed,dir is not created succ");  
  559.                     return;  
  560.                 }  
  561.             }  
  562.         }  
  563.     }  
  564.   
  565.     /** 
  566.      * 将日志文件转移到SD卡下面 
  567.      */  
  568.     private void moveLogfile()  
  569.     {  
  570.         if (!Environment.getExternalStorageState().equals(  
  571.                 Environment.MEDIA_MOUNTED))  
  572.         {  
  573.             // recordLogServiceLog("move file failed, sd card does not mount");  
  574.             return;  
  575.         }  
  576.         File file = new File(LOG_PATH_SDCARD_DIR);  
  577.         if (!file.isDirectory())  
  578.         {  
  579.             boolean mkOk = file.mkdirs();  
  580.             if (!mkOk)  
  581.             {  
  582.                 // recordLogServiceLog("move file failed,dir is not created succ");  
  583.                 return;  
  584.             }  
  585.         }  
  586.   
  587.         file = new File(LOG_PATH_MEMORY_DIR);  
  588.         if (file.isDirectory())  
  589.         {  
  590.             File[] allFiles = file.listFiles();  
  591.             for (File logFile : allFiles)  
  592.             {  
  593.                 String fileName = logFile.getName();  
  594.                 if (logServiceLogName.equals(fileName))  
  595.                 {  
  596.                     continue;  
  597.                 }  
  598.                 // String createDateInfo =  
  599.                 // getFileNameWithoutExtension(fileName);  
  600.                 boolean isSucc = copy(logFile, new File(LOG_PATH_SDCARD_DIR  
  601.                         + File.separator + fileName));  
  602.                 if (isSucc)  
  603.                 {  
  604.                     logFile.delete();  
  605.                     // recordLogServiceLog("move file success,log name is:"+fileName);  
  606.                 }  
  607.             }  
  608.         }  
  609.     }  
  610.   
  611.     /** 
  612.      * 删除内存下过期的日志 
  613.      */  
  614.     private void deleteSDcardExpiredLog()  
  615.     {  
  616.         File file = new File(LOG_PATH_SDCARD_DIR);  
  617.         if (file.isDirectory())  
  618.         {  
  619.             File[] allFiles = file.listFiles();  
  620.             for (File logFile : allFiles)  
  621.             {  
  622.                 String fileName = logFile.getName();  
  623.                 if (logServiceLogName.equals(fileName))  
  624.                 {  
  625.                     continue;  
  626.                 }  
  627.                 String createDateInfo = getFileNameWithoutExtension(fileName);  
  628.                 if (canDeleteSDLog(createDateInfo))  
  629.                 {  
  630.                     logFile.delete();  
  631.                     Log.d(TAG, "delete expired log success,the log path is:"  
  632.                             + logFile.getAbsolutePath());  
  633.   
  634.                 }  
  635.             }  
  636.         }  
  637.     }  
  638.   
  639.     /** 
  640.      * 判断sdcard上的日志文件是否可以删除 
  641.      *  
  642.      * @param createDateStr 
  643.      * @return 
  644.      */  
  645.     public boolean canDeleteSDLog(String createDateStr)  
  646.     {  
  647.         boolean canDel = false;  
  648.         Calendar calendar = Calendar.getInstance();  
  649.         calendar.add(Calendar.DAY_OF_MONTH, -1 * SDCARD_LOG_FILE_SAVE_DAYS);// 删除7天之前日志  
  650.         Date expiredDate = calendar.getTime();  
  651.         try  
  652.         {  
  653.             Date createDate = sdf.parse(createDateStr);  
  654.             canDel = createDate.before(expiredDate);  
  655.         } catch (ParseException e)  
  656.         {  
  657.             Log.e(TAG, e.getMessage(), e);  
  658.             canDel = false;  
  659.         }  
  660.         return canDel;  
  661.     }  
  662.   
  663.     /** 
  664.      * 删除内存中的过期日志,删除规则: 除了当前的日志和离当前时间最近的日志保存其他的都删除 
  665.      */  
  666.     private void deleteMemoryExpiredLog()  
  667.     {  
  668.         File file = new File(LOG_PATH_MEMORY_DIR);  
  669.         if (file.isDirectory())  
  670.         {  
  671.             File[] allFiles = file.listFiles();  
  672.             Arrays.sort(allFiles, new FileComparator());  
  673.             for (int i = 0; i < allFiles.length - 2; i++)  
  674.             { // "-2"保存最近的两个日志文件  
  675.                 File _file = allFiles[i];  
  676.                 if (logServiceLogName.equals(_file.getName())  
  677.                         || _file.getName().equals(CURR_INSTALL_LOG_NAME))  
  678.                 {  
  679.                     continue;  
  680.                 }  
  681.                 _file.delete();  
  682.                 Log.d(TAG, "delete expired log success,the log path is:"  
  683.                         + _file.getAbsolutePath());  
  684.             }  
  685.         }  
  686.     }  
  687.   
  688.     /** 
  689.      * 拷贝文件 
  690.      *  
  691.      * @param source 
  692.      * @param target 
  693.      * @return 
  694.      */  
  695.     private boolean copy(File source, File target)  
  696.     {  
  697.         FileInputStream in = null;  
  698.         FileOutputStream out = null;  
  699.         try  
  700.         {  
  701.             if (!target.exists())  
  702.             {  
  703.                 boolean createSucc = target.createNewFile();  
  704.                 if (!createSucc)  
  705.                 {  
  706.                     return false;  
  707.                 }  
  708.             }  
  709.             in = new FileInputStream(source);  
  710.             out = new FileOutputStream(target);  
  711.             byte[] buffer = new byte[8 * 1024];  
  712.             int count;  
  713.             while ((count = in.read(buffer)) != -1)  
  714.             {  
  715.                 out.write(buffer, 0, count);  
  716.             }  
  717.             return true;  
  718.         } catch (Exception e)  
  719.         {  
  720.             e.printStackTrace();  
  721.             Log.e(TAG, e.getMessage(), e);  
  722.             recordLogServiceLog("copy file fail");  
  723.             return false;  
  724.         } finally  
  725.         {  
  726.             try  
  727.             {  
  728.                 if (in != null)  
  729.                 {  
  730.                     in.close();  
  731.                 }  
  732.                 if (out != null)  
  733.                 {  
  734.                     out.close();  
  735.                 }  
  736.             } catch (IOException e)  
  737.             {  
  738.                 e.printStackTrace();  
  739.                 Log.e(TAG, e.getMessage(), e);  
  740.                 recordLogServiceLog("copy file fail");  
  741.                 return false;  
  742.             }  
  743.         }  
  744.   
  745.     }  
  746.   
  747.     /** 
  748.      * 记录日志服务的基本信息 防止日志服务有错,在LogCat日志中无法查找 此日志名称为Log.log 
  749.      *  
  750.      * @param msg 
  751.      */  
  752.     private void recordLogServiceLog(String msg)  
  753.     {  
  754.         if (writer != null)  
  755.         {  
  756.             try  
  757.             {  
  758.                 Date time = new Date();  
  759.                 writer.write(myLogSdf.format(time) + " : " + msg);  
  760.                 writer.write("\n");  
  761.                 writer.flush();  
  762.             } catch (IOException e)  
  763.             {  
  764.                 e.printStackTrace();  
  765.                 Log.e(TAG, e.getMessage(), e);  
  766.             }  
  767.         }  
  768.     }  
  769.   
  770.     /** 
  771.      * 去除文件的扩展类型(.log) 
  772.      *  
  773.      * @param fileName 
  774.      * @return 
  775.      */  
  776.     private String getFileNameWithoutExtension(String fileName)  
  777.     {  
  778.         return fileName.substring(0, fileName.indexOf("."));  
  779.     }  
  780.   
  781.     class ProcessInfo {  
  782.         public String user;  
  783.         public String pid;  
  784.         public String ppid;  
  785.         public String name;  
  786.   
  787.         @Override  
  788.         public String toString()  
  789.         {  
  790.             String str = "user=" + user + " pid=" + pid + " ppid=" + ppid  
  791.                     + " name=" + name;  
  792.             return str;  
  793.         }  
  794.     }  
  795.   
  796.     class StreamConsumer extends Thread {  
  797.         InputStream is;  
  798.         List<String> list;  
  799.   
  800.         StreamConsumer(InputStream is) {  
  801.             this.is = is;  
  802.         }  
  803.   
  804.         StreamConsumer(InputStream is, List<String> list) {  
  805.             this.is = is;  
  806.             this.list = list;  
  807.         }  
  808.   
  809.         public void run()  
  810.         {  
  811.             try  
  812.             {  
  813.                 InputStreamReader isr = new InputStreamReader(is);  
  814.                 BufferedReader br = new BufferedReader(isr);  
  815.                 String line = null;  
  816.                 while ((line = br.readLine()) != null)  
  817.                 {  
  818.                     if (list != null)  
  819.                     {  
  820.                         list.add(line);  
  821.                     }  
  822.                 }  
  823.             } catch (IOException ioe)  
  824.             {  
  825.                 ioe.printStackTrace();  
  826.             }  
  827.         }  
  828.     }  
  829.   
  830.     /** 
  831.      * 监控SD卡状态 
  832.      *  
  833.      * @author Administrator 
  834.      *  
  835.      */  
  836.     class SDStateMonitorReceiver extends BroadcastReceiver {  
  837.         public void onReceive(Context context, Intent intent)  
  838.         {  
  839.   
  840.             if (Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction()))  
  841.             { // 存储卡被卸载  
  842.                 if (CURR_LOG_TYPE == SDCARD_TYPE)  
  843.                 {  
  844.                     Log.d(TAG, "SDcar is UNMOUNTED");  
  845.                     CURR_LOG_TYPE = MEMORY_TYPE;  
  846.                     new LogCollectorThread().start();  
  847.                 }  
  848.             } else  
  849.             { // 存储卡被挂载  
  850.                 if (CURR_LOG_TYPE == MEMORY_TYPE)  
  851.                 {  
  852.                     Log.d(TAG, "SDcar is MOUNTED");  
  853.                     CURR_LOG_TYPE = SDCARD_TYPE;  
  854.                     new LogCollectorThread().start();  
  855.   
  856.                 }  
  857.             }  
  858.         }  
  859.     }  
  860.   
  861.     /** 
  862.      * 日志任务接收 切换日志,监控日志大小 
  863.      *  
  864.      * @author Administrator 
  865.      *  
  866.      */  
  867.     class LogTaskReceiver extends BroadcastReceiver {  
  868.         public void onReceive(Context context, Intent intent)  
  869.         {  
  870.             String action = intent.getAction();  
  871.             if (SWITCH_LOG_FILE_ACTION.equals(action))  
  872.             {  
  873.                 new LogCollectorThread().start();  
  874.             } else if (MONITOR_LOG_SIZE_ACTION.equals(action))  
  875.             {  
  876.                 checkLogSize();  
  877.             }  
  878.         }  
  879.     }  
  880.   
  881.     class FileComparator implements Comparator<File> {  
  882.         public int compare(File file1, File file2)  
  883.         {  
  884.             if (logServiceLogName.equals(file1.getName()))  
  885.             {  
  886.                 return -1;  
  887.             } else if (logServiceLogName.equals(file2.getName()))  
  888.             {  
  889.                 return 1;  
  890.             }  
  891.   
  892.             String createInfo1 = getFileNameWithoutExtension(file1.getName());  
  893.             String createInfo2 = getFileNameWithoutExtension(file2.getName());  
  894.   
  895.             try  
  896.             {  
  897.                 Date create1 = sdf.parse(createInfo1);  
  898.                 Date create2 = sdf.parse(createInfo2);  
  899.                 if (create1.before(create2))  
  900.                 {  
  901.                     return -1;  
  902.                 } else  
  903.                 {  
  904.                     return 1;  
  905.                 }  
  906.             } catch (ParseException e)  
  907.             {  
  908.                 return 0;  
  909.             }  
  910.         }  
  911.     }  
  912.   
  913.     @Override  
  914.     public void onDestroy()  
  915.     {  
  916.         super.onDestroy();  
  917.         recordLogServiceLog("LogService onDestroy");  
  918.         if (writer != null)  
  919.         {  
  920.             try  
  921.             {  
  922.                 writer.close();  
  923.             } catch (IOException e)  
  924.             {  
  925.                 e.printStackTrace();  
  926.             }  
  927.         }  
  928.         if (process != null)  
  929.         {  
  930.             process.destroy();  
  931.         }  
  932.   
  933.         unregisterReceiver(sdStateReceiver);  
  934.         unregisterReceiver(logTaskReceiver);  
  935.     }  
  936.   
  937. }  


最后不要忘记在配置文件中加入
Xml代码 
<uses-permission android:name="android.permission.READ_LOGS" />

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值