Skip to content

Android AAR VPN 前台服务通知对接指南

适用对象:Android 原生、React Native、Flutter、uni-app/Capacitor 等包含 Android 壳工程的前端团队
适用 SDK:包含 res/values/strings.xmlR.txt 的新版 sechttp-android-<version>.aar
对接目标:将 VPN 通知中的 SDK 默认名称和英文状态文案替换为宿主 App 的品牌名称及本地化文案

1. 前端 App 需要完成什么

接入新版 AAR 后,Android App 侧需要完成以下工作:

  1. 用新版 AAR 替换旧版 AAR。
  2. 在 Android App module 中创建或修改 strings.xml
  3. 使用 SDK 约定的同名 string resource 覆盖通知文案。
  4. Android 13 及以上版本运行时申请通知权限。
  5. 重新构建 APK/AAB,并在真机上检查连接、切换节点和断开通知。

不需要:

  • 修改 AAR 文件。
  • 反编译或重新编译 SDK。
  • 修改 SDK Java 字节码。
  • 由后端下发通知文案。
  • 在每次连接 VPN 时通过 JS 或 Java/Kotlin 传入通知文案。

宿主 App 的资源与 AAR 资源会在 APK/AAB 构建时自动合并。宿主定义了同名资源时,宿主 资源会覆盖 AAR 中的默认值。

2. 通知由谁创建

该通知是 Android SecHttpVpnService 创建的前台服务通知,不是:

  • iOS 通知。
  • APNs、FCM 或其他后端 Push。
  • 前端页面自己创建的普通通知。

Android VPN 需要以前台服务运行,因此通知不能直接删除。前端可以修改通知标题、状态 文案、操作按钮和通知渠道说明。

3. 新版 AAR 的默认行为

如果宿主 App 不提供任何覆盖资源,新版 SDK 默认显示:

通知位置默认值
通知标题宿主 App 的 android:label
连接中Connecting
已连接VPN active
切换节点Switching node
重连中Reconnecting
连接异常VPN unavailable
操作按钮Disconnect
通知渠道名称VPN connection
通知渠道说明Encrypted VPN connection

通知标题默认读取最终安装 App 的名称。例如:

xml
<application
    android:label="@string/app_name"
    ... />

如果 app_name 为“合作方应用”,通知标题默认就是“合作方应用”。

4. 替换新版 AAR

如果项目通过本地文件引入 AAR,将新版文件放入 App module 的 libs 目录。例如:

text
项目根目录/
└── android/
    └── app/
        └── libs/
            └── sechttp-android-<version>.aar

Gradle 示例:

kotlin
dependencies {
    implementation(files("libs/sechttp-android-<version>.aar"))
}

如果文件名或版本号发生变化,需要同步修改 Gradle 中的路径。删除旧 AAR,避免同时依赖 两个版本:

text
错误:
sechttp-android-旧版本.aar
sechttp-android-新版本.aar

正确:
只保留当前使用的新版本 AAR

替换后建议执行一次干净构建:

bash
cd android
./gradlew clean
./gradlew assembleDebug

原生 Android 项目在项目根目录执行对应的 Gradle 命令即可。

5. 在哪里定义同名资源

资源必须定义在最终生成 APK/AAB 的 Android App module 中,不能放在 JS、Dart、网页 资源或后端配置中。

5.1 原生 Android

通常路径为:

text
app/src/main/res/values/strings.xml

完整示例:

text
项目根目录/
└── app/
    └── src/
        └── main/
            └── res/
                └── values/
                    └── strings.xml

5.2 React Native

通常路径为:

text
android/app/src/main/res/values/strings.xml

5.3 Flutter

通常路径为:

text
android/app/src/main/res/values/strings.xml

5.4 uni-app、Capacitor 或其他跨端框架

应找到最终参与 Gradle 构建的 Android app module,通常也是:

text
android/app/src/main/res/values/strings.xml

如果框架会重新生成整个 android/ 目录,不要只修改临时生成结果。需要把资源配置加入 框架支持的原生工程模板、构建插件或不会被覆盖的 Android 工程目录。

6. 如何覆盖全部通知文案

打开或创建宿主 App 的 strings.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">合作方应用</string>

    <string name="sechttp_vpn_notification_title">合作方应用</string>
    <string name="sechttp_vpn_notification_connecting">正在建立安全连接</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
    <string name="sechttp_vpn_notification_switching">正在切换节点</string>
    <string name="sechttp_vpn_notification_reconnecting">网络异常,正在重新连接</string>
    <string name="sechttp_vpn_notification_error">安全连接暂不可用</string>
    <string name="sechttp_vpn_notification_disconnect">断开连接</string>
    <string name="sechttp_vpn_notification_channel_name">安全连接</string>
    <string name="sechttp_vpn_notification_channel_description">应用的加密网络连接</string>
</resources>

如果文件中已经存在 <resources>,只把需要的 <string> 元素加入现有 <resources> 内部,不要重复创建第二个根节点。

错误示例:

xml
<resources>
    <string name="app_name">合作方应用</string>
</resources>

<resources>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
</resources>

正确示例:

xml
<resources>
    <string name="app_name">合作方应用</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
