分类 开发笔记 下的文章

自 Android 7 起,应用会忽略用户提供的证书

自 Android 7 起,应用会忽略用户提供的证书,除非它们被配置为使用这些证书。由于大多数应用不会明确选择使用用户证书,我们需要将 mitmproxy CA 证书放入系统证书存储中,以避免必须为每个想要监控的应用打补丁。

注意:应用可以决定忽略系统证书存储并维护自己的 CA 证书。在这种情况下,你必须对该应用打补丁。

1. 先决条件

  • 已安装 Android Studio / Android SDK(已在 Linux 64 位版本 4.1.3 上测试)
  • 已创建 Android 虚拟设备(AVD)。设置文档可在此处获取
  • AVD 生产构建(标有“Google Play”的构建)会阻止你使用 adb root。如果你需要安装 Google Play,则需要使用 Magisk 方法
  • AVD 的代理设置已配置为使用 mitmproxy。文档在此处
  • Android SDK 中的 emulator 和 adb 可执行文件已添加到 $PATH 变量中

    • emulator 在 Linux 系统上通常位于 /home/<your_user_name>/Android/Sdk/emulator/emulator
    • adb 在 Linux 系统上通常位于 /home/<your_user_name>/Android/Sdk/platform-tools/adb
    • 我将这些行添加到了我的 .bashrc 中:

      export PATH=$PATH:$HOME/Android/Sdk/platform-tools
      export PATH=$PATH:$HOME/Android/Sdk/emulator
  • Mitmproxy CA 证书已创建

    • 在 Linux 系统上通常位于 ~/.mitmproxy/mitmproxy-ca-cert.cer
    • 如果该文件夹为空或不存在,请运行 mitmproxy 以生成证书

2. 重命名证书

Android 中的 CA 证书按其哈希值命名存储,扩展名为 0(例如:c8450d0d.0)。有必要计算出你的 CA 证书的哈希值,并将其复制到一个以该哈希值作为文件名的文件中。否则 Android 将忽略该证书。默认情况下,mitmproxy CA 证书位于此文件中:~/.mitmproxy/mitmproxy-ca-cert.cer

说明

  1. 进入你的证书文件夹:

    cd ~/.mitmproxy/
  2. 生成哈希并复制证书:

    hashed_name=`openssl x509 -inform PEM -subject_hash_old -in mitmproxy-ca-cert.cer | head -1` && cp mitmproxy-ca-cert.cer $hashed_name.0

3. 将证书插入系统证书存储

现在我们必须将我们的 CA 证书放入 Android 文件系统中位于 /system/etc/security/cacerts/ 的系统证书存储内。默认情况下,/system 分区以只读方式挂载。以下步骤描述了如何获得对 /system 分区的写入权限,以及如何复制上一步中创建的证书。

使用 Magisk 时的说明

如果你想使用生产构建(标有“Google Play”;就是那些安装了 Google Play 的构建),你可以使用 Magisk 在你的 AVD 中获取 root 权限。Magisk 允许在你的 Android 设备或模拟器上获得 root 权限。

有关在 AVD 上安装 Magisk 的说明,请参见此处。

注意:说明中说要启动你的 AVD。此时不要向 mitmproxy 提供 -http-proxy 指令。

完成后,你的模拟器将允许 root。你可以通过运行终端模拟器并输入 su 来检查这一点。Magisk 应该会询问你是否要向该程序授予 root 权限。授予后,输入 whoami 将显示 root。

然而,在你安装 Magisk 后,你不能再使用 -writable-system 启动模拟器。这会导致启动循环。(使用 -show-kernel 启动你的 AVD 以查看错误。)但是你可以通过将 mitmproxy 证书放入 Magisk 模块并安装该模块来安装它。Magisk 将在启动期间负责将你的证书复制到 /system/etc/security/cacerts/。

从 mitmweb 下载 Magisk 模块

如果你运行 mitmweb,你可以直接下载 Magisk 模块,而不必手工制作它:

  1. 停止你的 AVD,然后使用以下命令再次启动它:

    -http-proxy 127.0.0.1:8080

    (或你运行 mitmweb 代理所使用的任何 IP 和端口组合)

  2. 然后,在 AVD 内,启动浏览器并导航到:

    http://mitm.it/cert/magisk
  3. 你将被提示下载 mitmproxy-magisk-module.zip,这就是你需要的 Magisk 模块。将该文件存储在某处(例如“Downloads”中)。
  4. 然后打开 Magisk,点击 Modules 并安装你的模块。
  5. 重启你的 AVD。

