You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中自定义VPN连接状态下的Android系统通知实现方法

Flutter VPN应用隐藏Android系统通知断开按钮实现方案

你在Flutter开发VPN应用时看到的默认系统通知(带断开按钮)效果如下:
默认系统VPN通知效果

这个带断开按钮的通知是Android系统为VpnService自动生成的默认模板,要隐藏断开按钮,核心是主动替换系统默认渲染的VPN常驻通知,用自定义的前台服务通知覆盖系统默认布局即可,具体实现步骤如下:

1. 原生侧自定义VpnService逻辑

Android系统只会在你没有主动调用startForeground()传入自定义通知的时候,才会加载默认的带操作按钮的VPN通知模板。你需要自己实现VpnService子类(如果是用第三方Flutter VPN插件,就继承插件提供的VpnService基类重写通知逻辑),在VPN连接建立时主动传入自定义构建的通知。
注意:不要给自定义通知添加任何系统VPN相关的Action关联,否则系统会自动追加断开按钮。

2. 实现自定义通知构建逻辑

以下是Kotlin实现的参考代码:

class MyCustomVpnService : VpnService() {
    private val VPN_NOTIFICATION_ID = 1001
    private val VPN_CHANNEL_ID = "vpn_running_status"

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // VPN连接建立成功后,启动前台服务传入自定义通知
        startForeground(VPN_NOTIFICATION_ID, buildRunningNotification())
        // 原有VPN连接、流量处理逻辑保持不变
        return START_STICKY
    }

    // 创建通知渠道(Android 8.0+ 强制要求)
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                VPN_CHANNEL_ID,
                "VPN运行状态",
                NotificationManager.IMPORTANCE_LOW
            ).apply {
                description = "VPN连接常驻提示"
                setShowBadge(false)
                enableVibration(false)
            }
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }
    }

    // 构建不带断开按钮的常驻通知
    private fun buildRunningNotification(): Notification {
        val openAppIntent = PendingIntent.getActivity(
            this,
            0,
            Intent(this, MainActivity::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        return NotificationCompat.Builder(this, VPN_CHANNEL_ID)
            .setSmallIcon(R.mipmap.ic_launcher) // 替换为你应用的通知图标
            .setContentTitle("VPN已连接")
            .setContentText("网络流量已通过VPN加密传输")
            .setContentIntent(openAppIntent)
            .setOngoing(true) // 设置为常驻,用户无法手动滑动删除
            .setPriority(NotificationCompat.PRIORITY_LOW)
            // 关键:不添加任何断开VPN相关的Action,不绑定VPN断开的广播Intent
            .build()
    }
}

3. 清单文件与Flutter侧配置

  • 在AndroidManifest.xml中替换第三方插件默认声明的VpnService,指向你自己实现的子类:
<service
    android:name=".MyCustomVpnService"
    android:exported="true"
    android:permission="android.permission.BIND_VPN_SERVICE">
    <intent-filter>
        <action android:name="android.net.VpnService"/>
    </intent-filter>
</service>
  • Android 13(API 33)及以上版本需要在Flutter侧通过permission_handler等插件申请POST_NOTIFICATIONS运行时权限,如果权限未通过,系统会回退到默认带断开按钮的通知模板。
  • 适配注意:部分深度定制ROM(如旧版MIUI、EMUI)会强制给所有常驻通知追加操作按钮,这类系统级强制修改无法通过应用代码规避,原生AOSP、Pixel、OneUI等接近原生的系统均可正常实现隐藏按钮的效果。

内容的提问来源于stack exchange,提问作者BatuhanGnday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:27:29