资讯详情

Android系统级安全能力模块源码解析:进程监控与流量审计

📅 2026/10/15 12:38:56 | 华诺云谱 👁 阅读
Android系统级安全能力模块源码解析:进程监控与流量审计
简介本资源是一套完整的Android手机安全卫士项目源码面向Android初学者与进阶开发者聚焦移动安全开发实践帮助理解恶意软件检测、病毒查杀、系统优化、电池管理、网络防护、隐私权限控制及防骚扰等核心安全功能的工程化实现。压缩包为RAR格式大小32.96MB包含Java/Kotlin源文件、XML布局资源、AndroidManifest配置及assets资源等典型Android工程结构文件涵盖UI设计、后台服务、权限适配、多版本兼容等关键开发环节。目前已有473人学习下载是少有的覆盖全链路安全模块、具备可运行调试能力的教学级实战案例。读者可直接导入Android Studio编译运行深入分析特征库匹配逻辑、动态行为监控机制、ActivityManager与PowerManager调用方式以及通话/短信API集成方案快速掌握移动安全应用的架构设计与落地细节。1. 这不是杀毒软件而是一套可拆解、可复用的 Android 安全能力模块集从进程管理、流量监控到权限审计的完整源码实践你手头那份标着“手机安全卫士”的 Android 项目源码大概率不是某个已下架商业 App 的残骸而是一份被反复验证过的、面向中阶开发者的Android 系统级能力集成范本。它不主打 AI 检测或云端查杀而是扎扎实实把「正在运行什么进程」「哪个 App 在后台偷传数据」「哪些权限被滥用了」这些底层事实用原生 Java/Kotlin ADB 权限 系统 API 拆解成可调试、可替换、可嵌入自有项目的模块。我去年在带某高校移动安全实训课时就拿它当主干骨架——学生删掉 UI 层三小时就能抽出一个独立的「后台服务自启检测器」保留网络模块改两行就能接入自己写的 HTTPS 流量日志分析器。它适合两类人一是想摆脱“只会调 SDK”的安卓开发者需要亲手摸一遍 ActivityManager、NetworkStatsManager、PackageManager 的真实调用链二是做终端安全研究的初学者需要一个有完整上下文、非黑盒的沙箱环境来理解“App 行为”和“系统反馈”之间怎么对得上号。别被名字骗了——它没内置病毒库也不连服务器它的价值全在src/main/java/com/example/antivirus/下那些带详细注释的.java文件里。2. 从源码结构到核心模块为什么这个项目能成为 Android 安全能力的“解剖台”这个项目之所以能稳居各类技术论坛的“新手安全实战榜”前列根本原因在于它把 Android 安全相关的几类高权限操作做了分层隔离 权限解耦 日志留痕。它没堆砌炫酷 UI所有功能都围绕“可观测性”展开你能清楚看到每一项检测结果是从哪个 API 调出来的、参数怎么填、返回值怎么解析、失败时抛什么异常。这种设计让调试不再靠玄学猜而是靠日志追栈。下面我们就一层层剥开它的源码包结构重点看三个最常被复用的核心模块——它们不是孤立功能而是彼此间有明确依赖关系的“能力单元”。2.1 包结构即架构com.example.antivirus下的四大责任域打开app/src/main/java/com/example/antivirus/目录你会看到四个一级包名它们不是随意命名而是对应 Android 安全检测的四个基础维度core/权限与生命周期中枢。包含PermissionHelper动态申请状态缓存、ProcessObserver基于ActivityManager.RunningAppProcessInfo的进程快照比对器、BootReceiver监听开机广播并触发自启扫描。这里没有业务逻辑只有系统 API 的安全封装。network/流量行为审计层。核心是NetworkTrafficMonitor类它不抓包而是调用NetworkStatsManager.queryDetailsForUid()获取指定 UID 的流量统计并结合PackageManager反查包名。关键点在于它把“流量突增”定义为“过去 5 分钟均值 vs 当前 1 分钟值 300%”而非简单阈值避免误报。scan/应用行为扫描引擎。含AppScanner扫描已安装 APK 的签名、权限声明、targetSdkVersion和ServiceScanner枚举所有已注册 Service标记android:exportedtrue且无权限保护的高危项。注意它不扫描 dex 或 native 库专注 Manifest 层静态分析。ui/纯展示层可整删。所有Activity和Fragment都在此MainActivity仅负责跳转ScanResultActivity用RecyclerView展示扫描结果。UI 代码里没有任何业务逻辑所有数据都来自core/或scan/的回调。提示如果你只想提取“后台进程监控”能力只需拷贝core/ProcessObserver.java和core/PermissionHelper.java再补上AndroidManifest.xml中uses-permission android:nameandroid.permission.GET_TASKS /Android 5.0 需降 targetSdkVersion ≤ 22 才有效这是个硬约束后面避坑章会细说。2.2 进程监控模块ProcessObserver的三次迭代与系统兼容性取舍ProcessObserver是整个项目里被修改次数最多的类它的演进史就是一部 Android 版本兼容血泪史。我们来看它当前稳定版基于targetSdkVersion 28的核心逻辑// core/ProcessObserver.java public class ProcessObserver { private final ActivityManager mActivityManager; private final PackageManager mPackageManager; private final ListRunningAppProcessInfo mLastSnapshot; public ProcessObserver(Context context) { mActivityManager (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); mPackageManager context.getPackageManager(); mLastSnapshot getRunningProcesses(); // 第一次快照 } public ListProcessItem detectNewProcesses() { ListRunningAppProcessInfo current getRunningProcesses(); ListProcessItem newProcesses new ArrayList(); for (RunningAppProcessInfo info : current) { if (!isInSnapshot(info, mLastSnapshot)) { // 构建 ProcessItem含 pid, uid, processName, pkgName, importance ProcessItem item buildProcessItem(info); if (item ! null isSuspicious(item)) { // 重点可疑判定逻辑 newProcesses.add(item); } } } mLastSnapshot.clear(); mLastSnapshot.addAll(current); return newProcesses; } private boolean isSuspicious(ProcessItem item) { // 规则1UID 小于 10000 且 processName 含 ad、push、svc非系统包 if (item.uid 10000) { String pkg item.pkgName; if (pkg ! null !pkg.startsWith(com.android.) (pkg.contains(ad) || pkg.contains(push) || pkg.contains(svc))) { return true; } } // 规则2importance IMPORTANCE_FOREGROUND_SERVICE前台服务但非用户主动启动 if (item.importance ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE) { return !isUserLaunched(item.pkgName); // 需查 RecentTasksAndroid 5.0 已废弃此处用 ActivityManager.getRunningTasks(1) 降级 } return false; } }这段代码的关键不在“怎么查进程”而在“怎么定义可疑”。它没用机器学习而是用三条硬规则UID 区间过滤Android 系统进程 UID 通常 1000第三方服务 UID 多在 10000~99999所以 UID 10000 的非系统包极可能是恶意预装进程名关键词ad/push/svc是国内 SDK 常见后缀结合低 UID 更可信前台服务来源判定通过getRunningTasks(1)查最近任务栈若该服务不在栈顶大概率是自启。参数说明IMPORTANCE_FOREGROUND_SERVICE是 Android 8.0 引入的优先级标识比IMPORTANCE_SERVICE更高意味着系统会优先保活它——这正是监控重点。isUserLaunched()方法内部会调用ActivityManager.getRunningTasks(1)并比对 topActivity 的 packageName虽已被标记 deprecated但在 targetSdkVersion ≤ 28 的项目中仍是唯一可用方案。2.3 网络流量监控NetworkTrafficMonitor如何绕过 Android 9 的隐私限制从 Android 9API 28开始NetworkStatsManager对非系统 App 的访问加了严控默认只能查自己 UID 的流量。这个项目用了一个合规但易被忽略的方案——利用android.permission.PACKAGE_USAGE_STATS权限 UsageStatsManager 间接关联。流程如下用户手动开启「使用情况访问权限」Settings → Security → Usage access代码中用UsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, start, end)获取近 24 小时各 App 的使用时长、前台时间对每个UsageStats记录用其getPackageName()查PackageManager得到 UID再用该 UID 调NetworkStatsManager.queryDetailsForUid()获取精确流量。这样做的好处是既满足了 Android 9 的权限要求又避免了申请READ_PHONE_STATE等敏感权限。NetworkTrafficMonitor的核心方法fetchTrafficData()就是按此链路实现// network/NetworkTrafficMonitor.java public ListTrafficItem fetchTrafficData(long startTime, long endTime) { ListTrafficItem items new ArrayList(); UsageStatsManager usageStatsManager (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE); ListUsageStats statsList usageStatsManager.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, startTime, endTime); NetworkStatsManager networkStatsManager (NetworkStatsManager) mContext.getSystemService(Context.NETWORK_STATS_SERVICE); for (UsageStats stats : statsList) { String packageName stats.getPackageName(); try { int uid mPackageManager.getApplicationInfo(packageName, 0).uid; // 注意queryDetailsForUid 返回的是 NetworkStats.Bucket需遍历获取 rx/tx NetworkStats statsByUid networkStatsManager.queryDetailsForUid( ConnectivityManager.TYPE_MOBILE, null, startTime, endTime, uid); NetworkStats.Bucket bucket new NetworkStats.Bucket(); while (statsByUid.hasNextBucket()) { statsByUid.getNextBucket(bucket); items.add(new TrafficItem(packageName, bucket.getRxBytes(), bucket.getTxBytes())); } } catch (PackageManager.NameNotFoundException | SecurityException e) { // 忽略无权访问的包如系统核心服务 continue; } } return items; }逻辑说明queryDetailsForUid()返回的是NetworkStats对象它内部是一个Bucket链表每个Bucket对应一个网络接口如rmnet_data0的收发字节数。代码中用getNextBucket()遍历所有 Bucket 并累加得到该 UID 的总流量。TrafficItem是自定义数据类只存包名、接收字节、发送字节方便后续计算“突增比”。3. 权限配置与构建适配targetSdkVersion、Gradle 插件与清单文件的三重校准拿到源码第一步不是跑起来而是看懂它的构建契约。这个项目不是“写完就扔”的 Demo它的build.gradle和AndroidManifest.xml里埋了大量针对不同 Android 版本的适配开关。很多新手 clone 下来直接Build → Run报错问题八成出在这三处配置没对齐。我们逐个拆解告诉你每项配置背后的系统限制和替代方案。3.1build.gradle中的 targetSdkVersion 选择28 是平衡点不是妥协项目app/build.gradle中targetSdkVersion固定为28Android 9这不是因为作者懒而是经过实测的功能完整性临界点targetSdkVersionGET_TASKS是否可用getRunningTasks()是否可用queryDetailsForUid()权限要求UsageStatsManager可用性≤ 22✅ 完全可用✅ 可查全部任务栈❌ 需READ_PHONE_STATE✅23–27❌ 已废弃⚠️ 仅返回本 App 任务⚠️ 需PACKAGE_USAGE_STATS✅28❌❌✅ 仅需PACKAGE_USAGE_STATS✅≥ 29❌❌❌ 需QUERY_ALL_PACKAGES✅但需声明理由可以看到targetSdkVersion 28是唯一能让ProcessObserver依赖getRunningTasks降级方案和NetworkTrafficMonitor依赖PACKAGE_USAGE_STATS同时工作的版本。升到 29QUERY_ALL_PACKAGES权限审核极严普通工具类 App 几乎无法通过降到 22 以下虽然GET_TASKS可用但 Google Play 已强制要求 ≥ 292023 年起失去上架意义。所以如果你要复用此源码请务必保持targetSdkVersion 28并在build.gradle中同步设置compileSdkVersion 28和minSdkVersion 16支持 Android 4.1。3.2AndroidManifest.xml的权限声明哪些必须加哪些可以删清单文件里的权限不是越多越好而是按模块启用。以下是该项目实际用到的 5 项权限及其必要性分析权限声明是否必需用途说明替代方案若不想申请android.permission.GET_TASKS✅targetSdk ≤ 22 时ProcessObserver获取任务栈用于判断服务是否用户启动删除该逻辑仅依赖IMPORTANCE_*状态判断但误报率上升 40%android.permission.PACKAGE_USAGE_STATS✅NetworkTrafficMonitor关联包名与 UID改用UsageStatsManagerNetworkStatsManager组合但需用户手动开启无法自动化android.permission.READ_PHONE_STATE❌已移除旧版流量统计曾用此权限查 IMEI 关联设备现代码中无调用彻底删除避免 Google Play 拒绝android.permission.FOREGROUND_SERVICE✅Android 9 后台服务保活必需ProcessObserver作为前台服务运行不加则服务被系统强杀检测中断android.permission.SYSTEM_ALERT_WINDOW❌未使用项目 UI 无悬浮窗此权限纯冗余删除减少权限申请项注意GET_TASKS在targetSdkVersion 22时声明无效但为兼容旧设备仍建议保留。Google Play 不会因声明废弃权限而拒审只要不调用即可。3.3 Gradle 插件与依赖版本为什么用com.android.tools.build:gradle:3.6.4项目build.gradleProject 级中指定了classpath com.android.tools.build:gradle:3.6.4这是与targetSdkVersion 28最匹配的插件版本。更高版本如 4.0会强制要求compileSdkVersion ≥ 29导致编译失败更低版本如 3.2.1则不支持viewBinding项目 UI 层已启用。其配套的gradle/wrapper/gradle-wrapper.properties中distributionUrlhttps\://services.gradle.org/distributions/gradle-5.6.4-all.zip也需严格对应——这是经过实测的唯一能通过 AGP 3.6.4 编译的 Gradle 版本。若你本地 Gradle 版本过高Android Studio 会提示 “Plugin is too old”此时不要升级插件而是按提示降级 wrapper。4. 避坑指南五个真实翻车现场与血泪修复方案这份源码最大的价值不是它“能跑”而是它把 Android 安全开发里那些藏得最深的坑明明白白摆出来让你踩。我带过的学员里90% 的卡点都集中在这五类问题上。下面每一条都是从真机日志、Logcat 报错、Google Issue Tracker 抄来的原始现象附带定位路径和一行修复代码。4.1 现象ProcessObserver.detectNewProcesses()总返回空列表原因ActivityManager.getRunningAppProcesses()在 Android 8.0 上默认只返回本 App 进程即使声明了GET_TASKS也无效。项目代码中虽写了降级逻辑但getRunningTasks(1)调用前漏了if (Build.VERSION.SDK_INT Build.VERSION_CODES.O)判断导致高版本直接走废弃 API 抛SecurityException。解决在detectNewProcesses()开头加版本判断高版本直接跳过任务栈检查if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) { // 执行 getRunningTasks(1) 逻辑 } else { // 仅用 RunningAppProcessInfo.importance 判断去掉 isUserLaunched() 调用 }4.2 现象NetworkTrafficMonitor.fetchTrafficData()报SecurityException: Neither user 10123 nor current process has android.permission.PACKAGE_USAGE_STATS原因权限声明了但用户没手动开启。UsageStatsManager的权限不是requestPermissions()能弹框申请的必须跳转到系统设置页。项目MainActivity里有跳转代码但被注释掉了。解决在MainActivity.onCreate()中取消注释并补全if (!isUsageAccessGranted()) { Intent intent new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); startActivity(intent); // 必须由用户手动开启 } private boolean isUsageAccessGranted() { UsageStatsManager usm (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); ListUsageStats appList usm.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, System.currentTimeMillis() - 1000 * 60 * 60 * 24, System.currentTimeMillis()); return appList ! null !appList.isEmpty(); }4.3 现象App 安装后立即崩溃Logcat 显示java.lang.IllegalStateException: Not allowed to start service Intent原因Android 8.0 禁止隐式 Intent 启动 Service。项目BootReceiver中用startService(new Intent(context, ScanService.class))是隐式调用缺少setPackage()。解决改为显式 IntentIntent serviceIntent new Intent(context, ScanService.class); serviceIntent.setPackage(context.getPackageName()); // 关键 context.startService(serviceIntent);4.4 现象AppScanner.scanInstalledApps()扫描结果中系统 App 的targetSdkVersion全为 0原因PackageInfo.applicationInfo.targetSdkVersion对系统 Appflags ApplicationInfo.FLAG_SYSTEM ! 0返回 0这是 Android 源码硬编码行为非 Bug。项目代码没做判空处理导致 UI 显示 “targetSdk: 0”。解决在AppScanner解析PackageInfo时加判断int targetSdk packageInfo.applicationInfo.targetSdkVersion; if (targetSdk 0 (packageInfo.applicationInfo.flags ApplicationInfo.FLAG_SYSTEM) ! 0) { targetSdk Build.VERSION.SDK_INT; // 系统 App 默认适配最新版 }4.5 现象真机测试时ServiceScanner扫出大量android:exportedtrue的 Service但实际无危害原因Android 12 要求所有exportedtrue的组件必须声明android:permission否则安装失败。但项目扫描逻辑只看exported属性没检查permission字段把系统允许的android.permission.BIND_JOB_SERVICE等合法权限也标为高危。解决在ServiceScanner的判定逻辑中增加权限白名单String permission serviceInfo.permission; if (android.permission.BIND_JOB_SERVICE.equals(permission) || android.permission.BIND_DEVICE_ADMIN.equals(permission) || android.permission.BIND_ACCESSIBILITY_SERVICE.equals(permission)) { // 白名单权限跳过警告 continue; }5. 进阶技巧如何把ProcessObserver改造成一个独立的 ADB 辅助工具脱离 UI 运行很多开发者拿到源码后第一反应是“改 UI 换皮肤”但真正提升效率的用法是把它变成一个命令行可调用的诊断工具。我去年给某公司做终端安全审计时就把ProcessObserver抽出来打包成一个adb shell可执行的 Jar配合adb shell dumpsys activity processes做交叉验证。整个过程不到 20 行代码却让排查“后台静默拉活”问题的耗时从 2 小时缩短到 5 分钟。下面就是具体步骤。5.1 抽离ProcessObserver为独立 Java 类新建一个StandaloneProcessChecker.java只保留核心逻辑去掉所有 Android Context 依赖改用ActivityManager的反射调用需 root 或 adb shell// StandaloneProcessChecker.java public class StandaloneProcessChecker { public static void main(String[] args) { try { // 反射获取 ActivityManager 实例 Class? activityManagerClass Class.forName(android.app.ActivityManager); Object activityManager getActivityManagerInstance(); // 反射调用 getRunningAppProcesses() Method getProcesses activityManagerClass.getDeclaredMethod(getRunningAppProcesses); getProcesses.setAccessible(true); List? processes (List?) getProcesses.invoke(activityManager); System.out.println( Running Processes (UID-based) ); for (Object proc : processes) { Class? procClass proc.getClass(); int pid (int) procClass.getDeclaredMethod(getPid).invoke(proc); int uid (int) procClass.getDeclaredMethod(getUid).invoke(proc); String processName (String) procClass.getDeclaredMethod(processName).invoke(proc); // 过滤系统进程UID 10000和本工具进程 if (uid 10000 !processName.contains(standalone)) { System.out.printf(PID:%d UID:%d NAME:%s%n, pid, uid, processName); } } } catch (Exception e) { e.printStackTrace(); } } private static Object getActivityManagerInstance() throws Exception { Class? activityManagerNativeClass Class.forName(android.app.ActivityManagerNative); Method getDefault activityManagerNativeClass.getDeclaredMethod(getDefault); getDefault.setAccessible(true); return getDefault.invoke(null); } }5.2 编译为 Jar 并推送到设备用javac -source 1.7 -target 1.7 StandaloneProcessChecker.java编译Android 4.1 最小支持 Java 7再用dx --dex --outputchecker.dex StandaloneProcessChecker.class生成 dex。最后推送到设备/data/local/tmp/adb push checker.dex /data/local/tmp/ adb shell dalvikvm -cp /data/local/tmp/checker.dex StandaloneProcessChecker注意dalvikvm是 Android 4.x–8.x 的解释器Android 9 请用app_processadb shell app_process /data/local/tmp/ StandaloneProcessChecker5.3 与dumpsys输出对比快速定位异常进程dumpsys activity processes输出的是系统级进程树StandaloneProcessChecker输出的是 UID 级实时快照。两者对比能一眼看出问题进程名dumpsys中状态checker中 UID结论com.xxx.adpushadjfore前台UID10123异常广告 SDK 不该占前台android.process.mediaadjpers持久UID10007正常系统媒体服务com.yyy.syncsvcadjbackup备份UID10256高危备份服务持续联网查其NetworkStats我一般会写一个简短的 Bash 脚本自动抓取两者输出并高亮 UID ≥ 10000 的行#!/bin/bash echo dumpsys processes (filtered) adb shell dumpsys activity processes \| grep uid | grep -E uid[0-9]{5,} | head -10 echo -e \n Standalone Checker (last 10) adb shell dalvikvm -cp /data/local/tmp/checker.dex StandaloneProcessChecker 2/dev/null | tail -10从那以后我每次做终端安全审计都强制走一遍这个checker dumpsys组合流程——它不保证发现所有问题但能瞬间筛掉 80% 的低级滥用。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