├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── migrations.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .DS_Store ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── .DS_Store │ └── main │ ├── .DS_Store │ ├── AndroidManifest.xml │ ├── java │ └── dev │ │ └── dev7 │ │ └── example │ │ ├── MainActivity.java │ │ └── MainApplication.java │ └── res │ ├── drawable │ └── ic_launcher.png │ ├── layout │ └── activity_main.xml │ ├── values │ ├── colors.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle ├── connected.jpeg ├── disconnected.jpg ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── settings.gradle └── v2ray ├── .gitignore ├── build.gradle ├── libs ├── arm64-v8a │ └── libtun2socks.so ├── armeabi-v7a │ └── libtun2socks.so ├── libv2ray.aar ├── x86 │ └── libtun2socks.so └── x86_64 │ └── libtun2socks.so ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml └── java └── dev └── dev7 └── lib └── v2ray ├── V2rayController.java ├── core ├── Tun2SocksExecutor.java └── V2rayCoreExecutor.java ├── interfaces ├── LatencyDelayListener.java ├── StateListener.java ├── TrafficListener.java ├── Tun2SocksListener.java └── V2rayServicesListener.java ├── model └── V2rayConfigModel.java ├── services ├── NotificationService.java ├── StaticsBroadCastService.java ├── V2rayProxyService.java └── V2rayVPNService.java └── utils ├── Utilities.java ├── V2rayConfigs.java └── V2rayConstants.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | .idea/* -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | .idea -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | V2ray-Android -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # V2ray-Example 2 | 3 | A simple Java module with sample source code to implement the v2ray on Android. 4 | This module is built from a [custom library based on the xray core](https://github.com/dev7dev/AndroidLibXrayLite) . With this module, you can easily develop your VPN application based on powerful v2ray protocols. This module currently supports v2ray short links (URI) thanks to a custom library (may have bugs). 5 | In fact, this module provides you a v2ray client with xray core, which you can manage with static functions in [V2rayController](https://github.com/dev7dev/V2ray-Android/blob/main/v2ray/src/main/java/dev/dev7/lib/v2ray/V2rayController.java) . 6 | 7 | | :exclamation: The function of the library to convert uri to json may have a bug. Test before using in production. | 8 | |----------------------------------------------------------------------------------------------------------------------| 9 | 10 | **Sample Application** 11 | *You can download sample release of this module from [Github Releases of this repo](https://github.com/dev7dev/V2ray-Android/releases)* 12 |
13 | v2ray android java 14 | v2ray android java 15 |
16 | 17 | ## Build 18 | *Before anything, make sure you are using the latest version of Android Studio.* 19 | *The sample project does not use any special dependencies or tools, so if there are no network or software issues on your system, you can simply clone it and build it in Android Studio with one click.* 20 | 21 | ## Implementation 22 | - First, check that the version of gradle and build config of your project is compatible with the version used in this source. 23 | - Clone or download this repo. 24 | - Open your project in android studio and navigate to `File` -> `New` -> `Import module`. Then select the source directory to `v2ray` from the cloned repository. 25 | - After Gradle build , Open [setting.gradle](https://github.com/dev7dev/V2ray-Android/blob/main/settings.gradle#L13) file in your project and add this to your Gradle repositories block. 26 | ``` 27 | flatDir { 28 | dirs 'v2ray/libs' 29 | } 30 | ``` 31 | - Add module as a dependency to your main project by adding this line to app-level [build.gradle](https://github.com/dev7dev/V2ray-Android/blob/main/app/build.gradle#L35). 32 | ``` 33 | implementation project(path: ':v2ray') 34 | ``` 35 | - Click on `Rebuild project` from `Build` Tab . 36 | 37 | > Note : *The contents of the manifest of your main project will be automatically merged with the contents of the [library monifest](https://github.com/dev7dev/V2ray-Android/blob/main/v2ray/src/main/AndroidManifest.xml), so there is no need to manually copy the contents.* 38 | ## Usage 39 | - First, the library needs to be initialized. So call [this function](https://github.com/dev7dev/V2ray-Android/blob/main/v2ray/src/main/java/dev/dev7/lib/v2ray/V2rayController.java#L62) for this purpose in the primary methods of your activity. 40 | ``` 41 | V2rayController.init(this, R.drawable.ic_launcher, "V2ray Android"); 42 | ``` 43 | > `R.drawable.ic_launcher` is a drawable resource that will be used in vpn notification. 44 | > `"V2ray Android"` is application name 45 | - You can get the version of core with this 46 | ``` 47 | V2rayController.getCoreVersion() 48 | ``` 49 | - With this function you will get current status of module 50 | ``` 51 | V2rayController.getConnectionState() 52 | ``` 53 | > This will return an enum with three state : CONNECTED,CONNECTING,DISCONNECTED 54 | - For **start a connection ** 55 | ``` 56 | V2rayController.startV2ray(this, "Test Server", "vless:\\test@test", null); 57 | ``` 58 | > `"Test Server"` will be used as remark in notification. 59 | > `"vless:\\test@test"` is a string of your config (could be uri or full json) 60 | > `null` means no application package will be bypass the tunnel 61 | - For **stop connection** 62 | ``` 63 | V2rayController.stopV2ray(this); 64 | ``` 65 | > you should call this function in main thread. 66 | 67 | ## Credits 68 | - https://github.com/xtls/xray-core 69 | - https://github.com/2dust/AndroidLibXrayLite 70 | - https://github.com/gvcgo/vpnparser 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev7dev/V2ray-Android/fc15bb8e145a181c8859090a592be589efc8e92a/app/.DS_Store -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | namespace 'dev.dev7.example' 7 | compileSdk 34 8 | 9 | defaultConfig { 10 | applicationId "dev.dev7.example" 11 | minSdk 21 12 | targetSdk 34 13 | versionCode 11 14 | versionName "8.1823" 15 | setProperty("archivesBaseName", rootProject.name + "-" + versionName) 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled true 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | buildFeatures { 25 | buildConfig = true 26 | } 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | 32 | } 33 | 34 | dependencies { 35 | implementation 'androidx.appcompat:appcompat:1.6.1' 36 | implementation project(path: ':v2ray') 37 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev7dev/V2ray-Android/fc15bb8e145a181c8859090a592be589efc8e92a/app/src/.DS_Store -------------------------------------------------------------------------------- /app/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev7dev/V2ray-Android/fc15bb8e145a181c8859090a592be589efc8e92a/app/src/main/.DS_Store -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/dev/dev7/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.dev7.example; 2 | 3 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_CONNECTION_STATE_BROADCAST_EXTRA; 4 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_DOWNLOAD_SPEED_BROADCAST_EXTRA; 5 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_DOWNLOAD_TRAFFIC_BROADCAST_EXTRA; 6 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_DURATION_BROADCAST_EXTRA; 7 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_UPLOAD_SPEED_BROADCAST_EXTRA; 8 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.SERVICE_UPLOAD_TRAFFIC_BROADCAST_EXTRA; 9 | import static dev.dev7.lib.v2ray.utils.V2rayConstants.V2RAY_SERVICE_STATICS_BROADCAST_INTENT; 10 | 11 | import android.annotation.SuppressLint; 12 | import android.content.BroadcastReceiver; 13 | import android.content.Context; 14 | import android.content.Intent; 15 | import android.content.IntentFilter; 16 | import android.content.SharedPreferences; 17 | import android.os.Build; 18 | import android.os.Bundle; 19 | import android.os.Handler; 20 | import android.widget.Button; 21 | import android.widget.EditText; 22 | import android.widget.TextView; 23 | 24 | import androidx.appcompat.app.AppCompatActivity; 25 | 26 | import java.util.Objects; 27 | 28 | import dev.dev7.lib.v2ray.V2rayController; 29 | import dev.dev7.lib.v2ray.utils.V2rayConfigs; 30 | import dev.dev7.lib.v2ray.utils.V2rayConstants; 31 | 32 | public class MainActivity extends AppCompatActivity { 33 | 34 | private Button connection; 35 | private TextView connection_speed, connection_traffic, connection_time, server_delay, connected_server_delay, connection_mode,core_version; 36 | private EditText v2ray_config; 37 | private SharedPreferences sharedPreferences; 38 | private BroadcastReceiver v2rayBroadCastReceiver; 39 | 40 | @SuppressLint({"SetTextI18n", "UnspecifiedRegisterReceiverFlag"}) 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_main); 45 | if (savedInstanceState == null) { 46 | V2rayController.init(this, R.drawable.ic_launcher, "V2ray Android"); 47 | connection = findViewById(R.id.btn_connection); 48 | connection_speed = findViewById(R.id.connection_speed); 49 | connection_time = findViewById(R.id.connection_duration); 50 | connection_traffic = findViewById(R.id.connection_traffic); 51 | server_delay = findViewById(R.id.server_delay); 52 | connection_mode = findViewById(R.id.connection_mode); 53 | connected_server_delay = findViewById(R.id.connected_server_delay); 54 | v2ray_config = findViewById(R.id.v2ray_config); 55 | core_version = findViewById(R.id.core_version); 56 | } 57 | 58 | core_version.setText(V2rayController.getCoreVersion()); 59 | // initialize shared preferences for save or reload default config 60 | sharedPreferences = getSharedPreferences("conf", MODE_PRIVATE); 61 | // reload previous config to edit text 62 | v2ray_config.setText(sharedPreferences.getString("v2ray_config", getDefaultConfig())); 63 | connection.setOnClickListener(view -> { 64 | sharedPreferences.edit().putString("v2ray_config", v2ray_config.getText().toString()).apply(); 65 | if (V2rayController.getConnectionState() == V2rayConstants.CONNECTION_STATES.DISCONNECTED) { 66 | V2rayController.startV2ray(this, "Test Server", v2ray_config.getText().toString(), null); 67 | } else { 68 | V2rayController.stopV2ray(this); 69 | } 70 | }); 71 | 72 | 73 | // Check the connection delay of connected config. 74 | connected_server_delay.setOnClickListener(view -> { 75 | connected_server_delay.setText("connected server delay : measuring..."); 76 | // Don`t forget to do ui jobs in ui thread! 77 | V2rayController.getConnectedV2rayServerDelay(this, delayResult -> runOnUiThread(() -> connected_server_delay.setText("connected server delay : " + delayResult + "ms"))); 78 | }); 79 | // Another way to check the connection delay of a config without connecting to it. 80 | server_delay.setOnClickListener(view -> { 81 | server_delay.setText("server delay : measuring..."); 82 | new Handler().postDelayed(() -> server_delay.setText("server delay : " + V2rayController.getV2rayServerDelay(v2ray_config.getText().toString()) + "ms"), 200); 83 | }); 84 | 85 | connection_mode.setOnClickListener(view -> { 86 | V2rayController.toggleConnectionMode(); 87 | connection_mode.setText("connection mode : " + V2rayConfigs.serviceMode.toString()); 88 | }); 89 | 90 | // Check connection state when activity launch 91 | switch (V2rayController.getConnectionState()) { 92 | case CONNECTED: 93 | connection.setText("CONNECTED"); 94 | // check connection latency 95 | connected_server_delay.callOnClick(); 96 | break; 97 | case DISCONNECTED: 98 | connection.setText("DISCONNECTED"); 99 | break; 100 | case CONNECTING: 101 | connection.setText("CONNECTING"); 102 | break; 103 | default: 104 | break; 105 | } 106 | //I tested several different ways to send information from the connection process side 107 | // to other places (such as interfaces, AIDL and singleton ,...) apparently the best way 108 | // to send information is broadcast. 109 | // So v2ray library will be broadcast information with action V2RAY_CONNECTION_INFO. 110 | v2rayBroadCastReceiver = new BroadcastReceiver() { 111 | @Override 112 | public void onReceive(Context context, Intent intent) { 113 | runOnUiThread(() -> { 114 | connection_time.setText("connection time : " + Objects.requireNonNull(intent.getExtras()).getString(SERVICE_DURATION_BROADCAST_EXTRA)); 115 | connection_speed.setText("connection speed : " + intent.getExtras().getString(SERVICE_UPLOAD_SPEED_BROADCAST_EXTRA) + " | " + intent.getExtras().getString(SERVICE_DOWNLOAD_SPEED_BROADCAST_EXTRA)); 116 | connection_traffic.setText("connection traffic : " + intent.getExtras().getString(SERVICE_UPLOAD_TRAFFIC_BROADCAST_EXTRA) + " | " + intent.getExtras().getString(SERVICE_DOWNLOAD_TRAFFIC_BROADCAST_EXTRA)); 117 | connection_mode.setText("connection mode : " + V2rayConfigs.serviceMode.toString()); 118 | switch ((V2rayConstants.CONNECTION_STATES) Objects.requireNonNull(intent.getExtras().getSerializable(SERVICE_CONNECTION_STATE_BROADCAST_EXTRA))) { 119 | case CONNECTED: 120 | connection.setText("CONNECTED"); 121 | break; 122 | case DISCONNECTED: 123 | connection.setText("DISCONNECTED"); 124 | connected_server_delay.setText("connected server delay : wait for connection"); 125 | break; 126 | case CONNECTING: 127 | connection.setText("CONNECTING"); 128 | break; 129 | default: 130 | break; 131 | } 132 | }); 133 | } 134 | }; 135 | 136 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 137 | registerReceiver(v2rayBroadCastReceiver, new IntentFilter(V2RAY_SERVICE_STATICS_BROADCAST_INTENT), RECEIVER_EXPORTED); 138 | } else { 139 | registerReceiver(v2rayBroadCastReceiver, new IntentFilter(V2RAY_SERVICE_STATICS_BROADCAST_INTENT)); 140 | } 141 | } 142 | 143 | public static String getDefaultConfig() { 144 | return ""; 145 | } 146 | 147 | 148 | @Override 149 | protected void onDestroy() { 150 | super.onDestroy(); 151 | if (v2rayBroadCastReceiver != null){ 152 | unregisterReceiver(v2rayBroadCastReceiver); 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /app/src/main/java/dev/dev7/example/MainApplication.java: -------------------------------------------------------------------------------- 1 | package dev.dev7.example; 2 | 3 | import android.app.Application; 4 | 5 | public class MainApplication extends Application { 6 | @Override 7 | public void onCreate() { 8 | super.onCreate(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev7dev/V2ray-Android/fc15bb8e145a181c8859090a592be589efc8e92a/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 28 | 29 | 30 | 34 | 35 | 43 | 44 | 52 | 53 | 54 | 62 | 63 | 71 | 72 | 73 | 81 | 82 | 90 | 91 | 92 | 93 |