记录全部log

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.io.OutputStreamWriter;   
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.PowerManager.WakeLock;   
import android.util.Log;   
  
  
public class LogService extends Service {   
    private static final String TAG = "LogService";   
  
    private static final int MEMORY_LOG_FILE_MAX_SIZE = 10 * 1024 * 1024;           //内存中日志文件最大值,10M   
    private static final int MEMORY_LOG_FILE_MONITOR_INTERVAL = 10 * 60 * 1000;     //内存中的日志文件大小监控时间间隔,10分钟   
    private static final int SDCARD_LOG_FILE_SAVE_DAYS = 7;                         //sd卡中日志文件的最多保存天数   
       
    private String LOG_PATH_MEMORY_DIR;     //日志文件在内存中的路径(日志文件在安装目录中的路径)   
    private String LOG_PATH_SDCARD_DIR;     //日志文件在sdcard中的路径   
    @SuppressWarnings("unused")   
    private String LOG_SERVICE_LOG_PATH;    //本服务产生的日志,记录日志服务开启失败信息   
       
    private final int SDCARD_TYPE = 0;          //当前的日志记录类型为存储在SD卡下面   
    private final int MEMORY_TYPE = 1;          //当前的日志记录类型为存储在内存中   
    private int CURR_LOG_TYPE = SDCARD_TYPE;    //当前的日志记录类型   
       
    private String CURR_INSTALL_LOG_NAME;   //如果当前的日志写在内存中,记录当前的日志文件名称   
       
    private String logServiceLogName = "Log.log";//本服务输出的日志文件名称   
    private SimpleDateFormat myLogSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
    private OutputStreamWriter writer;   
       
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmmss");//日志名称格式   
       
    private Process process;   
       
    private WakeLock wakeLock;     
       
    private SDStateMonitorReceiver sdStateReceiver; //SDcard状态监测   
    private LogTaskReceiver logTaskReceiver;    
       
      
    private boolean logSizeMoniting = false;           
       
    private static String MONITOR_LOG_SIZE_ACTION = "com.walktour.gui.MONITOR_LOG_SIZE";        //日志文件监测action   
    private static String SWITCH_LOG_FILE_ACTION = "com.walktour.gui.SWITCH_LOG_FILE_ACTION";   //切换日志文件action   
       
    @Override  
    public IBinder onBind(Intent intent) {   
        return null;   
    }   
  
    @Override  
    public void onCreate() {   
        super.onCreate();   
        init();   
        register();   
        deploySwitchLogFileTask();     
        new LogCollectorThread().start();   
    }   
       
