LogUtil.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. package com.hgsoft.log;
  2. import android.content.Context;
  3. import android.text.TextUtils;
  4. import androidx.annotation.NonNull;
  5. import com.tencent.mars.xlog.Log;
  6. import net.lingala.zip4j.ZipFile;
  7. import net.lingala.zip4j.exception.ZipException;
  8. import java.io.File;
  9. import java.text.SimpleDateFormat;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.Calendar;
  13. import java.util.Date;
  14. import java.util.List;
  15. import java.util.Locale;
  16. /**
  17. * 打印日志封装
  18. *
  19. * @author yinxueqin
  20. */
  21. public final class LogUtil {
  22. /**
  23. * 可以全局控制android.util.Log是否打印log日志
  24. */
  25. private static boolean isPrintLog = true;
  26. /**
  27. * 在某些机器上小于4000,小于2000
  28. */
  29. private static int logMaxLength = 1800;
  30. /**
  31. * 长度最好不超过 23 个字符
  32. */
  33. public static final String TAG = "-hgits-log";
  34. public static boolean xlogInitComplete = false;
  35. /**
  36. * 向外提供日志输出
  37. */
  38. private static LogInfo mLogInfo;
  39. /**
  40. * 初始化Xlog(默认方式(文件默认保存10天,不设置文件最大字节)
  41. * @param context 上下文
  42. * @param isDebugStatus 是否debug false:不是,true:是
  43. * @param consoleLogOpen 控制台是否打印
  44. * @param logFileNamePrefix 日志文件名前缀
  45. * @param releasePubKey release版本时需要密钥
  46. * @param needPrintSystemInfo 需要打印的系统信息
  47. */
  48. public static void initXlog(Context context, boolean isDebugStatus, boolean consoleLogOpen, @NonNull String logFileNamePrefix,
  49. @NonNull String releasePubKey, @NonNull String needPrintSystemInfo) {
  50. LogUtil.appenderFlush(false);
  51. LogUtil.appenderClose();
  52. MarsXLogInit.getInstance().setXlogOpenStatus(false);
  53. MarsXLogInit.getInstance().setDebugStatus(isDebugStatus);
  54. MarsXLogInit.getInstance().setConsoleLogOpen(consoleLogOpen);
  55. if (isDebugStatus) {
  56. MarsXLogInit.getInstance().setPUBKEY("");
  57. MarsXLogInit.getInstance().setLogFileNamePrefix("Debug_" + logFileNamePrefix);
  58. } else {
  59. MarsXLogInit.getInstance().setPUBKEY(releasePubKey);
  60. MarsXLogInit.getInstance().setLogFileNamePrefix("Release_" + logFileNamePrefix);
  61. }
  62. MarsXLogInit.getInstance().openXlog(context);
  63. LogUtil.ei(TAG, needPrintSystemInfo);
  64. LogUtil.appenderFlush(false);
  65. }
  66. /**
  67. * 初始化Xlog(默认方式(文件默认保存10天,不设置文件最大字节)
  68. * @param context 上下文
  69. * @param isDebugStatus 是否debug false:不是,true:是
  70. * @param consoleLogOpen 控制台是否打印
  71. * @param logFileNamePrefix 日志文件名前缀
  72. * @param releasePubKey release版本时需要密钥
  73. * @param needPrintSystemInfo 需要打印的系统信息
  74. * @param logFileSaveDays 文件保存天数,这个保存天数根据文件创建属性决定。最小1天,默认10天
  75. * @param logFileMaxSize 单个文件最大字节 0:表示不分割 单位字节
  76. */
  77. public static void initXlog(Context context, boolean isDebugStatus, boolean consoleLogOpen, @NonNull String logFileNamePrefix,
  78. @NonNull String releasePubKey, @NonNull String needPrintSystemInfo, int logFileSaveDays, long logFileMaxSize) {
  79. LogUtil.appenderFlush(false);
  80. LogUtil.appenderClose();
  81. MarsXLogInit.getInstance().setXlogOpenStatus(false);
  82. MarsXLogInit.getInstance().setDebugStatus(isDebugStatus);
  83. MarsXLogInit.getInstance().setConsoleLogOpen(consoleLogOpen);
  84. MarsXLogInit.getInstance().setLogFileSaveDays(logFileSaveDays);
  85. MarsXLogInit.getInstance().setLogFileMaxSize(logFileMaxSize);
  86. if (isDebugStatus) {
  87. MarsXLogInit.getInstance().setPUBKEY("");
  88. MarsXLogInit.getInstance().setLogFileNamePrefix("Debug_" + logFileNamePrefix);
  89. } else {
  90. MarsXLogInit.getInstance().setPUBKEY(releasePubKey);
  91. MarsXLogInit.getInstance().setLogFileNamePrefix("Release_" + logFileNamePrefix);
  92. }
  93. MarsXLogInit.getInstance().openXlog(context);
  94. LogUtil.ei(TAG, needPrintSystemInfo);
  95. LogUtil.appenderFlush(false);
  96. }
  97. public static void initXlogState(boolean state) {
  98. xlogInitComplete = state;
  99. }
  100. /**
  101. * 设置android原生日志打印是否可以打印
  102. *
  103. * @param isPrint true:可以,false:不可以
  104. */
  105. public static void setAndroidLogPrintConsoleLog(final boolean isPrint) {
  106. isPrintLog = isPrint;
  107. }
  108. /**
  109. * 设置android logcat最大打印长度,超出将自动分割
  110. * @param logMaxLength 一条日志最大长度
  111. */
  112. public static void setLogPrintMaxLength(final int logMaxLength) {
  113. LogUtil.logMaxLength = logMaxLength;
  114. }
  115. /**
  116. * 打印日志,级别为:LEVEL_VERBOSE
  117. *
  118. * @param msg 日志信息
  119. */
  120. public static void v(final String msg) {
  121. v(TAG, msg);
  122. }
  123. /**
  124. * 打印日志,级别为:LEVEL_VERBOSE
  125. *
  126. * @param tagName 日志tag
  127. * @param msg 日志信息
  128. */
  129. public static void v(final String tagName, final String msg) {
  130. if (!xlogInitComplete) {
  131. androidLogV(tagName, msg);
  132. return;
  133. }
  134. List<String> logMsg = splitString(msg, logMaxLength);
  135. for (String log: logMsg) {
  136. Log.v(tagName + TAG, log);
  137. if (mLogInfo != null) {
  138. mLogInfo.log(LogLevel.LEVEL_VERBOSE, tagName + TAG, log);
  139. }
  140. }
  141. }
  142. /**
  143. * 打印日志,级别为:LEVEL_DEBUG
  144. *
  145. * @param msg 日志信息
  146. */
  147. public static void d(final String msg) {
  148. d(TAG, msg);
  149. }
  150. /**
  151. * 打印日志,级别为:LEVEL_DEBUG
  152. *
  153. * @param tagName 日志tag
  154. * @param msg 日志信息
  155. */
  156. public static void d(final String tagName, final String msg) {
  157. if (!xlogInitComplete) {
  158. androidLogD(tagName, msg);
  159. return;
  160. }
  161. List<String> logMsg = splitString(msg, logMaxLength);
  162. for (String log: logMsg) {
  163. Log.d(tagName + TAG, log);
  164. if (mLogInfo != null) {
  165. mLogInfo.log(LogLevel.LEVEL_DEBUG, tagName + TAG, log);
  166. }
  167. }
  168. }
  169. /**
  170. * 打印日志,级别为:LEVEL_INFO
  171. *
  172. * @param msg 日志信息
  173. */
  174. public static void i(final String msg) {
  175. i(TAG, msg);
  176. }
  177. /**
  178. * 打印日志,级别为:LEVEL_INFO
  179. *
  180. * @param tagName 日志tag
  181. * @param msg 日志信息
  182. */
  183. public static void i(final String tagName, final String msg) {
  184. if (!xlogInitComplete) {
  185. androidLogI(tagName, msg);
  186. return;
  187. }
  188. List<String> logMsg = splitString(msg, logMaxLength);
  189. for (String log: logMsg) {
  190. Log.i(tagName + TAG, log);
  191. if (mLogInfo != null) {
  192. mLogInfo.log(LogLevel.LEVEL_INFO, tagName + TAG, log);
  193. }
  194. }
  195. }
  196. /**
  197. * 打印日志,级别为:LEVEL_INFO,有额外返回
  198. *
  199. * @param tagName 日志tag
  200. * @param msg 日志信息
  201. */
  202. public static void ei(final String tagName, final String msg) {
  203. if (!xlogInitComplete) {
  204. androidLogI(tagName, msg);
  205. return;
  206. }
  207. List<String> logMsg = splitString(msg, logMaxLength);
  208. for (String log: logMsg) {
  209. Log.i(tagName + TAG, log);
  210. if (mLogInfo != null) {
  211. mLogInfo.log(LogLevel.LEVEL_INFO, tagName + TAG, log);
  212. mLogInfo.log(LogLevel.LEVEL_EXTRA, tagName + TAG, log);
  213. }
  214. }
  215. }
  216. /**
  217. * 打印日志,级别为:LEVEL_WARNING
  218. *
  219. * @param msg 日志信息
  220. */
  221. public static void w(final String msg) {
  222. w(TAG, msg);
  223. }
  224. /**
  225. * 打印日志,级别为:LEVEL_WARNING
  226. *
  227. * @param tagName 日志tag
  228. * @param msg 日志信息
  229. */
  230. public static void w(final String tagName, final String msg) {
  231. if (!xlogInitComplete) {
  232. androidLogW(tagName, msg);
  233. return;
  234. }
  235. List<String> logMsg = splitString(msg, logMaxLength);
  236. for (String log: logMsg) {
  237. Log.w(tagName + TAG, log);
  238. if (mLogInfo != null) {
  239. mLogInfo.log(LogLevel.LEVEL_WARNING, tagName + TAG, log);
  240. }
  241. }
  242. }
  243. /**
  244. * 打印日志,级别为:LEVEL_WARNING,有额外返回
  245. *
  246. * @param tagName 日志tag
  247. * @param msg 日志信息
  248. */
  249. public static void ew(final String tagName, final String msg) {
  250. if (!xlogInitComplete) {
  251. androidLogW(tagName, msg);
  252. return;
  253. }
  254. List<String> logMsg = splitString(msg, logMaxLength);
  255. for (String log: logMsg) {
  256. Log.w(tagName + TAG, log);
  257. if (mLogInfo != null) {
  258. mLogInfo.log(LogLevel.LEVEL_WARNING, tagName + TAG, log);
  259. mLogInfo.log(LogLevel.LEVEL_EXTRA, tagName + TAG, log);
  260. }
  261. }
  262. }
  263. /**
  264. * 打印日志,级别为:LEVEL_ERROR
  265. *
  266. * @param msg 日志信息
  267. */
  268. public static void e(final String msg) {
  269. e(TAG, msg);
  270. }
  271. /**
  272. * 打印日志,级别为:LEVEL_ERROR
  273. *
  274. * @param tagName 日志tag
  275. * @param msg 日志信息
  276. */
  277. public static void e(final String tagName, final String msg) {
  278. if (!xlogInitComplete) {
  279. androidLogE(tagName, msg);
  280. return;
  281. }
  282. List<String> logMsg = splitString(msg, logMaxLength);
  283. for (String log: logMsg) {
  284. Log.e(tagName + TAG, log);
  285. if (mLogInfo != null) {
  286. mLogInfo.log(LogLevel.LEVEL_ERROR, tagName + TAG, log);
  287. }
  288. }
  289. }
  290. /**
  291. * 打印日志,级别为:LEVEL_ERROR,有额外返回
  292. *
  293. * @param tagName 日志tag
  294. * @param msg 日志信息
  295. */
  296. public static void ee(final String tagName, final String msg) {
  297. if (!xlogInitComplete) {
  298. androidLogE(tagName, msg);
  299. return;
  300. }
  301. List<String> logMsg = splitString(msg, logMaxLength);
  302. for (String log: logMsg) {
  303. Log.e(tagName + TAG, log);
  304. if (mLogInfo != null) {
  305. mLogInfo.log(LogLevel.LEVEL_ERROR, tagName + TAG, log);
  306. mLogInfo.log(LogLevel.LEVEL_EXTRA, tagName + TAG, log);
  307. }
  308. }
  309. }
  310. /**
  311. * 打印日志,级别为:LEVEL_VERBOSE
  312. *
  313. * @param tagName 日志tag
  314. * @param msg 日志信息
  315. */
  316. public static void androidLogV(final String tagName, final String msg) {
  317. if (isPrintLog) {
  318. List<String> logMsg = splitString(msg, logMaxLength);
  319. for (String log: logMsg) {
  320. android.util.Log.v(tagName + TAG, log);
  321. }
  322. }
  323. }
  324. /**
  325. * 打印日志,级别为:LEVEL_DEBUG
  326. *
  327. * @param tagName 日志tag
  328. * @param msg 日志信息
  329. */
  330. public static void androidLogD(final String tagName, final String msg) {
  331. if (isPrintLog) {
  332. List<String> logMsg = splitString(msg, logMaxLength);
  333. for (String log: logMsg) {
  334. android.util.Log.d(tagName + TAG, log);
  335. }
  336. }
  337. }
  338. /**
  339. * 打印日志,级别为:LEVEL_INFO
  340. *
  341. * @param tagName 日志tag
  342. * @param msg 日志信息
  343. */
  344. public static void androidLogI(final String tagName, final String msg) {
  345. if (isPrintLog) {
  346. List<String> logMsg = splitString(msg, logMaxLength);
  347. for (String log: logMsg) {
  348. android.util.Log.i(tagName + TAG, log);
  349. }
  350. }
  351. }
  352. /**
  353. * 打印日志,级别为:LEVEL_WARNING
  354. *
  355. * @param tagName 日志tag
  356. * @param msg 日志信息
  357. */
  358. public static void androidLogW(final String tagName, final String msg) {
  359. if (isPrintLog) {
  360. List<String> logMsg = splitString(msg, logMaxLength);
  361. for (String log: logMsg) {
  362. android.util.Log.w(tagName + TAG, log);
  363. }
  364. }
  365. }
  366. /**
  367. * 打印日志,级别为:LEVEL_ERROR
  368. *
  369. * @param tagName 日志tag
  370. * @param msg 日志信息
  371. */
  372. public static void androidLogE(final String tagName, final String msg) {
  373. if (isPrintLog) {
  374. final List<String> logMsg = splitString(msg, logMaxLength);
  375. for (String log: logMsg) {
  376. android.util.Log.e(tagName + TAG, log);
  377. }
  378. }
  379. }
  380. /**
  381. * 获取当前使用者今天的日志文件压缩包,耗时操作,请在子线程调用
  382. *
  383. * @param context 上下文对象
  384. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  385. * @throws ZipException 压缩异常
  386. */
  387. public static File getCurrentUserLogFileZip(final Context context) throws ZipException {
  388. return getCurrentUserLogFileZip(context, null);
  389. }
  390. /**
  391. * 获取当前使用者今天的日志文件压缩包,耗时操作,请在子线程调用
  392. * @param context 上下文对象
  393. * @param sideFiles 额外文件
  394. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  395. * @throws ZipException 压缩异常
  396. */
  397. public static File getCurrentUserLogFileZip(final Context context, final List<File> sideFiles) throws ZipException {
  398. return getCurrentUserLogFileZip(context, sideFiles, null);
  399. }
  400. /**
  401. * 获取当前使用者今天的日志文件压缩包,耗时操作,请在子线程调用
  402. * @param context 上下文对象
  403. * @param sideFiles 额外文件
  404. * @param customZipFileName 压缩包名称,不包含后缀
  405. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  406. * @throws ZipException 压缩异常
  407. */
  408. public static File getCurrentUserLogFileZip(final Context context, final List<File> sideFiles, final String customZipFileName) throws ZipException {
  409. ZipFile zipFile = getLogZipFile(context, true, true,false, customZipFileName);
  410. if (sideFiles != null && sideFiles.size() > 0) {
  411. zipFile.addFiles(sideFiles);
  412. }
  413. return zipFile.getFile();
  414. }
  415. /**
  416. * 获取当前使用者的所有日志文件压缩包,耗时操作,请在子线程调用
  417. *
  418. * @param context 上下文对象
  419. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  420. * @throws ZipException 压缩异常
  421. */
  422. public static File getCurrentUserAllLogFileZip(final Context context) throws ZipException {
  423. return getCurrentUserAllLogFileZip(context, null);
  424. }
  425. /**
  426. * 获取当前使用者的所有日志文件压缩包,耗时操作,请在子线程调用
  427. * @param context 上下文对象
  428. * @param sideFiles 额外文件
  429. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  430. * @throws ZipException 压缩异常
  431. */
  432. public static File getCurrentUserAllLogFileZip(final Context context, final List<File> sideFiles) throws ZipException {
  433. return getCurrentUserAllLogFileZip(context, sideFiles, null);
  434. }
  435. /**
  436. * 获取当前使用者的所有日志文件压缩包,耗时操作,请在子线程调用
  437. * @param context 上下文对象
  438. * @param sideFiles 额外文件
  439. * @param customZipFileName 压缩包名称,不包含后缀
  440. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  441. * @throws ZipException 压缩异常
  442. */
  443. public static File getCurrentUserAllLogFileZip(final Context context, final List<File> sideFiles, final String customZipFileName) throws ZipException {
  444. ZipFile zipFile = getLogZipFile(context, true, false,false, customZipFileName);
  445. if (sideFiles != null && sideFiles.size() > 0) {
  446. zipFile.addFiles(sideFiles);
  447. }
  448. return zipFile.getFile();
  449. }
  450. /**
  451. * 获取当前使用者昨天的日志文件压缩包,耗时操作,请在子线程调用
  452. *
  453. * @param context 上下文对象
  454. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  455. * @throws ZipException 压缩异常
  456. */
  457. public static File getCurrentUserYesterdayLogFileZip(final Context context) throws ZipException {
  458. return getCurrentUserYesterdayLogFileZip(context, null);
  459. }
  460. /**
  461. * 获取当前使用者昨天的日志文件压缩包,耗时操作,请在子线程调用
  462. *
  463. * @param context 上下文对象
  464. * @param sideFiles 额外文件
  465. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  466. * @throws ZipException 压缩异常
  467. */
  468. public static File getCurrentUserYesterdayLogFileZip(final Context context, final List<File> sideFiles) throws ZipException {
  469. return getCurrentUserYesterdayLogFileZip(context, sideFiles, null);
  470. }
  471. /**
  472. * 获取当前使用者昨天的日志文件压缩包,耗时操作,请在子线程调用
  473. *
  474. * @param context 上下文对象
  475. * @param sideFiles 额外文件
  476. * @param customZipFileName 压缩包名称,不包含后缀
  477. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  478. * @throws ZipException 压缩异常
  479. */
  480. public static File getCurrentUserYesterdayLogFileZip(final Context context, final List<File> sideFiles, final String customZipFileName) throws ZipException {
  481. ZipFile zipFile = getLogZipFile(context, true, false,true, customZipFileName);
  482. if (sideFiles != null && sideFiles.size() > 0) {
  483. zipFile.addFiles(sideFiles);
  484. }
  485. return zipFile.getFile();
  486. }
  487. /**
  488. * 获取APP所有日志文件压缩包,耗时操作,请在子线程调用
  489. *
  490. * @param context 上下文对象
  491. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  492. * @throws ZipException 压缩异常
  493. */
  494. public static File getAppAllLogFileZip(final Context context) throws ZipException {
  495. return getAppAllLogFileZip(context, null);
  496. }
  497. /**
  498. * 获取APP所有日志文件压缩包,耗时操作,请在子线程调用
  499. * @param context 上下文对象
  500. * @param sideFiles 额外文件
  501. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  502. * @throws ZipException 压缩异常
  503. */
  504. public static File getAppAllLogFileZip(final Context context, final List<File> sideFiles) throws ZipException {
  505. return getAppAllLogFileZip(context, sideFiles, null);
  506. }
  507. /**
  508. * 获取APP所有日志文件压缩包,耗时操作,请在子线程调用
  509. * @param context 上下文对象
  510. * @param sideFiles 额外文件
  511. * @param customZipFileName 压缩包名称,不包含后缀
  512. * @return 如果存在这个文件就返回,否则根据默认的日志目录,创建一个压缩包对象,不能确定是否存在文件
  513. * @throws ZipException 压缩异常
  514. */
  515. public static File getAppAllLogFileZip(final Context context, final List<File> sideFiles, final String customZipFileName) throws ZipException {
  516. ZipFile zipFile = getLogZipFile(context, false, false, false, customZipFileName);
  517. if (sideFiles != null && sideFiles.size() > 0) {
  518. zipFile.addFiles(sideFiles);
  519. }
  520. return zipFile.getFile();
  521. }
  522. /**
  523. * 创建压缩包
  524. * @param context 上下文
  525. * @param isCurrent 当前用户
  526. * @param isToday 是否只压缩今天
  527. * @param isYesterday 是否只压缩明天
  528. * @param customZipFileName 压缩包名称,不包含后缀
  529. * @return 日志压缩文件对象
  530. * @throws ZipException 压缩异常
  531. */
  532. private static ZipFile getLogZipFile(final Context context, final boolean isCurrent, final boolean isToday,
  533. final boolean isYesterday, final String customZipFileName) throws ZipException {
  534. File externalFileDir = context.getExternalFilesDir("XLog");
  535. String logPath = null;
  536. if (externalFileDir != null) {
  537. logPath = externalFileDir.getAbsolutePath();
  538. }
  539. if (TextUtils.isEmpty(logPath)) {
  540. LogUtil.i(TAG, "Log缓存目录存在");
  541. logPath = context.getFilesDir().getPath() + "/XLog";
  542. } else {
  543. LogUtil.i(TAG, "Log目录存在");
  544. }
  545. File logPathFile = new File(logPath);
  546. if (logPathFile.exists()) {
  547. ZipFile logPathZipFile = createLogZipFile(logPath, context, isCurrent, isToday, isYesterday, customZipFileName);
  548. if (logPathZipFile != null && logPathZipFile.getFile() != null) {
  549. LogUtil.i(TAG, "压缩日志文件成功");
  550. return logPathZipFile;
  551. } else {
  552. LogUtil.i(TAG, "压缩日志文件失败");
  553. }
  554. }
  555. return new ZipFile(logPath);
  556. }
  557. /**
  558. * 创建压缩包
  559. * @param path 路径
  560. * @param context 上下文
  561. * @param isCurrent 是否当前用户
  562. * @param isToday 是否只压缩今天
  563. * @param isYesterday 是否只压缩明天
  564. * @param customZipFileName 压缩包名称,不包含后缀
  565. * @return 压缩文件
  566. * @throws ZipException 压缩异常
  567. */
  568. private static ZipFile createLogZipFile(final String path, final Context context, final boolean isCurrent,
  569. final boolean isToday, final boolean isYesterday, final String customZipFileName) throws ZipException {
  570. //或者压缩文件文件名称
  571. String zipFileName = getZipFileName(isCurrent, isToday, isYesterday, customZipFileName);
  572. File logZipDirFile = context.getExternalFilesDir("logZip");
  573. if (logZipDirFile != null && logZipDirFile.exists() && logZipDirFile.isDirectory()) {
  574. String zipPath = logZipDirFile.getAbsolutePath();
  575. //删除旧的压缩文件
  576. deleteZipFile(logZipDirFile);
  577. ZipFile zipFile = new ZipFile(zipPath + "/" + zipFileName);
  578. if (isCurrent && isToday) {
  579. getCurrentToday(zipFile, path);
  580. } else if (isCurrent && isYesterday) {
  581. getCurrentYesterday(zipFile, path);
  582. } else if (isCurrent) {
  583. getCurrentAll(zipFile, path);
  584. } else {
  585. getAll(zipFile, path);
  586. }
  587. return zipFile;
  588. }
  589. return null;
  590. }
  591. /**
  592. * 获取当前用户今天的日志
  593. * @param zipFile 压缩文件
  594. * @param path 日志目录
  595. */
  596. private static void getCurrentToday(final ZipFile zipFile, final String path) throws ZipException {
  597. List<String> startsWithName = new ArrayList<>();
  598. //主日志文件
  599. String logStartsWith = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + dateToDay(new Date());
  600. startsWithName.add(logStartsWith);
  601. //获取没有前缀的文件
  602. if (MarsXLogInit.getInstance().isDebugStatus()) {
  603. String logFileNameDebug = "Debug__" + dateToDay(new Date());
  604. startsWithName.add(logFileNameDebug);
  605. } else {
  606. String logFileNameRelease = "Release__" + dateToDay(new Date());
  607. startsWithName.add(logFileNameRelease);
  608. }
  609. List<File> logFiles = getStartsWithStringFile(startsWithName, path);
  610. zipFile.addFiles(logFiles);
  611. }
  612. /**
  613. * 获取当前用户昨天的日志
  614. * @param zipFile 压缩文件
  615. * @param path 日志目录
  616. */
  617. private static void getCurrentYesterday(final ZipFile zipFile, final String path) throws ZipException {
  618. List<String> startsWithName = new ArrayList<>();
  619. //主日志文件
  620. String logStartsWith = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + getPastDate(1, "yyyyMMdd");
  621. startsWithName.add(logStartsWith);
  622. //获取没有前缀的文件
  623. if (MarsXLogInit.getInstance().isDebugStatus()) {
  624. String logFileNameDebug = "Debug__" + getPastDate(1, "yyyyMMdd");
  625. startsWithName.add(logFileNameDebug);
  626. } else {
  627. String logFileNameRelease = "Release__" + getPastDate(1, "yyyyMMdd");
  628. startsWithName.add(logFileNameRelease);
  629. }
  630. List<File> logFiles = getStartsWithStringFile(startsWithName, path);
  631. zipFile.addFiles(logFiles);
  632. }
  633. /**
  634. * 获取当前用户所有的日志
  635. * @param zipFile 压缩文件
  636. * @param path 日志目录
  637. */
  638. private static void getCurrentAll(final ZipFile zipFile, final String path) throws ZipException {
  639. List<String> startsWithName = new ArrayList<>();
  640. //主日志文件
  641. String logStartsWith = MarsXLogInit.getInstance().getLogFileNamePrefix();
  642. startsWithName.add(logStartsWith);
  643. //获取没有前缀的文件
  644. if (MarsXLogInit.getInstance().isDebugStatus()) {
  645. String logFileNameDebug = "Debug__";
  646. startsWithName.add(logFileNameDebug);
  647. } else {
  648. String logFileNameRelease = "Release__";
  649. startsWithName.add(logFileNameRelease);
  650. }
  651. List<File> logFiles = getStartsWithStringFile(startsWithName, path);
  652. zipFile.addFiles(logFiles);
  653. }
  654. /**
  655. * 获取所有用户所有的日志
  656. * @param zipFile 压缩文件
  657. * @param path 日志目录
  658. */
  659. private static void getAll(final ZipFile zipFile, final String path) throws ZipException {
  660. File logPathFile = new File(path);
  661. File[] logFiles = logPathFile.listFiles();
  662. if (logFiles != null) {
  663. zipFile.addFiles(Arrays.asList(logFiles));
  664. }
  665. }
  666. /**
  667. * 获取以一些字符串开头的文件名的文件
  668. * @param startsWithName 需要的文件名开头集合
  669. * @param path 日志目录
  670. * @return 需要的文件
  671. */
  672. private static List<File> getStartsWithStringFile(final List<String> startsWithName, final String path) {
  673. List<File> needLogFile = new ArrayList<>();
  674. File logPathFile = new File(path);
  675. File[] logFiles = logPathFile.listFiles();
  676. if (logFiles != null) {
  677. List<File> logFileList = Arrays.asList(logFiles);
  678. for (File logFile: logFileList) {
  679. boolean isNeed = false;
  680. for (String name: startsWithName) {
  681. if (logFile.getName().startsWith(name)) {
  682. isNeed = true;
  683. }
  684. }
  685. if (isNeed) {
  686. needLogFile.add(logFile);
  687. }
  688. }
  689. }
  690. return needLogFile;
  691. }
  692. /**
  693. * 获取压缩包文件名称
  694. * @param isCurrent 是否当前用户
  695. * @param isToday 是否只压缩今天
  696. * @param isYesterday 是否只压缩明天
  697. * @param customZipFileName 压缩包名称,不包含后缀
  698. * @return 压缩包文件名称
  699. */
  700. private static String getZipFileName(final boolean isCurrent,
  701. final boolean isToday, final boolean isYesterday, final String customZipFileName) {
  702. String zipFileName;
  703. if (TextUtils.isEmpty(customZipFileName)) {
  704. if (isCurrent && isToday) {
  705. zipFileName = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + dateToDay(new Date()) + ".zip";
  706. } else if (isCurrent && isYesterday) {
  707. zipFileName = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + getPastDate(1, "yyyyMMdd") + ".zip";
  708. } else if (isCurrent) {
  709. if (MarsXLogInit.getInstance().getLogFileSaveDays() == 0) {
  710. zipFileName = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + getPastDate(10, "yyyyMMdd") + "~" + dateToDay(new Date()) + ".zip";
  711. } else {
  712. zipFileName = MarsXLogInit.getInstance().getLogFileNamePrefix() + "_" + getPastDate(MarsXLogInit.getInstance().getLogFileSaveDays(), "yyyyMMdd") + "~" + dateToDay(new Date()) + ".zip";
  713. }
  714. } else {
  715. String fileNamePrefix = MarsXLogInit.getInstance().getLogFileNamePrefix().substring(0, MarsXLogInit.getInstance().getLogFileNamePrefix().indexOf("_"));
  716. if (MarsXLogInit.getInstance().getLogFileSaveDays() == 0) {
  717. zipFileName = fileNamePrefix + "_all_user_" + getPastDate(10, "yyyyMMdd") + "~" + dateToDay(new Date()) + ".zip";
  718. } else {
  719. zipFileName = fileNamePrefix + "_all_user_" + getPastDate(MarsXLogInit.getInstance().getLogFileSaveDays(), "yyyyMMdd") + "~" + dateToDay(new Date()) + ".zip";
  720. }
  721. }
  722. } else {
  723. zipFileName = customZipFileName + ".zip";
  724. }
  725. return zipFileName;
  726. }
  727. /**
  728. * 删除旧的压缩文件
  729. * @param logZipDirFile 压缩文件目录
  730. */
  731. private static void deleteZipFile(File logZipDirFile) {
  732. File[] files = logZipDirFile.listFiles();
  733. if (files != null) {
  734. for (File file : files) {
  735. if (file.exists() && file.getName().endsWith(".zip")) {
  736. boolean result = file.delete();
  737. LogUtil.i(TAG, "删除旧的日志打包文件结果:" + result);
  738. }
  739. }
  740. }
  741. }
  742. private static String dateToDay(Date date) {
  743. return dateToStr(date, "yyyyMMdd");
  744. }
  745. private static String dateToStr(Date datetime, String format) {
  746. return new SimpleDateFormat(format, Locale.SIMPLIFIED_CHINESE).format(datetime);
  747. }
  748. /**
  749. * 获取过去第几天的日期
  750. *
  751. * @param past 天数
  752. * @param formatString 格式化
  753. * @return 日期
  754. */
  755. private static String getPastDate(final int past, final String formatString) {
  756. Calendar calendar = Calendar.getInstance();
  757. calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
  758. Date today = calendar.getTime();
  759. SimpleDateFormat format = new SimpleDateFormat(formatString, Locale.SIMPLIFIED_CHINESE);
  760. String result = format.format(today);
  761. return result;
  762. }
  763. /**
  764. * 关闭日志,在程序退出时调用。
  765. */
  766. public static void appenderClose() {
  767. MarsXLogInit.getInstance().setXlogOpenStatus(false);
  768. }
  769. /**
  770. * 当日志写入模式为异步时,调用该接口会把内存中的日志写入到文件。
  771. *
  772. * @param isSync isSync : true 为同步 flush,flush 结束后才会返回。 false 为异步 flush,不等待 flush 结束就返回。
  773. */
  774. public static void appenderFlush(final boolean isSync) {
  775. LogUtil.i(TAG, "appenderFlush:" + isSync);
  776. Log.appenderFlushSync(isSync);
  777. }
  778. /**
  779. * 设置日志回调
  780. * @param logInfo 回调对象
  781. */
  782. public static void logPrintInfo(final LogInfo logInfo) {
  783. mLogInfo = logInfo;
  784. }
  785. private static List<String> splitString(final String text, final int splitLength) {
  786. List<String> temp = new ArrayList<>();
  787. if (text != null && text.length() > 0) {
  788. if (text.length() <= splitLength) {
  789. temp.add(text);
  790. } else {
  791. int num = text.length() / splitLength;
  792. if (num * splitLength < text.length()) {
  793. num = num + 1;
  794. }
  795. for (int i = 0; i < num - 1; i++) {
  796. temp.add(text.substring(i * splitLength, (i + 1) * splitLength));
  797. }
  798. temp.add(text.substring((num -1) * splitLength));
  799. }
  800. }
  801. return temp;
  802. }
  803. }