flutter_v2ray_plus

Flutter plugin to run VLESS/VMESS as a local proxy and VPN on Android and iOS. V2Ray/Xray core. Shadowsocks, Trojan, Socks 5 support.

⚡️ Provides fine-grained routing for domains, sites, and apps, with built-in status tracking, delay testing, and extended configuration options.

Third-Party Components

This package uses the following third-party components:

  • XRay.xcframework - Xray core binary for iOS
  • jniLibs - Xray core binaries for Android

In contrast to similar plugins, we provide both iOS and Android versions out of the box and for free, with the package being fully open-source.

Make sure to give a like on pub.dev and star on GitHub if this package was useful for you <3

Table of contents


Key features

  • Supports iOS and Android out of the box, with routing and similar features available
  • Supports Android 16KB page size (API 35+)
  • Run flutter_v2ray_plus as a local proxy or using the VPN mode (Network Extension / VpnService).
  • Parse VLESS/VMESS share links and generate ready-to-run configurations.
  • Measure server delay (ping) for a configuration.
  • Edit configuration (ports, DNS, routing, etc.).

Quick Start (TL;DR)

  1. Install the package (see Installation).
  2. Complete platform setup (iOS / Android).
  3. Initialize the plugin and start flutter_v2ray_plus from your app.

Minimal copy‑paste example:

import 'package:flutter/material.dart';
import 'package:flutter_v2ray_plus/flutter_v2ray_plus.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final FlutterV2ray _flutterV2Ray;

  @override
  void initState() {
    super.initState();
    _flutterV2Ray = FlutterV2ray();
    _init();
  }

  Future<void> _init() async {
    await _flutterV2Ray.initializeVless(
      providerBundleIdentifier: 'com.example.myapp.VPNProvider',
      groupIdentifier: 'group.com.example.myapp',
    );
  }

  Future<void> _startFromShareLink(String shareLink) async {
    final FlutterV2RayURL parser = FlutterV2ray.parseFromURL(shareLink);
    final String config = parser.getFullConfiguration();

    final int delayMs = await _flutterV2Ray.getServerDelay(config: config);
    print('Server delay: ${delayMs}ms');

    final bool allowed = await _flutterV2Ray.requestPermission();
    if (!allowed) return;

    await _flutterV2Ray.startVless(
      remark: parser.remark,
      config: config,
    );
  }

  Future<void> _stop() async {
    await _flutterVless.stopVless();
  }

  @override
  Widget build(BuildContext context) => Container();
}

Requirements

  • Flutter SDK (the minimum supported version used by the package).
  • Android: recommended minSdkVersion >= 23; set targetSdkVersion to a recent API.
  • iOS: iOS Deployment Target >= 15.0 (may vary depending on Network Extension usage).
  • Running VPN mode on iOS requires Network Extension and a provisioning profile that allows it.

Installation

From pub.dev

dependencies:
  flutter_v2ray_plus: replace_with_current_plugin_version

Local development

dependencies:
  flutter_v2ray_plus:
    path: ../flutter_v2ray_plus

Then run:

flutter pub get

Platform setup (step-by-step)

Follow the platform steps below — without these the plugin cannot run VPN/Network Extension.

iOS

The XRay.xcframework (required for iOS) is automatically downloaded during pod install — no manual download needed.

Setup for IOS

Android

  1. Add the attribute android:extractNativeLibs="true" to the
<application
    android:name=".MyApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:extractNativeLibs="true">
    . . .
</application>

  1. Set minSdkVersion to >= 23. Ensure your minSdkVersion and targetSdkVersion match plugin and Play Store requirements.

Google Play note: apps that modify network traffic may require a privacy policy and additional disclosure in the store listing.


Usage examples

URL parser

import 'package:flutter_v2ray_plus/flutter_v2ray_plus.dart';

final String link = 'vmess://...'; // or vless://, trojan:// etc.
FlutterV2RayURL parsed = FlutterV2ray.parseFromURL(link);
print('Remark: ${parsed.remark}');
final String config = parsed.getFullConfiguration();
print('Config JSON: $config');

Edit Configuration

An example of how we work with routing through configuration is available in our example.

// Change listening port
parsed.inbound['port'] = 10890;
// Change listening host
parsed.inbound['listen'] = '0.0.0.0';
// Change dns
parsed.dns = {
    "servers": ["1.1.1.1"]
};
// and ...

Start / Stop FlutterV2Ray

final flutterV2Ray = FlutterV2ray();

await flutterV2Ray.initializeVless(
  providerBundleIdentifier: 'com.wisecodex.vpnapp',
  groupIdentifier: 'group.com.wisecodex.vpnapp',
);

if (await flutterV2Ray.requestPermission()) {
  await flutterV2Ray.startVless(
    remark: 'My server',
    config: newConfig,
    blockedApps: null, // list of package names
    bypassSubnets: FlutterV2ray.defaultBypassSubnets(),
    proxyOnly: false,
  );
}

await flutterV2Ray.stopVless();

FAQ / common issues

Q: The VPN permission is granted but the VPN doesn’t start. A: Check that providerBundleIdentifier and groupIdentifier match the values in Xcode, and that the provisioning profile allows Network Extensions.

Q: My Play Store submission was rejected. A: Ensure your app includes a clear privacy policy and a disclosure about VPN/proxy usage in the store listing.

Q: **``** shows very high latency. A: Verify DNS, server address, and network reachability. Try from a different network or device to exclude local network issues.


Contributing / Contact / License

Contributing

License

Contact

All rights reserved. Muhammad Shafique - https://shafique.dev