创建包含你的证书的 Magisk 模块

如果你不运行 mitmweb,你需要自己创建一个 Magisk 模块。有关 Magisk 模块的深入信息,请参见此处,但基本上可以归结为:

  1. 创建以下目录:

    mitmproxycert                    (这将是你的模块根目录)
    mitmproxycert/com/google/android
    mitmproxycert/system/etc/security/cacerts
  2. 将你在第 2 步中重命名后的证书放入 mitmproxycert/system/etc/security/cacerts,并对其执行:

    chmod 664
  3. 将 https://github.com/topjohnwu/Magisk/blob/master/scripts/module_installer.sh 的内容保存为本地文件 update-binary,并放入 mitmproxycert/com/google/android。
  4. 创建一个名为 updater-script 的文件,其中仅包含字符串:

    #MAGISK

    并将其放入 mitmproxycert/com/google/android。

  5. 创建一个名为 module.prop 的文件,并将其放入 mitmproxycert。该文件应包含类似以下内容:

    id=mitmproxycert
    name=MITM proxy certificate
    version=1
    versionCode=1
    author=mitmproxycert
    description=My shiny MITM proxy certificate to reveal all secrets and obtain world domination!
  6. 使用类似以下命令将模块打包:

    cd ./mitmproxycert ; zip -r ./../mitmproxycert.zip ./

    然后使用以下命令将其推送到你正在运行的 AVD:

    adb push ./../mitmproxycert.zip /storage/emulated/0/Download/.
  7. 然后转到你的 AVD,打开 Magisk,点击 Modules 并安装你的模块(你会在 Downloads 文件夹中找到它)。
  8. 重启你的 AVD。

API 级别 > 28 且使用 -writable-system 的说明

默认情况下,/system 分区以只读方式挂载。以下步骤描述了如何获得对 /system 分区的写入权限,以及如何复制第 2 章中创建的证书。

从 API 级别 29(Android 10)开始,似乎无法将“/”分区挂载为读写。Google 使用 OverlayFS 为此问题提供了解决方法。不幸的是,在撰写本文时(2021 年 4 月 11 日),此解决方法中的说明会导致你的模拟器陷入启动循环。Stackoverflow 上某个聪明人找到了一种仍然可以让 /system 目录可写的方法。

请记住:如果你想使用你的证书,你必须始终使用 -writable-system 选项启动模拟器。否则 Android 将加载一个“干净”的系统镜像。

已在运行 API 级别 29 和 30 的模拟器上测试。

说明

  1. 列出你的 AVD:

    emulator -list-avds

    (如果这返回空列表,请在 Android Studio AVD Manager 中创建一个新的 AVD)

  2. 启动所需的 AVD:

    emulator -avd <avd_name_here> -writable-system

    (添加 -show-kernel 标志以查看内核日志)

  3. 以 root 身份重启 adb:

    adb root
  4. 禁用安全启动验证:

    adb shell avbctl disable-verification
  5. 重启设备:

    adb reboot
  6. 以 root 身份重启 adb:

    adb root
  7. 执行分区重新挂载为读写:

    adb remount

    (如果 adb 告诉你需要重启,请再次重启 adb reboot 并再次运行 adb remount。)

  8. 推送你在第 2 步中重命名后的证书:

    adb push <path_to_certificate> /system/etc/security/cacerts
  9. 设置证书权限:

    adb shell chmod 644 /system/etc/security/cacerts/<name_of_pushed_certificate>
  10. 重启设备:

    adb reboot

API 级别 <= 28 且使用 -writable-system 的说明

已在运行 API 级别 26、27 和 28 的模拟器上测试。

请记住:如果你想使用你的证书,你必须始终使用 -writable-system 选项启动模拟器。否则 Android 将加载一个“干净”的系统镜像。