</resources>

7. 可以只覆盖部分文案吗

可以。没有覆盖的资源继续使用 AAR 默认值。

例如只修改标题和连接成功文案:

xml
<resources>
    <string name="sechttp_vpn_notification_title">合作方应用</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
</resources>

最终效果:

状态显示值
标题合作方应用
已连接网络保护已开启
连接中AAR 默认的 Connecting
切换节点AAR 默认的 Switching node

建议正式发布时覆盖全部资源,避免中英文混排。

8. 是否必须定义通知标题

不是。

如果不定义下面这个资源:

xml
<string name="sechttp_vpn_notification_title">合作方应用</string>

或者将它定义为空:

xml
<string name="sechttp_vpn_notification_title"></string>

SDK 会读取宿主 App 的 android:label 作为标题。

如果不同渠道需要显示不同通知品牌名,可以显式覆盖 sechttp_vpn_notification_title

9. 多语言配置

Android 会根据系统语言自动选择对应资源。

推荐目录:

text
android/app/src/main/res/
├── values/
│   └── strings.xml
├── values-zh-rCN/
│   └── strings.xml
└── values-en/
    └── strings.xml

默认资源 values/strings.xml 必须存在,建议使用英文或产品约定的兜底语言:

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="sechttp_vpn_notification_connecting">Connecting securely</string>
    <string name="sechttp_vpn_notification_active">Protection active</string>
    <string name="sechttp_vpn_notification_switching">Switching server</string>
    <string name="sechttp_vpn_notification_reconnecting">Reconnecting</string>
    <string name="sechttp_vpn_notification_error">Secure connection unavailable</string>
    <string name="sechttp_vpn_notification_disconnect">Disconnect</string>
    <string name="sechttp_vpn_notification_channel_name">Secure connection</string>
    <string name="sechttp_vpn_notification_channel_description">Encrypted network connection</string>
</resources>

简体中文 values-zh-rCN/strings.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="sechttp_vpn_notification_connecting">正在建立安全连接</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
    <string name="sechttp_vpn_notification_switching">正在切换节点</string>
    <string name="sechttp_vpn_notification_reconnecting">网络异常,正在重新连接</string>
    <string name="sechttp_vpn_notification_error">安全连接暂不可用</string>
    <string name="sechttp_vpn_notification_disconnect">断开连接</string>
    <string name="sechttp_vpn_notification_channel_name">安全连接</string>
    <string name="sechttp_vpn_notification_channel_description">应用的加密网络连接</string>
</resources>

各语言文件使用的 resource name 必须完全一致,只替换标签中间的文字。

10. 多环境和多渠道配置

如果项目使用 product flavor,可以在对应 source set 中覆盖资源。

示例:

text
android/app/src/
├── main/res/values/strings.xml
├── domestic/res/values/strings.xml
└── overseas/res/values/strings.xml

国内渠道:

xml
<!-- android/app/src/domestic/res/values/strings.xml -->
<resources>
    <string name="sechttp_vpn_notification_title">国内版应用</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
</resources>

海外渠道:

xml
<!-- android/app/src/overseas/res/values/strings.xml -->
<resources>
    <string name="sechttp_vpn_notification_title">Partner Global</string>
    <string name="sechttp_vpn_notification_active">Protection active</string>
</resources>

Gradle 构建不同 flavor 时会自动使用对应文案,不需要为每个渠道重新编译 AAR。

11. Android 13+ 通知权限

新版 AAR 已声明 POST_NOTIFICATIONS,但运行时权限必须由宿主 Activity 请求。SDK 不能替代 App 展示符合产品语境的权限说明。

Manifest 最终应包含:

xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Kotlin 示例:

kotlin
private val notificationPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        // granted 表示用户允许普通通知显示。
    }

private fun requestNotificationPermissionIfNeeded() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
        ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
    }
}

Java 示例:

java
private final ActivityResultLauncher<String> notificationPermissionLauncher =
        registerForActivityResult(
                new ActivityResultContracts.RequestPermission(),
                granted -> {
                    // granted 表示用户允许普通通知显示。
                });

private void requestNotificationPermissionIfNeeded() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
            && ContextCompat.checkSelfPermission(
                    this, Manifest.permission.POST_NOTIFICATIONS)
                    != PackageManager.PERMISSION_GRANTED) {
        notificationPermissionLauncher.launch(
                Manifest.permission.POST_NOTIFICATIONS);
    }
}

建议在用户主动开启 VPN 前请求,并说明该通知用于展示安全连接状态。

用户拒绝通知权限时,VPN 前台服务可能仍能运行,但普通通知可能不会显示在通知栏中。 不同 Android 版本和厂商系统的显示位置可能存在差异。

12. 修改文案后是否需要重新编译 AAR

不需要重新编译 AAR。

变更内容是否重新编译 AAR是否重新构建 App
宿主修改通知标题
宿主修改状态文案
宿主增加多语言
宿主为不同 flavor 配置不同文案
SDK 修改默认资源或通知逻辑

资源最终需要写入 APK/AAB,因此宿主文案修改后必须重新构建并安装新版 App。不能在已经 安装的旧 APK 中直接改变打包资源。

