- 浏览: 382858 次
最新评论
-
qq_19471875:
为了感谢楼主 我特意注册了一个账号!,谢谢!很实用!真棒
ViewPager刷新单个页面的方法 -
asdf658:
...
Eclipse安装server插件 -
JasonMichael:
多谢。搞定~
Eclipse安装server插件 -
passerby_whu:
应该是官网写错了。应该是144x144.
Android不太能够分辨率launcher icon的适配 -
zhengyong7232:
Create or replace function test ...
postgresql产生随机数和随机日期的存储过程
网上找的一个很强大的实现方法,原网页的链接找不到了,没法转载,特此声明一下。
原作者貌似还设了几个小陷阱,大概是不希望我们不劳而获,能多理解一下代码。很多人拿了源码去用,都说日志并没写出来,自己debug了下,果然有些地方是要做改动的,这里把改好的source贴上来,不保证全部正确了,因为我只跑了最基本的写日志,copy日志等功能。
debug一下看看,没有代码我也不好说,还有看看manifest里面读写文件的权限加了没
debug一下看看,没有代码我也不好说,还有看看manifest里面读写文件的权限加了没
原作者貌似还设了几个小陷阱,大概是不希望我们不劳而获,能多理解一下代码。很多人拿了源码去用,都说日志并没写出来,自己debug了下,果然有些地方是要做改动的,这里把改好的source贴上来,不保证全部正确了,因为我只跑了最基本的写日志,copy日志等功能。
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; 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.Notification; 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; import com.XXX.helloandroid.R; /** * 日志服务,日志默认会存储在SDcar里,如果没有SDcard会存储在内存中的安装目录下面。 * 1.本服务默认在SDcard中每天生成一个日志文件, * 2.如果有SDCard的话会将之前内存中的文件拷贝到SDCard中 * 3.如果没有SDCard,在安装目录下只保存当前在写日志 * 4.SDcard的装载卸载动作会在步骤2,3中切换 * 5.SDcard中的日志文件只保存7天 * 6.监视App运行的LogCat日志(sdcard mounted):sdcard/MyApp/log/yyyy-MM-dd HHmmss.log(默认) * 7.监视App运行的LogCat日志(sdcard unmounted):/data/data/包名/files/log/yyyy-MM-dd HHmmss.log * 8.本service的运行日志:/data/data/包名/files/log/Log.log * @author Administrator * */ 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; /* 是否正在监测日志文件大小; * 如果当前日志记录在SDcard中则为false * 如果当前日志记录在内存中则为true*/ private boolean logSizeMoniting = false; private static String MONITOR_LOG_SIZE_ACTION = "MONITOR_LOG_SIZE"; //日志文件监测action private static String SWITCH_LOG_FILE_ACTION = "SWITCH_LOG_FILE_ACTION"; //切换日志文件action @Override public IBinder onBind(Intent intent) { return null; } // This is the new method that instead of the old onStart method on the pre-2.0 platform. @Override //开始服务,执行更新widget组件的操作 public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "===================onStartCommand==========================="); Notification notification = new Notification(R.drawable.logo, "wf log service is running", System.currentTimeMillis()); PendingIntent pi=PendingIntent.getService(this, 0, intent, 0); notification.setLatestEventInfo(this, "WF Log Service", "wf log service is running!", pi); //让该service前台运行,避免手机休眠时系统自动杀掉该服务 //如果 id 为 0 ,那么状态栏的 notification 将不会显示。 startForeground(startId, notification); return Service.START_REDELIVER_INTENT; } @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 + "MyApp" + File.separator + "log"; createLogDir(); try { writer = new OutputStreamWriter(new FileOutputStream( LOG_SERVICE_LOG_PATH, true)); } catch (FileNotFoundException e) { Log.e(TAG, e.getMessage(), e); } 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); } /** * 获取当前应存储在内存中还是存储在SDCard中 * @return */ 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())); } /** * 日志收集 * 1.清除日志缓存 * 2.杀死应用程序已开启的Logcat进程防止多个进程写入一个日志文件 * 3.开启日志收集进程 * 4.处理日志文件 * 移动 OR 删除 */ 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"); } } } /** * 关闭由本程序开启的logcat进程: * 根据用户名称杀死进程(如果是本程序进程开启的Logcat收集进程那么两者的USER一致) * 如果不关闭会有多个进程读取logcat日志缓存信息写入日志文件 * * @param allProcList * @return */ private void killLogcatProc(List<ProcessInfo> allProcList) { if(process != null){ process.destroy(); } String packName = this.getPackageName(); String myUser = getAppUser(packName, allProcList); recordLogServiceLog("app user is:"+myUser); recordLogServiceLog("============= START TYPING PROC LIST INFO =============="); //只打印本App和logcat的进程信息,其他进程信息不打印 for (ProcessInfo processInfo : allProcList) { if (myUser.equals( processInfo.user ) || "logcat".equals( processInfo.name )) { recordLogServiceLog(processInfo.toString()); } } recordLogServiceLog("============= END TYPING PROC LIST INFO =============="); 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); } } } /** * 获取本程序的用户名称 * * @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; } /** * 根据ps命令得到的内容获取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 /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; } /** * 运行PS命令得到进程信息 * * @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"); 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()); } } /** * 根据当前的存储位置得到日志的绝对存储路径 * @return */ 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; } } /** * 处理日志文件 * 1.如果日志文件存储位置切换到内存中,删除除了正在写的日志文件 * 并且部署日志大小监控任务,控制日志大小不超过规定值 * 2.如果日志文件存储位置切换到SDCard中,删除7天之前的日志,移 * 动所有存储在内存中的日志到SDCard中,并将之前部署的日志大小 * 监控取消 */ 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 !"); Calendar calendar = Calendar.getInstance(); 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(); } } file = new File(LOG_SERVICE_LOG_PATH); if (!file.exists()) { try { mkOk = file.createNewFile(); if (!mkOk) { file.createNewFile(); } } catch (IOException e) { Log.e(TAG, e.getMessage(), e); } } 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; } } } } /** * 将日志文件转移到SD卡下面 */ 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(); //只copy App的LocCat日志文件【yyyy-MM-dd HHmmss.log】到sdcard,本LogService的运行日志【Log.log】不做copy对象 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); } } } } /** * 删除SDCard下过期的日志 */ 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()); } } } } /** * 判断sdcard上的日志文件是否可以删除 * @param createDateStr * @return */ 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()); } } } /** * 拷贝文件 * @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) { 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; } } } /** * 记录日志服务的基本信息 防止日志服务有错,在LogCat日志中无法查找 * 此日志名称为Log.log * * @param msg */ 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); } } } /** * 去除文件的扩展类型(.log) * @param fileName * @return */ 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(); } } } /** * 监控SD卡状态 * @author Administrator * */ 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(); } } } } /** * 日志任务接收 * 切换日志,监控日志大小 * @author Administrator * */ 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() { //对于通过startForeground启动的service,需要通过stopForeground来取消前台运行状态 stopForeground(true); // 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); } }
评论
4 楼
lovelease
2015-09-09
淘宝萧战 写道
我也遇到类似问题了,请问下有办法修改吗?
debug一下看看,没有代码我也不好说,还有看看manifest里面读写文件的权限加了没
3 楼
淘宝萧战
2015-04-14
我也遇到类似问题了,请问下有办法修改吗?
2 楼
lovelease
2014-11-06
dufangyu1990 写道
你好,博主,你的这段代码我运行出错
10-23 10:28:19.590: W/System.err(17852): java.io.IOException: read failed: EBADF (Bad file number)
10-23 10:28:19.590: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:435)
10-23 10:28:19.590: W/System.err(17852): at java.io.FileInputStream.read(FileInputStream.java:185)
10-23 10:28:19.594: W/System.err(17852): at java.io.InputStreamReader.read(InputStreamReader.java:244)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.readLine(BufferedReader.java:354)
10-23 10:28:19.594: W/System.err(17852): at com.example.demo.LogService$StreamConsumer.run(LogService.java:817)
10-23 10:28:19.594: W/System.err(17852): Caused by: libcore.io.ErrnoException: read failed: EBADF (Bad file number)
10-23 10:28:19.594: W/System.err(17852): at libcore.io.Posix.readBytes(Native Method)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.Posix.read(Posix.java:119)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:425)
10-23 10:28:19.597: W/System.err(17852): ... 5 more
10-23 10:28:19.590: W/System.err(17852): java.io.IOException: read failed: EBADF (Bad file number)
10-23 10:28:19.590: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:435)
10-23 10:28:19.590: W/System.err(17852): at java.io.FileInputStream.read(FileInputStream.java:185)
10-23 10:28:19.594: W/System.err(17852): at java.io.InputStreamReader.read(InputStreamReader.java:244)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.readLine(BufferedReader.java:354)
10-23 10:28:19.594: W/System.err(17852): at com.example.demo.LogService$StreamConsumer.run(LogService.java:817)
10-23 10:28:19.594: W/System.err(17852): Caused by: libcore.io.ErrnoException: read failed: EBADF (Bad file number)
10-23 10:28:19.594: W/System.err(17852): at libcore.io.Posix.readBytes(Native Method)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.Posix.read(Posix.java:119)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:425)
10-23 10:28:19.597: W/System.err(17852): ... 5 more
debug一下看看,没有代码我也不好说,还有看看manifest里面读写文件的权限加了没
1 楼
dufangyu1990
2014-10-23
你好,博主,你的这段代码我运行出错
10-23 10:28:19.590: W/System.err(17852): java.io.IOException: read failed: EBADF (Bad file number)
10-23 10:28:19.590: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:435)
10-23 10:28:19.590: W/System.err(17852): at java.io.FileInputStream.read(FileInputStream.java:185)
10-23 10:28:19.594: W/System.err(17852): at java.io.InputStreamReader.read(InputStreamReader.java:244)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.readLine(BufferedReader.java:354)
10-23 10:28:19.594: W/System.err(17852): at com.example.demo.LogService$StreamConsumer.run(LogService.java:817)
10-23 10:28:19.594: W/System.err(17852): Caused by: libcore.io.ErrnoException: read failed: EBADF (Bad file number)
10-23 10:28:19.594: W/System.err(17852): at libcore.io.Posix.readBytes(Native Method)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.Posix.read(Posix.java:119)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:425)
10-23 10:28:19.597: W/System.err(17852): ... 5 more
10-23 10:28:19.590: W/System.err(17852): java.io.IOException: read failed: EBADF (Bad file number)
10-23 10:28:19.590: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:435)
10-23 10:28:19.590: W/System.err(17852): at java.io.FileInputStream.read(FileInputStream.java:185)
10-23 10:28:19.594: W/System.err(17852): at java.io.InputStreamReader.read(InputStreamReader.java:244)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
10-23 10:28:19.594: W/System.err(17852): at java.io.BufferedReader.readLine(BufferedReader.java:354)
10-23 10:28:19.594: W/System.err(17852): at com.example.demo.LogService$StreamConsumer.run(LogService.java:817)
10-23 10:28:19.594: W/System.err(17852): Caused by: libcore.io.ErrnoException: read failed: EBADF (Bad file number)
10-23 10:28:19.594: W/System.err(17852): at libcore.io.Posix.readBytes(Native Method)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.Posix.read(Posix.java:119)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
10-23 10:28:19.597: W/System.err(17852): at libcore.io.IoBridge.read(IoBridge.java:425)
10-23 10:28:19.597: W/System.err(17852): ... 5 more
发表评论
-
Cocos2dx开发解决undefined reference to 'atof'和x86平台下报internal compiler error的错误
2016-11-21 17:10 2784最近在为游戏做java sdk的cocos2dx引擎层代码时遇 ... -
Android项目集成Jenkins(JUnit test & Coverage)
2016-08-26 14:12 4366为了实现持续集成,提 ... -
Android短信监听功能(解决onChange触发两次的问题)
2016-06-16 18:51 6851前言 项目要做短信验证码自动填充的功能,基本上两种方法:Con ... -
Android实现可自动关闭的定时器
2015-12-03 18:54 1402之前一篇文章里有用到过一个封装好的定时器工具类,现在又做了一些 ... -
Android不太能够分辨率launcher icon的适配
2015-04-24 11:01 1908网上讲android适配不同分辨率的文章很多,但是很少有说明不 ... -
Android 根据屏幕尺寸适配控件尺寸(按比例缩放)
2015-04-03 18:28 4634在做facebook登录时,正好看到其SDK中一段代码,可以根 ... -
Android获取状态栏高度
2015-01-28 12:04 1192获取状态栏高度有两种方法: 1.如果是在Activity中: ... -
Apktool打包和解包
2014-12-02 17:49 0本文的学习内容参考自[Android实例] 【eoeAndro ... -
Android 控件自动“移入、暂停、移出”效果的实现
2014-09-05 09:54 2387一个常见的效果:控件自动移入屏幕,停留几秒,再移出屏幕。项目中 ... -
Google Map 如何捕获onTouchEvent
2014-09-02 17:42 1713当我的项目中需要捕获google map的touch事件时,才 ... -
Android日期时间选择器实现以及自定义大小
2014-08-27 20:01 62556本文主要讲两个内容:1.如何将DatePicker和TimeP ... -
ViewPager刷新单个页面的方法
2014-08-22 11:09 39085使用ViewPager做滑动切换图片的效果时,如果图片是从 ... -
Android使用MediaPlayer开发时抛IllegalStateException
2014-08-18 16:45 59797在我开发的语音播放程序中,首次播放语音没问题,第二次播放时 ... -
Android 含有图片和文字的Button的实现
2014-07-17 20:15 8854要实现一个同时包含图片和文字的按钮,粗糙一点的做法当然是直 ... -
LinearLayout半透明效果
2014-07-16 18:12 17430透明效果有很多中实现方式,可以代码实现,也可以直接在布局文件中 ... -
Android图片压缩(质量压缩和尺寸压缩)
2014-07-04 18:16 4218在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩: ... -
Google Map无法显示:Error contacting Google servers. XXX authentication issue
2014-06-30 20:32 2080在开发google map时遇到的问题: 06-26 14 ... -
【转载】Android异步处理
2013-06-20 12:12 883关于Android异步处理的一整个系列的博文,共有4篇,博主写 ... -
android service被系统回收的解决方法
2013-06-14 11:20 7216自己的app的service总是容 ... -
Android 中的 Service 全面总结
2013-06-13 16:42 890关于Android Service的知识,可以参考以下博文,内 ...
相关推荐
Android一个简单实用把Log日志打印到手机本地文件,可以自行取出来上传到服务器开源代码
Android写LOG日志到SD卡文件之microlog4android使用
android将log保存到文件中的service,记得添加权限
有需要可以看看,动态将想要的数据通过该接口直接写到本地文件
android保存log到SD卡中
Log 文件顶部显示设备信息 Log 头部含有当前线程名 Log 头部含有当前类及行号和函数名,支持点击跳转 可设置 Log 是否写入文件 可设置 Log 写入文件目录 可设置 Log 写入文件前缀 可设置 Log 是否显示边框 可设置 ...
一个收集 app 输出日志的工具,输出文件:模拟器是 /sdcard/Android/data/项目包名/cache/,真机是 /Android/data/项目包名/cache/,里面的 crash 目录是崩溃日志,log 目录是 logcat 日志。 如何使用 在 module ...
平常工作经常用adb logcat >log.log这个命令抓log,抓出来都是文本文件,logcat又不能重读文件来查看,动辄log都是上万行查个有用的log很是费劲。 今天实在忍不住了,摆弄了一下java写了这个小程序来查看log,也希望...
示范如何在android工程中使用log4j记录日志
本资源包括 从手机端提取的log 文件 及问题描述,分析思路和解决办法。是一篇很好的log分析日志。
最近写的demo。安卓环境使用log4j 滚动日志。 实现数据format格式化传输记录日志内容。 非配置文件的方式
使用该文件可显示Android 7.0 log 名称为monitor.exe
基于 Android NDK 的学习之旅-----JNI LOG 打印 eclipse工程文件
android 写日志文件的方法,比较方便的读取文件,查找问题
android call: call not sent 的log 文件
主要介绍了microlog4android将Android Log日志写到SD卡文件中实现方法的相关资料,需要的朋友可以参考下
Android私有储存文件和外部储存文件读写,没有写界面,直接看log输出
有时候需要分析一个adb log,但是将log从ddms保存为文本文件后,不能再用ddms打开查看,而一般的文本编辑工具查看这些log时都不是很方便。 这个工具巧妙地利用了Excel的数据筛选功能,使可以用excel查看log,而且...
android log记录所需要的文件 1、建立使用logger对象 private static final Logger logger = LoggerFactory.getLogger(main.class); 2、在程序的第activit或者service的oncreate方法里初始化方法 ...
把崩溃的日志信息(带I/DEBUG标记)复制到xx文件中,用编辑器编辑工具中Android编译的符号(symbol)所在的位置,我的是在309行"SYMBOLS_DIR = './out/target/product/sirfsocv7/symbols’",保存,然后执行./stack xx ...