说明

  1. 列出你的 AVD:

    emulator -list-avds

    (如果这返回空列表,请在 Android Studio AVD Manager 中创建一个新的 AVD)

  2. 启动所需的 AVD:

    emulator -avd <avd_name_here> -writable-system

    (添加 -show-kernel 标志以查看内核日志)

  3. 以 root 身份重启 adb:

    adb root
  4. 执行分区重新挂载为读写:

    adb remount

    (如果 adb 告诉你需要重启,请再次重启 adb reboot 并再次运行 adb remount。)

  5. 推送你在第 2 步中重命名后的证书:

    adb push <path_to_certificate> /system/etc/security/cacerts
  6. 设置证书权限:

    adb shell chmod 644 /system/etc/security/cacerts/<name_of_pushed_certificate>
  7. 重启设备:

    adb reboot

测试你的证书是否从系统证书存储中加载

在你的 AVD 中,转到:

设置 → 安全 → 高级 → 加密与凭据 → 受信任的凭据

在列表中找到你的证书(默认名称为 mitmproxy)。

使用 WSL 尤其是 Ubuntu 系统时,使用 ls 显示 /mnt/ 下的目录如果有中文,可能会显示乱码(具体可能是 Unicode 编码)。

问题解决方法

可尝试在终端中执行以下命令,设置编码为 UTF-8

export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

当前的 React Native 开发生态中 Expo 已成为官方主推和社区广泛采用的开发方案。相比传统的 React Native CLI,Expo 有更简洁的项目初始化流程、更强大的工具链支持以及跨平台预览能力,适合初学者快速上手和中小型项目高效开发。

React Native CLI 依然可用,但其配置复杂、原生依赖管理繁琐,容易在不同操作系统上遇到兼容性问题。Expo 通过托管工作流(Managed Workflow)简化了原生模块的集成与构建流程,是现代 React Native 开发的首选方式。

本文将带你从零开始,完整走一遍使用 Expo 创建 React Native 项目、本地运行调试、打包 Android APK 与 iOS IPA 的全流程,涵盖环境准备、开发调试、签名配置及发布准备等关键环节。


一、环境准备

在开始之前,确保你的开发机器已安装以下工具:

  • Node.js
  • 包管理器:npm、yarn 或 pnpm 都可以,推荐优先用 npm 或 pnpm,后者在性能和依赖扁平化方面表现更好。

尽量保持所有工具为最新稳定版本。旧的 Node.js 或 npm 可能导致 node_modules 安装失败、依赖冲突或构建报错,出现莫名其妙的问题。

验证安装是否成功

打开终端(Terminal),依次执行以下命令:

node -v
npm -v

若能正常输出版本号(例如 v20.11.0 和 10.2.0),说明环境已就绪。


二、创建 React Native 项目

Expo 推荐使用 create-expo-app 快速初始化项目,无需手动配置 Webpack、Babel 原生工程。

初始化项目

在你希望存放项目的目录下执行:

npx create-expo-app myApp

创建一个标准 Expo 项目结构,里面有基础页面、配置文件和依赖项。

进入项目并启动开发服务器

cd myApp
npm start

成功启动后,终端会显示 Metro 打包服务(Metro Bundler)的运行界面,并自动打开浏览器页签(Expo DevTools)。

此时你会看到:

  • 一个 ASCII 风格的二维码
  • 一行提示文字:Scan the QR code above with Expo Go (Android) or the Camera app (iOS)
  • 多个快捷操作按钮(如运行模拟器、Web 预览等)

三、运行方式

Expo 支持多种方式运行应用。

1. 手机扫码运行

Android 设备

  1. 在 Google Play 商店下载并安装 Expo Go 应用。
  2. 打开应用 → 点击 "Scan QR Code" 。
  3. 对准电脑终端或浏览器中显示的二维码进行扫描。
  4. 应用将自动加载并运行。

iOS 设备

  1. 直接使用 系统相机 App 扫描二维码。
  2. 扫描后会弹出一个链接通知,点击选择在 Expo Go 中打开。
  3. 应用加载运行。

优势:无需数据线、无需编译,热重载(HMR)支持良好,非常适合真机调试。

2. 模拟器运行

在 Metro 终端界面中按对应键即可快速启动:

  • 按 a:启动 Android 模拟器(需已安装 Android Studio)
  • 按 i:启动 iOS 模拟器(仅限 macOS 用户)
  • 按 w:在浏览器中打开 Web 预览(基于 React Native for Web)

提示:Web 预览虽不能完全还原原生行为,但可用于快速验证 UI 布局和部分交互逻辑。


四、Android 打包

完成开发并准备发布测试包时,需要将项目构建成原生安装包(APK)。以下是基于 Expo 裸工作流(Bare Workflow)的手动打包流程。

