├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── LICENCE ├── README.md ├── README_EN.md ├── ScreenShot.png ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── mym │ │ └── prettylog │ │ ├── CrashPrinter.java │ │ ├── LintTestCase.java │ │ ├── MainActivity.java │ │ ├── PLogApplication.java │ │ ├── TextViewPrinter.java │ │ ├── data │ │ ├── JSONEntity.java │ │ ├── LoremIpsum.java │ │ ├── Singleton.java │ │ └── User.java │ │ ├── util │ │ └── CrashHandler.java │ │ └── wrapper │ │ └── LogWrapper.java │ └── res │ ├── drawable-hdpi │ └── ic_info_outline_white_24dp.png │ ├── drawable-mdpi │ └── ic_info_outline_white_24dp.png │ ├── drawable-xhdpi │ └── ic_info_outline_white_24dp.png │ ├── drawable-xxhdpi │ └── ic_info_outline_white_24dp.png │ ├── drawable-xxxhdpi │ └── ic_info_outline_white_24dp.png │ ├── layout │ ├── activity_main.xml │ ├── dialog_about.xml │ └── item_usage_case.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── default_config.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── plog-formatter ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── org │ └── mym │ └── plog │ └── formatter │ ├── DefaultFormatter.java │ ├── JSONFormatter.java │ ├── ObjectFormatter.java │ ├── ThrowableFormatter.java │ └── util │ └── ObjectUtil.java ├── plog-lint-aar ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ └── AndroidManifest.xml ├── plog-lint ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── mym │ └── plog │ └── lint │ ├── IssueRegistry.java │ └── LoggingIssueDetector.java ├── plog-printer ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── org │ └── mym │ └── plog │ └── printer │ ├── FilePrinter.java │ └── FilePrinterHelper.java ├── plog-timing ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── org │ └── mym │ └── plog │ └── timing │ └── TimingLogger.java ├── plog ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── org │ └── mym │ └── plog │ ├── AbsPrinter.java │ ├── Category.java │ ├── DebugPrinter.java │ ├── Formatter.java │ ├── Interceptor.java │ ├── LogEngine.java │ ├── LogRequest.java │ ├── PLog.java │ ├── PrintLevel.java │ ├── Printer.java │ ├── SimpleCategory.java │ ├── SoftWrapper.java │ ├── Style.java │ ├── config │ └── PLogConfig.java │ └── internal │ ├── WordBreakWrapper.java │ └── WordLengthWrapper.java └── settings.gradle /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 3 | 4 | ## Basic info 5 | PLog version: 6 | 7 | ## Figure out a bug 8 | 17 | 18 | ## Feature Request 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /local.properties 3 | /.idea 4 | .DS_Store 5 | /captures 6 | *.apk 7 | *.ap_ 8 | *.dex 9 | *.class 10 | bin/ 11 | gen/ 12 | out/ 13 | .gradle/ 14 | build/ 15 | proguard/ 16 | *.log 17 | .navigation/ 18 | captures/ 19 | *.jks 20 | 21 | ### Jekyll template 22 | _site/ 23 | .sass-cache/ 24 | .jekyll-metadata 25 | 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # https://docs.travis-ci.com/user/languages/android 2 | language: android 3 | android: 4 | components: 5 | - platform-tools 6 | - tools 7 | - build-tools-25.0.3 8 | - android-25 9 | # - sys-img-armeabi-v7a-android-24 10 | - extra-android-m2repository 11 | 12 | licenses: 13 | - 'android-sdk-license.*' 14 | 15 | #compileSdkVersion 'android-24' requires JDK 1.8 or later to compile. 16 | jdk: 17 | - oraclejdk8 18 | #Only CI for master & dev 19 | branches: 20 | only: 21 | - master 22 | - dev 23 | 24 | before_cache: 25 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 26 | cache: 27 | directories: 28 | - $HOME/.gradle/caches/ 29 | - $HOME/.gradle/wrapper/ 30 | 31 | #before_script: 32 | # # Create and start emulator 33 | # - echo no | android create avd --force -n test -t android-24 --abi armeabi-v7a 34 | # - emulator -avd test -no-skin -no-audio -no-window & 35 | # - android-wait-for-emulator 36 | # - adb shell input keyevent 82 & 37 | #script: 38 | # - ./gradlew clean connectAndroidTest assembleRelease --stacktrace 39 | 40 | script: 41 | ./gradlew clean build -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [ ![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android--PLog-brightgreen.svg?style=flat) ](https://android-arsenal.com/details/1/4884)[![](https://jitpack.io/v/Muyangmin/Android-PLog.svg)](https://jitpack.io/#Muyangmin/Android-PLog)[ ![Download](https://api.bintray.com/packages/muyangmin/org.mym/Android-PLog/images/download.svg) ](https://bintray.com/muyangmin/org.mym/Android-PLog/_latestVersion) 2 | 3 | # PLog = Pure, Pretty, Powerful logging tool [![Build Status](https://travis-ci.org/Muyangmin/Android-PLog.svg?branch=master)](https://travis-ci.org/Muyangmin/Android-PLog) 4 | 5 | ![logo](./app/src/main/res/mipmap-xxhdpi/ic_launcher.png) 6 | 7 | [English Version](README_EN.md) 8 | 9 | ## 概述 10 | Android-PLog 项目(简称 PLog )是一个专为 Android 11 | 应用程序设计的开源日志封装库,追求纯粹、易用、强大,帮助开发者更好地使用日志调试程序,提高开发效率。概括来讲,它具有以下特性: 12 | #### 容易打印 13 | * **支持无Tag打印** 14 | * **支持空消息打印(通常用于观察某处是否执行)** 15 | * **支持任意参数类型** 16 | * **支持变长参数和自动格式化** 17 | * **支持Builder方式打印** 18 | 19 | #### 输出可控 20 | * **支持多维度的输出拦截** 21 | * **支持自定义输出装饰样式** 22 | * **支持多通道同时输出** 23 | * **支持自动换行(SoftWrap)** 24 | 25 | #### 筛选容易 26 | * **支持全局Tag**(可以区分不同应用) 27 | * **支持自动Tag**(可以区分不同类名) 28 | * **支持保留堆栈**(可以区分不同文件和方法,并且实现在AS中**自动日志定位**) 29 | * **支持分组打印**(可以区分不同开发者, etc) 30 | 31 | #### 按需依赖 32 | 核心功能模块和定制特性完全分离,体积轻巧,并且全部支持Jcenter依赖。 33 | 34 | #### 扩展灵活 35 | 核心功能全部接口化,通过简单的设置和接口注入就可以完成绝大部分日志需求。 36 | 37 | 38 | **关于项目的更多信息,包括下载、使用和注意事项,请访问[完整文档地址](https://jumeirdgroup.github.io/Android-PLog/)。** 39 | 40 | ## Contribution & Contact 41 | 如果您在使用这个库的时候遇到困难,或者有任何的反馈、建议,都可以通过GitHub Issue 功能或下面的邮箱联系我: 42 | **** 43 | 44 | ## Licence 45 | ``` 46 | Copyright 2016-2017 Muyangmin 47 | 48 | Licensed under the Apache License, Version 2.0 (the "License"); 49 | you may not use this file except in compliance with the License. 50 | You may obtain a copy of the License at 51 | 52 | http://www.apache.org/licenses/LICENSE-2.0 53 | 54 | Unless required by applicable law or agreed to in writing, software 55 | distributed under the License is distributed on an "AS IS" BASIS, 56 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 57 | See the License for the specific language governing permissions and 58 | limitations under the License. 59 | ``` 60 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | #Android-PLog [![Build Status](https://travis-ci.org/Muyangmin/Android-PLog.svg?branch=master)](https://travis-ci.org/Muyangmin/Android-PLog)[ ![Download](https://api.bintray.com/packages/muyangmin/org.mym/Android-PLog/images/download.svg) ](https://bintray.com/muyangmin/org.mym/Android-PLog/_latestVersion) 2 | 3 | #### [中文版文档](./README.md) 4 | 5 | ## Summary 6 | PLog is a logging library for Android, which has following features: 7 | #### Easy to print 8 | * print without tag 9 | * print without message 10 | * accept anny type of arguments 11 | * accept variable length arguments 12 | * auto formatting 13 | * print with builder style code 14 | 15 | #### Controllable output 16 | * intercept with multi dimension 17 | * customizable output decoration (style) 18 | * multi channel output 19 | * soft wrap supported 20 | 21 | #### Easy to filter 22 | * global tag (for filtering apps) 23 | * auto tag (for filtering classes) 24 | * keep stacktrace (for filtering files and/or methods) 25 | * category (for filtering developers or groups, etc) 26 | 27 | #### Dependency on demand 28 | You can use `plog-core` module for simple scenarios, but you can also import other modules for 29 | advanced usage. As you like. 30 | 31 | #### Flexible Setting/Extension 32 | You can use built-in options or just a little interface implementation to satisfy almost all 33 | your needs. 34 | 35 | PLog is a logging library for Android, follows following principle: 36 | #### Applicability 37 | > Focus on log itself, discard divider lines and other complicated decors but still keep being 38 | powerful. 39 | 40 | #### Light weight 41 | > PLog is **zero dependency**! 42 | 43 | #### Flexibility and expandability 44 | > PLog provides multi configs to fit your custom needs. 45 | 46 | #### Convention over configuration 47 | > Although PLog provides `init` method,your program will still work by using default logging 48 | configurations. And you can user `Builder` class to simply build your own config. 49 | Bonus: `recommend` method maybe help you much! 50 | 51 | ## Usage 52 | Please view [Wiki](https://github.com/Muyangmin/Android-PLog/wiki) to get usage details and advanced 53 | features. 54 | 55 | ## Features 56 | * **Jcenter support, ZERO DEPENDENCY** 57 | * **Empty method support *(useful for observe somewhere executed )*** 58 | * **Log without tag/ global tag/ auto tag** 59 | * **Varargs support and auto formatting** 60 | * **JSON format support** 61 | * **Throwable format support** 62 | * **Timing log support** 63 | * **Line number and stackOffset support** 64 | * **Loggable controller with different level** 65 | * **Local file logger is available** 66 | * **Logger redirect support(useful for adapt a 3-party logging, etc)** 67 | * **Very long log content support, either auto line wrap(soft wrap)** 68 | 69 | ## Compare With Other Libs 70 | | Library Name | [Logger](https://github.com/orhanobut/logger) | [Timber](https://github.com/JakeWharton/timber) | [KLog](https://github.com/ZhaoKaiQiang/KLog) | [Android-PLog](https://github.com/Muyangmin/Android-PLog) 71 | | ------| ------ | ------ | ------ | ----- | 72 | | Star/Fork | 5.7K+/1.0K+ | 3.5K+/366 | 1.1K+/251 | **Welcome!**| 73 | | Easy To Print | √ | √ | √ | √ | 74 | | Easy To Use | √ | √ | √ | √ | 75 | | Flexible Settings | ☆ | ☆ | ☆ | ☆ | 76 | | Light Weight | ☆ | ☆☆ | ☆ | ☆☆ | 77 | | Locating in IDE | √ | × | √ | √ | 78 | | Thread Info | √ | × | × | √ | 79 | | Easy To Filter | ☆ | × | ☆ | ☆☆ | 80 | | Beautify | ☆ | × | ☆ | ☆☆ | 81 | | Controllable and Multi Output | × | ☆☆ | ☆ | ☆☆ | 82 | 83 | ## Sample Screen Shot 84 | ![ScreenShot](./ScreenShot.png) 85 | 86 | 87 | ## Contribution & Contact 88 | Thanks for using PLog, this library is still in active development.**Any contribution and suggestions are welcome.** 89 | Please feel free to contact me by using following way: 90 | 91 | **Email: muyangmin@foxmail.com** 92 | 93 | ## Licence 94 | ``` 95 | Copyright 2016-2017 Muyangmin 96 | 97 | Licensed under the Apache License, Version 2.0 (the "License"); 98 | you may not use this file except in compliance with the License. 99 | You may obtain a copy of the License at 100 | 101 | http://www.apache.org/licenses/LICENSE-2.0 102 | 103 | Unless required by applicable law or agreed to in writing, software 104 | distributed under the License is distributed on an "AS IS" BASIS, 105 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 106 | See the License for the specific language governing permissions and 107 | limitations under the License. 108 | ``` -------------------------------------------------------------------------------- /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/ScreenShot.png -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | //apply plugin: 'android-apt' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.COMPILE_SDK_VERSION as int 6 | buildToolsVersion rootProject.ext.BUILD_TOOLS_VERSION as String 7 | 8 | defaultConfig { 9 | applicationId "org.mym.prettylog" 10 | minSdkVersion rootProject.ext.MIN_SDK_VERSION as int 11 | // targetSdkVersion rootProject.ext.TARGET_SDK_VERSION as int 12 | targetSdkVersion 25 13 | versionCode 1 14 | versionName VERSION_NAME 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | packagingOptions { 24 | exclude 'LICENSE.txt' 25 | exclude 'NOTICE.txt' 26 | } 27 | lintOptions { 28 | abortOnError false 29 | } 30 | } 31 | 32 | dependencies { 33 | compile fileTree(include: ['*.jar'], dir: 'libs') 34 | compile "com.android.support:appcompat-v7:${rootProject.ext.SUPPORT_VERSION as String}" 35 | compile "com.android.support:design:${rootProject.ext.SUPPORT_VERSION as String}" 36 | compile 'org.mym.material:md-colors:1.0.0' 37 | 38 | compile('com.github.hotchemi:permissionsdispatcher:2.4.0') { 39 | exclude group: "com.android.support" 40 | } 41 | annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.4.0' 42 | 43 | compile(rootProject.ext.BUTTERKNIFE as String) 44 | annotationProcessor(rootProject.ext.BUTTERKNIFE_APT as String) 45 | 46 | compile project(':plog') 47 | compile project(':plog-printer') 48 | compile project(':plog-timing') 49 | compile project(':plog-formatter') 50 | compile project(':plog-lint-aar') 51 | // compile 'org.mym.plog:android-plog:1.7.0' 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\Developer\AndroidSdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/CrashPrinter.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | import android.text.TextUtils; 10 | import android.text.format.Formatter; 11 | import android.util.PrintStreamPrinter; 12 | 13 | import org.mym.plog.Category; 14 | import org.mym.plog.PrintLevel; 15 | import org.mym.plog.printer.FilePrinter; 16 | 17 | import java.io.File; 18 | import java.util.Arrays; 19 | 20 | /** 21 | * This class provides a default(sample) crash file utility. 22 | * Created by muyangmin on Jan 17, 2017. 23 | * 24 | * @since 2.0.0 25 | */ 26 | public class CrashPrinter extends FilePrinter { 27 | 28 | public static final String CAT_CRASH = "crash"; 29 | 30 | private static volatile CrashPrinter sInstance = null; 31 | private static String sExtraInfo; 32 | private Context mApplicationContext; 33 | 34 | private CrashPrinter(Context mContext) { 35 | //Assume not null 36 | //noinspection ConstantConditions 37 | // super(getCrashFileDir(mContext).getAbsolutePath(), 38 | super(mContext, DIR_EXT_FILES + "/crash", 39 | new TimingFileNameGenerator(), 1024 * 1024L); 40 | mApplicationContext = mContext.getApplicationContext(); 41 | } 42 | 43 | public static CrashPrinter getInstance(Context context) { 44 | //create a temp variable to improve performance for reading volatile field. 45 | CrashPrinter instance = sInstance; 46 | if (instance == null) { 47 | synchronized (CrashPrinter.class) { 48 | instance = sInstance; 49 | //double check here 50 | if (instance == null) { 51 | instance = new CrashPrinter(context); 52 | sInstance = instance; 53 | } 54 | } 55 | } 56 | return instance; 57 | } 58 | 59 | public static void setExtraInfo(@NonNull String extraInfo) { 60 | sExtraInfo = extraInfo; 61 | } 62 | 63 | 64 | @Override 65 | public boolean onIntercept(@PrintLevel int level, @NonNull String tag, 66 | @Nullable Category category, @NonNull String msg) { 67 | // accept only crash category! 68 | // return !CRASH.equals(category); 69 | return !(category != null && category.isSameAs(CAT_CRASH)); 70 | } 71 | 72 | @Override 73 | public void print(@PrintLevel int level, @NonNull String tag, @NonNull String msg) { 74 | super.print(level, tag, msg); 75 | //Only record one crash at a time. 76 | close(); 77 | } 78 | 79 | @Override 80 | protected void printFileHeader(PrintStreamPrinter ps) { 81 | 82 | //Print time and thread 83 | // SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss, z", 84 | // Locale.getDefault()); 85 | // ps.println("CrashTime: " + format.format(timestamp)); 86 | // ps.println("CrashThread: " + thread + ", belong to group " + thread 87 | // .getThreadGroup()); 88 | if (!TextUtils.isEmpty(sExtraInfo)) { 89 | ps.println(sExtraInfo); 90 | sExtraInfo = null; 91 | } 92 | 93 | //Print device info, app info, etc. 94 | ps.println(createCrashHeaderStr(mApplicationContext)); 95 | 96 | //Print throwable, the core stacktrace 97 | // ps.println(Log.getStackTraceString(throwable)); 98 | } 99 | 100 | private String createCrashHeaderStr(Context context) { 101 | StringBuilder sb = new StringBuilder(1024); 102 | 103 | sb.append("Device Model: ").append(Build.MODEL).append("\n") 104 | .append("Device Brand: ").append(Build.BRAND).append("\n") 105 | .append("Device Manufacturer: ").append(Build.MANUFACTURER).append("\n") 106 | .append("OS Version: ").append(Build.VERSION.SDK_INT).append("\n") 107 | .append("OS Name: ").append(Build.VERSION.RELEASE).append("\n") 108 | .append("CPU Hardware: ").append(Build.HARDWARE).append("\n"); 109 | 110 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 111 | sb.append("CPU API: ").append(Arrays.toString(Build.SUPPORTED_ABIS)).append("\n"); 112 | } 113 | 114 | //NOTE: 这里虽然列出了内存和外存的freeSpace, 但在测试设备 HUAWEI FRD-AL00上两者并不相同。 115 | // 而外存的剩余大小和设置页里看到的存储空间数据一致。 116 | try { 117 | File intStore = context.getFilesDir(); 118 | File extStore = context.getExternalFilesDir(null); 119 | sb.append("Internal Storage Free: ") 120 | .append(Formatter.formatFileSize(context, intStore.getFreeSpace())) 121 | .append("\n"); 122 | if (extStore != null) { 123 | sb.append("External Storage Free: ") 124 | .append(Formatter.formatFileSize(context, extStore.getFreeSpace())) 125 | .append("\n"); 126 | } 127 | } catch (SecurityException ignored) { 128 | 129 | } 130 | 131 | PackageInfo packageInfo = null; 132 | try { 133 | packageInfo = context.getPackageManager() 134 | .getPackageInfo(context.getPackageName(), 0); 135 | } catch (PackageManager.NameNotFoundException ignored) { 136 | //Empty 137 | } 138 | sb.append("App Version: ") 139 | .append(packageInfo == null ? "N/A" : packageInfo.versionName) 140 | .append("\n"); 141 | 142 | return sb.toString(); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/LintTestCase.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog; 2 | 3 | import android.util.Log; 4 | 5 | import org.mym.plog.PLog; 6 | 7 | import java.util.Locale; 8 | 9 | /** 10 | * This source is belong to main, I want it to be just like a normal biz code, 11 | * though its actual purpose is to show and check PLog lint issues. 12 | * Created by muyangmin on Jun 07, 2017. 13 | */ 14 | public final class LintTestCase { 15 | 16 | void testLintLogNotPLog() { 17 | System.out.print("This is a test code."); 18 | System.out.println("test lint not plog."); 19 | 20 | Log.d("Lint", "use android.util.Log class."); 21 | 22 | PLog.v("use PLog, this is right."); 23 | } 24 | 25 | void testLintNestedFormatInPLog() { 26 | PLog.d(String.format(Locale.US, "%s %s", "Hello", "World")); 27 | 28 | //emulate a normal formatting 29 | String result = String.format("This is %s right call.", 2); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/PLogApplication.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog; 2 | 3 | import android.Manifest; 4 | import android.app.Application; 5 | import android.content.pm.PackageManager; 6 | import android.support.v4.content.ContextCompat; 7 | 8 | import org.mym.plog.DebugPrinter; 9 | import org.mym.plog.PLog; 10 | import org.mym.plog.config.PLogConfig; 11 | import org.mym.prettylog.util.CrashHandler; 12 | 13 | /** 14 | *

