Android(安卓)logcat保存当前应用程序的日志并上传服务器或指定邮箱
16lz
2021-01-26
分享一个项目中用到的日志统计并提交服务器的日志工具类.
通过过得当前app的PID,采用命令行的方式实用logcat工具过滤日志。
源码如下:
项目地址:http://code.google.com/p/andutils/
001 | package org.and.util; |
002 |
003 | import java.io.BufferedReader; |
004 | import java.io.File; |
005 | import java.io.FileNotFoundException; |
006 | import java.io.FileOutputStream; |
007 | import java.io.IOException; |
008 | import java.io.InputStreamReader; |
009 | import java.util.ArrayList; |
010 | import java.util.List; |
011 |
012 | import android.content.Context; |
013 | import android.os.Environment; |
014 |
|
015 |
016 | /** |
017 |
* TODO: log日志统计保存、上传-工具类 |
018 |
* |
019 |
* @author hljdrl@gmail.com |
020 |
021 |
* @date 2012-8-27 上午11:43:52 |
022 |
023 |
*/ |
024 |
025 | public class LogcatHelper { |
026 |
027 |
private static LogcatHelper INSTANCE = null ; |
028 |
029 |
private static String PATH_LOGCAT ; |
030 |
031 |
private LogDumper mLogDumper = null ; |
032 |
033 |
private Context mContext; |
034 |
035 |
private int mPId; |
036 |
037 |
/** |
038 |
039 |
* 初始化目录 |
040 |
041 |
* */ |
042 |
043 |
public static void init(Context context) |
044 |
045 |
{ |
046 |
047 |
StringBuffer LogPath = new StringBuffer(); |
048 |
049 |
LogPath.append(Environment.getExternalStorageDirectory()); |
050 |
051 |
LogPath.append( "/Android/data/" ); |
052 |
053 |
LogPath.append(context.getPackageName()).append( "/" ); |
054 |
055 |
LogPath.append( "logs" ).append( "/" ); |
056 |
057 |
PATH_LOGCAT = LogPath.toString(); |
058 |
059 |
// |
060 |
061 | File file = new File(PATH_LOGCAT); |
062 |
063 | if (!file.exists()){ |
064 |
065 | file.mkdirs(); |
066 |
067 | } |
068 |
069 |
} |
070 |
071 |
public static LogcatHelper getInstance(Context context) |
072 |
073 |
{ |
074 |
075 |
if (INSTANCE == null ){ |
076 |
077 |
INSTANCE = new LogcatHelper(context); |
078 |
079 |
} |
080 |
081 |
return INSTANCE; |
082 |
083 |
} |
084 |
085 |
private LogcatHelper(Context context) { |
086 |
087 |
mContext = context; |
088 |
089 |
mPId = android.os.Process.myPid(); |
090 |
091 | } |
092 |
093 | public void start() { |
094 |
095 | if (mLogDumper== null ){ |
096 |
097 | mLogDumper = new LogDumper(String.valueOf(mPId),PATH_LOGCAT); |
098 |
099 | mLogDumper.start(); |
100 |
101 | } |
102 |
103 | } |
104 |
105 | public void stop() |
106 |
107 | { |
108 |
109 | if (mLogDumper!= null ){ |
110 |
111 | mLogDumper.stopLogs(); |
112 |
113 | mLogDumper = null ; |
114 |
115 | } |
116 |
117 | } |
118 |
119 | public void sendLogMessage(Context context,String user) |
120 |
121 | { |
122 |
123 | if (mLogDumper!= null ){ |
124 |
125 | mLogDumper.setLogFileLock( true ); |
126 |
127 | String file = mLogDumper.getLogFileName(); |
128 |
129 | File sendFile = new File(file); |
130 |
131 | if (sendFile.exists() && sendFile.length()> 2000 ){ |
132 |
133 | try { |
134 |
135 | EmailHelper.sendMail(context, user, file); |
136 |
137 | } catch (Exception ex){ |
138 |
139 | ex.printStackTrace(); |
140 |
141 | } |
142 |
143 | File newFile = new File(file); |
144 |
145 | try { |
146 |
147 | newFile.createNewFile(); |
148 |
149 | } catch (IOException e) { |
150 |
151 | e.printStackTrace(); |
152 |
153 | } |
154 |
155 | } |
156 |
157 | mLogDumper.setLogFileLock( false ); |
158 |
159 | } |
160 |
161 | } |
162 |
163 | private class LogDumper extends Thread{ |
164 |
165 | String fileName; |
166 |
167 | private Process logcatProc; |
168 |
169 |
private BufferedReader mReader = null ; |
170 |
171 | private boolean mRunning = false ; |
172 |
173 | String cmds= null ; |
174 |
175 | private final String mPID; |
176 |
177 | private FileOutputStream out = null ; |
178 |
179 | private List<String> logsMessage = new ArrayList<String>(); |
180 |
181 | private boolean mLogFileLock = false ; |
182 |
183 | private String logFileName; |
184 |
185 | public void setLogFileLock( boolean lock){ |
186 |
187 | mLogFileLock = lock; |
188 |
189 | } |
190 |
191 | public boolean isLogFileLock() |
192 |
193 | { |
194 |
195 | return mLogFileLock; |
196 |
197 | } |
198 |
199 | public LogDumper(String pid,String file) { |
200 |
201 | mPID = String.valueOf(pid); |
202 |
203 | fileName = file; |
204 |
205 | File mFile = new File(fileName, "error.txt" ); |
206 |
207 | if (!mFile.exists()){ |
208 |
209 | try { |
210 |
211 | mFile.createNewFile(); |
212 |
213 | } catch (IOException e) { |
214 |
215 | e.printStackTrace(); |
216 |
217 | } |
218 |
219 | } |
220 |
221 | try { |
222 |
223 | logFileName = mFile.toString(); |
224 |
225 | out = new FileOutputStream(mFile, true ); |
226 |
227 | } catch (FileNotFoundException e) { |
228 |
229 | e.printStackTrace(); |
230 |
231 | } |
232 |
233 | /** |
234 |
235 | * 日志等级:*:v , *:d , *:w , *:e , *:f , *:s |
236 |
237 | * 显示当前mPID程序的 E和W等级的日志. |
238 |
239 | * */ |
240 |
241 | cmds = "logcat *:e *:w | grep \"(" +mPID+ ")\"" ; |
242 |
243 | } |
244 |
245 | public String getLogFileName() |
246 |
247 | { |
248 |
249 | return logFileName; |
250 |
251 | } |
252 |
253 | public void stopLogs() { |
254 |
255 | mRunning = false ; |
256 |
257 | } |
258 |
259 | private boolean checkFileMaxSize(String file){ |
260 |
261 | File sizefile = new File(file); |
262 |
263 | if (sizefile.exists()){ |
264 |
265 | //1.5MB |
266 |
267 | if (sizefile.length()> 1572864 ){ |
268 |
269 | return true ; |
270 |
271 | } |
272 |
273 | else { |
274 |
275 | return false ; |
276 |
277 | } |
278 |
279 | } else { |
280 |
281 | return false ; |
282 |
283 | } |
284 |
285 | } |
286 |
287 |
|
288 |
289 | @Override |
290 |
291 | public void run() { |
292 |
293 | System.out.println( "LogCatHelper'" ); |
294 |
295 | mRunning = true ; |
296 |
297 | try { |
298 |
299 | logcatProc = Runtime.getRuntime() |
300 |
301 | .exec(cmds); |
302 |
303 |
|
304 |
305 | mReader = new BufferedReader( new InputStreamReader( |
306 |
307 | logcatProc.getInputStream()), 1024 ); |
308 |
309 | String line = null ; |
310 |
311 | while (mRunning && (line = mReader.readLine()) != null ) { |
312 |
313 | if (!mRunning) { |
314 |
315 | break ; |
316 |
317 | } |
318 |
319 | if (line.length() == 0 ) { |
320 |
321 | continue ; |
322 |
323 | } |
324 |
325 | synchronized (out) { |
326 |
327 | if (out != null ) { |
328 |
329 | boolean maxSize = checkFileMaxSize(getLogFileName()); |
330 |
331 | if (maxSize){ |
332 |
333 | //文件大小超过1.5mb |
334 |
335 | sendLogMessage(mContext, DeviceHelper.getInstance(mContext).getImei()); |
336 |
337 | } |
338 |
339 | if (isLogFileLock()) { |
340 |
341 | if (line.contains(mPID)){ |
342 |
343 | logsMessage.add(line.getBytes() + "\n" ); |
344 |
345 | } |
346 |
347 | } else { |
348 |
349 | if (logsMessage.size()> 0 ){ |
350 |
351 | for (String _log:logsMessage){ |
352 |
353 | out.write(_log.getBytes()); |
354 |
355 | } |
356 |
357 | logsMessage.clear(); |
358 |
359 | } |
360 |
361 | /** |
362 |
363 | * 再次过滤日志,筛选当前日志中有 mPID 则是当前程序的日志. |
364 |
365 | * */ |
366 |
367 | if (line.contains(mPID)){ |
368 |
369 | out.write(line.getBytes()); |
370 |
371 | out.write( "\n" .getBytes()); |
372 |
373 | } |
374 |
375 | } |
376 |
377 | } |
378 |
379 | } |
380 |
381 |
|
382 |
383 | } |
384 |
385 | } catch (IOException e) { |
386 |
387 | e.printStackTrace(); |
388 |
389 | return ; |
390 |
391 | } finally { |
392 |
393 | if (logcatProc != null ) { |
394 |
395 | logcatProc.destroy(); |
396 |
397 | logcatProc = null ; |
398 |
399 | } |
400 |
401 | if (mReader != null ) { |
402 |
403 | try { |
404 |
405 | mReader.close(); |
406 |
407 | mReader = null ; |
408 |
409 | } catch (IOException e) { |
410 |
411 | e.printStackTrace(); |
412 |
413 | } |
414 |
415 | } |
416 |
417 | if (out!= null ){ |
418 |
419 | try { |
420 |
421 | out.close(); |
422 |
423 | } catch (IOException e) { |
424 |
425 | e.printStackTrace(); |
426 |
427 | } |
428 |
429 | out = null ; |
430 |
431 | } |
432 |
433 | } |
434 |
435 | } |
436 |
437 | } |
438 |
439 |
|
440 |
441 | } |
更多相关文章
- tcping测试服务器TCP端口
- [Android自定义控件] Android(安卓)Scroller工具类和GestureDete
- 谷歌宣布Android(安卓)Studio将取代Eclipse
- Android(安卓)logback代码配置详解
- Android开源项目之二---工具库篇
- 使用线程执行堆栈StackTraceElement设计Android日志模块
- Android电量测试工具battery-historian学习小记
- Android(安卓)打印日志封装库
- 电量分析工具 Battery Historian 的配置及使用