├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── demo.apk ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wenming │ │ └── library │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── wenming │ │ │ └── library │ │ │ ├── BackgroundUtil.java │ │ │ ├── DetectService.java │ │ │ ├── MyApplication.java │ │ │ └── processutil │ │ │ ├── ProcessManager.java │ │ │ └── models │ │ │ ├── AndroidAppProcess.java │ │ │ ├── AndroidProcess.java │ │ │ ├── Cgroup.java │ │ │ ├── ControlGroup.java │ │ │ ├── ProcFile.java │ │ │ ├── Stat.java │ │ │ ├── Statm.java │ │ │ └── Status.java │ └── res │ │ ├── values │ │ └── strings.xml │ │ └── xml │ │ └── detection_service_config.xml │ └── test │ └── java │ └── com │ └── wenming │ └── library │ └── ExampleUnitTest.java ├── sample ├── .gitignore ├── 1.PNG ├── 2.PNG ├── 3.PNG ├── build.gradle ├── proguard-rules.pro ├── qrcode.png └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wenming │ │ └── androidprocess │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── wenming │ │ │ └── androidprocess │ │ │ ├── Features.java │ │ │ ├── activity │ │ │ └── MainActivity.java │ │ │ ├── adapter │ │ │ └── ViewPagerAdapter.java │ │ │ ├── fragment │ │ │ ├── OneFragment.java │ │ │ └── ProfileFragment.java │ │ │ ├── receiver │ │ │ └── MyReceiver.java │ │ │ └── service │ │ │ └── MyService.java │ └── res │ │ ├── drawable-xhdpi │ │ ├── clickbackground.xml │ │ ├── effectivematrixlogo.jpeg │ │ ├── image1.png │ │ ├── image2.png │ │ ├── largeicon.png │ │ ├── logo.png │ │ └── myicon.jpg │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_one.xml │ │ └── profile_layout.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-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── wenming │ └── androidprocess │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # git ignore 2 | 3 | # Android debug tools folder 4 | /captures 5 | 6 | 7 | # Gradle files 8 | .gradle 9 | build/ 10 | idea/ 11 | 12 | # IntelliJ IDEA project files 13 | .idea/ 14 | *.iml 15 | *.ipr 16 | *.iws 17 | 18 | .DS_Store 19 | 20 | 21 | 22 | 23 | # Files for the Dalvik VM 24 | *.dex 25 | 26 | # Java class files 27 | *.class 28 | 29 | # Generated files 30 | bin/ 31 | gen/ 32 | 33 | # Local configuration file (sdk path, etc) 34 | local.properties 35 | 36 | # Proguard folder generated by Eclipse 37 | proguard/ 38 | 39 | # Log Files 40 | *.log 41 | 42 | 43 | # Eclipse project files 44 | .classpath 45 | .project 46 | .settings/ 47 | 48 | 49 | # Ant 50 | build.xml 51 | local.properties 52 | 53 | 54 | # Maven 55 | target/ 56 | pom.xml.* 57 | release.properties -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidProcess 2 | 3 | 提供6种方法来判断App处于前台还是后台,并且封装成工具类供大家使用 4 | 5 | 最后一种方法堪称Android黑科技(非原创),既可以突破Android5.0以上的权限封锁,获取任意前台App的包名,又不需要权限,此方法并非我原创,原作者是国外的大神,[GitHub项目在这里](https://github.com/jaredrummler/AndroidProcesses),也一并加入到工程中,供大家做全面的参考选择 6 | 7 | 8 | **2016.2.11更新------感谢[@EffectiveMatrix](http://weibo.com/hatewx?refer_flag=1005050005_)大神带来的新的判断前后台的方法** 9 | 10 | 快速下载体验 11 | ----- 12 | [百度网盘](https://github.com/wenmingvs/AndroidProcess/blob/master/demo.apk) 13 | 14 | 预览图 15 | ----- 16 | ![enter image description here](http://ww2.sinaimg.cn/large/691cc151gw1f09z4gz35mg20bc0h01kx.gif) 17 | 18 | 19 | 20 | 21 | 用法 22 | ----- 23 | 传入Context参数与想要判断是否位于前台的App的包名,会返回ture或者false表示App是否位于前台 24 | 25 | ``` java 26 | 27 | //六种方法任选其一 28 | 29 | //使用方法一 30 | Boolean isForeground = BackgroundUtil.getRunningTask(context, packageName); 31 | //使用方法二 32 | Boolean isForeground = BackgroundUtil.getRunningAppProcesses(context, packageName); 33 | //使用方法三 34 | Boolean isForeground = BackgroundUtil.getApplicationValue(context); 35 | //使用方法四 36 | Boolean isForeground = BackgroundUtil.queryUsageStats(context, packageName); 37 | //使用方法五 38 | Boolean isForeground = BackgroundUtil.getFromAccessibilityService(context, packageName); 39 | //使用方法六 40 | Boolean isForeground = BackgroundUtil.getLinuxCoreInfo(context, packageName); 41 | ``` 42 | 43 | 六种方法的区别 44 | ----- 45 | |方法|判断原理|需要权限|可以判断其他应用位于前台|特点 46 | | ------ | ------ | ------ | ------ | ------ | 47 | |方法一|RunningTask|否|Android4.0系列可以,5.0以上机器不行|5.0此方法被废弃 48 | |方法二|RunningProcess|否|当App存在后台常驻的Service时失效|无 49 | |方法三|ActivityLifecycleCallbacks|否|否|简单有效,代码最少 50 | |方法四|UsageStatsManager|是|是|需要用户手动授权 51 | |方法五|通过Android无障碍功能实现|否|是|需要用户手动授权 52 | |方法六|读取/proc目录下的信息|否|是|当proc目录下文件夹过多时,过多的IO操作会引起耗时 53 | 54 | 55 | 方法一:通过RunningTask 56 | ----- 57 | 58 | ![enter image description here](http://ww2.sinaimg.cn/large/691cc151gw1f09z4gz35mg20bc0h01kx.gif) 59 | 60 | **原理** 61 | 当一个App处于前台的时候,会处于RunningTask的这个栈的栈顶,所以我们可以取出RunningTask的栈顶的任务进程,看他与我们的想要判断的App的包名是否相同,来达到效果 62 | 63 | **缺点** 64 | getRunningTask方法在Android5.0以上已经被废弃,只会返回自己和系统的一些不敏感的task,不再返回其他应用的task,用此方法来判断自身App是否处于后台,仍然是有效的,但是无法判断其他应用是否位于前台,因为不再能获取信息 65 | 66 | 67 | 方法二:通过RunningProcess 68 | ----- 69 | 70 | ![enter image description here](http://ww1.sinaimg.cn/mw690/691cc151gw1f09z4vmmcgg20bc0h07wh.gif) 71 | 72 | **原理** 73 | 通过runningProcess获取到一个当前正在运行的进程的List,我们遍历这个List中的每一个进程,判断这个进程的一个importance 属性是否是前台进程,并且包名是否与我们判断的APP的包名一样,如果这两个条件都符合,那么这个App就处于前台 74 | 75 | **缺点**: 76 | 在聊天类型的App中,常常需要常驻后台来不间断的获取服务器的消息,这就需要我们把Service设置成START_STICKY,kill 后会被重启(等待5秒左右)来保证Service常驻后台。如果Service设置了这个属性,这个App的进程就会被判断是前台,代码上的表现就是appProcess.importance的值永远是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,这样就永远无法判断出到底哪个是前台了。 77 | 78 | 方法三:通过ActivityLifecycleCallbacks 79 | ------ 80 | 81 | ![enter image description here](http://ww2.sinaimg.cn/mw690/691cc151gw1f09z59b1pzg20bc0h04qp.gif) 82 | 83 | **原理** 84 | AndroidSDK14在Application类里增加了ActivityLifecycleCallbacks,我们可以通过这个Callback拿到App所有Activity的生命周期回调。 85 | ``` java 86 | public interface ActivityLifecycleCallbacks { 87 | void onActivityCreated(Activity activity, Bundle savedInstanceState); 88 | void onActivityStarted(Activity activity); 89 | void onActivityResumed(Activity activity); 90 | void onActivityPaused(Activity activity); 91 | void onActivityStopped(Activity activity); 92 | void onActivitySaveInstanceState(Activity activity, Bundle outState); 93 | void onActivityDestroyed(Activity activity); 94 | } 95 | ``` 96 | 知道这些信息,我们就可以用更官方的办法来解决问题,当然还是利用方案二里的Activity生命周期的特性,我们只需要在Application的onCreate()里去注册上述接口,然后由Activity回调回来运行状态即可。 97 | 98 | 可能还有人在纠结,我用back键切到后台和用Home键切到后台,一样吗?以上方法适用吗?在Android应用开发中一般认为back键是可以捕获的,而Home键是不能捕获的(除非修改framework),但是上述方法从Activity生命周期着手解决问题,虽然这两种方式的Activity生命周期并不相同,但是二者都会执行onStop();所以并不关心到底是触发了哪个键切入后台的。另外,Application是否被销毁,都不会影响判断的正确性 99 | 100 | 方法四:通过使用UsageStatsManager获取 101 | ----- 102 | ![enter image description here](http://ww1.sinaimg.cn/mw690/691cc151gw1f09z5v4g7mg20bc0h0npd.gif) 103 | 104 | **原理** 105 | 通过使用UsageStatsManager获取,此方法是Android5.0之后提供的新API,可以获取一个时间段内的应用统计信息,但是必须满足一下要求 106 | 107 | **使用前提** 108 | 1. 此方法只在android5.0以上有效 109 | 2. AndroidManifest中加入此权限 110 | ``` java 111 | 112 | ``` 113 | 3. 打开手机设置,点击安全-高级,在有权查看使用情况的应用中,为这个App打上勾 114 | 115 | ![enter image description here](https://raw.githubusercontent.com/wenmingvs/AndroidProcess/master/sample/3.PNG) 116 | 117 | 方法五:通过Android自带的无障碍功能 118 | ------ 119 | 120 | 非常感谢[@EffectiveMatrix](http://weibo.com/hatewx?refer_flag=1005050005_)大神带来的新的判断前后台的方法 121 | 122 | 此方法属于他原创,具体的博文参照这里http://effmx.com/articles/tong-guo-android-fu-zhu-gong-neng-accessibility-service-jian-ce-ren-yi-qian-tai-jie-mian/ 123 | 124 | 此方法无法直观的通过下拉通知视图来进行前后台的观察,请到LogCat中进行观察即可,以下是LogCat中打印的信息 125 | 126 | ![enter image description here](http://ww3.sinaimg.cn/large/691cc151gw1f0uiy60md3j20fs07omzj.jpg) 127 | 128 | **原理** 129 | Android 辅助功能(AccessibilityService) 为我们提供了一系列的事件回调,帮助我们指示一些用户界面的状态变化。 我们可以派生辅助功能类,进而对不同的 AccessibilityEvent 进行处理。 同样的,这个服务就可以用来判断当前的前台应用 130 | 131 | **优势** 132 | 1. AccessibilityService 有非常广泛的 ROM 覆盖,特别是非国产手机,从 Android API Level 8(Android 2.2) 到 Android Api Level 23(Android 6.0) 133 | 2. AccessibilityService 不再需要轮询的判断当前的应用是不是在前台,系统会在窗口状态发生变化的时候主动回调,耗时和资源消耗都极小 134 | 3. 不需要权限请求 135 | 4. 它是一个稳定的方法,与 “方法6”读取 /proc 目录不同,它并非利用 Android 一些设计上的漏洞,可以长期使用的可能很大 136 | 5. 可以用来判断任意应用甚至 Activity, PopupWindow, Dialog 对象是否处于前台 137 | 138 | **劣势** 139 | 1. 需要要用户开启辅助功能 140 | 2. 辅助功能会伴随应用被“强行停止”而剥夺 141 | 142 | 方法六:读取Linux系统内核保存在/proc目录下的process进程信息 143 | ---- 144 | ![enter image description here](http://ww3.sinaimg.cn/mw690/691cc151gw1f09z6bjz9rg20bc0h0b29.gif) 145 | 146 | 此方法并非我原创,原作者是国外的大神,[GitHub项目在这里](https://github.com/jaredrummler/AndroidProcesses),也一并加入到工程中,供大家做全面的参考选择 147 | 148 | **原理** 149 | 无意中看到乌云上有人提的一个漏洞,Linux系统内核会把process进程信息保存在/proc目录下,Shell命令去获取的他,再根据进程的属性判断是否为前台 150 | 151 | **优点** 152 | 1. 不需要任何权限 153 | 2. 可以判断任意一个应用是否在前台,而不局限在自身应用 154 | 155 | **缺点** 156 | 1. 当/proc下文件夹过多时,此方法是耗时操作 157 | 158 | **用法** 159 | 获取一系列正在运行的App的进程 160 | ``` java 161 | List processes = ProcessManager.getRunningAppProcesses(); 162 | ``` 163 | 164 | 获取任一正在运行的App进程的详细信息 165 | ``` java 166 | AndroidAppProcess process = processes.get(location); 167 | String processName = process.name; 168 | 169 | Stat stat = process.stat(); 170 | int pid = stat.getPid(); 171 | int parentProcessId = stat.ppid(); 172 | long startTime = stat.stime(); 173 | int policy = stat.policy(); 174 | char state = stat.state(); 175 | 176 | Statm statm = process.statm(); 177 | long totalSizeOfProcess = statm.getSize(); 178 | long residentSetSize = statm.getResidentSetSize(); 179 | 180 | PackageInfo packageInfo = process.getPackageInfo(context, 0); 181 | String appName = packageInfo.applicationInfo.loadLabel(pm).toString(); 182 | ``` 183 | 184 | 判断是否在前台 185 | ``` java 186 | if (ProcessManager.isMyProcessInTheForeground()) { 187 | // do stuff 188 | } 189 | ``` 190 | 191 | 获取一系列正在运行的App进程的详细信息 192 | ``` java 193 | List processes = ProcessManager.getRunningAppProcessInfo(ctx); 194 | ``` 195 | 196 | Gradle 构建 197 | ------ 198 | - 版本 199 | - 最新 Android SDK 200 | - 最新 Gradle 201 | - 环境变量 202 | - ANDROID_HOME 203 | - GRADLE_HOME,同时把bin放入path变量 204 | - Android SDK 安装,都更新到最新 205 | - Android SDK Build-tools更新到最新 206 | - Google Repository更新到最新 207 | - Android Support Repository更新到最新 208 | - Android Support Library更新到最新 209 | 210 | 211 | 相信未来 212 | ----- 213 | 当蜘蛛网无情地查封了我的炉台 214 | 当灰烬的余烟叹息着贫困的悲哀 215 | 我依然固执地铺平失望的灰烬 216 | 用美丽的雪花写下:相信未来 217 | 218 | 当我的紫葡萄化为深秋的露水 219 | 当我的鲜花依偎在别人的情怀 220 | 我依然固执地用凝霜的枯藤 221 | 在凄凉的大地上写下:相信未来 222 | 223 | 我要用手指那涌向天边的排浪 224 | 我要用手掌那托住太阳的大海 225 | 摇曳着曙光那枝温暖漂亮的笔杆 226 | 用孩子的笔体写下:相信未来 227 | 228 | 我之所以坚定地相信未来 229 | 是我相信未来人们的眼睛 230 | 她有拨开历史风尘的睫毛 231 | 她有看透岁月篇章的瞳孔 232 | 233 | 不管人们对于我们腐烂的皮肉 234 | 那些迷途的惆怅、失败的苦痛 235 | 是寄予感动的热泪、深切的同情 236 | 还是给以轻蔑的微笑、辛辣的嘲讽 237 | 238 | 我坚信人们对于我们的脊骨 239 | 那无数次的探索、迷途、失败和成功 240 | 一定会给予热情、客观、公正的评定 241 | 是的,我焦急地等待着他们的评定 242 | 243 | 朋友,坚定地相信未来吧 244 | 相信不屈不挠的努力 245 | 相信战胜死亡的年轻 246 | 相信未来、热爱生命 247 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /demo.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/demo.apk -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Tue Jan 19 14:09:59 CST 2016 16 | systemProp.http.proxyHost=127.0.0.1 17 | systemProp.http.proxyPort=1080 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Apr 02 20:51:50 CST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:23.1.1' 25 | } 26 | -------------------------------------------------------------------------------- /library/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 D:\Android\AndroidSDK\sdk/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 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/wenming/library/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.wenming.library; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 8 | 9 | 10 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/BackgroundUtil.java: -------------------------------------------------------------------------------- 1 | package com.wenming.library; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.ActivityManager; 5 | import android.app.AppOpsManager; 6 | import android.app.Service; 7 | import android.app.usage.UsageStats; 8 | import android.app.usage.UsageStatsManager; 9 | import android.content.ComponentName; 10 | import android.content.Context; 11 | import android.content.Intent; 12 | import android.content.pm.ApplicationInfo; 13 | import android.content.pm.PackageManager; 14 | import android.os.Build; 15 | import android.provider.Settings; 16 | import android.text.TextUtils; 17 | import android.util.Log; 18 | import android.widget.Toast; 19 | 20 | import com.wenming.library.processutil.ProcessManager; 21 | import com.wenming.library.processutil.models.AndroidAppProcess; 22 | 23 | import java.util.Collections; 24 | import java.util.Comparator; 25 | import java.util.List; 26 | 27 | /** 28 | * Created by wenmingvs on 2016/1/14. 29 | */ 30 | public class BackgroundUtil { 31 | public static final int BKGMETHOD_GETRUNNING_TASK = 0; 32 | public static final int BKGMETHOD_GETRUNNING_PROCESS = 1; 33 | public static final int BKGMETHOD_GETAPPLICATION_VALUE = 2; 34 | public static final int BKGMETHOD_GETUSAGESTATS = 3; 35 | public static final int BKGMETHOD_GETACCESSIBILITYSERVICE = 4; 36 | public static final int BKGMETHOD_GETLINUXPROCESS = 5; 37 | 38 | 39 | /** 40 | * 自动根据参数选择判断前后台的方法 41 | * 42 | * @param context 上下文参数 43 | * @param packageName 需要检查是否位于栈顶的App的包名 44 | * @return 45 | */ 46 | public static boolean isForeground(Context context, int methodID, String packageName) { 47 | switch (methodID) { 48 | case BKGMETHOD_GETRUNNING_TASK: 49 | return getRunningTask(context, packageName); 50 | case BKGMETHOD_GETRUNNING_PROCESS: 51 | return getRunningAppProcesses(context, packageName); 52 | case BKGMETHOD_GETAPPLICATION_VALUE: 53 | return getApplicationValue((MyApplication) ((Service) context).getApplication()); 54 | case BKGMETHOD_GETUSAGESTATS: 55 | return queryUsageStats(context, packageName); 56 | case BKGMETHOD_GETACCESSIBILITYSERVICE: 57 | return getFromAccessibilityService(context, packageName); 58 | case BKGMETHOD_GETLINUXPROCESS: 59 | return getLinuxCoreInfo(context, packageName); 60 | default: 61 | return false; 62 | } 63 | } 64 | 65 | /** 66 | * 方法1:通过getRunningTasks判断App是否位于前台,此方法在5.0以上失效 67 | * 68 | * @param context 上下文参数 69 | * @param packageName 需要检查是否位于栈顶的App的包名 70 | * @return 71 | */ 72 | public static boolean getRunningTask(Context context, String packageName) { 73 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 74 | ComponentName cn = am.getRunningTasks(1).get(0).topActivity; 75 | return !TextUtils.isEmpty(packageName) && packageName.equals(cn.getPackageName()); 76 | } 77 | 78 | 79 | /** 80 | * 方法2:通过getRunningAppProcesses的IMPORTANCE_FOREGROUND属性判断是否位于前台,当service需要常驻后台时候,此方法失效, 81 | * 在小米 Note上此方法无效,在Nexus上正常 82 | * 83 | * @param context 上下文参数 84 | * @param packageName 需要检查是否位于栈顶的App的包名 85 | * @return 86 | */ 87 | public static boolean getRunningAppProcesses(Context context, String packageName) { 88 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 89 | List appProcesses = activityManager.getRunningAppProcesses(); 90 | if (appProcesses == null) { 91 | return false; 92 | } 93 | for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { 94 | if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) { 95 | return true; 96 | } 97 | } 98 | return false; 99 | } 100 | 101 | /** 102 | * 方法3:通过ActivityLifecycleCallbacks来批量统计Activity的生命周期,来做判断,此方法在API 14以上均有效,但是需要在Application中注册此回调接口 103 | * 必须: 104 | * 1. 自定义Application并且注册ActivityLifecycleCallbacks接口 105 | * 2. AndroidManifest.xml中更改默认的Application为自定义 106 | * 3. 当Application因为内存不足而被Kill掉时,这个方法仍然能正常使用。虽然全局变量的值会因此丢失,但是再次进入App时候会重新统计一次的 107 | * @param myApplication 108 | * @return 109 | */ 110 | 111 | public static boolean getApplicationValue(MyApplication myApplication) { 112 | return myApplication.getAppCount() > 0; 113 | } 114 | 115 | /** 116 | * 方法4:通过使用UsageStatsManager获取,此方法是ndroid5.0A之后提供的API 117 | * 必须: 118 | * 1. 此方法只在android5.0以上有效 119 | * 2. AndroidManifest中加入此权限 121 | * 3. 打开手机设置,点击安全-高级,在有权查看使用情况的应用中,为这个App打上勾 122 | * 123 | * @param context 上下文参数 124 | * @param packageName 需要检查是否位于栈顶的App的包名 125 | * @return 126 | */ 127 | 128 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 129 | public static boolean queryUsageStats(Context context, String packageName) { 130 | class RecentUseComparator implements Comparator { 131 | @Override 132 | public int compare(UsageStats lhs, UsageStats rhs) { 133 | return (lhs.getLastTimeUsed() > rhs.getLastTimeUsed()) ? -1 : (lhs.getLastTimeUsed() == rhs.getLastTimeUsed()) ? 0 : 1; 134 | } 135 | } 136 | RecentUseComparator mRecentComp = new RecentUseComparator(); 137 | long ts = System.currentTimeMillis(); 138 | UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService("usagestats"); 139 | List usageStats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, ts - 1000 * 10, ts); 140 | if (usageStats == null || usageStats.size() == 0) { 141 | if (HavaPermissionForTest(context) == false) { 142 | Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); 143 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 144 | context.startActivity(intent); 145 | Toast.makeText(context, "权限不够\n请打开手机设置,点击安全-高级,在有权查看使用情况的应用中,为这个App打上勾", Toast.LENGTH_SHORT).show(); 146 | } 147 | return false; 148 | } 149 | Collections.sort(usageStats, mRecentComp); 150 | String currentTopPackage = usageStats.get(0).getPackageName(); 151 | if (currentTopPackage.equals(packageName)) { 152 | return true; 153 | } else { 154 | return false; 155 | } 156 | } 157 | 158 | /** 159 | * 判断是否有用权限 160 | * 161 | * @param context 上下文参数 162 | */ 163 | @TargetApi(Build.VERSION_CODES.KITKAT) 164 | private static boolean HavaPermissionForTest(Context context) { 165 | try { 166 | PackageManager packageManager = context.getPackageManager(); 167 | ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); 168 | AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 169 | int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName); 170 | return (mode == AppOpsManager.MODE_ALLOWED); 171 | } catch (PackageManager.NameNotFoundException e) { 172 | return true; 173 | } 174 | } 175 | 176 | /** 177 | * 方法5:通过Android自带的无障碍功能,监控窗口焦点的变化,进而拿到当前焦点窗口对应的包名 178 | * 必须: 179 | * 1. 创建ACCESSIBILITY SERVICE INFO 属性文件 180 | * 2. 注册 DETECTION SERVICE 到 ANDROIDMANIFEST.XML 181 | * 182 | * @param context 183 | * @param packageName 184 | * @return 185 | */ 186 | public static boolean getFromAccessibilityService(Context context, String packageName) { 187 | if (DetectService.isAccessibilitySettingsOn(context) == true) { 188 | DetectService detectService = DetectService.getInstance(); 189 | String foreground = detectService.getForegroundPackage(); 190 | Log.d("wenming", "**方法五** 当前窗口焦点对应的包名为: =" + foreground); 191 | return packageName.equals(foreground); 192 | } else { 193 | Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); 194 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 195 | context.startActivity(intent); 196 | Toast.makeText(context, R.string.accessbiliityNo, Toast.LENGTH_SHORT).show(); 197 | return false; 198 | } 199 | } 200 | 201 | /** 202 | * 方法6:无意中看到乌云上有人提的一个漏洞,Linux系统内核会把process进程信息保存在/proc目录下,使用Shell命令去获取的他,再根据进程的属性判断是否为前台 203 | * 204 | * @param packageName 需要检查是否位于栈顶的App的包名 205 | */ 206 | public static boolean getLinuxCoreInfo(Context context, String packageName) { 207 | 208 | List processes = ProcessManager.getRunningForegroundApps(context); 209 | for (AndroidAppProcess appProcess : processes) { 210 | if (appProcess.getPackageName().equals(packageName) && appProcess.foreground) { 211 | return true; 212 | } 213 | } 214 | return false; 215 | 216 | } 217 | 218 | 219 | } 220 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/DetectService.java: -------------------------------------------------------------------------------- 1 | package com.wenming.library; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.content.Context; 5 | import android.provider.Settings; 6 | import android.util.Log; 7 | import android.view.accessibility.AccessibilityEvent; 8 | 9 | /** 10 | * Created by wenmingvs on 16/2/10. 11 | */ 12 | public class DetectService extends AccessibilityService { 13 | 14 | private static String mForegroundPackageName; 15 | private static DetectService mInstance = null; 16 | 17 | public DetectService() { 18 | } 19 | 20 | public static DetectService getInstance() { 21 | if (mInstance == null) { 22 | synchronized (DetectService.class) { 23 | if (mInstance == null) { 24 | mInstance = new DetectService(); 25 | } 26 | } 27 | } 28 | return mInstance; 29 | } 30 | 31 | /** 32 | * 监听窗口焦点,并且获取焦点窗口的包名 33 | * 34 | * @param event 35 | */ 36 | @Override 37 | public void onAccessibilityEvent(AccessibilityEvent event) { 38 | if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { 39 | mForegroundPackageName = event.getPackageName().toString(); 40 | } 41 | } 42 | 43 | @Override 44 | public void onInterrupt() { 45 | } 46 | 47 | public String getForegroundPackage() { 48 | return mForegroundPackageName; 49 | } 50 | 51 | 52 | /** 53 | * 此方法用来判断当前应用的辅助功能服务是否开启 54 | * 55 | * @param context 56 | * @return 57 | */ 58 | public static boolean isAccessibilitySettingsOn(Context context) { 59 | int accessibilityEnabled = 0; 60 | try { 61 | accessibilityEnabled = Settings.Secure.getInt(context.getContentResolver(), 62 | android.provider.Settings.Secure.ACCESSIBILITY_ENABLED); 63 | } catch (Settings.SettingNotFoundException e) { 64 | Log.d("wenming", e.getMessage()); 65 | } 66 | 67 | if (accessibilityEnabled == 1) { 68 | String services = Settings.Secure.getString(context.getContentResolver(), 69 | Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); 70 | if (services != null) { 71 | return services.toLowerCase().contains(context.getPackageName().toLowerCase()); 72 | } 73 | } 74 | return false; 75 | } 76 | } -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.wenming.library; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | 7 | /** 8 | * Created by wenmingvs on 2016/1/13. 9 | */ 10 | public class MyApplication extends Application { 11 | private int appCount = 0; 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { 17 | @Override 18 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 19 | } 20 | 21 | @Override 22 | public void onActivityStarted(Activity activity) { 23 | appCount++; 24 | } 25 | 26 | @Override 27 | public void onActivityResumed(Activity activity) { 28 | } 29 | 30 | @Override 31 | public void onActivityPaused(Activity activity) { 32 | } 33 | 34 | @Override 35 | public void onActivityStopped(Activity activity) { 36 | appCount--; 37 | } 38 | 39 | @Override 40 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 41 | 42 | } 43 | 44 | @Override 45 | public void onActivityDestroyed(Activity activity) { 46 | 47 | } 48 | }); 49 | } 50 | 51 | public int getAppCount() { 52 | return appCount; 53 | } 54 | 55 | public void setAppCount(int appCount) { 56 | this.appCount = appCount; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/ProcessManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil; 19 | 20 | import android.app.ActivityManager; 21 | import android.app.ActivityManager.RunningAppProcessInfo; 22 | import android.content.Context; 23 | import android.content.pm.PackageManager; 24 | import android.os.Build; 25 | import android.util.Log; 26 | 27 | import com.wenming.library.processutil.models.AndroidAppProcess; 28 | import com.wenming.library.processutil.models.AndroidProcess; 29 | 30 | import java.io.File; 31 | import java.io.IOException; 32 | import java.util.ArrayList; 33 | import java.util.Comparator; 34 | import java.util.List; 35 | 36 | /** 37 | * Helper class to get a list of processes on Android. 38 | *