15 | * This class shows how to init PLog Library. 16 | *

17 | * Created by muyangmin on 9/1/16. 18 | * 19 | * @author muyangmin 20 | * @since V1.3.0 21 | */ 22 | public class PLogApplication extends Application { 23 | @Override 24 | public void onCreate() { 25 | super.onCreate(); 26 | 27 | PLog.init(new PLogConfig.Builder() 28 | // .emptyMsgLevel(Log.INFO) 29 | .forceConcatGlobalTag(getResources().getBoolean(R.bool.cfg_concat_tag)) 30 | .keepLineNumber(getResources().getBoolean(R.bool.cfg_line_info)) 31 | .useAutoTag(getResources().getBoolean(R.bool.cfg_auto_tag)) 32 | .keepThreadInfo(getResources().getBoolean(R.bool.cfg_thread_info)) 33 | .globalTag(getString(R.string.cfg_global_tag)) 34 | .build()); 35 | 36 | PLog.prepare(new DebugPrinter(true)); 37 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) 38 | == PackageManager.PERMISSION_GRANTED) { 39 | PLog.appendPrinter(CrashPrinter.getInstance(this)); 40 | } 41 | 42 | CrashHandler.getInstance().init(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/TextViewPrinter.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.util.Log; 8 | import android.widget.TextView; 9 | 10 | import org.mym.plog.AbsPrinter; 11 | import org.mym.plog.Category; 12 | import org.mym.plog.Formatter; 13 | import org.mym.plog.PrintLevel; 14 | import org.mym.plog.formatter.DefaultFormatter; 15 | 16 | /** 17 | * This is a sample of customizing view printer. 18 | * 19 | * @author Muyangmin 20 | * @since 2.0.0 21 | */ 22 | public class TextViewPrinter extends AbsPrinter { 23 | 24 | private TextView mTextView; 25 | private Handler mHandler; 26 | 27 | public TextViewPrinter(@NonNull TextView mTextView) { 28 | this.mTextView = mTextView; 29 | mHandler = new Handler(Looper.getMainLooper()); 30 | } 31 | 32 | @Override 33 | public boolean onIntercept(@PrintLevel int level, @NonNull String tag, @Nullable Category 34 | category, @NonNull String msg) { 35 | //intercept nothing 36 | return false; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public Formatter getFormatter() { 42 | //we can explicit set formatter here 43 | return new DefaultFormatter(); 44 | } 45 | 46 | @Override 47 | public void print(final @PrintLevel int level, final @NonNull String tag, 48 | final @NonNull String msg) { 49 | mHandler.post(new Runnable() { 50 | @Override 51 | public void run() { 52 | mTextView.setText(createPrintText(level, tag, msg)); 53 | } 54 | }); 55 | } 56 | 57 | private String createPrintText(final int level, final String tag, final String msg) { 58 | String levelChar = "V"; 59 | switch (level) { 60 | case Log.VERBOSE: 61 | levelChar = "V"; 62 | break; 63 | case Log.DEBUG: 64 | levelChar = "D"; 65 | break; 66 | case Log.INFO: 67 | levelChar = "I"; 68 | break; 69 | case Log.WARN: 70 | levelChar = "W"; 71 | break; 72 | case Log.ERROR: 73 | levelChar = "E"; 74 | break; 75 | case Log.ASSERT: 76 | levelChar = "A"; 77 | break; 78 | } 79 | return String.format("%s/%s: %s", levelChar, tag, msg); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/data/JSONEntity.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.data; 2 | 3 | /** 4 | * Created by muyangmin on 9/9/16. 5 | * 6 | * @author muyangmin 7 | */ 8 | public class JSONEntity { 9 | public static final String DATA = "{\"favSites\":[{\"name\":\"google\",\"domain\":\"https:www" + 10 | ".google.com\"},{\"name\":\"facebook\",\"domain\":\"https:www.facebook.com\"}]," + 11 | "\"user\":{\"name\":\"Lari\",\"address\":null,\"cert\":true,\"preserved\":{}}}"; 12 | 13 | public static final String DATA1 = "{\"res\":true,\"data\":{\"id\":\"3\"," + 14 | "\"icon\":\"http:\\/\\/182.254.246" + 15 | ".232:8080\\/group1\\/M00\\/00\\/2E\\/Cvc9DVhGfa2AB2L8AAFB3Qh8cK4333.jpg\"," + 16 | "\"begin_time\":\"2016-02-18\",\"end_time\":\"2017-01-06\"}}"; 17 | 18 | public static final String DATA2 = "{\"res\":true,\"data\":[{\"id\":\"164\"," + 19 | "\"image\":\"http:\\/\\/182.254.246" + 20 | ".232:8080\\/group1\\/M00\\/00\\/4A\\/Cvc9DVizzdiAKY1jAAKRlAaLiKU118.png\"," + 21 | "\"name\":\"\\u6d4b\\u8bd5\\u670d\\u52a1963\",\"description\":\"\",\"url\":\"\"," + 22 | "\"android_url\":\"122\",\"ios_url\":\"123\",\"share_title\":\"\"," + 23 | "\"share_desc\":\"\",\"share_img\":\"\",\"share_url\":\"\"},{\"id\":\"163\"," + 24 | "\"image\":\"http:\\/\\/182.254.246" + 25 | ".232:8080\\/group1\\/M00\\/00\\/2A\\/Cvc9DVefAlKAP7h5AAOOMQZ-h_Q891.jpg\"," + 26 | "\"name\":\"\\u5317\\u4eac\\u9996\\u9875\\u5f39\\u51fa\\u5f0f\\u6d3b\\u52a8-\\u706b" + 27 | "\\u4e0a\\u56fe\\u7247111\"," + 28 | "\"description\":\"qwewe\\u63cf\\u8ff0\\u63cf\\u8ff0\\u63cf\\u8ff0\\u63cf\\u8ff0" + 29 | "\\u63cf\\u8ff0123\",\"url\":\"\",\"android_url\":\"\"," + 30 | "\"ios_url\":\"YouHuiQuanInfoViewController\"," + 31 | "\"share_title\":\"1\\u5206\\u4eab\\u6807\\u9898 " + 32 | "*\\u539a\\u5927\\u53f8\\u8003\\u79ef\\u5206\\u4f1a729387\"," + 33 | "\"share_desc\":\"2\\u5206\\u4eab\\u63cf\\u8ff0 *@#\\uffe5@#8988809\"," + 34 | "\"share_img\":\"http:\\/\\/182.254.246" + 35 | ".232:8080\\/group1\\/M00\\/00\\/28\\/Cvc9DVeC_ueAaqzNAAJ39TRp3Kw284.jpg\"," + 36 | "\"share_url\":\"https:\\/\\/www.hao123.com\"},{\"id\":\"161\"," + 37 | "\"image\":\"http:\\/\\/182.254.246" + 38 | ".232:8080\\/group1\\/M00\\/00\\/2E\\/Cvc9DVhHouWAGG8TAABqLfQC_gM131.jpg\"," + 39 | "\"name\":\"\\u6d4b\\u8bd5\\u8bf7\\u6c42\",\"description\":\"\"," + 40 | "\"url\":\"http:\\/\\/www.hao123.com\",\"android_url\":\"\",\"ios_url\":\"\"," + 41 | "\"share_title\":\"123\",\"share_desc\":\"123\",\"share_img\":\"http:\\/\\/182.254" + 42 | ".246.232:8080\\/group1\\/M00\\/00\\/4A\\/Cvc9DViqlEaAXZLBAAAlZ9C9s9E767.png\"," + 43 | "\"share_url\":\"http:\\/\\/www.hao123.com\"},{\"id\":\"160\"," + 44 | "\"image\":\"http:\\/\\/182.254.246" + 45 | ".232:8080\\/group1\\/M00\\/00\\/2B\\/Cvc9DVe0PleAA70nAAA5_udnrHw255.png\"," + 46 | "\"name\":\"\\u7838\\u91d1\\u86cb\",\"description\":\"\",\"url\":\"http:\\/\\/www" + 47 | ".hao123.com\",\"android_url\":\"\",\"ios_url\":\"\",\"share_title\":\"\"," + 48 | "\"share_desc\":\"\",\"share_img\":\"\",\"share_url\":\"\"},{\"id\":\"143\"," + 49 | "\"image\":\"http:\\/\\/182.254.246" + 50 | ".232:8080\\/group1\\/M00\\/00\\/2A\\/Cvc9DVekSpiAQT3rAANCQokEWDs795.png\"," + 51 | "\"name\":\"\\u65e0\\u9521\\u6d3b\\u52a8\",\"description\":\"\",\"url\":\"\"," + 52 | "\"android_url\":\"\",\"ios_url\":\"\",\"share_title\":\"\",\"share_desc\":\"\"," + 53 | "\"share_img\":\"\",\"share_url\":\"\"},{\"id\":\"141\",\"image\":\"http:\\/\\/182" + 54 | ".254.246.232:8080\\/group1\\/M00\\/00\\/18\\/Cvc9DVbFaAaAKDPSAAKXIjV3N8Y263.jpg\"," + 55 | "\"name\":\"\\u4e0a\\u6d77\",\"description\":\"\",\"url\":\"\",\"android_url\":\"\"," + 56 | "\"ios_url\":\"\",\"share_title\":\"\",\"share_desc\":\"\",\"share_img\":\"\"," + 57 | "\"share_url\":\"\"}]}"; 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/data/LoremIpsum.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.data; 2 | 3 | /** 4 | * This is a sample random text to test long logs. The text content is not reviewed. 5 | *

6 | * Generated by http://cn.lipsum.com/, please visit this site for more details. 7 | *

8 | * Created by muyangmin on Sep 19, 2017. 9 | */ 10 | public final class LoremIpsum { 11 | public static final String TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + 12 | "Duis malesuada ligula mauris, eget consectetur dolor rhoncus in. Fusce vulputate dui" + 13 | " sit amet elit laoreet elementum. Etiam aliquet, diam vel tincidunt iaculis, odio " + 14 | "ipsum convallis nunc, id laoreet lorem odio in tellus. Suspendisse fringilla sodales" + 15 | " ligula, volutpat ornare elit placerat vitae. Cras iaculis gravida ipsum, in tempus " + 16 | "eros laoreet in. Pellentesque nisl dolor, bibendum ac vehicula at, molestie et ex. " + 17 | "In hac habitasse platea dictumst. Aliquam sem lorem, lacinia nec urna at, tempor " + 18 | "fringilla lectus. Suspendisse potenti. Ut quis faucibus quam.\n" + 19 | "\n" + 20 | "Duis a arcu non leo placerat aliquam quis sed lectus. Class aptent taciti sociosqu " + 21 | "ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas non ex leo. " + 22 | "Sed luctus at diam at pulvinar. Aenean ut condimentum justo, sit amet luctus est. " + 23 | "Sed nisi purus, accumsan eu posuere id, fermentum sit amet diam. Praesent interdum " + 24 | "felis pretium suscipit placerat. Aenean a vehicula dui. Orci varius natoque " + 25 | "penatibus et magnis dis parturient montes, nascetur ridiculus mus.\n" + 26 | "\n" + 27 | "Fusce dignissim ut erat eget eleifend. Donec tristique nunc diam, quis blandit lacus" + 28 | " ornare at. Duis rhoncus nulla purus, nec gravida lorem efficitur sit amet. Sed nec " + 29 | "accumsan velit, vel pretium justo. Nullam dignissim ultricies nisl. Maecenas " + 30 | "malesuada vitae eros vitae tincidunt. Cras sed augue dictum, scelerisque orci sit " + 31 | "amet, vulputate tortor. In laoreet mauris lorem, in laoreet dui placerat vitae. " + 32 | "Morbi rutrum purus neque, sed consequat dui laoreet eget. Curabitur mattis et massa " + 33 | "nec porttitor. Donec pulvinar a quam at mattis. Phasellus feugiat est eget aliquet " + 34 | "pretium. Donec orci elit, lacinia et ex in, semper ultricies nisl.\n" + 35 | "\n" + 36 | "Mauris vel dapibus purus. Duis non semper turpis. Cras aliquam posuere lacus, eget " + 37 | "posuere enim tempus quis. Suspendisse condimentum, tellus vitae cursus ullamcorper, " + 38 | "lorem sapien congue lectus, in auctor orci lorem nec erat. Aenean viverra risus " + 39 | "tellus, gravida maximus libero ullamcorper ac. Sed id orci id eros consequat " + 40 | "molestie. Donec iaculis erat eget aliquam congue. Proin fringilla, lectus maximus " + 41 | "rutrum dapibus, diam lorem volutpat diam, in condimentum erat lorem ut ante.\n" + 42 | "\n" + 43 | "Sed dui tortor, interdum sit amet bibendum sed, maximus sed ante. Aliquam nec " + 44 | "scelerisque leo, in condimentum mauris. Lorem ipsum dolor sit amet, consectetur " + 45 | "adipiscing elit. Etiam congue elit in tincidunt aliquet. Vivamus erat felis, laoreet" + 46 | " sed tellus at, egestas lacinia odio. Pellentesque vitae facilisis tellus. Donec " + 47 | "porta arcu non dui lacinia, non vulputate leo eleifend. Mauris sit amet mauris " + 48 | "commodo nisl finibus luctus. Nullam vitae justo ac enim semper tempor.\n" + 49 | "\n" + 50 | "Suspendisse egestas dictum tellus, a dapibus leo suscipit eu. Quisque commodo tempor" + 51 | " blandit. Ut vehicula quis sem ut tempor. Donec posuere pellentesque vulputate. In " + 52 | "eu ex eget neque lobortis vehicula vitae eu turpis. Suspendisse potenti. Nam " + 53 | "porttitor efficitur enim, id vehicula risus sodales ac. Ut et enim nec justo " + 54 | "consequat gravida vitae vel risus. Praesent hendrerit consectetur eros eget ornare. " + 55 | "Proin pharetra ante vitae tellus ultricies commodo. Aenean at libero non risus " + 56 | "pellentesque porta id aliquet quam. Curabitur in dolor imperdiet, lobortis dolor eu," + 57 | " tempus elit. Sed metus sem, gravida at laoreet eget, aliquam nec metus. Sed rhoncus" + 58 | " turpis eu elit ornare, ut mollis libero luctus. Fusce pulvinar magna volutpat augue" + 59 | " mattis, in accumsan lorem ultrices.\n" + 60 | "\n" + 61 | "Donec mollis venenatis tellus. Phasellus quis viverra erat. Etiam ultrices ipsum a " + 62 | "dignissim finibus. Cras quis ligula ullamcorper, tempus erat eu, commodo nisi. Class" + 63 | " aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos " + 64 | "himenaeos. Cras est tortor, sodales gravida lectus nec, lacinia commodo tellus. Nam " + 65 | "dapibus sodales ipsum in porta. Donec eget diam placerat, luctus ligula ac, cursus " + 66 | "justo.\n" + 67 | "\n" + 68 | "Vestibulum est tortor, tristique nec semper ac, mollis vitae quam. Proin efficitur " + 69 | "felis sed massa vulputate, quis maximus urna viverra. Etiam molestie blandit ante, " + 70 | "in laoreet tortor fringilla in. Phasellus in ante diam. Suspendisse mi mi, luctus " + 71 | "quis mauris non, venenatis viverra quam. Lorem ipsum dolor sit amet, consectetur " + 72 | "adipiscing elit. Mauris risus arcu, semper in luctus ut, interdum eget mauris. Donec" + 73 | " malesuada orci mi, nec congue mi luctus quis. Vivamus placerat mi mauris, ut " + 74 | "laoreet diam scelerisque ac. Aenean et sem id dolor dictum blandit. Duis at lobortis" + 75 | " nibh. Vivamus cursus risus dui, sed lacinia erat commodo iaculis.\n" + 76 | "\n" + 77 | "Aenean gravida aliquet arcu, eu ultrices est gravida et. Orci varius natoque " + 78 | "penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec ut augue " + 79 | "consequat, scelerisque tellus sed, eleifend odio. Sed nec vehicula erat. Mauris nibh" + 80 | " dolor, ultrices vel risus at, congue sollicitudin sapien. Integer eu mattis augue. " + 81 | "Maecenas vitae venenatis lorem, sit amet finibus justo. Cras lacinia pellentesque " + 82 | "lorem, eget imperdiet massa rhoncus ac. Pellentesque eu sem at libero consequat " + 83 | "hendrerit quis sit amet quam. Curabitur convallis pretium molestie. Nunc placerat " + 84 | "elit eu dictum euismod. Suspendisse potenti.\n" + 85 | "\n" + 86 | "Nulla pellentesque nibh felis, sit amet ornare tortor pulvinar ac. Praesent id diam " + 87 | "ut erat fermentum commodo. Nam eu feugiat ligula, ac vulputate leo. Integer justo " + 88 | "quam, ultricies sed metus sit amet, pretium congue felis. Cras iaculis blandit " + 89 | "scelerisque. Proin faucibus nulla sem, ac hendrerit tellus iaculis sit amet. Nunc " + 90 | "vulputate pellentesque leo vitae dapibus. Fusce lacus mi, efficitur id diam sit " + 91 | "amet, mollis dictum lacus. Sed nec arcu a ante tempor dapibus. Duis ultrices odio at" + 92 | " erat tempus cursus.\n" + 93 | "\n" + 94 | "Sed rhoncus, arcu non porttitor feugiat, sem nibh ullamcorper neque, id rutrum leo " + 95 | "purus imperdiet velit. In hac habitasse platea dictumst. Etiam semper a purus ac " + 96 | "tincidunt. Mauris vulputate, velit vel ultrices ullamcorper, libero arcu ultrices " + 97 | "sapien, quis iaculis justo massa at neque. Praesent pellentesque tristique metus, " + 98 | "vel dictum odio. Cras vitae commodo massa, quis laoreet justo. Vestibulum fermentum " + 99 | "interdum diam non cursus. Proin quis elementum ante, id commodo nisl. Class aptent " + 100 | "taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. " + 101 | "Maecenas quis ante rutrum, condimentum nisi eget, placerat lacus. Donec a urna eu " + 102 | "justo maximus dictum. Praesent at vulputate orci. Quisque sit amet pellentesque diam" + 103 | ".\n" + 104 | "\n" + 105 | "Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos " + 106 | "himenaeos. Duis at auctor massa. Mauris iaculis iaculis ante, molestie pharetra urna" + 107 | " venenatis ac. Donec ac quam sed eros varius lacinia ornare ac nisi. Class aptent " + 108 | "taciti sociosqu ad litora torquent per."; 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/data/Singleton.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.data; 2 | 3 | /** 4 | * This is a test case class for cycling reference sample: singleton. 5 | *

6 | * Without recursive depth handling, recursively access this object will lead to 7 | * StackOverflowError. 8 | *

9 | * Created by muyangmin on Sep 19, 2017. 10 | */ 11 | public class Singleton { 12 | private static volatile Singleton sInstance = null; 13 | 14 | private Singleton() { 15 | 16 | } 17 | 18 | public static Singleton getInstance() { 19 | //create a temp variable to improve performance for reading volatile field. 20 | Singleton instance = sInstance; 21 | if (instance == null) { 22 | synchronized (Singleton.class) { 23 | instance = sInstance; 24 | //double check here 25 | if (instance == null) { 26 | instance = new Singleton(); 27 | sInstance = instance; 28 | } 29 | } 30 | } 31 | return instance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/data/User.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.data; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 7 | * @author muyangmin 8 | * @since V1.3.0 9 | */ 10 | @SuppressWarnings("FieldCanBeLocal") 11 | public class User { 12 | 13 | private String name; 14 | private int age; 15 | private List cats; 16 | private Cat favCat; 17 | 18 | public User(String name, int age, List cats) { 19 | this.name = name; 20 | this.age = age; 21 | this.cats = cats; 22 | if (cats != null && cats.size() > 0) { 23 | this.favCat = cats.get(0); 24 | } 25 | } 26 | 27 | //toString method is not overridden 28 | 29 | public static final class Cat { 30 | public String name; 31 | public String color; 32 | 33 | public Cat(String name, String color) { 34 | this.name = name; 35 | this.color = color; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/util/CrashHandler.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.util; 2 | 3 | import android.util.Log; 4 | 5 | import org.mym.plog.PLog; 6 | import org.mym.prettylog.CrashPrinter; 7 | 8 | import java.text.SimpleDateFormat; 9 | import java.util.Locale; 10 | 11 | /** 12 | * Created by muyangmin on 9/8/16. 13 | * 14 | * @author muyangmin 15 | */ 16 | public class CrashHandler implements Thread.UncaughtExceptionHandler { 17 | 18 | private static volatile CrashHandler sInstance = null; 19 | private Thread.UncaughtExceptionHandler mDefaultHandler; 20 | 21 | private CrashHandler() { 22 | 23 | } 24 | 25 | public static CrashHandler getInstance() { 26 | //create a temp variable to improve performance for reading volatile field. 27 | CrashHandler instance = sInstance; 28 | if (instance == null) { 29 | synchronized (CrashHandler.class) { 30 | instance = sInstance; 31 | //double check here 32 | if (instance == null) { 33 | instance = new CrashHandler(); 34 | sInstance = instance; 35 | } 36 | } 37 | } 38 | return instance; 39 | } 40 | 41 | public void init() { 42 | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 43 | Thread.setDefaultUncaughtExceptionHandler(this); 44 | } 45 | 46 | 47 | @Override 48 | public void uncaughtException(Thread thread, Throwable throwable) { 49 | //TODO consider remove this on release version 50 | throwable.printStackTrace(); 51 | CrashPrinter.setExtraInfo(generateExtraInfo(thread)); 52 | PLog.level(Log.ERROR).category(CrashPrinter.CAT_CRASH).params(throwable).print(); 53 | if (mDefaultHandler != null) { 54 | mDefaultHandler.uncaughtException(thread, throwable); 55 | } 56 | 57 | } 58 | 59 | private String generateExtraInfo(Thread thread) { 60 | //Print time and thread 61 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss, z", 62 | Locale.getDefault()); 63 | //noinspection StringBufferReplaceableByString 64 | StringBuilder sb = new StringBuilder(); 65 | sb.append("CrashTime: ").append(format.format(System.currentTimeMillis())); 66 | sb.append("CrashThread: ").append(thread.toString()); 67 | return sb.toString(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/org/mym/prettylog/wrapper/LogWrapper.java: -------------------------------------------------------------------------------- 1 | package org.mym.prettylog.wrapper; 2 | 3 | //import android.content.Context; 4 | // 5 | //import org.mym.plog.PLog; 6 | //import org.mym.plog.config.EasyLogController; 7 | //import org.mym.plog.config.PLogConfig; 8 | 9 | /** 10 | *

11 | * This class is a sample for how to wrap the log library for extensibility or replace library. 12 | * But I still recommend you to continuously use PLog library :) 13 | * This file is published on GitHub Gist; you can find it in my public gist list: 14 | * https://gist.github.com/Muyangmin 15 | *

16 | * Created by muyangmin on 9/7/16. 17 | * 18 | * @author muyangmin 19 | * @since V1.3.0 20 | */ 21 | @SuppressWarnings("unused") 22 | public class LogWrapper { 23 | // 24 | // private static IAppLogger sLogger; 25 | // 26 | // /** 27 | // * This context param is not necessary for PLog; however I cannot promise other library 28 | // * does not need it. 29 | // * @param context should be application context 30 | // */ 31 | // public static void init(Context context){ 32 | // sLogger = LogFactory.createLogger(); 33 | // sLogger.init(context); 34 | // } 35 | // 36 | // public static void addTimingSplit(String label) { 37 | // sLogger.addTimingSplit(label); 38 | // } 39 | // 40 | // public static void objects(Object... objects) { 41 | // sLogger.objects(objects); 42 | // } 43 | // 44 | // public static void i(String msg, Object... obj) { 45 | // sLogger.i(msg, obj); 46 | // } 47 | // 48 | // public static void resetTiming(String tag, String label) { 49 | // sLogger.resetTiming(tag, label); 50 | // } 51 | // 52 | // public static void d(String msg, Object... obj) { 53 | // sLogger.d(msg, obj); 54 | // } 55 | // 56 | // public static void w(String msg, Object... obj) { 57 | // sLogger.w(msg, obj); 58 | // } 59 | // 60 | // public static void resetTiming() { 61 | // sLogger.resetTiming(); 62 | // } 63 | // 64 | // public static void i(String tag, String msg, Object... obj) { 65 | // sLogger.i(tag, msg, obj); 66 | // } 67 | // 68 | // public static void empty() { 69 | // sLogger.empty(); 70 | // } 71 | // 72 | // public static void v(String msg, Object... obj) { 73 | // sLogger.v(msg, obj); 74 | // } 75 | // 76 | // public static void e(String msg, Object... obj) { 77 | // sLogger.e(msg, obj); 78 | // } 79 | // 80 | // public static void dumpTiming() { 81 | // sLogger.dumpTiming(); 82 | // } 83 | // 84 | // private interface IAppLogger { 85 | // 86 | // /** 87 | // * This context param is not necessary for PLog; however I cannot promise other library 88 | // * does not need it. 89 | // * @param context should be application context 90 | // */ 91 | // void init(Context context); 92 | // 93 | // void v(String msg, Object... obj); 94 | // void d(String msg, Object... obj); 95 | // void i(String msg, Object... obj); 96 | // void w(String msg, Object... obj); 97 | // void e(String msg, Object... obj); 98 | // 99 | // void i(String tag, String msg, Object... obj); //other method contains tag param is omitted 100 | // 101 | // void objects(Object... objects); 102 | // 103 | // void empty(); 104 | // 105 | // //For timing 106 | // void resetTiming(); 107 | // void resetTiming(String tag, String label); 108 | // void addTimingSplit(String splitLabel); 109 | // void dumpTiming(); 110 | // } 111 | // 112 | // private static class LogFactory { 113 | // public static IAppLogger createLogger(){ 114 | // return new PLogImpl(); 115 | // } 116 | // } 117 | // 118 | // private static class PLogImpl implements IAppLogger { 119 | // @Override 120 | // public void addTimingSplit(String splitLabel) { 121 | // PLog.addTimingSplit(splitLabel); 122 | // } 123 | // 124 | // @Override 125 | // public void init(Context context) { 126 | // PLog.init(PLogConfig.newBuilder() 127 | // .useAutoTag(true) 128 | // //1 is wrapper layer level 129 | // // while LogWrapper is 1 and PLogImpl is 2 130 | // .globalStackOffset(2) 131 | // .keepLineNumber(true) 132 | // .keepInnerClass(true) 133 | // .forceConcatGlobalTag(true) 134 | // .getMaxLengthPerLine(160) 135 | // //TODO replace your BuildConfig.DEBUG here 136 | // .controller(new EasyLogController(true, true)) 137 | // .build()); 138 | // } 139 | // 140 | // @Override 141 | // public void v(String msg, Object... obj) { 142 | // PLog.v(msg, obj); 143 | // } 144 | // 145 | // @Override 146 | // public void d(String msg, Object... obj) { 147 | // PLog.d(msg, obj); 148 | // } 149 | // 150 | // @Override 151 | // public void i(String msg, Object... obj) { 152 | // PLog.i(msg, obj); 153 | // } 154 | // 155 | // @Override 156 | // public void w(String msg, Object... obj) { 157 | // PLog.w(msg, obj); 158 | // } 159 | // 160 | // @Override 161 | // public void e(String msg, Object... obj) { 162 | // PLog.e(msg, obj); 163 | // } 164 | // 165 | // @Override 166 | // public void i(String tag, String msg, Object... obj) { 167 | // PLog.i(tag, msg, obj); 168 | // } 169 | // 170 | // @Override 171 | // public void objects(Object... objects) { 172 | // PLog.objects(objects); 173 | // } 174 | // 175 | // @Override 176 | // public void empty() { 177 | // PLog.empty(); 178 | // } 179 | // 180 | // @Override 181 | // public void resetTiming() { 182 | // PLog.resetTimingLogger(); 183 | // } 184 | // 185 | // @Override 186 | // public void resetTiming(String tag, String label) { 187 | // PLog.resetTimingLogger(tag, label); 188 | // } 189 | // 190 | // @Override 191 | // public void dumpTiming() { 192 | // PLog.dumpTimingToLog(); 193 | // } 194 | // } 195 | } 196 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_info_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/app/src/main/res/drawable-hdpi/ic_info_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_info_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/app/src/main/res/drawable-mdpi/ic_info_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_info_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/app/src/main/res/drawable-xhdpi/ic_info_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_info_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/app/src/main/res/drawable-xxhdpi/ic_info_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_info_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JumeiRdGroup/Android-PLog/904b1957f9a7f9c64221673e8949d15effc97b64/app/src/main/res/drawable-xxxhdpi/ic_info_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 | 26 | 27 | 34 | 35 | 44 | 45 | 53 | 54 | 63 | 64 | 74 | 75 |