# 安卓demo **Repository Path**: null_775_7982/android-demo ## Basic Information - **Project Name**: 安卓demo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master_dev1.0 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-20 - **Last Updated**: 2026-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Android Demo Framework 这是一个 Java/AndroidX 双模块示例工程,包含通用 Activity/Fragment、MVP、网络、WebView、扫码、权限、图片、文件、定位、支付与分享等能力。 本次审查覆盖 `app`、`mylibrary` 的构建配置、Manifest、资源和全部 **182 个 Java 文件(约 4.31 万行)**。审查基线为 Android Gradle Plugin 8.12.2、Gradle 8.13、Java 11、compile/target SDK 35、min SDK 22。 ## 当前状态 - `gradlew clean assembleDebug lintDebug`:通过。 - 整改前 Lint:`mylibrary` 7 errors / 189 warnings;继续检查 `app` 后另发现 2 errors。 - 整改后 Lint:`app` 0 errors / 159 warnings,`mylibrary` 0 errors / 183 warnings。 - Debug APK:`build/app/outputs/apk/debug/android-demo_v1.0.0_debug.apk`。 - Lint 报告:`build/app/reports/lint-results-debug.html`、`build/mylibrary/reports/lint-results-debug.html`。 Lint 警告包含第三方 native library 的 16 KB 页对齐、旧 API、无障碍、国际化和资源适配问题。它们不阻断当前构建,但发布前仍应按本文优先级继续处理。 ## 架构概览 ```text app ├─ app/manager Application、Activity 栈、语言、网络初始化 ├─ base Activity/Fragment/Dialog/Popup/WebView 基类 ├─ mvp 传统 MVP 生命周期桥接及示例 ├─ liveDataBus/eventbus 两套进程内事件机制 ├─ widget/webView WebView、JS Bridge、权限与文件选择 ├─ thirdAppUtil 地图、定位、支付、微信和友盟分享 └─ ui 启动、引导、首页与复制示例 mylibrary ├─ action Context/View/跳转/Toast 等默认接口 ├─ http OkGo 回调、转换、错误和数据模型 ├─ scaner Camera1 + ZXing 扫码链路 ├─ utils 文件、网络、设备、日期、图片等工具 ├─ permissionUtil XXPermissions 二次封装 └─ view 输入框、状态页、评分与大图控件 ``` 总体判断:工程可编译、能力较全,但不是“空白项目”。它是一个积累多年的综合工具框架,存在职责过宽、旧 API 较多、依赖外溢和多套同类机制并存的问题。短期应以安全与稳定修复为主,长期应拆分 library 能力并收窄公开 API。 ## 本轮已修复 | 优先级 | 问题 | 修复前 | 本次调整 | 直接收益 | |---|---|---|---|---| | P0 | HTTPS 信任任意证书 | OkGo 使用无校验 SSL SocketFactory,可被中间人攻击 | 恢复 OkHttp 系统证书链和主机名校验 | HTTPS 证书无效时连接失败,保护 Token 和业务数据 | | P0 | 发布签名泄露/未签名发布 | JKS 路径、别名和密码写在 `app/build.gradle`,缺失配置时可生成未签名 Release | 改为 Gradle properties 注入;Debug 使用默认 debug keystore;Release 缺少参数即失败 | 避免继续暴露凭据或误发布未签名包 | | P0 | WebView 基类启动崩溃 | `BaseWebViewActivity` 未绑定 WebView/ProgressBar 就使用 | 在 `initView` 绑定控件,补状态恢复并完整销毁 WebView | 基类被使用时可正常打开,减少 Activity/WebView 泄漏 | | P0 | Manifest 引用不存在类 | 声明了不存在的抖音、钉钉回调 Activity | 删除无效声明;保留依赖已有入口 | Lint 错误消除,避免回调启动失败 | | P1 | Application 非法构造 | `getInstance()` 在为空时 `new MyApplication()` | 未初始化时明确抛出异常 | 不再产生未 attach 的伪 Application/Context | | P1 | Wi-Fi 扫描递归 | 扫描失败后无终止递归调用自身 | 取消递归;补权限和异常处理;返回非空的系统缓存列表 | 避免栈溢出、权限拒绝崩溃,并兼容 Android 扫描限频 | | P1 | 网络权限崩溃 | 直接访问 Telephony/Wi-Fi 受限 API | 运行时权限检查并捕获 `SecurityException` | Android 6+ 拒绝权限时安全降级 | | P1 | Cursor 泄漏/非法列 | Cursor 不关闭,`getColumnIndex=-1` 仍读取 | try-with-resources + 列索引校验 | 消除资源泄漏与越界崩溃 | | P1 | LiveDataBus 漏事件/乱序 | 毫秒时间判断新旧;并发建通道覆盖;`postValue` 合并高频事件 | 原子序列号、`putIfAbsent`、单一主线程队列逐个 `setValue` | 判定稳定、跨线程发送/清除顺序一致、连续事件不合并 | | P1 | JS Bridge 注入/释放 | 未从 WebView 移除接口;字符串转义不完整;任意方法名拼接 | 移除接口、JSON 转义、校验 JS 标识符、主线程执行 | 降低注入面及销毁后残留风险 | | P1 | WebView 宽松配置 | 允许混合内容、文件访问、保存密码 | 全部关闭,SSL 错误直接取消 | 缩小本地文件和明文内容攻击面 | | P1 | WebView 销毁时重建 Client | 传 null 给封装方法会创建新 Client | 销毁时直接给父类设置 null | 正确断开 Activity/Client 引用 | | P1 | JS Bridge 销毁竞争 | LiveData 赋 null,异步 JS 仍可能调用 | 保留 LiveData,增加 destroyed 状态 | 避免竞争性空指针 | | P1 | AccessToken 日志泄露 | BODY 日志常开并输出 Token 明文 | 日志跟随 `BuildConfig.DEBUG`,不打印 Token | Release 不泄露请求正文和认证信息 | | P1 | 启动页延迟任务 | Handler 延迟任务不可取消 | Handler 成员化并在销毁时清理 | 页面提前退出时不继续跳转 | | P1 | MVP 空引用 | attach 前调用 `getView()` 会 NPE | 空安全读取弱引用 | Presenter 边界调用安全 | | P2 | 动态依赖不可复现 | 多个 `+` / `latest` 版本 | 固定为本次解析成功的版本 | CI 与开发机依赖一致 | | P2 | 明文/备份默认开启 | `allowBackup`、`usesCleartextTraffic` 为 true | 关闭备份;按现有后端要求保留全局 HTTP,并仅在 Debug 信任用户抓包证书 | 保持明文后端兼容性,避免 Release 信任用户证书 | | P2 | library 污染宿主 | library 设置 label、backup、RTL | Application 节点只保留组件 | 宿主自行决定全局策略 | 注意:仓库中的 `app/fjwl.jks` 曾与密码一起提交。本次没有删除该文件,以免破坏既有发布流程,但原凭据应视为已经泄露:请轮换正式签名/密码,并把正式 keystore 移到仓库外。 ## 团队签名配置 仓库只提交 `signing.properties.example`,不提交实际的 `app/signing.properties`。成员在 `app` 目录复制模板后填写与 `app/fjwl.jks` 对应的团队签名信息;CI 使用同名 Gradle properties 或 Secret 注入。Gradle 属性优先于本地文件,因此 CI 不需要保留本地签名文件。 ## 仍需整改的重点 ### P0:发布前必须确认 1. **第三方 Key 仍在源码/Manifest**:百度 Key、友盟 Key、Bugly/微信占位值应改为 `local.properties`、CI Secret 或受控 Gradle property,经 `manifestPlaceholders` / `BuildConfig` 注入。进入 Git 历史的真实 Key 应在平台轮换。 2. **权限过宽**:当前申请 `MANAGE_EXTERNAL_STORAGE`、后台定位、电话状态、写系统设置、安装 APK、日历、蓝牙、麦克风等权限。应按真实功能拆分并删除不用项,尤其 `MANAGE_EXTERNAL_STORAGE` 涉及商店专项审核。 3. **Release 未混淆**:`minifyEnabled false` 增加包体和逆向风险。开启前需补全分享、地图、支付、Gson、OkGo 等规则并完整回归。 4. **native 16 KB 页对齐**:Lint 指向百度地图、百度定位、MMKV 等 `.so`。需升级至供应商明确支持 16 KB page size 的版本,并在相应模拟器或真机验证,不能用 suppress 解决。 5. **回调接入不完整**:抖音入口由友盟库声明;钉钉若启用回调,必须按最终 applicationId 和平台文档新增真实 Activity。 ### P1:稳定性与兼容性 1. `PermissionTipDialogUtils` 使用静态 `Dialog`,可能持有已销毁 Activity。建议改为 Activity 实例持有或 `DialogFragment`。 2. `CameraManager` 静态单例持有 Context;`ActivityScanerCode_Two` 两个非静态 Handler 有泄漏风险。建议统一迁移 CameraX + LifecycleOwner,至少先改 Application Context、静态 Handler + WeakReference。 3. `RxNetworkMgr` 大量依赖弃用的 `NetworkInfo`、隐藏 API 和网络开关。建议新增 `NetworkCapabilities` 实现,旧接口标记弃用,并删除普通应用无法可靠执行的 `setDataEnabled`。 4. `RxFileTool`、`RxFileUtils`、`RxPhotoTool` 大量依赖绝对路径和 `MediaStore.DATA`。Android 10+ 应使用 `content://`、SAF 和 scoped storage,避免 Uri 强转 File。 5. `RxRootUtil`、`RxSilentInstall` 运行 `su`。只应存在于明确的设备所有者/系统应用产品线;普通应用建议移除。 6. `BaseActivity`、`BaseFragment`、`BaseDialog`、`BasePopupWindow` 分别约 872/739/1508/746 行。应拆成导航、权限、加载状态、系统栏、结果回调组件,以 LifecycleObserver 释放。 7. `BaseWebViewActivity` 和 `BrowserWebView` 是两套配置,长期会再次漂移。建议只保留 `BrowserWebView`,并在加载前增加 HTTPS/域名 allowlist。 8. `LiveDataBus` 和 EventBus 并存,事件来源难追踪。新代码只选一种;页面事件优先 ViewModel/显式接口。 ### P2:维护性、性能与体验 1. `mylibrary` 几乎所有依赖使用 `api`,导致地图、分享、相机等全部外溢。内部依赖改 `implementation`,并拆为 core/network/scanner/location/share 模块。 2. 本地 OkGo JAR、旧 OkHttp 3.8.1、Chuck 1.1.0、RxJava 2 和大量 SDK 并存。应建立版本目录后按模块逐个升级。 3. 17 个 locale 警告可能导致土耳其语环境大小写错误。协议、扩展名、哈希统一使用 `Locale.ROOT`。 4. `android.media.ExifInterface` 应替换为 AndroidX 实现。 5. 状态栏/导航栏高度通过内部资源或反射读取,应迁移 `WindowInsetsCompat`。 6. 硬编码文本、dp 字号、RTL、contentDescription、键盘不可达和位图 density 警告应分批清理。 7. 当前无测试。优先覆盖事件总线、坐标转换、日期/校验/加密;WebView、权限、启动流程用仪器测试。 8. AspectJ 在 JavaCompile 后织入且使用旧接口,存在 Gradle 9 风险。中期改稳定插件或普通点击防抖组件。 ## 全类审查索引 以下逐包列出全部 Java 文件。**已修**表示本轮有整改;**关注**表示有明确技术债;**可保留**表示未发现阻断级错误,但仍需测试覆盖。 ### app 模块 - `app`:`AppConfig`(已修:日志门禁;关注 Key 注入)、`MyApplication`(已修:禁止非法构造;关注第三方初始化时机)。 - `base`:`BaseActivity`(关注:职责过宽、旧 result API 并存)、`BaseDialog`(关注:体积过大)、`BaseFragment`(关注:反射清理和懒加载复杂)、`BaseFragmentPagerAdapter`(关注:旧 ViewPager)、`BaseFragmentStateAdapter`(可保留)、`BasePopupWindow`(关注:生命周期复杂)、`BaseWebViewActivity`(已修 NPE、安全和销毁;建议合并)。 - `base.aop`:`SingleClick`、`SingleClickAspect`(可用;关注 AspectJ/Gradle 9 兼容)。 - `eventbus`:`MyEvent`(可保留;建议领域事件替代通用 what)。 - `http.api`:`Urls`(关注:按环境注入)。 - `liveDataBus`:`LiveDataBus`(已修顺序、并发和反射;关注与 EventBus 重复)。 - `manager`:`AppActivityManager`(可保留)、`AppLanguageManager`(关注 locale/configuration 回归)、`OkGoManager`(已修 TLS、日志、Token;关注旧 OkGo/OkHttp)。 - `mvp`:`BaseMvpPresenter`(已修空安全)、`MvpActivity`、`MvpFragment`、`MvpPresenter`、`MvpView`(可运行;关注原始泛型和 Fragment 生命周期)。 - `mvp.example`:`MainActivity`、`MainContract`、`MainPresenterImpl`(示例;关注空 URL 和异常路径)。 - `thirdAppUtil`:`AlipayUtils`(关注线程取消/回调覆盖)、`BaiduMapAppUtils`、`GaodeMapAppUtils`、`TencentMapAppUtils`(关注 Intent/包可见性/坐标系)、`BaiduMapLocationUtils`、`GaodeMapLocationUtils`(关注单例、隐私和生命周期)、`UMConfig`(关注 Key)、`UMShareUtils`(关注体积和 Activity 释放)、`WeChatHelper`(关注全局单回调并发覆盖)。 - `thirdAppUtil.model/util`:`LocationInfo`、`LocationConvertUtils`(可保留;补精度和边界测试)。 - `ui.copy`:`CopyActivity`、`CopyFragment`(示例,可保留)。 - `ui.home`:`HomeActivity`、`NavigationAdapter`、`NavigationItem`、`HomeFragment`(可运行;关注硬编码标题、旧 ViewPager、Timer 生命周期)。 - `ui.start`:`GuideActivity`、`GuideAdapter`(可保留;首次启动状态未持久化)、`StartActivity`(已修 Handler)、`WelcomeActivity`(生产应移除重复观察和测试事件)。 - `utils`:`ThemeUtils`(可保留;监听器须对称注销)。 - `view.dialog`:`DateDialog`(可保留;补闰年、时区、边界测试)、`StyleDialog`(可保留)。 - `widget`:`NoScrollViewPager`(可保留;新页面优先 ViewPager2)。 - `widget.webView`:`AppJsBridge`(已修销毁竞争)、`BrowserChromeClient`(已修拒绝回调;关注来源域)、`BrowserViewClient`(关注 scheme allowlist)、`BrowserWebView`(已修安全和销毁)、`NestedScrollWebView`(可保留)。 - `widget.webView.bean/iface/manager`:`JsInteractionData`、`IJsBridge`、`OnJsDataCallback`(可保留)、`JsBridgeManager`(已修接口移除、转义、校验和线程)。 - `wxapi`:`WXEntryActivity`、`WXPayEntryActivity`(可保留;需真实 AppID 联调冷启动/进程重建)。 ### mylibrary 模块 - `action`:`ActivityAction`、`AnimAction`、`BundleAction`、`ClickAction`、`HandlerAction`、`KeyboardAction`、`ResourcesAction`、`TitleBarAction`、`ToastAction`(整体可保留;后续建议显式组合)。 - `http`:`HttpManage`(关注单例、OkGo 强耦合和取消标签)。 - `http.callback`:`BitmapDialogCallback`、`DialogCallback`、`EncryptCallback`、`JsonCallback`、`JsonConvert`、`StringDialogCallback`(关注 Dialog 生命周期、泛型转换异常和错误体关闭)。 - `http.config/exception/model`:`HttpConfig`、`ErrorCodeEnum`、`MyException`、`BasePostEntity`、`GankResponse`、`LzyResponse`、`SimpleResponse`(可保留;统一错误码/nullability)。 - `interfaces`:`OnRxScanerListener`、`OnUpdateListener`(可保留)。 - `scaner`:`ActivityScanerCode`、`ActivityScanerCode_Two`(关注重复与 Handler 泄漏)、`AutoFocusCallback`、`CameraConfigurationManager`、`CameraManager`、`CaptureActivityHandler`、`DecodeHandler`、`DecodeThread`、`FlashlightManager`、`PreviewCallback`(旧 Camera1,建议 CameraX)、`BitmapLuminanceSource`、`PlanarYUVLuminanceSource`、`RxQrBarTool`(可保留)、`RxImageTool`(关注 OOM 和旧 Exif)。 - `scaner.decoding`:`FinishListener`、`InactivityTimer`(可运行;需生命周期测试)。 - `utils`:`DeviceUuidFactory`(关注隐私/commit)、`RxAnimationTool`、`RxDensityTool`、`RxEncodeTool`、`RxInfoTool`、`RxKeyboardTool`、`RxVibrateTool`、`RxWindowTool`(可保留,逐步现代化)、`RxAppApplicationMgr`、`RxPhoneMgr`(关注包可见性、权限和 Cursor)、`RxBarTool`、`RxScreenTool`、`RxViewTool`(关注隐藏 API/Insets)、`RxBeepTool`(关注资源释放)、`RxConstTool`(可保留)、`RxDataTool`(关注职责过多)、`RxEncryptTool`(安全用途禁止 MD5/ECB)、`RxFileTool`(已修 Cursor;关注 scoped storage)、`RxFileUtils`(关注重复)、`RxGlideTool`(关注 Glide 生命周期)、`RxJsonTool`(关注重复)、`RxNetworkMgr`(已修权限、递归和 Context;关注旧 API)、`RxPhotoTool`(关注 Uri/File)、`RxResourceTool`(关注反射)、`RxRootUtil`、`RxSilentInstall`(高风险,仅受控设备)、`RxSharePreferenceTool`(关注图片写 SP/同步提交)、`RxSysDateTool`(可保留;补时区测试)、`RxTimerUtil`(可保留;补并发取消)、`RxValidationTool`(关注规则混杂和 locale)。 - `utils.base64`:`AESTool`(关注模式、IV、认证标签;优先 AES-GCM)、`BASE64Decoder`、`BASE64Encoder`、`CEFormatException`、`CEStreamExhausted`、`CharacterDecoder`、`CharacterEncoder`(旧实现,建议统一标准 Base64)、`MD5Utils`(仅非安全校验)。 - `utils.enums`:`LanguageType`(可保留;与语言管理统一映射)。 - `utils.json`:`Convert`、`JsonUtils`(关注与 RxJsonTool 重复、反射和 locale)。 - `utils.klog`:`KLog`、`KLogUtil`、`BaseLog`、`FileLog`、`JsonLog`、`XmlLog`(可用;Release 需脱敏和保留期)。 - `utils.manager`:`AppLogManager`(关注统一日志门禁)、`LoginHelper`、`LoginStatusManager`(关注状态源一致性和线程)。 - `utils.permissionUtil`:`PermissionCallback`、`PermissionRejectDialog`、`RxPermissionUtils`(可运行;权限最小化)、`PermissionTipDialogUtils`(关注静态 Dialog)。 - `utils.rvItemDecoration`:`GridSpaceItemDecoration`、`GridSpaceItemDecorationSame`、`HorizontalItemDecoration`、`LastItemNoDividerDecoration`、`VerticalSpaceItemDecoration`(可保留;统一 RTL/边界)、`PickerLayoutManager`(补空列表/快速滚动测试)。 - `view`:`SimpleRatingBar`(关注体积、无障碍和 locale)、`SmartTextView`(可保留)。 - `view.dialog`:`AlertDialogForIp`、`CustomAlertDialogBuilder`、`ProgressLoadingDialog`、`RxDialog`(关注 Context 生命周期、inflate root 和重复体系)。 - `view.editText`:`ClearEditText`、`PasswordEditText`、`RegexEditText`(关注 `performClick` 无障碍和触摸区域)。 - `view.loadingStateView`:`MultipleStatusView`、`NetworkStateView`(可保留;建议合并并补 saved state)。 - `view.scaleimage`:`ImageSource`、`ImageViewState`(可保留)、`RxScaleImageView`(关注旧 Exif、无障碍和超大图内存)。 - `view.scaleimage.decoder`:`CompatDecoderFactory`、`DecoderFactory`、`ImageDecoder`、`ImageRegionDecoder`、`SkiaImageDecoder`、`SkiaImageRegionDecoder`(可保留;补异常关闭、并发和新格式测试)。 ## 后续实施顺序 1. 轮换并外置签名、地图、统计、分享和崩溃平台凭据。 2. 依据真实产品功能删除权限,建立 Android 13/14/15 权限与 scoped storage 用例。 3. 升级含 native `.so` 的 SDK,完成 16 KB page size 验证。 4. 修复静态 Dialog、Camera Handler 和路径类遗留问题。 5. 合并 WebView、事件总线、文件/JSON/状态 View 的重复实现。 6. 拆分 `mylibrary` 为可选模块,将内部 `api` 改为 `implementation`。 7. 添加测试和 CI,每次提交运行 `assembleDebug`、`lintDebug` 和单元测试。 ## 构建 前置条件:JDK 11、Android SDK 35。Android Studio 使用工程自带 Gradle Wrapper。 ```powershell .\gradlew.bat clean assembleDebug lintDebug ``` 如果 `local.properties` 设置了 `build.dir`,产物在该目录下的 `android-demo/build/...`;否则在仓库根目录 `build/...`。 ## Release 签名 不要把密码写入项目文件。在用户目录 `~/.gradle/gradle.properties` 或 CI Secret 中配置: ```properties RELEASE_STORE_FILE=D:/secure/release.jks RELEASE_STORE_PASSWORD=replace_me RELEASE_KEY_ALIAS=replace_me RELEASE_KEY_PASSWORD=replace_me ``` ```powershell .\gradlew.bat assembleRelease ``` 未提供完整四项配置时,Release 不绑定正式签名;Debug 始终使用 Android 默认 debug 签名。 ## 开发约束 - 默认只允许有效 HTTPS;确需 HTTP 时使用仅覆盖指定域名的 Network Security Config。 - WebView 只加载可信 HTTPS 域名;注册 JS Bridge 前确认页面来源,外部 scheme 使用 allowlist。 - 不记录 Token、Cookie、支付参数、定位、手机号或完整响应正文。 - 权限在使用功能时再申请,拒绝后安全降级,不在启动时批量索取。 - 新工具类先确认是否已有同类能力,避免继续扩充超大 `Rx*Tool`。 - 第三方升级必须显式改版本号并执行构建、Lint、关键 SDK 真机回调测试。