39 | *

Note: Every method in this class should not be executed on the main thread.

40 | */ 41 | public class ProcessManager { 42 | 43 | public static final String TAG = "AndroidProcesses"; 44 | 45 | private static boolean loggingEnabled; 46 | 47 | /** 48 | * Toggle whether debug logging is enabled. 49 | * 50 | * @param enabled {@code true} to enable logging. This should be only be used for debugging purposes. 51 | * @see #isLoggingEnabled() 52 | * @see #log(String, Object...) 53 | * @see #log(Throwable, String, Object...) 54 | */ 55 | public static void setLoggingEnabled(boolean enabled) { 56 | loggingEnabled = enabled; 57 | } 58 | 59 | /** 60 | * @return {@code true} if logging is enabled. 61 | * @see #setLoggingEnabled(boolean) 62 | */ 63 | public static boolean isLoggingEnabled() { 64 | return loggingEnabled; 65 | } 66 | 67 | /** 68 | * Send a log message if logging is enabled. 69 | * 70 | * @param message the message to log 71 | * @param args list of arguments to pass to the formatter 72 | */ 73 | public static void log(String message, Object... args) { 74 | if (loggingEnabled) { 75 | Log.d(TAG, args.length == 0 ? message : String.format(message, args)); 76 | } 77 | } 78 | 79 | /** 80 | * Send a log message if logging is enabled. 81 | * 82 | * @param error An exception to log 83 | * @param message the message to log 84 | * @param args list of arguments to pass to the formatter 85 | */ 86 | public static void log(Throwable error, String message, Object... args) { 87 | if (loggingEnabled) { 88 | Log.d(TAG, args.length == 0 ? message : String.format(message, args), error); 89 | } 90 | } 91 | 92 | /** 93 | * @return a list of all processes running on the device. 94 | */ 95 | public static List getRunningProcesses() { 96 | List processes = new ArrayList<>(); 97 | File[] files = new File("/proc").listFiles(); 98 | for (File file : files) { 99 | if (file.isDirectory()) { 100 | int pid; 101 | try { 102 | pid = Integer.parseInt(file.getName()); 103 | } catch (NumberFormatException e) { 104 | continue; 105 | } 106 | try { 107 | processes.add(new AndroidProcess(pid)); 108 | } catch (IOException e) { 109 | log(e, "Error reading from /proc/%d.", pid); 110 | // System apps will not be readable on Android 5.0+ if SELinux is enforcing. 111 | // You will need root access or an elevated SELinux context to read all files under /proc. 112 | } 113 | } 114 | } 115 | return processes; 116 | } 117 | 118 | /** 119 | * @return a list of all running app processes on the device. 120 | */ 121 | public static List getRunningAppProcesses() { 122 | List processes = new ArrayList<>(); 123 | File[] files = new File("/proc").listFiles(); 124 | for (File file : files) { 125 | if (file.isDirectory()) { 126 | int pid; 127 | try { 128 | pid = Integer.parseInt(file.getName()); 129 | } catch (NumberFormatException e) { 130 | continue; 131 | } 132 | try { 133 | processes.add(new AndroidAppProcess(pid)); 134 | } catch (AndroidAppProcess.NotAndroidAppProcessException ignored) { 135 | } catch (IOException e) { 136 | log(e, "Error reading from /proc/%d.", pid); 137 | // System apps will not be readable on Android 5.0+ if SELinux is enforcing. 138 | // You will need root access or an elevated SELinux context to read all files under /proc. 139 | } 140 | } 141 | } 142 | return processes; 143 | } 144 | 145 | /** 146 | * Get a list of user apps running in the foreground. 147 | * 148 | * @param ctx the application context 149 | * @return a list of user apps that are in the foreground. 150 | */ 151 | public static List getRunningForegroundApps(Context ctx) { 152 | List processes = new ArrayList<>(); 153 | File[] files = new File("/proc").listFiles(); 154 | PackageManager pm = ctx.getPackageManager(); 155 | for (File file : files) { 156 | if (file.isDirectory()) { 157 | int pid; 158 | try { 159 | pid = Integer.parseInt(file.getName()); 160 | } catch (NumberFormatException e) { 161 | continue; 162 | } 163 | try { 164 | AndroidAppProcess process = new AndroidAppProcess(pid); 165 | if (process.foreground 166 | // ignore system processes. First app user starts at 10000. 167 | && (process.uid < 1000 || process.uid > 9999) 168 | // ignore processes that are not running in the default app process. 169 | && !process.name.contains(":") 170 | // Ignore processes that the user cannot launch. 171 | && pm.getLaunchIntentForPackage(process.getPackageName()) != null) { 172 | processes.add(process); 173 | } 174 | } catch (AndroidAppProcess.NotAndroidAppProcessException ignored) { 175 | } catch (IOException e) { 176 | log(e, "Error reading from /proc/%d.", pid); 177 | // System apps will not be readable on Android 5.0+ if SELinux is enforcing. 178 | // You will need root access or an elevated SELinux context to read all files under /proc. 179 | } 180 | } 181 | } 182 | return processes; 183 | } 184 | 185 | /** 186 | * @return {@code true} if this process is in the foreground. 187 | */ 188 | public static boolean isMyProcessInTheForeground() { 189 | List processes = getRunningAppProcesses(); 190 | int myPid = android.os.Process.myPid(); 191 | for (AndroidAppProcess process : processes) { 192 | if (process.pid == myPid && process.foreground) { 193 | return true; 194 | } 195 | } 196 | return false; 197 | } 198 | 199 | /** 200 | * Returns a list of application processes that are running on the device. 201 | *

202 | *

NOTE: On Lollipop (SDK 22) this does not provide 203 | * {@link RunningAppProcessInfo#pkgList}, 204 | * {@link RunningAppProcessInfo#importance}, 205 | * {@link RunningAppProcessInfo#lru}, 206 | * {@link RunningAppProcessInfo#importanceReasonCode}, 207 | * {@link RunningAppProcessInfo#importanceReasonComponent}, 208 | * {@link RunningAppProcessInfo#importanceReasonPid}, 209 | * etc. If you need more process information try using 210 | * {@link #getRunningAppProcesses()} or {@link android.app.usage.UsageStatsManager}

211 | * 212 | * @param ctx the application context 213 | * @return a list of RunningAppProcessInfo records, or null if there are no 214 | * running processes (it will not return an empty list). This list ordering is not 215 | * specified. 216 | */ 217 | public static List getRunningAppProcessInfo(Context ctx) { 218 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { 219 | List runningAppProcesses = ProcessManager.getRunningAppProcesses(); 220 | List appProcessInfos = new ArrayList<>(); 221 | for (AndroidAppProcess process : runningAppProcesses) { 222 | RunningAppProcessInfo info = new RunningAppProcessInfo(process.name, process.pid, null); 223 | info.uid = process.uid; 224 | // TODO: Get more information about the process. pkgList, importance, lru, etc. 225 | appProcessInfos.add(info); 226 | } 227 | return appProcessInfos; 228 | } 229 | ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); 230 | return am.getRunningAppProcesses(); 231 | } 232 | 233 | private ProcessManager() { 234 | throw new AssertionError("no instances"); 235 | } 236 | 237 | /** 238 | * Comparator to list processes by name 239 | */ 240 | public static final class ProcessComparator implements Comparator { 241 | 242 | @Override 243 | public int compare(AndroidProcess p1, AndroidProcess p2) { 244 | return p1.name.compareToIgnoreCase(p2.name); 245 | } 246 | 247 | } 248 | 249 | } 250 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/AndroidAppProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.content.Context; 21 | import android.content.pm.PackageInfo; 22 | import android.content.pm.PackageManager; 23 | import android.os.Build; 24 | import android.os.Parcel; 25 | 26 | import com.wenming.library.processutil.ProcessManager; 27 | 28 | import java.io.File; 29 | import java.io.IOException; 30 | 31 | public class AndroidAppProcess extends AndroidProcess { 32 | 33 | private static final boolean SYS_SUPPORTS_SCHEDGROUPS = new File("/dev/cpuctl/tasks").exists(); 34 | 35 | /** 36 | * {@code true} if the process is in the foreground 37 | */ 38 | public final boolean foreground; 39 | 40 | /** 41 | * The user id of this process. 42 | */ 43 | public final int uid; 44 | 45 | public AndroidAppProcess(int pid) throws IOException, NotAndroidAppProcessException { 46 | super(pid); 47 | final boolean foreground; 48 | int uid; 49 | 50 | if (SYS_SUPPORTS_SCHEDGROUPS) { 51 | Cgroup cgroup = cgroup(); 52 | ControlGroup cpuacct = cgroup.getGroup("cpuacct"); 53 | ControlGroup cpu = cgroup.getGroup("cpu"); 54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 55 | if (cpu == null || cpuacct == null || !cpuacct.group.contains("pid_")) { 56 | throw new NotAndroidAppProcessException(pid); 57 | } 58 | foreground = !cpu.group.contains("bg_non_interactive"); 59 | try { 60 | uid = Integer.parseInt(cpuacct.group.split("/")[1].replace("uid_", "")); 61 | } catch (Exception e) { 62 | uid = status().getUid(); 63 | } 64 | ProcessManager.log("name=%s, pid=%d, uid=%d, foreground=%b, cpuacct=%s, cpu=%s", 65 | name, pid, uid, foreground, cpuacct.toString(), cpu.toString()); 66 | } else { 67 | if (cpu == null || cpuacct == null || !cpu.group.contains("apps")) { 68 | throw new NotAndroidAppProcessException(pid); 69 | } 70 | foreground = !cpu.group.contains("bg_non_interactive"); 71 | try { 72 | uid = Integer.parseInt(cpuacct.group.substring(cpuacct.group.lastIndexOf("/") + 1)); 73 | } catch (Exception e) { 74 | uid = status().getUid(); 75 | } 76 | ProcessManager.log("name=%s, pid=%d, uid=%d foreground=%b, cpuacct=%s, cpu=%s", 77 | name, pid, uid, foreground, cpuacct.toString(), cpu.toString()); 78 | } 79 | } else { 80 | // this is a really ugly way to check if the process is an application. 81 | // we could possibly check the UID name (starts with "app_" or "u_a") 82 | if (name.startsWith("/") || !new File("/data/data", getPackageName()).exists()) { 83 | throw new NotAndroidAppProcessException(pid); 84 | } 85 | Stat stat = stat(); 86 | Status status = status(); 87 | // https://github.com/android/platform_system_core/blob/jb-mr1-release/libcutils/sched_policy.c#L245-256 88 | foreground = stat.policy() == 0; // SCHED_NORMAL 89 | uid = status.getUid(); 90 | ProcessManager.log("name=%s, pid=%d, uid=%d foreground=%b", name, pid, uid, foreground); 91 | } 92 | 93 | this.foreground = foreground; 94 | this.uid = uid; 95 | } 96 | 97 | /** 98 | * @return the app's package name 99 | * @see #name 100 | */ 101 | public String getPackageName() { 102 | return name.split(":")[0]; 103 | } 104 | 105 | /** 106 | * Retrieve overall information about the application package. 107 | *

108 | *

Throws {@link PackageManager.NameNotFoundException} if a package with the given name can 109 | * not be found on the system.

110 | * 111 | * @param context the application context 112 | * @param flags Additional option flags. Use any combination of 113 | * {@link PackageManager#GET_ACTIVITIES}, {@link PackageManager#GET_GIDS}, 114 | * {@link PackageManager#GET_CONFIGURATIONS}, {@link PackageManager#GET_INSTRUMENTATION}, 115 | * {@link PackageManager#GET_PERMISSIONS}, {@link PackageManager#GET_PROVIDERS}, 116 | * {@link PackageManager#GET_RECEIVERS}, {@link PackageManager#GET_SERVICES}, 117 | * {@link PackageManager#GET_SIGNATURES}, {@link PackageManager#GET_UNINSTALLED_PACKAGES} 118 | * to modify the data returned. 119 | * @return a PackageInfo object containing information about the package. 120 | */ 121 | public PackageInfo getPackageInfo(Context context, int flags) 122 | throws PackageManager.NameNotFoundException { 123 | return context.getPackageManager().getPackageInfo(getPackageName(), flags); 124 | } 125 | 126 | @Override 127 | public void writeToParcel(Parcel dest, int flags) { 128 | super.writeToParcel(dest, flags); 129 | dest.writeByte((byte) (foreground ? 0x01 : 0x00)); 130 | dest.writeInt(uid); 131 | } 132 | 133 | protected AndroidAppProcess(Parcel in) { 134 | super(in); 135 | foreground = in.readByte() != 0x00; 136 | uid = in.readInt(); 137 | } 138 | 139 | public static final Creator CREATOR = new Creator() { 140 | 141 | @Override 142 | public AndroidAppProcess createFromParcel(Parcel source) { 143 | return new AndroidAppProcess(source); 144 | } 145 | 146 | @Override 147 | public AndroidAppProcess[] newArray(int size) { 148 | return new AndroidAppProcess[size]; 149 | } 150 | }; 151 | 152 | public static final class NotAndroidAppProcessException extends Exception { 153 | 154 | public NotAndroidAppProcessException(int pid) { 155 | super(String.format("The process %d does not belong to any application", pid)); 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/AndroidProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | import android.os.Parcelable; 22 | import android.text.TextUtils; 23 | 24 | import java.io.IOException; 25 | 26 | public class AndroidProcess implements Parcelable { 27 | 28 | /** 29 | * Get the name of a running process. 30 | * 31 | * @param pid 32 | * the process id. 33 | * @return the name of the process. 34 | * @throws IOException 35 | * if the file does not exist or we don't have read permissions. 36 | */ 37 | static String getProcessName(int pid) throws IOException { 38 | String cmdline = null; 39 | try { 40 | cmdline = ProcFile.readFile(String.format("/proc/%d/cmdline", pid)).trim(); 41 | } catch (IOException ignored) { 42 | } 43 | if (TextUtils.isEmpty(cmdline)) { 44 | return Stat.get(pid).getComm(); 45 | } 46 | return cmdline; 47 | } 48 | 49 | /** the process name */ 50 | public final String name; 51 | 52 | /** the process id */ 53 | public final int pid; 54 | 55 | /** 56 | * AndroidProcess constructor 57 | * 58 | * @param pid 59 | * the process id 60 | * @throws IOException 61 | * if /proc/[pid] does not exist or we don't have read access. 62 | */ 63 | public AndroidProcess(int pid) throws IOException { 64 | this.pid = pid; 65 | this.name = getProcessName(pid); 66 | } 67 | 68 | /** 69 | * Read the contents of a file in /proc/[pid]/[filename]. 70 | * 71 | * @param filename 72 | * the relative path to the file. 73 | * @return the contents of the file. 74 | * @throws IOException 75 | * if the file does not exist or we don't have read permissions. 76 | */ 77 | public String read(String filename) throws IOException { 78 | return ProcFile.readFile(String.format("/proc/%d/%s", pid, filename)); 79 | } 80 | 81 | /** 82 | *

/proc/[pid]/attr/current (since Linux 2.6.0)

83 | * 84 | *

The contents of this file represent the current security attributes of the process.

85 | * 86 | *

In SELinux, this file is used to get the security context of a process. Prior to Linux 87 | * 2.6.11, this file could not be used to set the security context (a write was always denied), 88 | * since SELinux limited process security transitions to execve(2) (see the description of 89 | * /proc/[pid]/attr/exec, below). ince Linux 2.6.11, SELinux lifted this restriction and began 90 | * supporting "set" operations via writes to this node if authorized by policy, although use of 91 | * this operation is only suitable for applications that are trusted to maintain any desired 92 | * separation between the old and new security contexts. Prior to Linux 2.6.28, SELinux did not 93 | * allow threads within a multi- threaded process to set their security context via this node as 94 | * it would yield an inconsistency among the security contexts of the threads sharing the same 95 | * memory space. Since Linux 2.6.28, SELinux lifted this restriction and began supporting "set" 96 | * operations for threads within a multithreaded process if the new security context is bounded 97 | * by the old security context, where the bounded relation is defined in policy and guarantees 98 | * that the new security context has a subset of the permissions of the old security context. 99 | * Other security modules may choose to support "set" operations via writes to this node.

100 | * 101 | * @return the contents of /proc/[pid]/attr/current 102 | * @throws IOException 103 | * if the file does not exist or we don't have read permissions. 104 | */ 105 | public String attr_current() throws IOException { 106 | return read("attr/current"); 107 | } 108 | 109 | /** 110 | *

/proc/[pid]/cmdline

111 | * 112 | *

This read-only file holds the complete command line for the process, unless the process is 113 | * a zombie. In the latter case, there is nothing in this file: that is, a read on this file will 114 | * return 0 characters. The command-line arguments appear in this file as a set of strings 115 | * separated by null bytes ('\0'), with a further null byte after the last string.

116 | * 117 | * @return the name of the process. (note: process name may be empty. In case it is empty get 118 | * the process name from /proc/[pid]/stat). 119 | * @throws IOException 120 | * if the file does not exist or we don't have read permissions. 121 | * @see #name 122 | */ 123 | public String cmdline() throws IOException { 124 | return read("cmdline"); 125 | } 126 | 127 | /** 128 | *

/proc/[pid]/cgroup (since Linux 2.6.24)

129 | * 130 | *

This file describes control groups to which the process/task belongs. For each cgroup 131 | * hierarchy there is one entry containing colon-separated fields of the form:

132 | * 133 | *

5:cpuacct,cpu,cpuset:/daemons

134 | * 135 | *

The colon-separated fields are, from left to right:

136 | * 137 | *
    138 | *
  1. hierarchy ID number
  2. 139 | *
  3. set of subsystems bound to the hierarchy
  4. 140 | *
  5. control group in the hierarchy to which the process belongs
  6. 141 | *
142 | * 143 | *

This file is present only if the CONFIG_CGROUPS kernel configuration option is enabled.

144 | * 145 | * @return the {@link Cgroup} for this process 146 | * @throws IOException 147 | */ 148 | public Cgroup cgroup() throws IOException { 149 | return Cgroup.get(pid); 150 | } 151 | 152 | /** 153 | *

/proc/[pid]/oom_score (since Linux 2.6.11)

154 | * 155 | *

This file displays the current score that the kernel gives to this process for the 156 | * purpose of selecting a process for the OOM-killer. A higher score means that the 157 | * process is more likely to be selected by the OOM-killer.

158 | * 159 | *

The basis for this score is the amount of memory used by the process, with 160 | * increases (+) or decreases (-) for factors including:

161 | * 162 | *
    163 | *
  • whether the process creates a lot of children using fork(2)(+);
  • 164 | *
  • whether the process has been running a long time, or has used a lot of CPU time (-);
  • 165 | *
  • whether the process has a low nice value (i.e., > 0) (+);
  • 166 | *
  • whether the process is privileged (-); and
  • 167 | *
  • whether the process is making direct hardware access (-).
  • 168 | *
169 | * 170 | *

The oom_score also reflects the adjustment specified by the oom_score_adj 171 | * or oom_adj setting for the process.

172 | * 173 | * @return the oom_score value for this process 174 | * @throws IOException 175 | * if the file does not exist or we don't have read permissions. 176 | */ 177 | public int oom_score() throws IOException { 178 | return Integer.parseInt(read("oom_score")); 179 | } 180 | 181 | /** 182 | *

/proc/[pid]/oom_adj (since Linux 2.6.11)

183 | * 184 | *

This file can be used to adjust the score used to select which process should be killed in 185 | * an out-of-memory (OOM) situation. The kernel uses this value for a bit-shift operation of the 186 | * process's oom_score value: valid values are in the* range -16 to +15, plus the special value 187 | * -17, which disables OOM-killing altogether for this process. A positive score increases the 188 | * likelihood of this process being killed by the OOM-killer; a negative score decreases the 189 | * likelihood.

190 | * 191 | *

The default value for this file is 0; a new process inherits its parent's oom_adj setting. 192 | * A process must be privileged (CAP_SYS_RESOURCE) to update this file.

193 | * 194 | *

Since Linux 2.6.36, use of this file is deprecated in favor of 195 | * /proc/[pid]/oom_score_adj.

196 | * 197 | * @return the oom_adj value for this process 198 | * @throws IOException 199 | * if the file does not exist or we don't have read permissions. 200 | */ 201 | public int oom_adj() throws IOException { 202 | return Integer.parseInt(read("oom_adj")); 203 | } 204 | 205 | /** 206 | *

/proc/[pid]/oom_score_adj (since Linux 2.6.36)

207 | * 208 | *

This file can be used to adjust the badness heuristic used to select which process gets 209 | * killed in out-of-memory conditions.

210 | * 211 | *

The badness heuristic assigns a value to each candidate task ranging from 0 (never kill) to 212 | * 1000 (always kill) to determine which process is targeted. The units are roughly a proportion 213 | * along that range of allowed memory the process may allocate from, based on an estimation of 214 | * its current memory and swap use. For example, if a task is using all allowed memory, its 215 | * badness score will be 1000. If it is using half of its allowed memory, its score will be 216 | * 500.

217 | * 218 | *

There is an additional factor included in the badness score: root processes are given 3% 219 | * extra memory over other tasks.

220 | * 221 | *

The amount of "allowed" memory depends on the context in which the OOM-killer was called. 222 | * If it is due to the memory assigned to the allocating task's cpuset being exhausted, the 223 | * allowed memory represents the set of mems assigned to that cpuset (see cpuset(7)). If it is 224 | * due to a mempolicy's node(s) being exhausted, the allowed memory represents the set of 225 | * mempolicy nodes. If it is due to a memory limit (or swap limit) being reached, the allowed 226 | * memory is that configured limit. Finally, if it is due to the entire system being out of 227 | * memory, the allowed memory represents all allocatable resources.

228 | * 229 | *

The value of oom_score_adj is added to the badness score before it is used to determine 230 | * which task to kill. Acceptable values range from -1000 (OOM_SCORE_ADJ_MIN) to +1000 231 | * (OOM_SCORE_ADJ_MAX). This allows user space to control the preference for OOM-killing, ranging 232 | * from always preferring a certain task or completely disabling it from OOM killing. The lowest 233 | * possible value, -1000, is equivalent to disabling OOM- killing entirely for that task, since 234 | * it will always report a badness score of 0.

235 | * 236 | *

Consequently, it is very simple for user space to define the amount of memory to consider 237 | * for each task. Setting a oom_score_adj value of +500, for example, is roughly equivalent to 238 | * allowing the remainder of tasks sharing the same system, cpuset, mempolicy, or memory 239 | * controller resources to use at least 50% more memory. A value of -500, on the other hand, 240 | * would be roughly equivalent to discounting 50% of the task's allowed memory from being 241 | * considered as scoring against the task.

242 | * 243 | *

For backward compatibility with previous kernels, /proc/[pid]/oom_adj can still be used to 244 | * tune the badness score. Its value is scaled linearly with oom_score_adj.

245 | * 246 | *

Writing to /proc/[pid]/oom_score_adj or /proc/[pid]/oom_adj will change the other with its 247 | * scaled value.

248 | * 249 | * @return the oom_score_adj value for this process 250 | * @throws IOException 251 | * if the file does not exist or we don't have read permissions. 252 | */ 253 | public int oom_score_adj() throws IOException { 254 | return Integer.parseInt(read("oom_score_adj")); 255 | } 256 | 257 | /** 258 | *

/proc/[pid]/stat

259 | * 260 | *

Status information about the process. This is used by ps(1). It is defined in the kernel 261 | * source file fs/proc/array.c.

262 | * 263 | *

The fields, in order, with their proper scanf(3) format specifiers, are:

264 | * 265 | *
    266 | * 267 | *
  1. pid %d The process ID.
  2. 268 | * 269 | *
  3. comm %s The filename of the executable, in parentheses. This is visible whether or not 270 | * the executable is swapped out.
  4. 271 | * 272 | *
  5. state %c One of the following characters, indicating process state: 273 | *
      274 | *
    • R Running
    • 275 | *
    • S Sleeping in an interruptible wait
    • 276 | *
    • D Waiting in uninterruptible disk sleep
    • 277 | *
    • Z Zombie
    • 278 | *
    • T Stopped (on a signal) or (before Linux 2.6.33) trace stopped
    • 279 | *
    • t Tracing stop (Linux 2.6.33 onward)
    • 280 | *
    • W Paging (only before Linux 2.6.0)
    • 281 | *
    • X Dead (from Linux 2.6.0 onward)
    • 282 | *
    • x Dead (Linux 2.6.33 to 3.13 only)
    • 283 | *
    • K Wakekill (Linux 2.6.33 to 3.13 only)
    • 284 | *
    • W Waking (Linux 2.6.33 to 3.13 only)
    • 285 | *
    • P Parked (Linux 3.9 to 3.13 only)
    • 286 | *
    287 | *
  6. 288 | * 289 | *
  7. ppid %d The PID of the parent of this process.
  8. 290 | * 291 | *
  9. pgrp %d The process group ID of the process.
  10. 292 | * 293 | *
  11. session %d The session ID of the process.
  12. 294 | * 295 | *
  13. tty_nr %d The controlling terminal of the process. (The minor device number is contained 296 | * in the combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8.) 297 | *
  14. 298 | * 299 | *
  15. tpgid %d The ID of the foreground process group of the controlling terminal of the 300 | * process.
  16. 301 | * 302 | *
  17. flags %u The kernel flags word of the process. For bit meanings, see the PF_* defines in 303 | * the Linux kernel source file include/linux/sched.h. Details depend on the kernel version. 304 | * The format for this field was %lu before Linux 2.6.
  18. 305 | * 306 | *
  19. minflt %lu The number of minor faults the process has made which have not required 307 | * loading a memory page from disk.
  20. 308 | * 309 | *
  21. cminflt %lu The number of minor faults that the process's waited-for children have 310 | * made
  22. 311 | * 312 | *
  23. majflt %lu The number of major faults the process has made which have required loading a 313 | * memory page from disk.
  24. 314 | * 315 | *
  25. cmajflt %lu The number of major faults that the process's waited-for children have 316 | * made
  26. 317 | * 318 | *
  27. utime %lu Amount of time that this process has been scheduled in user mode, measured in 319 | * clock ticks (divide by sysconf(_SC_CLK_TCK)). This includes guest time, guest_time (time 320 | * spent running a virtual CPU, see below), so that applications that are not aware of the guest 321 | * time field do not lose that time from their calculations.
  28. 322 | * 323 | *
  29. stime %lu Amount of time that this process has been scheduled in kernel mode, measured 324 | * in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  30. 325 | * 326 | *
  31. cutime %ld Amount of time that this process's waited-for children have been scheduled in 327 | * user mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). (See also times(2).) 328 | * This includes guest time, cguest_time (time spent running a virtual CPU, see below).
  32. 329 | * 330 | *
  33. cstime %ld Amount of time that this process's waited-for children have been scheduled in 331 | * kernel mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  34. 332 | * 333 | *
  35. priority %ld (Explanation for Linux 2.6) For processes running a real-time scheduling 334 | * policy (policy below; see sched_setscheduler(2)), this is the negated scheduling priority, 335 | * minus one; that is, a number in the range -2 to -100, corresponding to real-time priorities 1 336 | * to 99. For processes running under a non-real-time scheduling policy, this is the raw nice 337 | * value (setpriority(2)) as represented in the kernel. The kernel stores nice values as numbers 338 | * in the range 0 (high) to 39 (low), corresponding to the user-visible nice range of -20 to 19. 339 | * Before Linux 2.6, this was a scaled value based on the scheduler weighting given to this 340 | * process
  36. 341 | * 342 | *
  37. nice %ld The nice value (see setpriority(2)), a value in the range 19 (low priority) to 343 | * -20 (high priority).
  38. 344 | * 345 | *
  39. num_threads %ld Number of threads in this process (since Linux 2.6). Before kernel 2.6, 346 | * this field was hard coded to 0 as a placeholder for an earlier removed field.
  40. 347 | * 348 | *
  41. itrealvalue %ld The time in jiffies before the next SIGALRM is sent to the process due 349 | * to an interval timer. Since kernel 2.6.17, this field is no longer maintained, and is hard 350 | * coded as 0.
  42. 351 | * 352 | *
  43. starttime %llu The time the process started after system boot. In kernels before Linux 353 | * 2.6, this value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock 354 | * ticks (divide by sysconf(_SC_CLK_TCK)).
  44. 355 | * 356 | *
  45. The format for this field was %lu before Linux 2.6. (23) vsize %lu Virtual memory size 357 | * in bytes.
  46. 358 | * 359 | *
  47. rss %ld Resident Set Size: number of pages the process has in real memory. This is just 360 | * the pages which count toward text, data, or stack space. This does not include pages which 361 | * have not been demand-loaded in, or which are swapped out.
  48. 362 | * 363 | *
  49. rsslim %lu Current soft limit in bytes on the rss of the process; see the description of 364 | * RLIMIT_RSS in getrlimit(2).
  50. 365 | * 366 | *
  51. startcode %lu The address above which program text can run.
  52. 367 | * 368 | *
  53. endcode %lu The address below which program text can run.
  54. 369 | * 370 | *
  55. startstack %lu The address of the start (i.e., bottom) of the stack.
  56. 371 | * 372 | *
  57. kstkesp %lu The current value of ESP (stack pointer), as found in the kernel stack page 373 | * for the process.
  58. 374 | * 375 | *
  59. kstkeip %lu The current EIP (instruction pointer).
  60. 376 | * 377 | *
  61. signal %lu The bitmap of pending signals, displayed as a decimal number. Obsolete, 378 | * because it does not provide information on real-time signals; use /proc/[pid]/status 379 | * instead
  62. 380 | * 381 | *
  63. blocked %lu The bitmap of blocked signals, displayed as a decimal number. Obsolete, 382 | * because it does not provide information on real-time signals; use /proc/[pid]/status 383 | * instead
  64. 384 | * 385 | *
  65. sigignore %lu The bitmap of ignored signals, displayed as a decimal number. Obsolete, 386 | * because it does not provide information on real-time signals; use /proc/[pid]/status 387 | * instead
  66. 388 | * 389 | *
  67. sigcatch %lu The bitmap of caught signals, displayed as a decimal number. Obsolete, 390 | * because it does not provide information on real-time signals; use /proc/[pid]/status 391 | * instead.
  68. 392 | * 393 | *
  69. wchan %lu This is the "channel" in which the process is waiting. It is the address of a 394 | * location in the kernel where the process is sleeping. The corresponding symbolic name can be 395 | * found in /proc/[pid]/wchan.
  70. 396 | * 397 | *
  71. nswap %lu Number of pages swapped (not maintained).
  72. 398 | * 399 | *
  73. cnswap %lu Cumulative nswap for child processes (not maintained).
  74. 400 | * 401 | *
  75. exit_signal %d (since Linux 2.1.22) Signal to be sent to parent when we die.
  76. 402 | * 403 | *
  77. processor %d (since Linux 2.2.8) CPU number last executed on.
  78. 404 | * 405 | *
  79. rt_priority %u (since Linux 2.5.19) Real-time scheduling priority, a number in the 406 | * range 1 to 99 for processes scheduled under a real-time policy, or 0, for non-real-time 407 | * processes (see sched_setscheduler(2)).
  80. 408 | * 409 | *
  81. policy %u (since Linux 2.5.19) Scheduling policy (see sched_setscheduler(2)). Decode 410 | * using the SCHED_* constants in linux/sched.h. The format for this field was %lu before Linux 411 | * 2.6.22.
  82. 412 | * 413 | *
  83. delayacct_blkio_ticks %llu (since Linux 2.6.18) Aggregated block I/O delays, measured 414 | * in clock ticks (centiseconds).
  84. 415 | * 416 | *
  85. guest_time %lu (since Linux 2.6.24) Guest time of the process (time spent running a 417 | * virtual CPU for a guest operating system), measured in clock ticks (divide by 418 | * sysconf(_SC_CLK_TCK)).
  86. 419 | * 420 | *
  87. cguest_time %ld (since Linux 2.6.24) Guest time of the process's children, measured in 421 | * clock ticks (divide by sysconf(_SC_CLK_TCK)).
  88. 422 | * 423 | *
  89. start_data %lu (since Linux 3.3) Address above which program initialized and 424 | * uninitialized (BSS) data are placed.
  90. 425 | * 426 | *
  91. end_data %lu (since Linux 3.3) Address below which program initialized and 427 | * uninitialized (BSS) data are placed.
  92. 428 | * 429 | *
  93. start_brk %lu (since Linux 3.3) Address above which program heap can be expanded with 430 | * brk(2).
  94. 431 | * 432 | *
  95. arg_start %lu (since Linux 3.5) Address above which program command-line arguments 433 | * (argv) are placed.
  96. 434 | * 435 | *
  97. arg_end %lu (since Linux 3.5) Address below program command-line arguments (argv) are 436 | * placed.
  98. 437 | * 438 | *
  99. env_start %lu (since Linux 3.5) Address above which program environment is placed.
  100. 439 | * 440 | *
  101. env_end %lu (since Linux 3.5) Address below which program environment is placed.
  102. 441 | * 442 | *
  103. exit_code %d (since Linux 3.5) The thread's exit status in the form reported by 443 | * waitpid(2).
  104. 444 | * 445 | *
446 | * 447 | * @return the {@link Stat} for this process 448 | * @throws IOException 449 | * if the file does not exist or we don't have read permissions. 450 | */ 451 | public Stat stat() throws IOException { 452 | return Stat.get(pid); 453 | } 454 | 455 | /** 456 | *

Provides information about memory usage, measured in pages.

457 | * 458 | *

The columns are:

459 | * 460 | *
    461 | *
  • size (1) total program size (same as VmSize in /proc/[pid]/status)
  • 462 | *
  • resident (2) resident set size (same as VmRSS in /proc/[pid]/status)
  • 463 | *
  • share (3) shared pages (i.e., backed by a file)
  • 464 | *
  • text (4) text (code)
  • 465 | *
  • lib (5) library (unused in Linux 2.6)
  • 466 | *
  • data (6) data + stack
  • 467 | *
  • dt (7) dirty pages (unused in Linux 2.6)
  • 468 | *
469 | * 470 | * @return the {@link Statm} for this process 471 | * @throws IOException 472 | * if the file does not exist or we don't have read permissions. 473 | */ 474 | public Statm statm() throws IOException { 475 | return Statm.get(pid); 476 | } 477 | 478 | /** 479 | *

/proc/[pid]/status

480 | * 481 | *

Provides much of the information in /proc/[pid]/stat and /proc/[pid]/statm in a format 482 | * that's 483 | * easier for humans to parse.

484 | * 485 | *

Here's an example:

486 | * 487 | *
488 |    * $ cat /proc/$$/status
489 |    * Name:   bash
490 |    * State:  S (sleeping)
491 |    * Tgid:   3515
492 |    * Pid:    3515
493 |    * PPid:   3452
494 |    * TracerPid:      0
495 |    * Uid:    1000    1000    1000    1000
496 |    * Gid:    100     100     100     100
497 |    * FDSize: 256
498 |    * Groups: 16 33 100
499 |    * VmPeak:     9136 kB
500 |    * VmSize:     7896 kB
501 |    * VmLck:         0 kB
502 |    * VmPin:         0 kB
503 |    * VmHWM:      7572 kB
504 |    * VmRSS:      6316 kB
505 |    * VmData:     5224 kB
506 |    * VmStk:        88 kB
507 |    * VmExe:       572 kB
508 |    * VmLib:      1708 kB
509 |    * VmPMD:         4 kB
510 |    * VmPTE:        20 kB
511 |    * VmSwap:        0 kB
512 |    * Threads:        1
513 |    * SigQ:   0/3067
514 |    * SigPnd: 0000000000000000
515 |    * ShdPnd: 0000000000000000
516 |    * SigBlk: 0000000000010000
517 |    * SigIgn: 0000000000384004
518 |    * SigCgt: 000000004b813efb
519 |    * CapInh: 0000000000000000
520 |    * CapPrm: 0000000000000000
521 |    * CapEff: 0000000000000000
522 |    * CapBnd: ffffffffffffffff
523 |    * Seccomp:        0
524 |    * Cpus_allowed:   00000001
525 |    * Cpus_allowed_list:      0
526 |    * Mems_allowed:   1
527 |    * Mems_allowed_list:      0
528 |    * voluntary_ctxt_switches:        150
529 |    * nonvoluntary_ctxt_switches:     545
530 |    * 
531 | * 532 | *

The fields are as follows:

533 | * 534 | *
    535 | *
  1. Name: Command run by this process.
  2. 536 | *
  3. State: Current state of the process. One of "R (running)", "S (sleeping)", "D (disk 537 | * sleep)", 538 | * "T (stopped)", "T (tracing stop)", "Z (zombie)", or "X (dead)".
  4. 539 | *
  5. Tgid: Thread group ID (i.e., Process ID).
  6. 540 | *
  7. Pid: Thread ID (see gettid(2)).
  8. 541 | *
  9. PPid: PID of parent process.
  10. 542 | *
  11. TracerPid: PID of process tracing this process (0 if not being traced).
  12. 543 | *
  13. Uid, Gid: Real, effective, saved set, and filesystem UIDs (GIDs).
  14. 544 | *
  15. FDSize: Number of file descriptor slots currently allocated.
  16. 545 | *
  17. Groups: Supplementary group list.
  18. 546 | *
  19. VmPeak: Peak virtual memory size.
  20. 547 | *
  21. VmSize: Virtual memory size.
  22. 548 | *
  23. VmLck: Locked memory size (see mlock(3)).
  24. 549 | *
  25. VmPin: Pinned memory size (since Linux 3.2). These are pages that can't be moved because 550 | * something needs to directly access physical memory.
  26. 551 | *
  27. VmHWM: Peak resident set size ("high water mark").
  28. 552 | *
  29. VmRSS: Resident set size.
  30. 553 | *
  31. VmData, VmStk, VmExe: Size of data, stack, and text segments.
  32. 554 | *
  33. VmLib: Shared library code size.
  34. 555 | *
  35. VmPTE: Page table entries size (since Linux 2.6.10).
  36. 556 | *
  37. VmPMD: Size of second-level page tables (since Linux 4.0).
  38. 557 | *
  39. VmSwap: Swapped-out virtual memory size by anonymous private pages; shmem swap usage is 558 | * not 559 | * included (since Linux 2.6.34).
  40. 560 | *
  41. Threads: Number of threads in process containing this thread.
  42. 561 | *
  43. SigQ: This field contains two slash-separated numbers that relate to queued signals for 562 | * the 563 | * real user ID of this process. The first of these is the number of currently queued signals 564 | * for 565 | * this real user ID, and the second is the resource limit on the number of queued signals for 566 | * this 567 | * process (see the description of RLIMIT_SIGPENDING in getrlimit(2)).
  44. 568 | *
  45. SigPnd, ShdPnd: Number of signals pending for thread and for process as a whole (see 569 | * pthreads(7) and signal(7)).
  46. 570 | *
  47. SigBlk, SigIgn, SigCgt: Masks indicating signals being blocked, ignored, and caught (see 571 | * signal(7)).
  48. 572 | *
  49. CapInh, CapPrm, CapEff: Masks of capabilities enabled in inheritable, permitted, and 573 | * effective sets (see capabilities(7)).
  50. 574 | *
  51. CapBnd: Capability Bounding set (since Linux 2.6.26, see capabilities(7)).
  52. 575 | *
  53. Seccomp: Seccomp mode of the process (since Linux 3.8, see seccomp(2)). 0 means 576 | * SECCOMP_MODE_DISABLED; 1 means SECCOMP_MODE_STRICT; 2 means SECCOMP_MODE_FILTER. This field is 577 | * provided only if the kernel was built with the CONFIG_SECCOMP kernel configuration option 578 | * enabled.
  54. 579 | *
  55. Cpus_allowed: Mask of CPUs on which this process may run (since Linux 2.6.24, see 580 | * cpuset(7)).
  56. 581 | *
  57. Cpus_allowed_list: Same as previous, but in "list format" (since Linux 2.6.26, see 582 | * cpuset(7)).
  58. 583 | *
  59. Mems_allowed: Mask of memory nodes allowed to this process (since Linux 2.6.24, see 584 | * cpuset(7)).
  60. 585 | *
  61. Mems_allowed_list: Same as previous, but in "list format" (since Linux 2.6.26, see 586 | * cpuset(7)). 587 | * voluntary_ctxt_switches, nonvoluntary_ctxt_switches: Number of voluntary and involuntary 588 | * context 589 | * switches (since Linux 2.6.23).
  62. 590 | *
591 | * 592 | * @return the {@link Status} for this process 593 | * @throws IOException 594 | * if the file does not exist or we don't have read permissions. 595 | */ 596 | public Status status() throws IOException { 597 | return Status.get(pid); 598 | } 599 | 600 | /** 601 | * The symbolic name corresponding to the location in the kernel where the process is sleeping. 602 | * 603 | * @return the contents of /proc/[pid]/wchan 604 | * @throws IOException 605 | * if the file does not exist or we don't have read permissions. 606 | */ 607 | public String wchan() throws IOException { 608 | return read("wchan"); 609 | } 610 | 611 | @Override public int describeContents() { 612 | return 0; 613 | } 614 | 615 | @Override public void writeToParcel(Parcel dest, int flags) { 616 | dest.writeString(this.name); 617 | dest.writeInt(this.pid); 618 | } 619 | 620 | protected AndroidProcess(Parcel in) { 621 | this.name = in.readString(); 622 | this.pid = in.readInt(); 623 | } 624 | 625 | public static final Creator CREATOR = new Creator() { 626 | 627 | @Override public AndroidProcess createFromParcel(Parcel source) { 628 | return new AndroidProcess(source); 629 | } 630 | 631 | @Override public AndroidProcess[] newArray(int size) { 632 | return new AndroidProcess[size]; 633 | } 634 | }; 635 | 636 | } 637 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/Cgroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | 22 | import java.io.IOException; 23 | import java.util.ArrayList; 24 | 25 | /** 26 | *

/proc/[pid]/cgroup (since Linux 2.6.24)

27 | * 28 | *

This file describes control groups to which the process/task belongs. For each cgroup 29 | * hierarchy there is one entry containing colon-separated fields of the form:

30 | * 31 | *

5:cpuacct,cpu,cpuset:/daemons

32 | * 33 | *

The colon-separated fields are, from left to right:

34 | * 35 | *
    36 | *
  1. hierarchy ID number
  2. 37 | *
  3. set of subsystems bound to the hierarchy
  4. 38 | *
  5. control group in the hierarchy to which the process belongs
  6. 39 | *
40 | * 41 | *

This file is present only if the CONFIG_CGROUPS kernel configuration option is enabled.

42 | * 43 | * @see ControlGroup 44 | */ 45 | public final class Cgroup extends ProcFile { 46 | 47 | /** 48 | * Read /proc/[pid]/cgroup. 49 | * 50 | * @param pid 51 | * the processes id. 52 | * @return the {@link Cgroup} 53 | * @throws IOException 54 | * if the file does not exist or we don't have read permissions. 55 | */ 56 | public static Cgroup get(int pid) throws IOException { 57 | return new Cgroup(String.format("/proc/%d/cgroup", pid)); 58 | } 59 | 60 | /** the process' control groups */ 61 | public final ArrayList groups; 62 | 63 | private Cgroup(String path) throws IOException { 64 | super(path); 65 | String[] lines = content.split("\n"); 66 | groups = new ArrayList<>(); 67 | for (String line : lines) { 68 | try { 69 | groups.add(new ControlGroup(line)); 70 | } catch (Exception ignored) { 71 | } 72 | } 73 | } 74 | 75 | private Cgroup(Parcel in) { 76 | super(in); 77 | this.groups = in.createTypedArrayList(ControlGroup.CREATOR); 78 | } 79 | 80 | public ControlGroup getGroup(String subsystem) { 81 | for (ControlGroup group : groups) { 82 | String[] systems = group.subsystems.split(","); 83 | for (String name : systems) { 84 | if (name.equals(subsystem)) { 85 | return group; 86 | } 87 | } 88 | } 89 | return null; 90 | } 91 | 92 | @Override public void writeToParcel(Parcel dest, int flags) { 93 | super.writeToParcel(dest, flags); 94 | dest.writeTypedList(groups); 95 | } 96 | 97 | public static final Creator CREATOR = new Creator() { 98 | 99 | @Override public Cgroup createFromParcel(Parcel source) { 100 | return new Cgroup(source); 101 | } 102 | 103 | @Override public Cgroup[] newArray(int size) { 104 | return new Cgroup[size]; 105 | } 106 | }; 107 | 108 | } 109 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/ControlGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | import android.os.Parcelable; 22 | 23 | public class ControlGroup implements Parcelable { 24 | 25 | /** hierarchy ID number */ 26 | public final int id; 27 | 28 | /** set of subsystems bound to the hierarchy */ 29 | public final String subsystems; 30 | 31 | /** control group in the hierarchy to which the process belongs */ 32 | public final String group; 33 | 34 | protected ControlGroup(String line) throws NumberFormatException, IndexOutOfBoundsException { 35 | String[] fields = line.split(":"); 36 | id = Integer.parseInt(fields[0]); 37 | subsystems = fields[1]; 38 | group = fields[2]; 39 | } 40 | 41 | protected ControlGroup(Parcel in) { 42 | this.id = in.readInt(); 43 | this.subsystems = in.readString(); 44 | this.group = in.readString(); 45 | } 46 | 47 | @Override public int describeContents() { 48 | return 0; 49 | } 50 | 51 | @Override public void writeToParcel(Parcel dest, int flags) { 52 | dest.writeInt(this.id); 53 | dest.writeString(this.subsystems); 54 | dest.writeString(this.group); 55 | } 56 | 57 | @Override public String toString() { 58 | return String.format("%d:%s:%s", id, subsystems, group); 59 | } 60 | 61 | public static final Creator CREATOR = new Creator() { 62 | 63 | @Override public ControlGroup createFromParcel(Parcel source) { 64 | return new ControlGroup(source); 65 | } 66 | 67 | @Override public ControlGroup[] newArray(int size) { 68 | return new ControlGroup[size]; 69 | } 70 | }; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/ProcFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | import android.os.Parcelable; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.File; 25 | import java.io.FileReader; 26 | import java.io.IOException; 27 | 28 | public class ProcFile extends File implements Parcelable { 29 | 30 | /** 31 | * Read the contents of a file. 32 | * 33 | * @param path 34 | * the absolute path to the file. 35 | * @return the contents of the file. 36 | * @throws IOException 37 | * if an error occurred while reading. 38 | */ 39 | protected static String readFile(String path) throws IOException { 40 | BufferedReader reader = null; 41 | try { 42 | StringBuilder output = new StringBuilder(); 43 | reader = new BufferedReader(new FileReader(path)); 44 | for (String line = reader.readLine(), newLine = ""; line != null; line = reader.readLine()) { 45 | output.append(newLine).append(line); 46 | newLine = "\n"; 47 | } 48 | return output.toString(); 49 | } finally { 50 | if (reader != null) { 51 | reader.close(); 52 | } 53 | } 54 | } 55 | 56 | public final String content; 57 | 58 | protected ProcFile(String path) throws IOException { 59 | super(path); 60 | content = readFile(path); 61 | } 62 | 63 | protected ProcFile(Parcel in) { 64 | super(in.readString()); 65 | this.content = in.readString(); 66 | } 67 | 68 | @Override public long length() { 69 | return content.length(); 70 | } 71 | 72 | @Override public int describeContents() { 73 | return 0; 74 | } 75 | 76 | @Override public void writeToParcel(Parcel dest, int flags) { 77 | dest.writeString(getAbsolutePath()); 78 | dest.writeString(this.content); 79 | } 80 | 81 | public static final Creator CREATOR = new Creator() { 82 | 83 | @Override public ProcFile createFromParcel(Parcel in) { 84 | return new ProcFile(in); 85 | } 86 | 87 | @Override public ProcFile[] newArray(int size) { 88 | return new ProcFile[size]; 89 | } 90 | }; 91 | 92 | } 93 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/Stat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | import android.os.Parcelable; 22 | 23 | import java.io.IOException; 24 | 25 | /** 26 | *

/proc/[pid]/stat

27 | * 28 | *

Status information about the process. This is used by ps(1). It is defined in the kernel 29 | * source file fs/proc/array.c.

30 | * 31 | *

The fields, in order, with their proper scanf(3) format specifiers, are:

32 | * 33 | *
    34 | *
  1. pid %d The process ID.
  2. 35 | *
  3. comm %s The filename of the executable, in parentheses. This is visible whether or not 36 | * the executable is swapped out.
  4. 37 | *
  5. state %c One of the following characters, indicating process state: 38 | *
      39 | *
    • R Running
    • 40 | *
    • S Sleeping in an interruptible wait
    • 41 | *
    • D Waiting in uninterruptible disk sleep
    • 42 | *
    • Z Zombie
    • 43 | *
    • T Stopped (on a signal) or (before Linux 2.6.33) trace stopped
    • 44 | *
    • t Tracing stop (Linux 2.6.33 onward)
    • 45 | *
    • W Paging (only before Linux 2.6.0)
    • 46 | *
    • X Dead (from Linux 2.6.0 onward)
    • 47 | *
    • x Dead (Linux 2.6.33 to 3.13 only)
    • 48 | *
    • K Wakekill (Linux 2.6.33 to 3.13 only)
    • 49 | *
    • W Waking (Linux 2.6.33 to 3.13 only)
    • 50 | *
    • P Parked (Linux 3.9 to 3.13 only)
    • 51 | *
    52 | *
  6. 53 | *
  7. ppid %d The PID of the parent of this process.
  8. 54 | *
  9. pgrp %d The process group ID of the process.
  10. 55 | *
  11. session %d The session ID of the process.
  12. 56 | *
  13. tty_nr %d The controlling terminal of the process. (The minor device number is contained 57 | * in the combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8.) 58 | *
  14. 59 | *
  15. tpgid %d The ID of the foreground process group of the controlling terminal of the 60 | * process.
  16. 61 | *
  17. flags %u The kernel flags word of the process. For bit meanings, see the PF_* defines in 62 | * the Linux kernel source file include/linux/sched.h. Details depend on the kernel version. 63 | * The format for this field was %lu before Linux 2.6.
  18. 64 | *
  19. minflt %lu The number of minor faults the process has made which have not required 65 | * loading a memory page from disk.
  20. 66 | *
  21. cminflt %lu The number of minor faults that the process's waited-for children have 67 | * made
  22. 68 | *
  23. majflt %lu The number of major faults the process has made which have required loading a 69 | * memory page from disk.
  24. 70 | *
  25. cmajflt %lu The number of major faults that the process's waited-for children have 71 | * made
  26. 72 | *
  27. utime %lu Amount of time that this process has been scheduled in user mode, measured in 73 | * clock ticks (divide by sysconf(_SC_CLK_TCK)). This includes guest time, guest_time (time 74 | * spent running a virtual CPU, see below), so that applications that are not aware of the guest 75 | * time field do not lose that time from their calculations.
  28. 76 | *
  29. stime %lu Amount of time that this process has been scheduled in kernel mode, measured 77 | * in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  30. 78 | *
  31. cutime %ld Amount of time that this process's waited-for children have been scheduled in 79 | * user mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). (See also times(2).) 80 | * This includes guest time, cguest_time (time spent running a virtual CPU, see below).
  32. 81 | *
  33. cstime %ld Amount of time that this process's waited-for children have been scheduled in 82 | * kernel mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
  34. 83 | *
  35. priority %ld (Explanation for Linux 2.6) For processes running a real-time scheduling 84 | * policy (policy below; see sched_setscheduler(2)), this is the negated scheduling priority, 85 | * minus one; that is, a number in the range -2 to -100, corresponding to real-time priorities 1 86 | * to 99. For processes running under a non-real-time scheduling policy, this is the raw nice 87 | * value (setpriority(2)) as represented in the kernel. The kernel stores nice values as numbers 88 | * in the range 0 (high) to 39 (low), corresponding to the user-visible nice range of -20 to 19. 89 | * Before Linux 2.6, this was a scaled value based on the scheduler weighting given to this 90 | * process
  36. 91 | *
  37. nice %ld The nice value (see setpriority(2)), a value in the range 19 (low priority) to 92 | * -20 (high priority).
  38. 93 | *
  39. num_threads %ld Number of threads in this process (since Linux 2.6). Before kernel 2.6, 94 | * this field was hard coded to 0 as a placeholder for an earlier removed field.
  40. 95 | *
  41. itrealvalue %ld The time in jiffies before the next SIGALRM is sent to the process due 96 | * to an interval timer. Since kernel 2.6.17, this field is no longer maintained, and is hard 97 | * coded as 0.
  42. 98 | *
  43. starttime %llu The time the process started after system boot. In kernels before Linux 99 | * 2.6, this value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock 100 | * ticks (divide by sysconf(_SC_CLK_TCK)).
  44. 101 | *
  45. The format for this field was %lu before Linux 2.6. (23) vsize %lu Virtual memory size 102 | * in bytes.
  46. 103 | *
  47. rss %ld Resident Set Size: number of pages the process has in real memory. This is just 104 | * the pages which count toward text, data, or stack space. This does not include pages which 105 | * have not been demand-loaded in, or which are swapped out.
  48. 106 | *
  49. rsslim %lu Current soft limit in bytes on the rss of the process; see the description of 107 | * RLIMIT_RSS in getrlimit(2).
  50. 108 | *
  51. startcode %lu The address above which program text can run.
  52. 109 | *
  53. endcode %lu The address below which program text can run.
  54. 110 | *
  55. startstack %lu The address of the start (i.e., bottom) of the stack.
  56. 111 | *
  57. kstkesp %lu The current value of ESP (stack pointer), as found in the kernel stack page 112 | * for the process.
  58. 113 | *
  59. kstkeip %lu The current EIP (instruction pointer).
  60. 114 | *
  61. signal %lu The bitmap of pending signals, displayed as a decimal number. Obsolete, 115 | * because it does not provide information on real-time signals; use /proc/[pid]/status 116 | * instead
  62. 117 | *
  63. blocked %lu The bitmap of blocked signals, displayed as a decimal number. Obsolete, 118 | * because it does not provide information on real-time signals; use /proc/[pid]/status 119 | * instead
  64. 120 | *
  65. sigignore %lu The bitmap of ignored signals, displayed as a decimal number. Obsolete, 121 | * because it does not provide information on real-time signals; use /proc/[pid]/status 122 | * instead
  66. 123 | *
  67. sigcatch %lu The bitmap of caught signals, displayed as a decimal number. Obsolete, 124 | * because it does not provide information on real-time signals; use /proc/[pid]/status 125 | * instead.
  68. 126 | *
  69. wchan %lu This is the "channel" in which the process is waiting. It is the address of a 127 | * location in the kernel where the process is sleeping. The corresponding symbolic name can be 128 | * found in /proc/[pid]/wchan.
  70. 129 | *
  71. nswap %lu Number of pages swapped (not maintained).
  72. 130 | *
  73. cnswap %lu Cumulative nswap for child processes (not maintained).
  74. 131 | *
  75. exit_signal %d (since Linux 2.1.22) Signal to be sent to parent when we die.
  76. 132 | *
  77. processor %d (since Linux 2.2.8) CPU number last executed on.
  78. 133 | *
  79. rt_priority %u (since Linux 2.5.19) Real-time scheduling priority, a number in the 134 | * range 1 to 99 for processes scheduled under a real-time policy, or 0, for non-real-time 135 | * processes (see sched_setscheduler(2)).
  80. 136 | *
  81. policy %u (since Linux 2.5.19) Scheduling policy (see sched_setscheduler(2)). Decode 137 | * using the SCHED_* constants in linux/sched.h. The format for this field was %lu before Linux 138 | * 2.6.22.
  82. 139 | *
  83. delayacct_blkio_ticks %llu (since Linux 2.6.18) Aggregated block I/O delays, measured 140 | * in clock ticks (centiseconds).
  84. 141 | *
  85. guest_time %lu (since Linux 2.6.24) Guest time of the process (time spent running a 142 | * virtual CPU for a guest operating system), measured in clock ticks (divide by 143 | * sysconf(_SC_CLK_TCK)).
  86. 144 | *
  87. cguest_time %ld (since Linux 2.6.24) Guest time of the process's children, measured in 145 | * clock ticks (divide by sysconf(_SC_CLK_TCK)).
  88. 146 | *
  89. start_data %lu (since Linux 3.3) Address above which program initialized and 147 | * uninitialized (BSS) data are placed.
  90. 148 | *
  91. end_data %lu (since Linux 3.3) Address below which program initialized and 149 | * uninitialized (BSS) data are placed.
  92. 150 | *
  93. start_brk %lu (since Linux 3.3) Address above which program heap can be expanded with 151 | * brk(2).
  94. 152 | *
  95. arg_start %lu (since Linux 3.5) Address above which program command-line arguments 153 | * (argv) are placed.
  96. 154 | *
  97. arg_end %lu (since Linux 3.5) Address below program command-line arguments (argv) are 155 | * placed.
  98. 156 | *
  99. env_start %lu (since Linux 3.5) Address above which program environment is placed.
  100. 157 | *
  101. env_end %lu (since Linux 3.5) Address below which program environment is placed.
  102. 158 | *
  103. exit_code %d (since Linux 3.5) The thread's exit status in the form reported by 159 | * waitpid(2).
  104. 160 | *
161 | */ 162 | public final class Stat extends ProcFile { 163 | 164 | /** 165 | * Read /proc/[pid]/stat. 166 | * 167 | * @param pid 168 | * the process id. 169 | * @return the {@link Stat} 170 | * @throws IOException 171 | * if the file does not exist or we don't have read permissions. 172 | */ 173 | public static Stat get(int pid) throws IOException { 174 | return new Stat(String.format("/proc/%d/stat", pid)); 175 | } 176 | 177 | private final String[] fields; 178 | 179 | private Stat(String path) throws IOException { 180 | super(path); 181 | fields = content.split("\\s+"); 182 | } 183 | 184 | private Stat(Parcel in) { 185 | super(in); 186 | this.fields = in.createStringArray(); 187 | } 188 | 189 | /** The process ID. */ 190 | public int getPid() { 191 | return Integer.parseInt(fields[0]); 192 | } 193 | 194 | /** 195 | * The filename of the executable, in parentheses. This is visible whether or not the 196 | * executable is swapped out. 197 | */ 198 | public String getComm() { 199 | return fields[1].replace("(", "").replace(")", ""); 200 | } 201 | 202 | /** 203 | *

One of the following characters, indicating process state:

204 | * 205 | *
    206 | *
  • 'R' Running
  • 207 | *
  • 'S' Sleeping in an interruptible wait
  • 208 | *
  • 'D' Waiting in uninterruptible disk sleep
  • 209 | *
  • 'Z' Zombie
  • 210 | *
  • 'T' Stopped (on a signal) or (before Linux 2.6.33) trace stopped
  • 211 | *
  • 't' Tracing stop (Linux 2.6.33 onward)
  • 212 | *
  • 'W' Paging (only before Linux 2.6.0)
  • 213 | *
  • 'X' Dead (from Linux 2.6.0 onward)
  • 214 | *
  • 'x' Dead (Linux 2.6.33 to 3.13 only)
  • 215 | *
  • 'K' Wakekill (Linux 2.6.33 to 3.13 only)
  • 216 | *
  • 'W' Waking (Linux 2.6.33 to 3.13 only)
  • 217 | *
  • 'P' Parked (Linux 3.9 to 3.13 only)
  • 218 | *
219 | */ 220 | public char state() { 221 | return fields[2].charAt(0); 222 | } 223 | 224 | /** 225 | * The PID of the parent of this process. 226 | */ 227 | public int ppid() { 228 | return Integer.parseInt(fields[3]); 229 | } 230 | 231 | /** 232 | * The process group ID of the process. 233 | */ 234 | public int pgrp() { 235 | return Integer.parseInt(fields[4]); 236 | } 237 | 238 | /** 239 | * The session ID of the process. 240 | */ 241 | public int session() { 242 | return Integer.parseInt(fields[5]); 243 | } 244 | 245 | /** 246 | * The controlling terminal of the process. (The minor device number is contained in the 247 | * combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8.) 248 | */ 249 | public int tty_nr() { 250 | return Integer.parseInt(fields[6]); 251 | } 252 | 253 | /** 254 | * The ID of the foreground process group of the controlling terminal of the process. 255 | */ 256 | public int tpgid() { 257 | return Integer.parseInt(fields[7]); 258 | } 259 | 260 | /** 261 | *

The kernel flags word of the process. For bit meanings, see the PF_* defines in the Linux 262 | * kernel source file include/linux/sched.h. Details depend on the kernel version.

263 | * 264 | *

The format for this field was %lu before Linux 2.6.

265 | */ 266 | public int flags() { 267 | return Integer.parseInt(fields[8]); 268 | } 269 | 270 | /** 271 | * The number of minor faults the process has made which have not required loading a memory 272 | * page from disk. 273 | */ 274 | public long minflt() { 275 | return Long.parseLong(fields[9]); 276 | } 277 | 278 | /** 279 | * The number of minor faults that the process's waited-for children have made. 280 | */ 281 | public long cminflt() { 282 | return Long.parseLong(fields[10]); 283 | } 284 | 285 | /** 286 | * The number of major faults the process has made which have required loading a memory page 287 | * from disk. 288 | */ 289 | public long majflt() { 290 | return Long.parseLong(fields[11]); 291 | } 292 | 293 | /** 294 | * The number of major faults that the process's waited-for children have made. 295 | */ 296 | public long cmajflt() { 297 | return Long.parseLong(fields[12]); 298 | } 299 | 300 | /** 301 | * Amount of time that this process has been scheduled in user mode, measured in clock ticks 302 | * (divide by sysconf(_SC_CLK_TCK)). This includes guest time, guest_time (time spent running 303 | * a virtual CPU, see below), so that applications that are not aware of the guest time field 304 | * do not lose that time from their calculations. 305 | */ 306 | public long utime() { 307 | return Long.parseLong(fields[13]); 308 | } 309 | 310 | /** 311 | * Amount of time that this process has been scheduled in kernel mode, measured in clock ticks 312 | * (divide by sysconf(_SC_CLK_TCK)). 313 | */ 314 | public long stime() { 315 | return Long.parseLong(fields[14]); 316 | } 317 | 318 | /** 319 | * Amount of time that this process's waited-for children have been scheduled in user mode, 320 | * measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). (See also times(2).) This 321 | * includes guest time, cguest_time (time spent running a virtual CPU, see below). 322 | */ 323 | public long cutime() { 324 | return Long.parseLong(fields[15]); 325 | } 326 | 327 | /** 328 | * Amount of time that this process's waited-for children have been scheduled in kernel mode, 329 | * measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). 330 | */ 331 | public long cstime() { 332 | return Long.parseLong(fields[16]); 333 | } 334 | 335 | /** 336 | *

(Explanation for Linux 2.6) For processes running a real-time scheduling policy (policy 337 | * below; see sched_setscheduler(2)), this is the negated scheduling priority, minus one; that 338 | * is, 339 | * a number in the range -2 to -100, corresponding to real-time priorities 1 to 99. For 340 | * processes 341 | * running under a non-real-time scheduling policy, this is the raw nice value (setpriority(2)) 342 | * as 343 | * represented in the kernel. The kernel stores nice values as numbers in the range 0 (high) to 344 | * 39 (low), corresponding to the user-visible nice range of -20 to 19.

345 | * 346 | *

Before Linux 2.6, this was a scaled value based on the scheduler weighting given to this 347 | * process.

348 | */ 349 | public long priority() { 350 | return Long.parseLong(fields[17]); 351 | } 352 | 353 | /** 354 | * The nice value (see setpriority(2)), a value in the range 19 (low priority) to -20 (high 355 | * priority). 356 | */ 357 | public int nice() { 358 | return Integer.parseInt(fields[18]); 359 | } 360 | 361 | /** 362 | * Number of threads in this process (since Linux 2.6). Before kernel 2.6, this field was hard 363 | * coded to 0 as a placeholder for an earlier removed field. 364 | */ 365 | public long num_threads() { 366 | return Long.parseLong(fields[19]); 367 | } 368 | 369 | /** 370 | * The time in jiffies before the next SIGALRM is sent to the process due to an interval timer. 371 | * Since kernel 2.6.17, this field is no longer maintained, and is hard coded as 0. 372 | */ 373 | public long itrealvalue() { 374 | return Long.parseLong(fields[20]); 375 | } 376 | 377 | /** 378 | *

The time the process started after system boot. In kernels before Linux 2.6, this value was 379 | * expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks (divide by 380 | * sysconf(_SC_CLK_TCK)).

381 | * 382 | *

The format for this field was %lu before Linux 2.6.

383 | */ 384 | public long starttime() { 385 | return Long.parseLong(fields[21]); 386 | } 387 | 388 | /** 389 | * Virtual memory size in bytes. 390 | */ 391 | public long vsize() { 392 | return Long.parseLong(fields[22]); 393 | } 394 | 395 | /** 396 | * Resident Set Size: number of pages the process has in real memory. This is just the pages 397 | * which count toward text, data, or stack space. This does not include pages which have not 398 | * been demand-loaded in, or which are swapped out. 399 | */ 400 | public long rss() { 401 | return Long.parseLong(fields[23]); 402 | } 403 | 404 | /** 405 | * Current soft limit in bytes on the rss of the process; see the description of RLIMIT_RSS in 406 | * getrlimit(2). 407 | */ 408 | public long rsslim() { 409 | return Long.parseLong(fields[24]); 410 | } 411 | 412 | /** 413 | * The address above which program text can run. 414 | */ 415 | public long startcode() { 416 | return Long.parseLong(fields[25]); 417 | } 418 | 419 | /** 420 | * The address below which program text can run. 421 | */ 422 | public long endcode() { 423 | return Long.parseLong(fields[26]); 424 | } 425 | 426 | /** 427 | * The address of the start (i.e., bottom) of the stack. 428 | */ 429 | public long startstack() { 430 | return Long.parseLong(fields[27]); 431 | } 432 | 433 | /** 434 | * The current value of ESP (stack pointer), as found in the kernel stack page for the process. 435 | */ 436 | public long kstkesp() { 437 | return Long.parseLong(fields[28]); 438 | } 439 | 440 | /** 441 | * The current EIP (instruction pointer). 442 | */ 443 | public long kstkeip() { 444 | return Long.parseLong(fields[29]); 445 | } 446 | 447 | /** 448 | * The bitmap of pending signals, displayed as a decimal number. Obsolete, because it does not 449 | * provide information on real-time signals; use /proc/[pid]/status instead. 450 | */ 451 | public long signal() { 452 | return Long.parseLong(fields[30]); 453 | } 454 | 455 | /** 456 | * The bitmap of blocked signals, displayed as a decimal number. Obsolete, because it does not 457 | * provide information on real-time signals; use /proc/[pid]/status instead. 458 | */ 459 | public long blocked() { 460 | return Long.parseLong(fields[31]); 461 | } 462 | 463 | /** 464 | * The bitmap of ignored signals, displayed as a decimal number. Obsolete, because it does not 465 | * provide information on real-time signals; use /proc/[pid]/status instead. 466 | */ 467 | public long sigignore() { 468 | return Long.parseLong(fields[32]); 469 | } 470 | 471 | /** 472 | * The bitmap of caught signals, displayed as a decimal number. Obsolete, because it does not 473 | * provide information on real-time signals; use /proc/[pid]/status instead. 474 | */ 475 | public long sigcatch() { 476 | return Long.parseLong(fields[33]); 477 | } 478 | 479 | /** 480 | * This is the "channel" in which the process is waiting. It is the address of a location in the 481 | * kernel where the process is sleeping. The corresponding symbolic name can be found in 482 | * /proc/[pid]/wchan. 483 | */ 484 | public long wchan() { 485 | return Long.parseLong(fields[34]); 486 | } 487 | 488 | /** 489 | * Number of pages swapped (not maintained). 490 | */ 491 | public long nswap() { 492 | return Long.parseLong(fields[35]); 493 | } 494 | 495 | /** 496 | * Cumulative nswap for child processes (not maintained). 497 | */ 498 | public long cnswap() { 499 | return Long.parseLong(fields[36]); 500 | } 501 | 502 | /** 503 | * (since Linux 2.1.22) 504 | * Signal to be sent to parent when we die. 505 | */ 506 | public int exit_signal() { 507 | return Integer.parseInt(fields[37]); 508 | } 509 | 510 | /** 511 | * (since Linux 2.2.8) 512 | * CPU number last executed on. 513 | */ 514 | public int processor() { 515 | return Integer.parseInt(fields[38]); 516 | } 517 | 518 | /** 519 | * (since Linux 2.5.19) 520 | * Real-time scheduling priority, a number in the range 1 to 99 for processes scheduled under a 521 | * real-time policy, or 0, for non-real-time processes (see sched_setscheduler(2)). 522 | */ 523 | public int rt_priority() { 524 | return Integer.parseInt(fields[39]); 525 | } 526 | 527 | /** 528 | *

(since Linux 2.5.19) Scheduling policy (see sched_setscheduler(2)). Decode using the 529 | * SCHED_* 530 | * constants in linux/sched.h.

531 | * 532 | *

The format for this field was %lu before Linux 2.6.22.

533 | */ 534 | public int policy() { 535 | return Integer.parseInt(fields[40]); 536 | } 537 | 538 | /** 539 | * (since Linux 2.6.18) 540 | * Aggregated block I/O delays, measured in clock ticks (centiseconds). 541 | */ 542 | public long delayacct_blkio_ticks() { 543 | return Long.parseLong(fields[41]); 544 | } 545 | 546 | /** 547 | * (since Linux 2.6.24) 548 | * Guest time of the process (time spent running a virtual CPU for a guest operating system), 549 | * measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). 550 | */ 551 | public long guest_time() { 552 | return Long.parseLong(fields[42]); 553 | } 554 | 555 | /** 556 | * (since Linux 2.6.24) 557 | * Guest time of the process's children, measured in clock ticks (divide by 558 | * sysconf(_SC_CLK_TCK)). 559 | */ 560 | public long cguest_time() { 561 | return Long.parseLong(fields[43]); 562 | } 563 | 564 | /** 565 | * (since Linux 3.3) 566 | * Address above which program initialized and uninitialized (BSS) data are placed. 567 | */ 568 | public long start_data() { 569 | return Long.parseLong(fields[44]); 570 | } 571 | 572 | /** 573 | * (since Linux 3.3) 574 | * Address below which program initialized and uninitialized (BSS) data are placed. 575 | */ 576 | public long end_data() { 577 | return Long.parseLong(fields[45]); 578 | } 579 | 580 | /** 581 | * (since Linux 3.3) 582 | * Address above which program heap can be expanded with brk(2). 583 | */ 584 | public long start_brk() { 585 | return Long.parseLong(fields[46]); 586 | } 587 | 588 | /** 589 | * (since Linux 3.5) 590 | * Address above which program command-line arguments (argv) are placed. 591 | */ 592 | public long arg_start() { 593 | return Long.parseLong(fields[47]); 594 | } 595 | 596 | /** 597 | * (since Linux 3.5) 598 | * Address below program command-line arguments (argv) are placed. 599 | */ 600 | public long arg_end() { 601 | return Long.parseLong(fields[48]); 602 | } 603 | 604 | /** 605 | * (since Linux 3.5) 606 | * Address above which program environment is placed. 607 | */ 608 | public long env_start() { 609 | return Long.parseLong(fields[49]); 610 | } 611 | 612 | /** 613 | * (since Linux 3.5) 614 | * Address below which program environment is placed. 615 | */ 616 | public long env_end() { 617 | return Long.parseLong(fields[50]); 618 | } 619 | 620 | /** 621 | * (since Linux 3.5) 622 | * The thread's exit status in the form reported by waitpid(2). 623 | */ 624 | public int exit_code() { 625 | return Integer.parseInt(fields[51]); 626 | } 627 | 628 | @Override public void writeToParcel(Parcel dest, int flags) { 629 | super.writeToParcel(dest, flags); 630 | dest.writeStringArray(fields); 631 | } 632 | 633 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 634 | 635 | @Override public Stat createFromParcel(Parcel source) { 636 | return new Stat(source); 637 | } 638 | 639 | @Override public Stat[] newArray(int size) { 640 | return new Stat[size]; 641 | } 642 | }; 643 | 644 | } 645 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/Statm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | import android.os.Parcelable; 22 | 23 | import java.io.IOException; 24 | 25 | /** 26 | *

Provides information about memory usage, measured in pages.

27 | * 28 | *

The columns are:

29 | * 30 | *
    31 | *
  • size (1) total program size (same as VmSize in /proc/[pid]/status)
  • 32 | *
  • resident (2) resident set size (same as VmRSS in /proc/[pid]/status)
  • 33 | *
  • share (3) shared pages (i.e., backed by a file)
  • 34 | *
  • text (4) text (code)
  • 35 | *
  • lib (5) library (unused in Linux 2.6)
  • 36 | *
  • data (6) data + stack
  • 37 | *
  • dt (7) dirty pages (unused in Linux 2.6)
  • 38 | *
39 | */ 40 | public final class Statm extends ProcFile { 41 | 42 | /** 43 | * Read /proc/[pid]/statm. 44 | * 45 | * @param pid 46 | * the process id. 47 | * @return the {@link Statm} 48 | * @throws IOException 49 | * if the file does not exist or we don't have read permissions. 50 | */ 51 | public static Statm get(int pid) throws IOException { 52 | return new Statm(String.format("/proc/%d/statm", pid)); 53 | } 54 | 55 | public final String[] fields; 56 | 57 | private Statm(String path) throws IOException { 58 | super(path); 59 | fields = content.split("\\s+"); 60 | } 61 | 62 | private Statm(Parcel in) { 63 | super(in); 64 | this.fields = in.createStringArray(); 65 | } 66 | 67 | /** 68 | * @return the total program size in bytes 69 | */ 70 | public long getSize() { 71 | return Long.parseLong(fields[0]) * 1024; 72 | } 73 | 74 | /** 75 | * @return the resident set size in bytes 76 | */ 77 | public long getResidentSetSize() { 78 | return Long.parseLong(fields[1]) * 1024; 79 | } 80 | 81 | @Override public void writeToParcel(Parcel dest, int flags) { 82 | super.writeToParcel(dest, flags); 83 | dest.writeStringArray(this.fields); 84 | } 85 | 86 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 87 | 88 | @Override public Statm createFromParcel(Parcel source) { 89 | return new Statm(source); 90 | } 91 | 92 | @Override public Statm[] newArray(int size) { 93 | return new Statm[size]; 94 | } 95 | }; 96 | 97 | } 98 | -------------------------------------------------------------------------------- /library/src/main/java/com/wenming/library/processutil/models/Status.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015. Jared Rummler 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.wenming.library.processutil.models; 19 | 20 | import android.os.Parcel; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | *

/proc/[pid]/status

26 | * 27 | *

Provides much of the information in /proc/[pid]/stat and /proc/[pid]/statm in a format that's 28 | * easier for humans to parse.

29 | * 30 | *

Here's an example:

31 | * 32 | *
 33 |  * $ cat /proc/$$/status
 34 |  * Name:   bash
 35 |  * State:  S (sleeping)
 36 |  * Tgid:   3515
 37 |  * Pid:    3515
 38 |  * PPid:   3452
 39 |  * TracerPid:      0
 40 |  * Uid:    1000    1000    1000    1000
 41 |  * Gid:    100     100     100     100
 42 |  * FDSize: 256
 43 |  * Groups: 16 33 100
 44 |  * VmPeak:     9136 kB
 45 |  * VmSize:     7896 kB
 46 |  * VmLck:         0 kB
 47 |  * VmPin:         0 kB
 48 |  * VmHWM:      7572 kB
 49 |  * VmRSS:      6316 kB
 50 |  * VmData:     5224 kB
 51 |  * VmStk:        88 kB
 52 |  * VmExe:       572 kB
 53 |  * VmLib:      1708 kB
 54 |  * VmPMD:         4 kB
 55 |  * VmPTE:        20 kB
 56 |  * VmSwap:        0 kB
 57 |  * Threads:        1
 58 |  * SigQ:   0/3067
 59 |  * SigPnd: 0000000000000000
 60 |  * ShdPnd: 0000000000000000
 61 |  * SigBlk: 0000000000010000
 62 |  * SigIgn: 0000000000384004
 63 |  * SigCgt: 000000004b813efb
 64 |  * CapInh: 0000000000000000
 65 |  * CapPrm: 0000000000000000
 66 |  * CapEff: 0000000000000000
 67 |  * CapBnd: ffffffffffffffff
 68 |  * Seccomp:        0
 69 |  * Cpus_allowed:   00000001
 70 |  * Cpus_allowed_list:      0
 71 |  * Mems_allowed:   1
 72 |  * Mems_allowed_list:      0
 73 |  * voluntary_ctxt_switches:        150
 74 |  * nonvoluntary_ctxt_switches:     545
 75 |  * 
76 | * 77 | *

The fields are as follows:

78 | * 79 | *
    80 | *
  1. Name: Command run by this process.
  2. 81 | *
  3. State: Current state of the process. One of "R (running)", "S (sleeping)", "D (disk 82 | * sleep)", 83 | * "T (stopped)", "T (tracing stop)", "Z (zombie)", or "X (dead)".
  4. 84 | *
  5. Tgid: Thread group ID (i.e., Process ID).
  6. 85 | *
  7. Pid: Thread ID (see gettid(2)).
  8. 86 | *
  9. PPid: PID of parent process.
  10. 87 | *
  11. TracerPid: PID of process tracing this process (0 if not being traced).
  12. 88 | *
  13. Uid, Gid: Real, effective, saved set, and filesystem UIDs (GIDs).
  14. 89 | *
  15. FDSize: Number of file descriptor slots currently allocated.
  16. 90 | *
  17. Groups: Supplementary group list.
  18. 91 | *
  19. VmPeak: Peak virtual memory size.
  20. 92 | *
  21. VmSize: Virtual memory size.
  22. 93 | *
  23. VmLck: Locked memory size (see mlock(3)).
  24. 94 | *
  25. VmPin: Pinned memory size (since Linux 3.2). These are pages that can't be moved because 95 | * something needs to directly access physical memory.
  26. 96 | *
  27. VmHWM: Peak resident set size ("high water mark").
  28. 97 | *
  29. VmRSS: Resident set size.
  30. 98 | *
  31. VmData, VmStk, VmExe: Size of data, stack, and text segments.
  32. 99 | *
  33. VmLib: Shared library code size.
  34. 100 | *
  35. VmPTE: Page table entries size (since Linux 2.6.10).
  36. 101 | *
  37. VmPMD: Size of second-level page tables (since Linux 4.0).
  38. 102 | *
  39. VmSwap: Swapped-out virtual memory size by anonymous private pages; shmem swap usage is not 103 | * included (since Linux 2.6.34).
  40. 104 | *
  41. Threads: Number of threads in process containing this thread.
  42. 105 | *
  43. SigQ: This field contains two slash-separated numbers that relate to queued signals for the 106 | * real user ID of this process. The first of these is the number of currently queued signals for 107 | * this real user ID, and the second is the resource limit on the number of queued signals for this 108 | * process (see the description of RLIMIT_SIGPENDING in getrlimit(2)).
  44. 109 | *
  45. SigPnd, ShdPnd: Number of signals pending for thread and for process as a whole (see 110 | * pthreads(7) and signal(7)).
  46. 111 | *
  47. SigBlk, SigIgn, SigCgt: Masks indicating signals being blocked, ignored, and caught (see 112 | * signal(7)).
  48. 113 | *
  49. CapInh, CapPrm, CapEff: Masks of capabilities enabled in inheritable, permitted, and 114 | * effective sets (see capabilities(7)).
  50. 115 | *
  51. CapBnd: Capability Bounding set (since Linux 2.6.26, see capabilities(7)).
  52. 116 | *
  53. Seccomp: Seccomp mode of the process (since Linux 3.8, see seccomp(2)). 0 means 117 | * SECCOMP_MODE_DISABLED; 1 means SECCOMP_MODE_STRICT; 2 means SECCOMP_MODE_FILTER. This field is 118 | * provided only if the kernel was built with the CONFIG_SECCOMP kernel configuration option 119 | * enabled.
  54. 120 | *
  55. Cpus_allowed: Mask of CPUs on which this process may run (since Linux 2.6.24, see 121 | * cpuset(7)).
  56. 122 | *
  57. Cpus_allowed_list: Same as previous, but in "list format" (since Linux 2.6.26, see 123 | * cpuset(7)).
  58. 124 | *
  59. Mems_allowed: Mask of memory nodes allowed to this process (since Linux 2.6.24, see 125 | * cpuset(7)).
  60. 126 | *
  61. Mems_allowed_list: Same as previous, but in "list format" (since Linux 2.6.26, see 127 | * cpuset(7)). 128 | * voluntary_ctxt_switches, nonvoluntary_ctxt_switches: Number of voluntary and involuntary context 129 | * switches (since Linux 2.6.23).
  62. 130 | *
131 | */ 132 | public final class Status extends ProcFile { 133 | 134 | /** 135 | * Read /proc/[pid]/status. 136 | * 137 | * @param pid 138 | * the process id. 139 | * @return the {@link Status} 140 | * @throws IOException 141 | * if the file does not exist or we don't have read permissions. 142 | */ 143 | public static Status get(int pid) throws IOException { 144 | return new Status(String.format("/proc/%d/status", pid)); 145 | } 146 | 147 | private Status(String path) throws IOException { 148 | super(path); 149 | } 150 | 151 | private Status(Parcel in) { 152 | super(in); 153 | } 154 | 155 | /** 156 | * Get the value of one of the fields. 157 | * 158 | * @param fieldName 159 | * the field name. E.g "PPid", "Uid", "Groups". 160 | * @return The value of the field or {@code null}. 161 | */ 162 | public String getValue(String fieldName) { 163 | String[] lines = content.split("\n"); 164 | for (String line : lines) { 165 | if (line.startsWith(fieldName + ":")) { 166 | return line.split(fieldName + ":")[1].trim(); 167 | } 168 | } 169 | return null; 170 | } 171 | 172 | /** 173 | * @return The process' UID or -1 if parsing the UID failed. 174 | */ 175 | public int getUid() { 176 | try { 177 | return Integer.parseInt(getValue("Uid").split("\\s+")[0]); 178 | } catch (Exception e) { 179 | return -1; 180 | } 181 | } 182 | 183 | /** 184 | * @return The process' GID or -1 if parsing the GID failed. 185 | */ 186 | public int getGid() { 187 | try { 188 | return Integer.parseInt(getValue("Gid").split("\\s+")[0]); 189 | } catch (Exception e) { 190 | return -1; 191 | } 192 | } 193 | 194 | public static final Creator CREATOR = new Creator() { 195 | 196 | @Override public Status createFromParcel(Parcel source) { 197 | return new Status(source); 198 | } 199 | 200 | @Override public Status[] newArray(int size) { 201 | return new Status[size]; 202 | } 203 | }; 204 | 205 | } 206 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Library 3 | 请为App打开辅助功能开关!! 4 | 5 | -------------------------------------------------------------------------------- /library/src/main/res/xml/detection_service_config.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/test/java/com/wenming/library/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.wenming.library; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/1.PNG -------------------------------------------------------------------------------- /sample/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/2.PNG -------------------------------------------------------------------------------- /sample/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/3.PNG -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.wenming.androidprocess" 9 | minSdkVersion 14 10 | targetSdkVersion 20 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | compile 'com.android.support:design:23.1.1' 27 | compile project(':library') 28 | compile 'com.commit451:PhotoView:1.2.4' 29 | } 30 | -------------------------------------------------------------------------------- /sample/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 D:\Android\AndroidSDK\sdk/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 | -------------------------------------------------------------------------------- /sample/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/qrcode.png -------------------------------------------------------------------------------- /sample/src/androidTest/java/com/wenming/androidprocess/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/Features.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess; 2 | 3 | /** 4 | * Created by wenmingvs on 2016/1/14. 5 | */ 6 | public class Features { 7 | public static int BGK_METHOD = 0; 8 | public static boolean showForeground = false; 9 | public static boolean showProfile = true; 10 | } 11 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.design.widget.TabLayout; 7 | import android.support.v4.view.ViewPager; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.Toolbar; 10 | import android.view.View; 11 | 12 | import com.wenming.andriodprocess.R; 13 | import com.wenming.androidprocess.Features; 14 | import com.wenming.androidprocess.adapter.ViewPagerAdapter; 15 | import com.wenming.androidprocess.fragment.OneFragment; 16 | import com.wenming.androidprocess.fragment.ProfileFragment; 17 | import com.wenming.androidprocess.service.MyService; 18 | import com.wenming.library.BackgroundUtil; 19 | 20 | 21 | public class MainActivity extends AppCompatActivity { 22 | 23 | private Toolbar toolbar; 24 | private TabLayout tabLayout; 25 | private ViewPager viewPager; 26 | private Context mContext; 27 | private Intent intent; 28 | 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_main); 34 | mContext = this; 35 | initToolBar(); 36 | initTabViewPager(); 37 | Features.showForeground = true; 38 | intent = new Intent(mContext, MyService.class); 39 | startService(intent); 40 | } 41 | 42 | private void initToolBar() { 43 | toolbar = (Toolbar) findViewById(R.id.toolbar); 44 | setSupportActionBar(toolbar); 45 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 46 | toolbar.setVisibility(View.GONE); 47 | } 48 | 49 | private void initTabViewPager() { 50 | viewPager = (ViewPager) findViewById(R.id.viewpager); 51 | ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); 52 | adapter.addFragment(new OneFragment(mContext), getString(R.string.tab1)); 53 | adapter.addFragment(new ProfileFragment(mContext), getString(R.string.tab3)); 54 | viewPager.setAdapter(adapter); 55 | tabLayout = (TabLayout) findViewById(R.id.tabs); 56 | tabLayout.setupWithViewPager(viewPager); 57 | viewPager.setCurrentItem(0, false); 58 | } 59 | 60 | @Override 61 | protected void onDestroy() { 62 | Features.showForeground = false; 63 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETRUNNING_TASK; 64 | stopService(intent); 65 | super.onDestroy(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/adapter/ViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by wenmingvs on 2016/1/14. 12 | */ 13 | public class ViewPagerAdapter extends FragmentPagerAdapter { 14 | private final List mFragmentList = new ArrayList<>(); 15 | private final List mFragmentTitleList = new ArrayList<>(); 16 | 17 | public ViewPagerAdapter(FragmentManager manager) { 18 | super(manager); 19 | } 20 | 21 | @Override 22 | public Fragment getItem(int position) { 23 | return mFragmentList.get(position); 24 | } 25 | 26 | @Override 27 | public int getCount() { 28 | return mFragmentList.size(); 29 | } 30 | 31 | public void addFragment(Fragment fragment, String title) { 32 | mFragmentList.add(fragment); 33 | mFragmentTitleList.add(title); 34 | } 35 | 36 | @Override 37 | public CharSequence getPageTitle(int position) { 38 | return mFragmentTitleList.get(position); 39 | } 40 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/fragment/OneFragment.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.fragment; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.CheckBox; 13 | import android.widget.CompoundButton; 14 | import android.widget.RelativeLayout; 15 | import android.widget.Toast; 16 | 17 | import com.wenming.andriodprocess.R; 18 | import com.wenming.androidprocess.Features; 19 | import com.wenming.androidprocess.service.MyService; 20 | import com.wenming.library.BackgroundUtil; 21 | 22 | import java.util.ArrayList; 23 | 24 | 25 | /** 26 | * Created by wenmingvs on 2016/1/14. 27 | */ 28 | public class OneFragment extends Fragment { 29 | 30 | private Context mContext; 31 | private View mView; 32 | 33 | private CheckBox checkBox1, checkBox2, checkBox3, checkBox4, checkBox5, checkBox6; 34 | private ArrayList reminderlist; 35 | 36 | @Override 37 | public void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | reminderlist = new ArrayList(); 40 | reminderlist.add(getResources().getString(R.string.reminder1)); 41 | reminderlist.add(getResources().getString(R.string.reminder2)); 42 | reminderlist.add(getResources().getString(R.string.reminder3)); 43 | reminderlist.add(getResources().getString(R.string.reminder4)); 44 | reminderlist.add(getResources().getString(R.string.reminder5)); 45 | reminderlist.add(getResources().getString(R.string.reminder6)); 46 | } 47 | 48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 49 | Bundle savedInstanceState) { 50 | mView = inflater.inflate(R.layout.fragment_one, container, false); 51 | initCheckBox(); 52 | layoutClick(); 53 | return mView; 54 | } 55 | 56 | @Override 57 | public void onViewStateRestored(@Nullable Bundle savedInstanceState) { 58 | super.onViewStateRestored(savedInstanceState); 59 | } 60 | 61 | public OneFragment(Context context) { 62 | mContext = context; 63 | } 64 | 65 | 66 | private void startService() { 67 | Features.showForeground = true; 68 | Intent intent = new Intent(mContext, MyService.class); 69 | mContext.startService(intent); 70 | } 71 | 72 | private void initCheckBox() { 73 | checkBox1 = (CheckBox) mView.findViewById(R.id.checkbox1); 74 | checkBox2 = (CheckBox) mView.findViewById(R.id.checkbox2); 75 | checkBox3 = (CheckBox) mView.findViewById(R.id.checkbox3); 76 | checkBox4 = (CheckBox) mView.findViewById(R.id.checkbox4); 77 | checkBox5 = (CheckBox) mView.findViewById(R.id.checkbox5); 78 | checkBox6 = (CheckBox) mView.findViewById(R.id.checkbox6); 79 | checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 80 | @Override 81 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 82 | if (isChecked == true) { 83 | startService(); 84 | deselectAll(); 85 | checkBox1.setChecked(true); 86 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETRUNNING_TASK; 87 | } 88 | } 89 | }); 90 | checkBox2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 91 | @Override 92 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 93 | if (isChecked == true) { 94 | startService(); 95 | deselectAll(); 96 | checkBox2.setChecked(true); 97 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETRUNNING_PROCESS; 98 | 99 | } 100 | } 101 | }); 102 | checkBox3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 103 | @Override 104 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 105 | if (isChecked == true) { 106 | startService(); 107 | deselectAll(); 108 | checkBox3.setChecked(true); 109 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETAPPLICATION_VALUE; 110 | 111 | } 112 | } 113 | }); 114 | checkBox4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 115 | @Override 116 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 117 | if (isChecked == true) { 118 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 119 | startService(); 120 | deselectAll(); 121 | checkBox4.setChecked(true); 122 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETUSAGESTATS; 123 | 124 | } else { 125 | Toast.makeText(mContext, "此方法需要在Android5.0以上才能使用!", Toast.LENGTH_SHORT).show(); 126 | checkBox4.setChecked(false); 127 | } 128 | } 129 | } 130 | }); 131 | 132 | checkBox5.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 133 | @Override 134 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 135 | if (isChecked == true) { 136 | startService(); 137 | deselectAll(); 138 | checkBox5.setChecked(true); 139 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETACCESSIBILITYSERVICE; 140 | } 141 | } 142 | }); 143 | checkBox6.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 144 | @Override 145 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 146 | if (isChecked == true) { 147 | startService(); 148 | deselectAll(); 149 | checkBox6.setChecked(true); 150 | Features.BGK_METHOD = BackgroundUtil.BKGMETHOD_GETLINUXPROCESS; 151 | } 152 | } 153 | }); 154 | 155 | 156 | } 157 | 158 | public void layoutClick() { 159 | RelativeLayout relativeLayout = (RelativeLayout) mView.findViewById(R.id.clearForeground); 160 | relativeLayout.setOnClickListener(new View.OnClickListener() { 161 | @Override 162 | public void onClick(View v) { 163 | Features.showForeground = false; 164 | Intent intent = new Intent(mContext, MyService.class); 165 | mContext.stopService(intent); 166 | deselectAll(); 167 | } 168 | }); 169 | } 170 | 171 | private void deselectAll() { 172 | checkBox1.setChecked(false); 173 | checkBox2.setChecked(false); 174 | checkBox3.setChecked(false); 175 | checkBox4.setChecked(false); 176 | checkBox5.setChecked(false); 177 | checkBox6.setChecked(false); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/fragment/ProfileFragment.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.view.KeyEvent; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.webkit.WebView; 11 | import android.webkit.WebViewClient; 12 | 13 | import com.wenming.andriodprocess.R; 14 | import com.wenming.androidprocess.Features; 15 | 16 | 17 | /** 18 | * Created by wenmingvs on 2016/1/14. 19 | */ 20 | public class ProfileFragment extends Fragment { 21 | private Context mContext; 22 | private View mView; 23 | private WebView mContentWv; 24 | 25 | public ProfileFragment(Context context) { 26 | mContext = context; 27 | } 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | } 33 | 34 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 35 | Bundle savedInstanceState) { 36 | mView = inflater.inflate(R.layout.profile_layout, container, false); 37 | mContentWv = (WebView) mView.findViewById(R.id.wv_webview_content); 38 | initWebView(); 39 | 40 | return mView; 41 | } 42 | 43 | private void initWebView() { 44 | if (Features.showProfile) { 45 | mContentWv.getSettings().setJavaScriptEnabled(true); 46 | mContentWv.loadUrl("https://github.com/wenmingvs"); 47 | mContentWv.setWebViewClient(new WebViewClient() { 48 | @Override 49 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 50 | view.loadUrl(url); 51 | return true; 52 | } 53 | }); 54 | 55 | mContentWv.setOnKeyListener(new View.OnKeyListener() { 56 | @Override 57 | public boolean onKey(View v, int keyCode, KeyEvent event) { 58 | if (event.getAction() == KeyEvent.ACTION_DOWN) { 59 | if (keyCode == KeyEvent.KEYCODE_BACK && mContentWv.canGoBack()) { //表示按返回键 60 | mContentWv.goBack(); //后退 61 | //webview.goForward();//前进 62 | return true; //已处理 63 | } 64 | } 65 | return false; 66 | } 67 | }); 68 | 69 | } 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/receiver/MyReceiver.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.wenming.androidprocess.Features; 8 | import com.wenming.androidprocess.service.MyService; 9 | 10 | 11 | /** 12 | * Created by wenmingvs on 2016/1/13. 13 | */ 14 | public class MyReceiver extends BroadcastReceiver { 15 | @Override 16 | public void onReceive(Context context, Intent intent) { 17 | if (Features.showForeground) { 18 | Intent i = new Intent(context, MyService.class); 19 | context.startService(i); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sample/src/main/java/com/wenming/androidprocess/service/MyService.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess.service; 2 | 3 | import android.app.AlarmManager; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.app.Service; 8 | import android.content.Context; 9 | import android.content.Intent; 10 | import android.os.IBinder; 11 | import android.os.SystemClock; 12 | import android.support.v4.app.NotificationCompat; 13 | import android.util.Log; 14 | 15 | import com.wenming.andriodprocess.R; 16 | import com.wenming.androidprocess.Features; 17 | import com.wenming.androidprocess.activity.MainActivity; 18 | import com.wenming.androidprocess.receiver.MyReceiver; 19 | import com.wenming.library.BackgroundUtil; 20 | 21 | import java.util.ArrayList; 22 | 23 | /** 24 | * Created by wenmingvs on 2016/1/13. 25 | */ 26 | public class MyService extends Service { 27 | 28 | private static final float UPDATA_INTERVAL = 0.5f;//in seconds 29 | private String status; 30 | private Context mContext; 31 | private ArrayList mContentList; 32 | private Notification notification; 33 | private AlarmManager manager; 34 | private PendingIntent pendingIntent; 35 | private NotificationCompat.Builder mBuilder; 36 | private Intent mIntent; 37 | private NotificationManager mNotificationManager; 38 | private static final int NOTICATION_ID = 0x1; 39 | 40 | @Override 41 | public IBinder onBind(Intent intent) { 42 | return null; 43 | } 44 | 45 | @Override 46 | public void onCreate() { 47 | super.onCreate(); 48 | mContext = this; 49 | mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 50 | initContentData(); 51 | startNotification(); 52 | } 53 | 54 | 55 | @Override 56 | public int onStartCommand(Intent intent, int flags, int startId) { 57 | if (Features.showForeground) { 58 | manager = (AlarmManager) getSystemService(ALARM_SERVICE); 59 | int updateTime = (int) UPDATA_INTERVAL * 1000; 60 | long triggerAtTime = SystemClock.elapsedRealtime() + updateTime; 61 | Intent i = new Intent(mContext, MyReceiver.class); 62 | PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0); 63 | manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi); 64 | updateNotification(); 65 | 66 | } else { 67 | stopForeground(true); 68 | mNotificationManager.cancelAll(); 69 | stopSelf(); 70 | } 71 | return Service.START_NOT_STICKY; 72 | } 73 | 74 | @Override 75 | public void onDestroy() { 76 | Features.showForeground = false; 77 | stopForeground(true); 78 | super.onDestroy(); 79 | } 80 | 81 | private void startNotification() { 82 | status = getAppStatus() ? "前台" : "后台"; 83 | mIntent = new Intent(mContext, MainActivity.class); 84 | pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT); 85 | mBuilder = new NotificationCompat.Builder(mContext) 86 | .setSmallIcon(R.drawable.largeicon) 87 | .setContentText(mContentList.get(Features.BGK_METHOD)) 88 | .setContentTitle("App处于" + status) 89 | .setAutoCancel(true) 90 | .setContentIntent(pendingIntent); 91 | notification = mBuilder.build(); 92 | startForeground(NOTICATION_ID, notification); 93 | } 94 | 95 | private void updateNotification() { 96 | status = getAppStatus() ? "前台" : "后台"; 97 | mBuilder.setContentTitle("App处于" + status); 98 | mBuilder.setContentText(mContentList.get(Features.BGK_METHOD)); 99 | if (Features.BGK_METHOD == BackgroundUtil.BKGMETHOD_GETACCESSIBILITYSERVICE) { 100 | mBuilder.setContentTitle("请到LogCat中观察前后台变化"); 101 | Log.d("wenming", "**方法五** App处于" + status); 102 | } 103 | notification = mBuilder.build(); 104 | mNotificationManager.notify(NOTICATION_ID, notification); 105 | } 106 | 107 | private void initContentData() { 108 | mContentList = new ArrayList(); 109 | mContentList.add("通过getRunningTask判断"); 110 | mContentList.add("通过getRunningAppProcess判断"); 111 | mContentList.add("通过ActivityLifecycleCallbacks判断"); 112 | mContentList.add("通过UsageStatsManager判断"); 113 | mContentList.add("通过AccessibilityService判断"); 114 | mContentList.add("通过LinuxCoreInfo判断"); 115 | } 116 | 117 | private boolean getAppStatus() { 118 | return BackgroundUtil.isForeground(mContext, Features.BGK_METHOD, mContext.getPackageName()); 119 | } 120 | 121 | 122 | } 123 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/clickbackground.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/effectivematrixlogo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/effectivematrixlogo.jpeg -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/image1.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/image2.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/largeicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/largeicon.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/logo.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/myicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/drawable-xhdpi/myicon.jpg -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 21 | 22 | 28 | 29 | 30 | 35 | 36 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_one.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 26 | 27 | 32 | 33 | 41 | 42 | 51 | 52 | 60 | 61 | 69 | 70 | 78 | 79 | 80 | 87 | 88 | 97 | 98 | 106 | 107 | 115 | 116 | 123 | 124 | 125 | 126 | 133 | 134 | 143 | 144 | 152 | 153 | 161 | 162 | 169 | 170 | 171 | 178 | 179 | 188 | 189 | 197 | 198 | 206 | 207 | 214 | 215 | 216 | 223 | 224 | 233 | 234 | 242 | 243 | 251 | 252 | 259 | 260 | 261 | 262 | 269 | 270 | 279 | 280 | 288 | 289 | 297 | 298 | 305 | 306 | 307 | 308 | 309 | 317 | 318 | 319 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/profile_layout.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenmingvs/AndroidProcess/0c05dd14279cc3dc32baffdbb94e76d5ead56f33/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sample/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FFFFFF 5 | #FFFFFF 6 | #000000 7 | 8 | 9 | #EEEEEE 10 | #FFFFFF 11 | 12 | 13 | #125688 14 | #125688 15 | #c8e8ff 16 | 17 | 18 | #E14638 19 | #E14638 20 | #F7B7B2 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 264dp 6 | 16dp 7 | 14sp 8 | 72dp 9 | 10 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ProcessDemo 3 | Settings 4 | Hello World from section: %1$d 5 | 6 | App是否后台方法 7 | 通知的样式 8 | 关于我 9 | 10 | 方法1:\ngetRunningTask方法在Android5.0以上已经被废弃,只会返回自己和系统的一些不敏感的task,不再返回其他应用的task,用此方法来判断自身App是否处于后台,仍然是有效的,但是无法判断其他应用是否位于前台,因为不再能获取信息 11 | 方法2:\ngetRunningAppProcesses方法在Nexus5上测试正常,但是在小米Note上测试失败,因为在聊天类型的App中,常常需要常驻后台来不间断的获取服务器的消息,如果把我们把Service设置成START_STICKY来保证Service重启来达到常驻后台的效果,就会被小米系统判断是前台,appProcess.importance的值永远都会是forground,所以无法区别前后台 12 | 方法3:\n通过ActivityLifecycleCallbacks来批量管理Activity的生命周期,进而实现判断,此方法在API 14以上均有效,\n\n\n注意:\n1. 请务必在Application中注册此回调接口 13 | 方法4:\n通过使用UsageStatsManager获取,此方法是Android5.0之后提供的新API,可以获取一个时间段内的应用统计信息\n\n\n注意:\n1. 务必提供在AndroidManifest中加入对应的权限\n2. 打开手机设置,点击安全-高级,在有权查看使用情况的应用中,为这个App打上勾 14 | 方法5:\nLinux系统内核会把Process进程信息保存在/proc目录下,通过遍历进程的属性信息来判断位于前台的任一应用 15 | 方法6:\n通过Android自带的无障碍功能,监控窗口焦点的变化,进而拿到当前焦点窗口对应的包名 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 | 23 | 24 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /sample/src/test/java/com/wenming/androidprocess/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.wenming.androidprocess; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':sample', ':library' 2 | --------------------------------------------------------------------------------