    private void init(){   
        LOG_PATH_MEMORY_DIR = getFilesDir().getAbsolutePath() + File.separator + "log";   
        LOG_SERVICE_LOG_PATH = LOG_PATH_MEMORY_DIR + File.separator + logServiceLogName;   
        LOG_PATH_SDCARD_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator   
                            +   "walktour" + File.separator + "log";   
        createLogDir();   
           
          
        PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);   
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);   
           
        CURR_LOG_TYPE = getCurrLogType();   
        Log.i(TAG, "LogService onCreate");   
    }   
       
    private void register(){   
        IntentFilter sdCarMonitorFilter = new IntentFilter();   
        sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);   
        sdCarMonitorFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);   
        sdCarMonitorFilter.addDataScheme("file");   
        sdStateReceiver = new SDStateMonitorReceiver();   
        registerReceiver(sdStateReceiver, sdCarMonitorFilter);   
           
        IntentFilter logTaskFilter = new IntentFilter();   
        logTaskFilter.addAction(MONITOR_LOG_SIZE_ACTION);   
        logTaskFilter.addAction(SWITCH_LOG_FILE_ACTION);   
        logTaskReceiver = new LogTaskReceiver();   
        registerReceiver(logTaskReceiver,logTaskFilter);   
    }   
       
       
       
      
    public int getCurrLogType(){   
        if (!Environment.getExternalStorageState().equals(   
                Environment.MEDIA_MOUNTED)) {   
            return MEMORY_TYPE;   
        }else{   
            return SDCARD_TYPE;   
        }   
    }   
  
      
    private void deploySwitchLogFileTask() {   
        Intent intent = new Intent(SWITCH_LOG_FILE_ACTION);   
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);   
        Calendar calendar = Calendar.getInstance();   
        calendar.add(Calendar.DAY_OF_MONTH, 1);   
        calendar.set(Calendar.HOUR_OF_DAY, 0);   
        calendar.set(Calendar.MINUTE, 0);   
        calendar.set(Calendar.SECOND, 0);   
  
        // 部署任务   
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);   
        am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, sender);   
        recordLogServiceLog("deployNextTask succ,next task time is:"+myLogSdf.format(calendar.getTime()));   
    }   
  
      
    class LogCollectorThread extends Thread {   
           
        public LogCollectorThread(){   
            super("LogCollectorThread");   
            Log.d(TAG, "LogCollectorThread is create");   
        }   
           
        @Override  
        public void run() {   
            try {   
                wakeLock.acquire(); //唤醒手机   
                   
                clearLogCache();   
                   
                List<String> orgProcessList = getAllProcess();   
                List<ProcessInfo> processInfoList = getProcessInfoList(orgProcessList);   
                killLogcatProc(processInfoList);   
                   
                createLogCollector();   
                   
                Thread.sleep(1000);//休眠,创建文件,然后处理文件,不然该文件还没创建,会影响文件删除   
                   
                handleLog();   
                   
                wakeLock.release(); //释放   
            } catch (Exception e) {   
                e.printStackTrace();   
                recordLogServiceLog(Log.getStackTraceString(e));   
            }   
        }   
    }   
       
      
    private void 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");   
                recordLogServiceLog("clearLogCache clearLogCache proc.waitFor() != 0");   
            }   
        } catch (Exception e) {   
            Log.e(TAG, "clearLogCache failed", e);   
            recordLogServiceLog("clearLogCache failed");   
        } finally {   
            try {   
                proc.destroy();   
            } catch (Exception e) {   
                Log.e(TAG, "clearLogCache failed", e);   
                recordLogServiceLog("clearLogCache failed");   
            }   
        }   
    }   
  
      
    private void killLogcatProc(List<ProcessInfo> allProcList) {   
        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));   
                //recordLogServiceLog("kill another logcat process success,the process info is:"   
                //      + processInfo);   
            }   
        }   
    }   
  
      
    private String getAppUser(String packName, List<ProcessInfo> allProcList) {   
        for (ProcessInfo processInfo : allProcList) {   
            if (processInfo.name.equals(packName)) {   
                return processInfo.user;   
            }   
        }   
        return null;   
    }   
  
      
    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 /init   
            List<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;   
    }   
  
      
    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");   
                recordLogServiceLog("getAllProcess proc.waitFor() != 0");   
            }   
        } catch (Exception e) {   
            Log.e(TAG, "getAllProcess failed", e);   
            recordLogServiceLog("getAllProcess failed");   
        } finally {   
            try {   
                proc.destroy();   
            } catch (Exception e) {   
                Log.e(TAG, "getAllProcess failed", e);   
                recordLogServiceLog("getAllProcess failed");   
            }   
        }   
        return orgProcList;   
    }   
       
      
    public void createLogCollector() {   
        String logFileName = sdf.format(new Date()) + ".log";// 日志文件名称   
        List<String> commandList = new ArrayList<String>();   
        commandList.add("logcat");   
        commandList.add("-f");   
        //commandList.add(LOG_PATH_INSTALL_DIR + File.separator + logFileName);   
        commandList.add(getLogPath());   
        commandList.add("-v");   
        commandList.add("time");   
        commandList.add("*:I");   
           
        //commandList.add("*:E");// 过滤所有的错误信息   
  
        // 过滤指定TAG的信息   
        // commandList.add("MyAPP:V");   
        // commandList.add("*:S");   
        try {   
            process = Runtime.getRuntime().exec(   
                    commandList.toArray(new String[commandList.size()]));   
            recordLogServiceLog("start collecting the log,and log name is:"+logFileName);   
            // process.waitFor();   
        } catch (Exception e) {   
            Log.e(TAG, "CollectorThread == >" + e.getMessage(), e);   
            recordLogServiceLog("CollectorThread == >" + e.getMessage());   
        }   
    }   
       
      
    public String getLogPath(){   
        createLogDir();   
        String logFileName = sdf.format(new Date()) + ".log";// 日志文件名称   
        if(CURR_LOG_TYPE == MEMORY_TYPE){   
            CURR_INSTALL_LOG_NAME = logFileName;   
            Log.d(TAG, "Log stored in memory, the path is:"+LOG_PATH_MEMORY_DIR + File.separator + logFileName);   
            return LOG_PATH_MEMORY_DIR + File.separator + logFileName;   
        }else{   
            CURR_INSTALL_LOG_NAME = null;   
            Log.d(TAG, "Log stored in SDcard, the path is:"+LOG_PATH_SDCARD_DIR + File.separator + logFileName);   
            return LOG_PATH_SDCARD_DIR + File.separator + logFileName;   
        }   
    }   
       
      
    public void handleLog(){   
        if(CURR_LOG_TYPE == MEMORY_TYPE){   
            deployLogSizeMonitorTask();   
            deleteMemoryExpiredLog();   
        }else{   
            moveLogfile();   
            cancelLogSizeMonitorTask();   
            deleteSDcardExpiredLog();   
        }   
    }   
       
      
    private void deployLogSizeMonitorTask() {   
        if(logSizeMoniting){    //如果当前正在监控着,则不需要继续部署   
            return;   
        }   
        logSizeMoniting = true;   
        Intent intent = new Intent(MONITOR_LOG_SIZE_ACTION);   
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);   
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);   
        am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), MEMORY_LOG_FILE_MONITOR_INTERVAL, sender);   
        Log.d(TAG, "deployLogSizeMonitorTask() succ !");   
        //recordLogServiceLog("deployLogSizeMonitorTask() succ ,start time is " + calendar.getTime().toLocaleString());   
    }   
       
         
    private void cancelLogSizeMonitorTask() {   
        logSizeMoniting = false;   
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);   
        Intent intent = new Intent(MONITOR_LOG_SIZE_ACTION);   
        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);   
        am.cancel(sender);   
           
        Log.d(TAG, "canelLogSizeMonitorTask() succ");   
    }   
       
      
    private void checkLogSize(){   
        if(CURR_INSTALL_LOG_NAME != null && !"".equals(CURR_INSTALL_LOG_NAME)){   
            String path = LOG_PATH_MEMORY_DIR + File.separator + CURR_INSTALL_LOG_NAME;   
            File file = new File(path);   
            if(!file.exists()){   
                return;   
            }   
            Log.d(TAG, "checkLog() ==> The size of the log is too big?");   
            if(file.length() >= MEMORY_LOG_FILE_MAX_SIZE){   
                Log.d(TAG, "The log's size is too big!");   
                new LogCollectorThread().start();   
            }   
        }   
    }   
       
      
    private void createLogDir() {   
        File file = new File(LOG_PATH_MEMORY_DIR);   
        boolean mkOk;   
        if (!file.isDirectory()) {   
            mkOk = file.mkdirs();   
            if (!mkOk) {   
                mkOk = file.mkdirs();   
            }   
        }   
  
          
           
        if (Environment.getExternalStorageState().equals(   
                Environment.MEDIA_MOUNTED)) {   
            file = new File(LOG_PATH_SDCARD_DIR);   
            if (!file.isDirectory()) {   
                mkOk = file.mkdirs();   
                if (!mkOk) {   
                    recordLogServiceLog("move file failed,dir is not created succ");   
                    return;   
                }   
            }   
        }   
    }   
       
      
    private void moveLogfile() {   
        if (!Environment.getExternalStorageState().equals(   
                Environment.MEDIA_MOUNTED)) {   
            //recordLogServiceLog("move file failed, sd card does not mount");   
            return;   
        }   
        File file = new File(LOG_PATH_SDCARD_DIR);   
        if (!file.isDirectory()) {   
            boolean mkOk = file.mkdirs();   
            if (!mkOk) {   
                //recordLogServiceLog("move file failed,dir is not created succ");   
                return;   
            }   
        }   
  
        file = new File(LOG_PATH_MEMORY_DIR);   
        if (file.isDirectory()) {   
            File[] allFiles = file.listFiles();   
            for (File logFile : allFiles) {   
                String fileName = logFile.getName();   
                if (logServiceLogName.equals(fileName)) {   
                    continue;   
                }   
                //String createDateInfo = getFileNameWithoutExtension(fileName);   
                boolean isSucc = copy(logFile, new File(LOG_PATH_SDCARD_DIR   
                            + File.separator + fileName));   
                if (isSucc) {   
                    logFile.delete();   
                    //recordLogServiceLog("move file success,log name is:"+fileName);   
                }   
            }   
        }   
    }   
  
      
    private void deleteSDcardExpiredLog() {   
        File file = new File(LOG_PATH_SDCARD_DIR);   
        if (file.isDirectory()) {   
            File[] allFiles = file.listFiles();   
            for (File logFile : allFiles) {   
                String fileName = logFile.getName();   
                if (logServiceLogName.equals(fileName)) {   
                    continue;   
                }   
                String createDateInfo = getFileNameWithoutExtension(fileName);   
                if (canDeleteSDLog(createDateInfo)) {   
                    logFile.delete();   
                    Log.d(TAG, "delete expired log success,the log path is:"  
                            + logFile.getAbsolutePath());   
  
                }   
            }   
        }   
    }   
       
      
    public boolean canDeleteSDLog(String createDateStr) {   
        boolean canDel = false;   
        Calendar calendar = Calendar.getInstance();   
        calendar.add(Calendar.DAY_OF_MONTH, -1 * SDCARD_LOG_FILE_SAVE_DAYS);//删除7天之前日志   
        Date expiredDate = calendar.getTime();   
        try {   
            Date createDate = sdf.parse(createDateStr);   
            canDel = createDate.before(expiredDate);   
        } catch (ParseException e) {   
            Log.e(TAG, e.getMessage(), e);   
            canDel = false;   
        }   
        return canDel;   
    }   
  
       
      
    private void deleteMemoryExpiredLog(){   
        File file = new File(LOG_PATH_MEMORY_DIR);   
        if (file.isDirectory()) {   
            File[] allFiles = file.listFiles();   
            Arrays.sort(allFiles, new FileComparator());   
            for (int i=0;i<allFiles.length-2;i++) {  //"-2"保存最近的两个日志文件   
                File _file =  allFiles[i];   
                if (logServiceLogName.equals(_file.getName()) ||  _file.getName().equals(CURR_INSTALL_LOG_NAME)) {   
                    continue;   
                }   
                _file.delete();   
                Log.d(TAG, "delete expired log success,the log path is:"+_file.getAbsolutePath());   
            }   
        }   
    }   
       
      
    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) {   
            e.printStackTrace();   
            Log.e(TAG, e.getMessage(), e);   
            recordLogServiceLog("copy file fail");   
            return false;   
        } finally{   
            try {   
                if(in != null){   
                    in.close();   
                }   
                if(out != null){   
                    out.close();   
                }   
            } catch (IOException e) {   
                e.printStackTrace();   
                Log.e(TAG, e.getMessage(), e);   
                recordLogServiceLog("copy file fail");   
                return false;   
            }   
        }   
           
    }   
  
      
    private void recordLogServiceLog(String msg) {   
        if (writer != null) {   
            try {   
                Date time = new Date();   
                writer.write(myLogSdf.format(time) + " : " + msg);   
                writer.write("\n");   
                writer.flush();   
            } catch (IOException e) {   
                e.printStackTrace();   
                Log.e(TAG, e.getMessage(), e);   
            }   
        }   
    }   
       
      
    private String getFileNameWithoutExtension(String fileName){   
        return fileName.substring(0, fileName.indexOf("."));   
    }   
  
    class ProcessInfo {   
        public String user;   
        public String pid;   
        public String ppid;   
        public String name;   
  
        @Override  
        public String toString() {   
            String str = "user=" + user + " pid=" + pid + " ppid=" + ppid   
                    + " name=" + name;   
            return str;   
        }   
    }   
    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();   
            }   
        }   
    }   
       
      
    class SDStateMonitorReceiver extends BroadcastReceiver{   
        public void onReceive(Context context, Intent intent) {   
               
            if(Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction())){   //存储卡被卸载   
                if(CURR_LOG_TYPE == SDCARD_TYPE){   
                    Log.d(TAG, "SDcar is UNMOUNTED");   
                    CURR_LOG_TYPE = MEMORY_TYPE;   
                    new LogCollectorThread().start();   
                }   
            }else{                                                          //存储卡被挂载   
                if(CURR_LOG_TYPE == MEMORY_TYPE){   
                    Log.d(TAG, "SDcar is MOUNTED");   
                    CURR_LOG_TYPE = SDCARD_TYPE;   
                    new LogCollectorThread().start();   
                       
                }   
            }   
        }   
    }   
       
      
    class LogTaskReceiver extends BroadcastReceiver{   
        public void onReceive(Context context, Intent intent) {   
            String action = intent.getAction();   
            if(SWITCH_LOG_FILE_ACTION.equals(action)){   
                new LogCollectorThread().start();   
            }else if(MONITOR_LOG_SIZE_ACTION.equals(action)){   
                checkLogSize();   
            }   
        }   
    }   
       
    class FileComparator implements Comparator<File>{   
        public int compare(File file1, File file2) {   
            if(logServiceLogName.equals(file1.getName())){   
                return -1;   
            }else if(logServiceLogName.equals(file2.getName())){   
                return 1;   
            }   
               
            String createInfo1 = getFileNameWithoutExtension(file1.getName());   
            String createInfo2 = getFileNameWithoutExtension(file2.getName());   
               
            try {   
                Date create1 = sdf.parse(createInfo1);   
                Date create2 = sdf.parse(createInfo2);   
                if(create1.before(create2)){   
                    return -1;   
                }else{   
                    return 1;   
                }   
            } catch (ParseException e) {   
                return 0;   
            }   
        }   
    }   
       
    @Override  
    public void onDestroy() {   
        super.onDestroy();   
        recordLogServiceLog("LogService onDestroy");   
        if (writer != null) {   
            try {   
                writer.close();   
            } catch (IOException e) {   
                e.printStackTrace();   
            }   
        }   
        if (process != null) {   
            process.destroy();   
        }   
           
        unregisterReceiver(sdStateReceiver);   
        unregisterReceiver(logTaskReceiver);   
    }   
  
}  

添加权限<uses-permission android:name="android.permission.READ_LOGS" /> 

亲测可用的

对了 在manifest里面添加

<service android:name=".utils.LogService"/>

猜你喜欢

转载自my.oschina.net/u/274829/blog/1486481