13. 通知渠道的特殊说明

Android 8.0 及以上使用固定通知渠道:

text
security_http_vpn

sechttp_vpn_notification_channel_namesechttp_vpn_notification_channel_description 用于系统通知设置页面中的渠道名称与 说明。它们不是通知卡片上的连接状态文案。

部分 Android 厂商系统会缓存已经创建的通知渠道。修改渠道名称后如果测试机仍显示旧值:

  1. 先强制停止 App 并重新打开。
  2. 如果仍未更新,卸载旧 App 后重新安装。
  3. 或在测试机上清除该 App 的数据后重新启动。

清除数据或卸载会同时清除 App 本地数据和 VPN 授权状态,测试前应做好准备。

14. 构建后如何确认覆盖成功

14.1 最终 APK 资源检查

如果本机安装了 Android SDK Build Tools,可以检查 APK 中的最终资源:

bash
aapt2 dump resources app-debug.apk \
  | grep -A 2 "sechttp_vpn_notification"

输出中应该能看到宿主提供的最终文案,例如:

text
resource ... string/sechttp_vpn_notification_active
  () "网络保护已开启"

如果看到的是 VPN active,说明宿主同名资源没有参与最终构建。

14.2 真机验证

建议至少验证以下场景:

场景预期通知
开始连接标题为宿主名称,内容为连接中文案
连接成功内容切换为已连接文案
切换节点内容切换为节点切换文案
网络中断并恢复内容显示重连文案,恢复后显示已连接文案
点击断开按钮VPN 停止,持续通知消失
切换系统语言通知使用对应语言资源
App 退到后台VPN 运行期间通知持续存在

建议在至少一台原生 Android 和一台 MIUI/HyperOS、EMUI/HarmonyOS、ColorOS 或 OriginOS 设备上验证。不同厂商通知卡片外观可能不同,但标题和正文应使用同一组资源。

15. 常见问题

15.1 已定义同名资源,但仍显示 Security HTTP

优先检查:

  1. 项目是否仍在使用旧版 AAR。
  2. libs 中是否同时存在新旧两个 AAR。
  3. Gradle 是否引用了另一个目录中的旧文件。
  4. 是否执行了 clean 后重新安装 App。
  5. 标题是否来自旧 App 安装包或厂商通知缓存。

新版 AAR 在没有显式标题覆盖时,应使用宿主 android:label,不应继续固定显示 Security HTTP

15.2 提示 resource 重复定义

宿主与 AAR 定义同名 string 是预期行为,标准 Android App 构建会用宿主资源覆盖依赖库。

如果构建脚本直接把多个 XML 文件简单拼接,而不是使用 Android Gradle Plugin/AAPT2 合并资源,可能出现错误。应让宿主资源和 AAR 资源走标准 Android resource merge。

15.3 修改 JS 文案为什么没有效果

通知由 Android VPN Service 创建,读取的是 APK/AAB 中的 Android string resource。 React Native JS、Flutter Dart 或 Web 页面中的国际化文案不会自动进入 Android 原生资源。

必须修改:

text
android/app/src/main/res/...

修改后重新构建 Android App。

15.4 能否连接时动态传入任意通知文案

当前版本不支持,也不建议把品牌和本地化文案作为每次连接参数传入。通知文案属于 App 打包资源,使用 Android 标准资源覆盖可以稳定支持进程重启、前台服务重建、多语言和 product flavor。

如果未来确实需要用户级动态内容,应另行评审新的 SDK 配置接口。

15.5 能否隐藏通知

不能以 SDK 配置方式关闭。Android VPN 使用前台服务运行,系统要求提供持续通知。用户 可以在系统设置中管理通知权限,但宿主 App 不应依赖隐藏通知维持 VPN 生命周期。

15.6 通知小图标能否通过这些 string resource 修改

不能。本文中的资源只负责文字。当前通知小图标仍由 SDK 设置。如需支持宿主自定义通知 图标,需要 SDK 增加单独的 drawable/resource 配置能力。

16. 推荐的最小对接配置

如果前端暂时不做多语言,至少添加以下内容:

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="sechttp_vpn_notification_title">合作方应用</string>
    <string name="sechttp_vpn_notification_connecting">正在建立安全连接</string>
    <string name="sechttp_vpn_notification_active">网络保护已开启</string>
    <string name="sechttp_vpn_notification_switching">正在切换节点</string>
    <string name="sechttp_vpn_notification_reconnecting">网络异常,正在重新连接</string>
    <string name="sechttp_vpn_notification_error">安全连接暂不可用</string>
    <string name="sechttp_vpn_notification_disconnect">断开连接</string>
    <string name="sechttp_vpn_notification_channel_name">安全连接</string>
    <string name="sechttp_vpn_notification_channel_description">应用的加密网络连接</string>
</resources>

并完成:

  • 替换新版 AAR。
  • Android 13+ 通知权限申请。
  • clean 后重新构建和安装。
  • 真机验证连接中、已连接、切换节点、重连和断开。

完成以上步骤后,前端无需再为通知文案调用任何 SDK 接口。

Security HTTP SDK 官方对接技术文档