配置 Android 构建环境

  1. 安装 Android Studio(推荐最新稳定版),安装过程中确保包含:

    • Android SDK
    • Android SDK Platform-Tools
    • Android SDK Build-Tools
    • Android Emulator(可选)
  2. 配置系统环境变量:

    • 新建系统变量 ANDROID_HOME,值为 SDK 路径(常见路径):
C:\Users\<你的用户名>\AppData\Local\Android\Sdk
- 将以下路径添加到 `PATH`:
%ANDROID_HOME%\platform-tools
%ANDROID_HOME%\emulator  (可选,用于命令行启动模拟器)

验证:终端执行 adb devices,若有设备列表返回则说明配置成功。

进入项目并运行原生构建命令

# 在项目根目录执行
npx expo run:android

首次运行可能出现红字警告提示未检测到设备或模拟器,可暂时忽略。此命令会尝试连接设备或启动模拟器。

随后进入原生工程目录:

cd android

创建 local.properties 文件(指定 SDK 路径)

在 android/ 目录下创建 local.properties 文件,内容如下(Windows 示例):

sdk.dir=C:\\Users\\<你的用户名>\\AppData\\Local\\Android\\Sdk

注意:如果是 Windows,路径中的反斜杠需用双反斜杠转义,且路径必须真实存在。


生成不同类型的 APK 包

1. 生成 Debug 包(用于测试)

./gradlew assembleDebug
  • 输出路径:android/app/build/outputs/apk/debug/app-debug.apk
  • 未签名,仅用于本地测试,不可上架。

2. 生成 Release 包(用于发布)

./gradlew assembleRelease
  • 输出路径:android/app/build/outputs/apk/release/app-release.apk
  • 可发布,但必须完成签名配置,否则无法安装。

五、Release 签名配置

为了发布到应用市场,APK 必须经过数字签名。以下是完整的签名流程配置。

1. 生成 Keystore 文件

在项目合适位置(如 android/app/)生成密钥库:

keytool -genkeypair -v -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 \
-keystore keystor.jks -alias keystor

将生成的 keystor.jks 文件复制到 android/app/ 目录下。

2. 配置全局变量(android/gradle.properties)

在该文件中添加以下内容(若不存在可手动创建):

MYAPP_UPLOAD_STORE_FILE=keystor.jks
MYAPP_UPLOAD_KEY_ALIAS=keystor
MYAPP_UPLOAD_STORE_PASSWORD=你的仓库密码
MYAPP_UPLOAD_KEY_PASSWORD=你的密钥密码

安全建议:不要将密码硬编码在代码中,可考虑使用环境变量或 CI/CD 秘钥管理。

3. 修改构建脚本(android/app/build.gradle)

找到 android {... } 块内的 signingConfigs,修改 release 配置:

signingConfigs {
    release {
        if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
            storeFile file(MYAPP_UPLOAD_STORE_FILE)
            storePassword MYAPP_UPLOAD_STORE_PASSWORD
            keyAlias MYAPP_UPLOAD_KEY_ALIAS
            keyPassword MYAPP_UPLOAD_KEY_PASSWORD
        }
    }
}

同时确保 buildTypes.release 使用了该签名配置:

buildTypes {
    release {
        signingConfig signingConfigs.release
        minifyEnabled false
        shrinkResources false
    }
}

完成签名后重新打包

./gradlew clean
./gradlew assembleRelease

此时生成的 app-release.apk 即为已签名的正式发布包,可用于内测或上传应用商店。


六、iOS 打包

重要提醒:在 Windows 系统上无法编译 iOS 安装包。iOS 构建必须在 macOS 系统 上完成,并需配备 Xcode 和真实设备测试。

打包前提条件

  1. 一台运行较新 macOS 的 Mac 电脑
  2. 已安装 Xcode(App Store 下载)
  3. 已安装 Command Line Tools
  4. 网络通畅(建议开启代理以加速依赖下载)
  5. 已有可运行的 Expo 项目

1. 验证 Xcode 命令行工具

终端执行:

xcode-select -p

预期输出:

/Applications/Xcode.app/Contents/Developer

若无输出,请运行:

sudo xcode-select --install

2. 安装依赖并预构建项目

npm install
npx expo prebuild -p ios

