Skip to content

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

适用对象:Android 原生、React Native、Flutter、uni-app/Capacitor 等包含 Android 壳工程的前端团队
适用 SDK:包含 res/values/strings.xml 和 R.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_name 和 sechttp_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 官方对接技术文档