prebuild 命令会根据 app.json 配置生成原生工程目录(ios/ 和 android/)。若已有原生目录,可加 --clean 强制重建。

若提示 CocoaPods 错误

请先安装 Homebrew(若未安装):

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

再安装 CocoaPods:

brew install cocoapods

然后进入 ios/ 目录执行:

cd ios
pod install --repo-update

3. 使用 Xcode 打开项目

打开生成的 Workspace 文件:

open MyApp.xcworkspace

务必打开 **.xcworkspace**,而非 .xcodeproj,否则可能导致依赖加载失败。

4. 登录 Apple ID 并配置签名

个人开发者账号(未支付 $99/年)

  1. 在 Xcode 中进入 Preferences > Accounts,点击 “+” 添加 Apple ID。
  2. 登录后选中该账号,在项目 General 设置中选择对应的 Team。
  3. 同意最新的开发者协议(可能需访问 Apple Developer 网站确认)。

5. 添加设备 UDID

image

image

完成后重启 Xcode,确保签名状态变为 “Ready to Run”。

image


6. 手动生成 IPA

确保无误之后编译 Archive。

image

编译无误完成后会弹出如下界面:

image

image

image

image

  1. 在 Xcode 的 Products 目录下找到 .app 文件。
  2. 新建一个文件夹命名为 Payload。
  3. 将 .app 文件复制进去。
  4. 右键压缩 Payload 文件夹 → 得到 Payload.zip。
  5. 将 .zip 改名为 .ipa,即得到可安装的 IPA 包。

可通过邮件、企业分发平台等方式发送给测试人员安装。


七、结语

通过 Expo 构建 React Native 项目,不仅能享受“开箱即用”的开发体验,还能灵活切换托管与裸工作流,在需要时深入原生配置进行定制化打包。

场景推荐方式
快速原型开发Expo 托管工作流 + Expo Go 扫码
内测发布配置签名后构建 Release APK/IPA
上架应用市场使用 Expo Application Services (EAS) 或 Xcode 归档上传
持续集成推荐使用 EAS Build + CI/CD 工具链

随着 Expo 对 EAS(Expo Application Services)的持续优化,未来开发者甚至可以完全脱离本地原生环境,通过云端构建一键生成 Android 和 iOS 安装包,进一步降低入门门槛。

@REM example:
@REM del "%userprofile%/AppData/Local/Microsoft/vscode-cpptools/ipch/" /s /q /f
@REM rd "%userprofile%/AppData/Local/Microsoft/vscode-cpptools/ipch/" /s /q
@REM md "%userprofile%/AppData/Local/Microsoft/vscode-cpptools/ipch/"

@echo off

call:EmptyOneDir "%userprofile%\AppData\Local\Microsoft\vscode-cpptools\ipch"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\CachedExtensionVSIXs"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\Cache"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\CachedData"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\CachedExtensions"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\CachedExtensionVSIXs"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\Code Cache"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\Crashpad"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\logs"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\Service Worker\CacheStorage"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\Service Worker\ScriptCache"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\User\workspaceStorage"
call:EmptyOneDir "%userprofile%\AppData\Roaming\Code\User\History"

goto end

:EmptyOneDir  rem same as Let empty [path] /q
    echo empty %1
    echo del %1 /s /q /f
    del %1 /s /q /f
    echo rd %1 /s /q
    rd %1 /s /q
    echo md %1
    md %1
:end
来源:https://blog.csdn.net/Tisfy/article/details/126082324

在安装 Debian 时,如果使用了网络镜像,即使选择的是国内镜像,下载软件包也会非常慢。

解决方法

在开始安装时需要修改启动参数,后面附加如下内容:

apt-setup/security_host=mirrors.tencent.com apt-setup/security_path=/debian-security

BIOS 启动方式设置

  • 第一个界面(启动项)选择 Graphical intall
  • 按 Ctrl + i
  • 启动参数的后面追加 apt-setup/security_host=mirrors.tencent.com apt-setup/security_path=/debian-security
  • 按 Enter

2.webp

UEFI 启动方式设置

  • 第一个界面选中 Graphical intall
  • 按 e
  • 在 linux /install.amd/vmlinuz vga=788 --- quiet 的后面追加 apt-setup/security_host=mirrors.tencent.com apt-setup/security_path=/debian-security
  • 按 Ctrl + x 或 F10

3.webp