├── .github └── ISSUE_TEMPLATE │ ├── bug_cn.md │ └── config.yml ├── .gitignore ├── AndroidLibV2rayLite └── README.md ├── CR.md ├── LICENSE ├── Mahsa.jpg ├── Mahsa_logo.jpg ├── README.md ├── V2rayNG ├── .gitignore ├── app │ ├── .gitignore │ ├── build.gradle │ ├── libs │ │ ├── arm64-v8a │ │ │ └── libtun2socks.so │ │ ├── armeabi-v7a │ │ │ └── libtun2socks.so │ │ ├── json.jar │ │ ├── x86 │ │ │ └── libtun2socks.so │ │ └── x86_64 │ │ │ └── libtun2socks.so │ ├── proguard-rules.pro │ └── src │ │ ├── dev │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── ServerLess_TLSFrag_Xray_Config.json │ │ │ ├── ads_block_rule.txt │ │ │ ├── custom_routing_block │ │ │ ├── custom_routing_direct │ │ │ ├── custom_routing_proxy │ │ │ ├── geoip_c4u.dat │ │ │ ├── geosite_c4u.dat │ │ │ ├── irgfw_block_rules.txt │ │ │ ├── irgfw_direct_rules.txt │ │ │ ├── privacy_policy.txt │ │ │ ├── proxy_packagename.txt │ │ │ ├── terms_of_service.txt │ │ │ ├── v2ray_HTTPS_config.json │ │ │ └── v2ray_config.json │ │ ├── ic_launcher-playstore.png │ │ ├── ic_launcher-web.png │ │ ├── java │ │ │ └── com │ │ │ │ └── v2ray │ │ │ │ └── ang │ │ │ │ ├── GFW_help_Activity.java │ │ │ │ ├── GFW_setting_Activity.java │ │ │ │ ├── GFW_youtube_config_Activity.java │ │ │ │ └── helper │ │ │ │ ├── GFW_privacy_policy_Activity.java │ │ │ │ ├── GFW_terms_service_Activity.java │ │ │ │ ├── ItemTouchHelperAdapter.java │ │ │ │ ├── ItemTouchHelperViewHolder.java │ │ │ │ ├── OnStartDragListener.java │ │ │ │ └── SimpleItemTouchHelperCallback.java │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── v2ray │ │ │ │ └── ang │ │ │ │ ├── AngApplication.kt │ │ │ │ ├── AppConfig.kt │ │ │ │ ├── dto │ │ │ │ ├── AngConfig.kt │ │ │ │ ├── AppInfo.kt │ │ │ │ ├── ConfigResult.kt │ │ │ │ ├── EConfigType.kt │ │ │ │ ├── ERoutingMode.kt │ │ │ │ ├── Hysteria2Bean.kt │ │ │ │ ├── ServerAffiliationInfo.kt │ │ │ │ ├── ServerConfig.kt │ │ │ │ ├── ServersCache.kt │ │ │ │ ├── SubscriptionItem.kt │ │ │ │ ├── V2rayConfig.kt │ │ │ │ └── VmessQRCode.kt │ │ │ │ ├── extension │ │ │ │ └── _Ext.kt │ │ │ │ ├── gfwknocker │ │ │ │ ├── BackServ.kt │ │ │ │ ├── DoH_over_Fragment.kt │ │ │ │ ├── HTTPS_Fragmentor.kt │ │ │ │ └── TLS_Fragmentor.kt │ │ │ │ ├── plugin │ │ │ │ ├── NativePlugin.kt │ │ │ │ ├── Plugin.kt │ │ │ │ ├── PluginContract.kt │ │ │ │ ├── PluginList.kt │ │ │ │ ├── PluginManager.kt │ │ │ │ └── ResolvedPlugin.kt │ │ │ │ ├── receiver │ │ │ │ ├── TaskerReceiver.kt │ │ │ │ └── WidgetProvider.kt │ │ │ │ ├── service │ │ │ │ ├── QSTileService.kt │ │ │ │ ├── ServiceControl.kt │ │ │ │ ├── V2RayProxyOnlyService.kt │ │ │ │ ├── V2RayServiceManager.kt │ │ │ │ ├── V2RayTestService.kt │ │ │ │ └── V2RayVpnService.kt │ │ │ │ ├── ui │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── FragmentAdapter.kt │ │ │ │ ├── LogcatActivity.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MainRecyclerAdapter.kt │ │ │ │ ├── PerAppProxyActivity.kt │ │ │ │ ├── PerAppProxyAdapter.kt │ │ │ │ ├── RoutingSettingsActivity.kt │ │ │ │ ├── RoutingSettingsFragment.kt │ │ │ │ ├── ScScannerActivity.kt │ │ │ │ ├── ScSwitchActivity.kt │ │ │ │ ├── ScannerActivity.kt │ │ │ │ ├── ServerActivity.kt │ │ │ │ ├── ServerCustomConfigActivity.kt │ │ │ │ ├── SettingsActivity.kt │ │ │ │ ├── SubEditActivity.kt │ │ │ │ ├── SubSettingActivity.kt │ │ │ │ ├── SubSettingRecyclerAdapter.kt │ │ │ │ ├── TaskerActivity.kt │ │ │ │ ├── UrlSchemeActivity.kt │ │ │ │ └── UserAssetActivity.kt │ │ │ │ ├── util │ │ │ │ ├── AngConfigManager.kt │ │ │ │ ├── AppManagerUtil.kt │ │ │ │ ├── MessageUtil.kt │ │ │ │ ├── MmkvManager.kt │ │ │ │ ├── MyContextWrapper.kt │ │ │ │ ├── QRCodeDecoder.kt │ │ │ │ ├── SpeedtestUtil.kt │ │ │ │ ├── Utils.kt │ │ │ │ ├── V2rayConfigUtil.kt │ │ │ │ └── fmt │ │ │ │ │ ├── ShadowsocksFmt.kt │ │ │ │ │ ├── SocksFmt.kt │ │ │ │ │ ├── TrojanFmt.kt │ │ │ │ │ ├── VlessFmt.kt │ │ │ │ │ ├── VmessFmt.kt │ │ │ │ │ └── WireguardFmt.kt │ │ │ │ └── viewmodel │ │ │ │ ├── MainViewModel.kt │ │ │ │ └── SettingsViewModel.kt │ │ └── res │ │ │ ├── anim │ │ │ ├── fade_in.xml │ │ │ └── fade_out.xml │ │ │ ├── color │ │ │ ├── arrays.xml │ │ │ ├── attrs.xml │ │ │ ├── color_highlight_material.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── ic_banner_background.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ ├── drawable-hdpi │ │ │ ├── ic_stat_direct.png │ │ │ ├── ic_stat_name.png │ │ │ └── ic_stat_proxy.png │ │ │ ├── drawable-mdpi │ │ │ ├── ic_stat_direct.png │ │ │ ├── ic_stat_name.png │ │ │ └── ic_stat_proxy.png │ │ │ ├── drawable-xhdpi │ │ │ ├── ic_stat_direct.png │ │ │ ├── ic_stat_name.png │ │ │ └── ic_stat_proxy.png │ │ │ ├── drawable-xxhdpi │ │ │ ├── donate.png │ │ │ ├── ic_stat_direct.png │ │ │ ├── ic_stat_name.png │ │ │ ├── ic_stat_proxy.png │ │ │ └── side_nav_bar.xml │ │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_stat_direct.png │ │ │ ├── ic_stat_name.png │ │ │ └── ic_stat_proxy.png │ │ │ ├── drawable │ │ │ ├── ic_action_done.xml │ │ │ ├── ic_add_white_24dp.xml │ │ │ ├── ic_attach_money_black_24dp.xml │ │ │ ├── ic_attach_money_white_24dp.xml │ │ │ ├── ic_close_grey_800_24dp.xml │ │ │ ├── ic_cloud_download_white_24dp.xml │ │ │ ├── ic_copy_white.xml │ │ │ ├── ic_delete_black_24dp.xml │ │ │ ├── ic_delete_white_24dp.xml │ │ │ ├── ic_description_black_24dp.xml │ │ │ ├── ic_description_white_24dp.xml │ │ │ ├── ic_edit_black_24dp.xml │ │ │ ├── ic_fab_check.xml │ │ │ ├── ic_feedback_white_24dp.xml │ │ │ ├── ic_file_white_24dp.xml │ │ │ ├── ic_image_photo.xml │ │ │ ├── ic_info_black_24dp.xml │ │ │ ├── ic_logcat_white_24dp.xml │ │ │ ├── ic_outline_filter_alt_white_24.xml │ │ │ ├── ic_qu_scan_black_24dp.xml │ │ │ ├── ic_qu_settings_black_24dp.xml │ │ │ ├── ic_qu_switch_black_24dp.xml │ │ │ ├── ic_rounded_corner_grey.xml │ │ │ ├── ic_rounded_corner_theme.xml │ │ │ ├── ic_save_white_24dp.xml │ │ │ ├── ic_scan_black_24dp.xml │ │ │ ├── ic_select_all_white_24dp.xml │ │ │ ├── ic_settings_white_24dp.xml │ │ │ ├── ic_share_black_24dp.xml │ │ │ ├── ic_share_white_24dp.xml │ │ │ ├── ic_shortcut_background.xml │ │ │ ├── ic_subscriptions_black_24dp.xml │ │ │ ├── ic_subscriptions_white_24dp.xml │ │ │ ├── ic_whatshot_black_24dp.xml │ │ │ ├── ic_whatshot_white_24dp.xml │ │ │ └── nav_header_bg.png │ │ │ ├── layout │ │ │ ├── activity_bypass_list.xml │ │ │ ├── activity_gfw_donate_config.xml │ │ │ ├── activity_gfw_help.xml │ │ │ ├── activity_gfw_lan_info.xml │ │ │ ├── activity_gfw_setting.xml │ │ │ ├── activity_gfw_terms_service.xml │ │ │ ├── activity_gfw_tlg_proxy.xml │ │ │ ├── activity_gfw_update.xml │ │ │ ├── activity_gfw_warp.xml │ │ │ ├── activity_gfw_warp_generator.xml │ │ │ ├── activity_gfw_youtube_config.xml │ │ │ ├── activity_logcat.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_none.xml │ │ │ ├── activity_routing_settings.xml │ │ │ ├── activity_server_custom_config.xml │ │ │ ├── activity_server_hysteria2.xml │ │ │ ├── activity_server_shadowsocks.xml │ │ │ ├── activity_server_socks.xml │ │ │ ├── activity_server_trojan.xml │ │ │ ├── activity_server_vless.xml │ │ │ ├── activity_server_vmess.xml │ │ │ ├── activity_server_wireguard.xml │ │ │ ├── activity_settings.xml │ │ │ ├── activity_sub_edit.xml │ │ │ ├── activity_sub_setting.xml │ │ │ ├── activity_tasker.xml │ │ │ ├── dialog_config_filter.xml │ │ │ ├── fragment_routing_settings.xml │ │ │ ├── gfw_captcha_dialog.xml │ │ │ ├── gfw_config_filter_spinner.xml │ │ │ ├── gfw_filter_sub_dialog.xml │ │ │ ├── gfw_fragment_dialog.xml │ │ │ ├── gfw_generic_dialog.xml │ │ │ ├── gfw_license_dialog.xml │ │ │ ├── gfw_progress_layout.xml │ │ │ ├── item_qrcode.xml │ │ │ ├── item_recycler_bypass_list.xml │ │ │ ├── item_recycler_footer.xml │ │ │ ├── item_recycler_main.xml │ │ │ ├── item_recycler_sub_setting.xml │ │ │ ├── item_recycler_user_asset.xml │ │ │ ├── layout_tls.xml │ │ │ ├── layout_tls_hysteria2.xml │ │ │ ├── layout_transport.xml │ │ │ ├── nav_header.xml │ │ │ ├── nav_toolbar.xml │ │ │ ├── nav_view.xml │ │ │ ├── preference_with_help_link.xml │ │ │ ├── tls_layout.xml │ │ │ └── widget_switch.xml │ │ │ ├── menu │ │ │ ├── action_server.xml │ │ │ ├── action_sub_setting.xml │ │ │ ├── menu_asset.xml │ │ │ ├── menu_bypass_list.xml │ │ │ ├── menu_drawer.xml │ │ │ ├── menu_logcat.xml │ │ │ ├── menu_main.xml │ │ │ ├── menu_routing.xml │ │ │ └── menu_scanner.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_banner.xml │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_banner.png │ │ │ ├── ic_banner_foreground.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── raw │ │ │ └── licenses.xml │ │ │ ├── values-fa │ │ │ └── strings.xml │ │ │ ├── values-night │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ │ ├── values-ru │ │ │ └── strings.xml │ │ │ ├── values-sw360dp-v13 │ │ │ └── values-preference.xml │ │ │ ├── values-v35 │ │ │ └── styles.xml │ │ │ ├── values-vi │ │ │ └── strings.xml │ │ │ ├── values-zh-rCN │ │ │ └── strings.xml │ │ │ ├── values-zh-rTW │ │ │ └── strings.xml │ │ │ ├── values │ │ │ ├── arrays.xml │ │ │ ├── attrs.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── ic_banner_background.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ ├── app_widget_provider.xml │ │ │ ├── pref_settings.xml │ │ │ └── shortcuts.xml │ │ ├── pre_release │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── v2ray │ │ │ └── ang │ │ │ └── ExampleUnitTest.java │ │ └── kotlin │ │ └── com │ │ └── v2ray │ │ └── ang │ │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── mahsa_EMS_accounts.json ├── mahsa_accounts.txt ├── mahsa_sub.json ├── remote_config_update.json ├── remote_config_update_v10.json ├── remote_config_update_v11.json ├── remote_config_update_v12.json ├── remote_config_update_v13.json ├── remote_config_update_v3.json ├── remote_config_update_v4.json ├── remote_config_update_v5.json ├── remote_config_update_v6.json ├── remote_config_update_v7.json ├── remote_config_update_v8.json ├── remote_config_update_v9.json ├── txt_announcement.txt └── web_announcement.html /.github/ISSUE_TEMPLATE/bug_cn.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: v2rayNG程序问题 3 | about: 创建一个报告来帮助我们改进 4 | --- 5 | 6 | 在提出问题前请先自行排除服务器端问题,同时也请通过搜索确认是否有人提出过相同问题。 7 | 8 | 9 | ### 预期行为 10 | 描述你认为应该发生什么 11 | 12 | ### 实际行为 13 | 描述实际发生了什么 14 | 15 | ### 复现方法 16 | 1. 17 | 2. 18 | 3. 19 | 20 | ### 日志信息 21 |
22 | 23 | 通过`adb logcat -s com.v2ray.ang GoLog V2rayConfigUtilGoLog Main`获取日志。请自行删减日志中可能出现的敏感信息。 24 | 25 | 如果问题可重现,建议先执行`adb logcat -c`清空系统日志再执行上述命令,再操作重现问题。 26 | ``` 27 | 在这里粘贴日志 28 | ``` 29 |
30 | 31 | ### 环境信息 32 | 33 | ### 额外信息(可选) 34 | 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: V2Ray程序问题 4 | url: https://github.com/v2fly/v2ray-core/ 5 | about: 如果您有V2Ray而非v2rayNG的问题,请至这个链接讨论。 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dat 2 | *.jks 3 | V2rayNG/app/release/output.json 4 | .idea/ 5 | .gradle/ 6 | -------------------------------------------------------------------------------- /AndroidLibV2rayLite/README.md: -------------------------------------------------------------------------------- 1 | # AndroidLibV2rayLite 2 | 3 | ### Preparation 4 | - latest Ubuntu environment 5 | - At lease 30G free space 6 | - Get Repo [AndroidLibV2rayLite](https://github.com/2dust/AndroidLibV2rayLite) or [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite) 7 | ### Prepare Go 8 | - Go to https://golang.org/doc/install and install latest go 9 | - Make sure `go version` works as expected 10 | ### Prepare gomobile 11 | - Go to https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile and install gomobile 12 | - export PATH=$PATH:~/go/bin 13 | - Make sure `gomobile init` works as expected 14 | ### Prepare NDK 15 | - Go to https://developer.android.com/ndk/downloads and install latest NDK 16 | - export PATH=$PATH: 17 | - Make sure `ndk-build -v` works as expected 18 | ### Make 19 | - sudo apt install make 20 | - Read and understand [build script](https://github.com/2dust/AndroidLibV2rayLite/blob/master/Makefile) 21 | -------------------------------------------------------------------------------- /CR.md: -------------------------------------------------------------------------------- 1 | v2rayNG 隐私条款 2 | 3 | 最后更新 2017-11-22 4 | 5 | v2rayNG 尊重并保护所有用户的个人隐私权,为此我们向大众公开这份隐私条款。**您使用 v2rayNG 即代表您以阅读并同意了这份条款,如果您不同意这份条款请立即停止使用并卸载 v2rayNG。** 6 | 7 | 1. 信息收集 8 | 9 | v2rayNG 软件自身不会发送任何信息到开发者,但是您下载软件的应用市场(如 Google Play)可能会收集关于应用运行状态的相关信息并提供给 v2rayNG 开发者。有关这些信息,请阅读您使用的应用市场所提供的隐私条款。 10 | 11 | v2rayNG 软件中可能包含需要通过 IAP 支付解锁的功能,您的支付信息将由相关的 IAP 渠道进行处理,而我们对支付信息没有访问权。 12 | 13 | 当您向 v2rayNG 开发者反馈软件运行中的错误时,开发者可能会要求您提供软件以及系统的日志以帮助确认问题的原因。因日志中可能包括敏感信息,此类信息只能由您自己操作发送。**我们不对任何传输服务的安全性和隐私性做任何明示或暗示的担保,请您在传送相关信息时选择可以您自身可以接受的方式。** 14 | 15 | 2. 信息共享 16 | 17 | 我们不会向任何第三方出售收集到的用户数据。我们可能向外部开发者提供信息以协助软件的开发,但是在提供信息之前我们会传达相关保密义务并确定其可以遵守。 18 | 19 | 3. 信息存留 20 | 21 | 除非有相关法律规定,我们会在 30 天内清除不需要继续使用的用户数据,或将统计数据整合为无法识别单个用户的综合报告。 22 | 23 | 4. 信息泄露 24 | 25 | 我们会使用合理的技术和安全手段尽力保护用户的数据,但是无法保证数据的绝对安全。如果我们确认数据发生了泄露,我们会在 7 天内通过可用的渠道通知用户。**您同意不向我们追责任何因不可抗力而造成的损失。** 26 | 27 | 5. 条款修改 28 | 29 | 我们保留修改这份隐私条款的权利,但是会确保在更新条款前至少 30 天通过我们的可用渠道和应用内提示来通知用户。**在新条款生效后继续使用软件即表示您同意修改后的隐私条款。** 30 | -------------------------------------------------------------------------------- /Mahsa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/Mahsa.jpg -------------------------------------------------------------------------------- /Mahsa_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/Mahsa_logo.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MahsaNG 2 | - [Download Mahsa NG vpn from google playstore](https://play.google.com/store/apps/details?id=com.MahsaNet.MahsaNG) 3 | - [ MahsaNG VPN دانلود آخرین نسخه از گیتهاب](https://github.com/GFW-knocker/MahsaNG/releases/latest) 4 | - [mahsa_net telegram channel](https://t.me/mahsa_net) 5 | - MahsaNG is a v2rayNG client aimed to provide free vpn for everyone
6 |
7 | 8 | 9 | # What is the idea 10 | - MahsaNG is client-side of project [Segaro_Dream](https://github.com/GFW-knocker/Segaro_Dream) 11 | - MahsaNG is a decentralized non-profit vpn platform in which everyone can share their configs to help others 12 | - Donated configs continuously monitored and redistributed to users based on clients feedback in each subnet-ip 13 | - Our goal is to make a superior vpn platform which is free,stable,scalable,distributed & filter-resistant 14 | 15 | # Difference to v2rayNG 16 | - vpn providers can use ADS service to make income instead of direct sell 17 | - everyone can share their unused vps bandwidth to help others 18 | - prevent free configs to be stolen and reselled 19 | - Automatic report for refining config collection at central servers 20 | - DNS over HTTPS 21 | - TLS Fragmentor 22 | - HTTP & WS fake Host 23 | - Rotating Configs 24 | - Random Subdomain 25 | - & much more ... 26 | 27 | # build from source 28 | - the code can NOT build standalone apk directly from source 29 | - some parts of source used for encrypting config is closed to prevent leakage & thus reselling of donated configs 30 | - classes responsible for authentication with [mahsa server](https://www.mahsaserver.com/) is also closed to prevent abusing of mahsa server 31 | - all other technology used to bypass filtering is willingly published in [Mahsa Xray-Core](https://github.com/GFW-knocker/Xray-core) including but not limited to Wireguard Noise, Youtube Direct , TLS & HTTPS & DoH fragmentor & fake Host 32 | 33 | # build NikaNG from source 34 | - [NikaNG](https://github.com/mahsanet/NikaNG) is a fork of v2rayNG with [Mahsa Xray-core](https://github.com/GFW-knocker/Xray-core) 35 | - its fully open souce and it can build by github action or locally 36 | - if you are interested in Mahsa-core as a developer , NikaNG is for you. 37 | - you need to place [libv2ray.aar](https://github.com/GFW-knocker/AndroidLibXrayLite) in v2rayng/apps/libs folder before compile 38 | 39 | -------------------------------------------------------------------------------- /V2rayNG/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | *.apk 9 | signing.properties 10 | *.aar 11 | -------------------------------------------------------------------------------- /V2rayNG/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /google-services.json 3 | -------------------------------------------------------------------------------- /V2rayNG/app/libs/arm64-v8a/libtun2socks.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/libs/arm64-v8a/libtun2socks.so -------------------------------------------------------------------------------- /V2rayNG/app/libs/armeabi-v7a/libtun2socks.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/libs/armeabi-v7a/libtun2socks.so -------------------------------------------------------------------------------- /V2rayNG/app/libs/json.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/libs/json.jar -------------------------------------------------------------------------------- /V2rayNG/app/libs/x86/libtun2socks.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/libs/x86/libtun2socks.so -------------------------------------------------------------------------------- /V2rayNG/app/libs/x86_64/libtun2socks.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/libs/x86_64/libtun2socks.so -------------------------------------------------------------------------------- /V2rayNG/app/proguard-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/proguard-rules.pro -------------------------------------------------------------------------------- /V2rayNG/app/src/dev/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | v2rayNG (DEV) 4 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/ads_block_rule.txt: -------------------------------------------------------------------------------- 1 | ext:geosite_c4u.dat:category-ads-all, 2 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/custom_routing_block: -------------------------------------------------------------------------------- 1 | geosite:category-porn, 2 | 10.10.34.34, 3 | 10.10.34.35, 4 | 10.10.34.36, 5 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/custom_routing_direct: -------------------------------------------------------------------------------- 1 | domain:ir, 2 | geosite:category-ir, 3 | geosite:private, 4 | geoip:ir, 5 | geoip:private, 6 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/custom_routing_proxy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/src/main/assets/custom_routing_proxy -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/geoip_c4u.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/src/main/assets/geoip_c4u.dat -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/geosite_c4u.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/src/main/assets/geosite_c4u.dat -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/irgfw_block_rules.txt: -------------------------------------------------------------------------------- 1 | ext:geosite_c4u.dat:category-ads-all, 2 | ext:geosite_c4u.dat:nsfw, 3 | ext:geosite_c4u.dat:malware, 4 | ext:geosite_c4u.dat:phishing, 5 | ext:geosite_c4u.dat:cryptominers, 6 | ext:geoip_c4u.dat:malware, 7 | ext:geoip_c4u.dat:phishing, 8 | 10.10.34.34, 9 | 10.10.34.35, 10 | 10.10.34.36, 11 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/irgfw_direct_rules.txt: -------------------------------------------------------------------------------- 1 | regexp:.*\.ir$, 2 | regexp:.*\.xn--mgba3a4f16a$, 3 | ext:geosite_c4u.dat:ir, 4 | ext:geoip_c4u.dat:ir, 5 | geoip:private, 6 | geosite:private, 7 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/privacy_policy.txt: -------------------------------------------------------------------------------- 1 | Privacy Policy 2 | 3 | Mahsa Server does only facilitate providing and sharing free VPN servers and does not collect any personal information or sensitive data except the ones that are mentioned in Section 1.2. 4 | 5 | Users should know that their public IP address, DNS queries and SNI fields can be collected by Server Owners (same as your ISP) and it is out of our control. This even applies in the case of most secure TLS-based VPN configurations. Currently, we only encourage Server Owners not to collect these data; but we don’t act on behalf of them. 6 | 7 | Note 1: Please always make sure to use official apps and follow this guide (https://support.google.com/chrome/answer/95617?hl=en) to make sure the website you are visiting is legit and secure while you are using MahsaNG VPN. 8 | 9 | Note 2: We strongly advise against using MahsaNG for sensitive tasks, such as banking or any activities that may be deemed illegal in your country unless you are using a VPN config that you trust. 10 | 1. Data Collection 11 | 1.1 Data Not Collected 12 | 13 | We do not gather the following information: 14 | 15 | Names (including subscriber names, usernames, and screen names) 16 | Addresses (residential and business) 17 | Telephone numbers 18 | Payment details (credit card numbers, bank account info, billing records) 19 | 20 | We don’t store sensitive data and engineered systems avoid this. 21 | 22 | No logs are collected on online activities such as: 23 | 24 | Browsing history 25 | Traffic destination 26 | Data content 27 | DNS queries 28 | 29 | 1.2 Data Collection 30 | 31 | Limited anonymous data is collected to provide the best possible VPN configs using the Mahsa Server. 32 | 33 | It includes the following: 34 | 35 | IP Address of the Client (first 3 octets only) 36 | Timezone of the client 37 | Android Version 38 | App Version 39 | Connection Status (Connected/Not Connected/Ping value) 40 | 41 | 1.3 App Permissions 42 | 43 | The app does not need any permissions to access your phone’s contacts, location, device id, storage, microphone, camera, etc. 44 | 2. Data Usage 45 | 46 | Data is used for: 47 | 48 | Maintaining a list of healthy and working donated VPN configs 49 | Regional distribution algorithm to help the clients to get the best configs based on their region and ISP 50 | 51 | 3. Data Sharing and Transfer 52 | 53 | We do not share any data with the any third parties. 54 | 4. Security Measures 55 | 56 | Strong security measures implemented to protect data. Staff access limited. 57 | 5. Data Retention 58 | 59 | Data retained for legitimate business needs. Deleted when not needed, securely stored otherwise. 60 | 6. Right to Be Forgotten 61 | 62 | Data erased when: 63 | 64 | No longer necessary 65 | Consent withdrawn (via data removal form) 66 | 67 | 7. Third Party Services 68 | 69 | Using third party services while on MahsaNG is subject to their policies. 70 | 8. Advertising 71 | 72 | We do not get paid for the VPN configs that we provide. 73 | We do not collect any data for the advertisement purposes. 74 | 75 | 9. Children’s Privacy 76 | 77 | Parents encouraged to teach children about online privacy. 78 | 10. Data Deletion 79 | 80 | You can use the following link to request for deleting your data. 81 | 82 | Data Deletion Request 83 | https://www.mahsaserver.com/delete-request-form/ 84 | 85 | https://www.mahsaserver.com/privacy/ 86 | 87 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/terms_of_service.txt: -------------------------------------------------------------------------------- 1 | Terms of Service 2 | General 3 | 4 | Our aim is to provide quality service to all of our users. Before accessing the site or the service, please carefully read these terms of service. 5 | 6 | These Terms of Service (“the Terms”) govern your usage of MahsaNG and its associated website domains (“the Site”) and related services (“the Services”), owned and operated by the MahsaNG Team (“MahsaNG,” “our,” “we,” or “us”). The Terms establish a legally binding agreement (“the Agreement”) between you and the MahsaNet Team. 7 | 8 | MahsaNG Service 9 | 10 | You comprehend that we offer you a VPN client that provides you a curated list of healthy VPN configs. We do not manage any VPN server. It is your responsibility to make sure that the VPN config that you are connecting to is safe. 11 | Usage Policy 12 | 13 | BY USING THE MahsaNG SERVICE (the “Service”) YOU AGREE: 14 | 15 | NOT to launch any attacks on other computers or networks while using our service. 16 | NOT to utilize the service in ways that could harm our network or others. 17 | It is the user’s responsibility to be aware of and understand relevant laws in their jurisdiction. MahsaNG is not liable for user actions, including criminal and civil liabilities. 18 | The Software is under a limited license for the purpose stated by MahsaNG and as per these Terms. Unauthorized use of the Software is prohibited. 19 | 20 | Disclaimers 21 | 22 | While we aim to prevent Site and Service interruptions, they are provided “as is” and “as available.” We do not warrant the accuracy of materials or information provided, or their suitability for any purpose. 23 | Actual service coverage, speeds, and quality may vary. The Service may be unavailable for various factors beyond our control. It may be interrupted, limited, or curtailed. 24 | We do not guarantee the Service will meet your requirements or be uninterrupted, timely, secure, or error-free. You access the Site and Service at your own risk. 25 | We are not liable for data loss, delays, or misdirection due to Service interruptions or network issues. We may impose limits or block certain usage to protect users or the Service. Network speed is an estimate. Accuracy and timeliness of data are not guaranteed. 26 | We do not log user activity but log access attempts for troubleshooting. We do not engage in censorship or share personal info with third parties. 27 | MahsaNet does not have any responsibility for third-party VPNs that are usable through the app. 28 | The user is obligated to observe basic security principles, including SSL indicator check, when using third-party VPNs. 29 | 30 | Changes to the Terms 31 | 32 | MahsaNG may update the Terms without notice. Changes will be posted on the Site and considered effective upon posting. Significant changes will be notified through the App or on the Website. 33 | 34 | 35 | https://www.mahsaserver.com/terms/ 36 | 37 | 38 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/assets/v2ray_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "stats":{}, 3 | "log": { 4 | "loglevel": "none" 5 | }, 6 | "policy":{ 7 | "levels": { 8 | "8": { 9 | "handshake": 4, 10 | "connIdle": 300, 11 | "uplinkOnly": 1, 12 | "downlinkOnly": 1 13 | } 14 | }, 15 | "system": { 16 | "statsOutboundUplink": true, 17 | "statsOutboundDownlink": true 18 | } 19 | }, 20 | "inbounds": [{ 21 | "tag": "socks", 22 | "port": 10808, 23 | "protocol": "socks", 24 | "settings": { 25 | "auth": "noauth", 26 | "udp": true, 27 | "userLevel": 8 28 | }, 29 | "sniffing": { 30 | "enabled": true, 31 | "destOverride": [ 32 | "http", 33 | "tls" 34 | ] 35 | } 36 | }, 37 | { 38 | "tag": "http", 39 | "port": 10809, 40 | "protocol": "http", 41 | "settings": { 42 | "userLevel": 8 43 | } 44 | } 45 | ], 46 | "outbounds": [{ 47 | "tag": "proxy", 48 | "protocol": "vmess", 49 | "settings": { 50 | "vnext": [ 51 | { 52 | "address": "v2ray.cool", 53 | "port": 10086, 54 | "users": [ 55 | { 56 | "id": "a3482e88-686a-4a58-8126-99c9df64b7bf", 57 | "alterId": 0, 58 | "security": "auto", 59 | "level": 8 60 | } 61 | ] 62 | } 63 | ], 64 | "servers": [ 65 | { 66 | "address": "v2ray.cool", 67 | "method": "chacha20", 68 | "ota": false, 69 | "password": "123456", 70 | "port": 10086, 71 | "level": 8 72 | } 73 | ] 74 | }, 75 | "streamSettings": { 76 | "network": "tcp" 77 | }, 78 | "mux": { 79 | "enabled": false 80 | } 81 | }, 82 | { 83 | "protocol": "freedom", 84 | "settings": {}, 85 | "tag": "direct" 86 | }, 87 | { 88 | "protocol": "blackhole", 89 | "tag": "block", 90 | "settings": { 91 | "response": { 92 | "type": "http" 93 | } 94 | } 95 | } 96 | ], 97 | "routing": { 98 | "domainStrategy": "IPIfNonMatch", 99 | "rules": [] 100 | }, 101 | "dns": { 102 | "hosts": {}, 103 | "servers": [] 104 | } 105 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /V2rayNG/app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GFW-knocker/MahsaNG/d57c97921adf497d2ebf33c17687156bae162ec9/V2rayNG/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/GFW_help_Activity.java: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.ActionBar; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import com.v2ray.ang.gfwknocker.my_preference_storage; 8 | import com.v2ray.ang.gfwknocker.wget_module; 9 | 10 | import android.os.Bundle; 11 | import android.view.MenuItem; 12 | import android.webkit.WebView; 13 | import android.widget.TextView; 14 | 15 | public class GFW_help_Activity extends AppCompatActivity { 16 | my_preference_storage mystrg; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_gfw_help); 22 | 23 | ActionBar actionBar = getSupportActionBar(); 24 | if(actionBar!=null) { 25 | actionBar.setDisplayHomeAsUpEnabled(true); 26 | } 27 | 28 | mystrg = new my_preference_storage(this); 29 | String url_announcement_txt = mystrg.get_value("url_announcement_txt",getResources().getString(R.string.announcement_txt_url)); 30 | String url_announcement_html = mystrg.get_value("url_announcement_html",getResources().getString(R.string.announcement_html_url)); 31 | 32 | TextView tv = (TextView) findViewById(R.id.textView_help_remote); 33 | WebView wv = (WebView) findViewById(R.id.webview_help_remote); 34 | 35 | 36 | // Start a new thread to fetch the URL 37 | new Thread(new Runnable() { 38 | @Override 39 | public void run() { 40 | String s7 = wget_module.auto_routed_fetch_remote_text(url_announcement_txt); 41 | final String mytxt; 42 | if((s7==null) || (s7.isEmpty())) { 43 | mytxt = "fail to fetch remote txt"; 44 | }else{ 45 | mytxt = s7; 46 | } 47 | runOnUiThread(new Runnable() { 48 | @Override 49 | public void run() { 50 | tv.setText(mytxt); 51 | } 52 | }); 53 | } 54 | }).start(); 55 | 56 | 57 | 58 | new Thread(new Runnable() { 59 | @Override 60 | public void run() { 61 | String s8 = wget_module.auto_routed_fetch_remote_text(url_announcement_html); 62 | final String myhtml; 63 | if((s8==null) || (s8.isEmpty())) { 64 | myhtml = "fail to fetch webpage"; 65 | }else{ 66 | myhtml = s8; 67 | } 68 | runOnUiThread(new Runnable() { 69 | @Override 70 | public void run() { 71 | wv.loadData(myhtml,"text/html","utf-8"); 72 | } 73 | }); 74 | } 75 | }).start(); 76 | 77 | 78 | } 79 | 80 | 81 | 82 | 83 | @Override 84 | public boolean onOptionsItemSelected(@NonNull MenuItem item){ 85 | if (item.getItemId() == android.R.id.home) { 86 | this.finish(); 87 | return true; 88 | } 89 | return super.onOptionsItemSelected(item); 90 | } 91 | 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/GFW_youtube_config_Activity.java: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.gfwknocker; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.appcompat.app.ActionBar; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.webkit.WebView; 13 | import android.widget.Button; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.v2ray.ang.R; 18 | import com.v2ray.ang.ui.MainActivity; 19 | import com.v2ray.ang.util.AngConfigManager; 20 | import com.v2ray.ang.util.MmkvManager; 21 | 22 | public class GFW_youtube_config_Activity extends AppCompatActivity { 23 | 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_gfw_youtube_config); 29 | 30 | ActionBar actionBar = getSupportActionBar(); 31 | if(actionBar!=null) { 32 | actionBar.setDisplayHomeAsUpEnabled(true); 33 | } 34 | // 35 | // String url_ADS_txt = mystrg.get_value("url_ADS_txt",getResources().getString(R.string.announcement_txt_url)); 36 | // String url_ADS_html = mystrg.get_value("url_ADS_html",getResources().getString(R.string.announcement_html_url)); 37 | 38 | 39 | Button btn = (Button) findViewById(R.id.btn_youtube_config); 40 | 41 | btn.setOnClickListener(new View.OnClickListener() { 42 | @Override 43 | public void onClick(View v) { 44 | 45 | String server = "vmess://ew0KICAidiI6ICIyIiwNCiAgInBzIjogIllvdXR1YmUgJiBUd2l0dGVyIiwNCiAgImFkZCI6ICJnZncueW91dHViZS5jb20iLA0KICAicG9ydCI6ICI0NDMiLA0KICAiaWQiOiAiZTA4NTUxMTktNGIxOC00MDQ1LWI5MDMtOGY2OTliMGM1NDE0IiwNCiAgImFpZCI6ICIwIiwNCiAgInNjeSI6ICJhdXRvIiwNCiAgIm5ldCI6ICJ0Y3AiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiIiwNCiAgInBhdGgiOiAiIiwNCiAgInRscyI6ICIiLA0KICAic25pIjogIiIsDQogICJhbHBuIjogIiIsDQogICJmcCI6ICIiDQp9"; 46 | String mahsa_subid = MmkvManager.INSTANCE.import_Mahsa_Subscription("GFW-knocker"); 47 | AngConfigManager.INSTANCE.importBatchConfig(server, mahsa_subid , false); 48 | 49 | Toast.makeText(GFW_youtube_config_Activity.this,"enjoy direct Youtube & Twitter",Toast.LENGTH_LONG).show(); 50 | } 51 | }); 52 | 53 | 54 | } 55 | 56 | 57 | @Override 58 | public boolean onOptionsItemSelected(@NonNull MenuItem item){ 59 | if (item.getItemId() == android.R.id.home) { 60 | this.finish(); 61 | return true; 62 | } 63 | return super.onOptionsItemSelected(item); 64 | } 65 | 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/helper/GFW_privacy_policy_Activity.java: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.helper; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.ActionBar; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import android.content.Context; 8 | import android.os.Bundle; 9 | import android.view.MenuItem; 10 | import android.widget.TextView; 11 | 12 | import com.v2ray.ang.R; 13 | 14 | import java.io.InputStreamReader; 15 | import java.io.Reader; 16 | 17 | public class GFW_privacy_policy_Activity extends AppCompatActivity { 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_gfw_privacy_policy); 23 | 24 | 25 | ActionBar actionBar = getSupportActionBar(); 26 | if(actionBar!=null) { 27 | actionBar.setDisplayHomeAsUpEnabled(true); 28 | } 29 | 30 | 31 | TextView tv = (TextView) findViewById(R.id.textView_privacy_policy); 32 | 33 | String tmp = fetch_text_file_from_asset(GFW_privacy_policy_Activity.this); 34 | tv.setText(tmp); 35 | 36 | 37 | } 38 | 39 | 40 | 41 | 42 | 43 | // read text file from asset 44 | private String fetch_text_file_from_asset(Context ctx){ 45 | try { 46 | 47 | int bufferSize = 4096; 48 | char[] buffer = new char[bufferSize]; 49 | StringBuilder sb = new StringBuilder(); 50 | Reader in = new InputStreamReader(ctx.getAssets().open("privacy_policy.txt")); 51 | for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) { 52 | sb.append(buffer, 0, numRead); 53 | } 54 | in.close(); 55 | return sb.toString(); 56 | 57 | }catch(Exception e){ 58 | System.out.println("file reading ERR: "+e.getMessage()); 59 | return ""; 60 | } 61 | } 62 | 63 | 64 | @Override 65 | public boolean onOptionsItemSelected(@NonNull MenuItem item){ 66 | if (item.getItemId() == android.R.id.home) { 67 | this.finish(); 68 | return true; 69 | } 70 | return super.onOptionsItemSelected(item); 71 | } 72 | 73 | 74 | 75 | 76 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/helper/GFW_terms_service_Activity.java: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.helper; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.ActionBar; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import android.content.Context; 8 | import android.os.Bundle; 9 | import android.os.TestLooperManager; 10 | import android.view.MenuItem; 11 | import android.widget.TextView; 12 | 13 | import com.v2ray.ang.R; 14 | 15 | import java.io.BufferedReader; 16 | import java.io.InputStream; 17 | import java.io.InputStreamReader; 18 | import java.io.Reader; 19 | import java.nio.charset.StandardCharsets; 20 | 21 | public class GFW_terms_service_Activity extends AppCompatActivity { 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_gfw_terms_service); 27 | 28 | 29 | ActionBar actionBar = getSupportActionBar(); 30 | if(actionBar!=null) { 31 | actionBar.setDisplayHomeAsUpEnabled(true); 32 | } 33 | 34 | 35 | TextView tv = (TextView) findViewById(R.id.textView_terms_service); 36 | 37 | String tmp = fetch_text_file_from_asset(GFW_terms_service_Activity.this); 38 | tv.setText(tmp); 39 | 40 | 41 | } 42 | 43 | 44 | 45 | 46 | 47 | 48 | // read text file from asset 49 | private String fetch_text_file_from_asset(Context ctx){ 50 | try { 51 | 52 | int bufferSize = 4096; 53 | char[] buffer = new char[bufferSize]; 54 | StringBuilder sb = new StringBuilder(); 55 | Reader in = new InputStreamReader(ctx.getAssets().open("terms_of_service.txt")); 56 | for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) { 57 | sb.append(buffer, 0, numRead); 58 | } 59 | in.close(); 60 | return sb.toString(); 61 | 62 | }catch(Exception e){ 63 | System.out.println("file reading ERR: "+e.getMessage()); 64 | return ""; 65 | } 66 | } 67 | 68 | 69 | @Override 70 | public boolean onOptionsItemSelected(@NonNull MenuItem item){ 71 | if (item.getItemId() == android.R.id.home) { 72 | this.finish(); 73 | return true; 74 | } 75 | return super.onOptionsItemSelected(item); 76 | } 77 | 78 | 79 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.v2ray.ang.helper; 18 | 19 | import androidx.recyclerview.widget.RecyclerView; 20 | import androidx.recyclerview.widget.ItemTouchHelper; 21 | 22 | /** 23 | * Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}. 24 | * 25 | * @author Paul Burke (ipaulpro) 26 | */ 27 | public interface ItemTouchHelperAdapter { 28 | 29 | /** 30 | * Called when an item has been dragged far enough to trigger a move. This is called every time 31 | * an item is shifted, and not at the end of a "drop" event.
32 | *
33 | * Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after 34 | * adjusting the underlying data to reflect this move. 35 | * 36 | * @param fromPosition The start position of the moved item. 37 | * @param toPosition Then resolved position of the moved item. 38 | * @return True if the item was moved to the new adapter position. 39 | * 40 | * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) 41 | * @see RecyclerView.ViewHolder#getAdapterPosition() 42 | */ 43 | boolean onItemMove(int fromPosition, int toPosition); 44 | 45 | 46 | void onItemMoveCompleted(); 47 | 48 | /** 49 | * Called when an item has been dismissed by a swipe.
50 | *
51 | * Implementations should call {@link RecyclerView.Adapter#notifyItemRemoved(int)} after 52 | * adjusting the underlying data to reflect this removal. 53 | * 54 | * @param position The position of the item dismissed. 55 | * 56 | * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) 57 | * @see RecyclerView.ViewHolder#getAdapterPosition() 58 | */ 59 | void onItemDismiss(int position); 60 | } 61 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperViewHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.v2ray.ang.helper; 18 | 19 | import androidx.recyclerview.widget.ItemTouchHelper; 20 | 21 | /** 22 | * Interface to notify an item ViewHolder of relevant callbacks from {@link 23 | * ItemTouchHelper.Callback}. 24 | * 25 | * @author Paul Burke (ipaulpro) 26 | */ 27 | public interface ItemTouchHelperViewHolder { 28 | 29 | /** 30 | * Called when the {@link ItemTouchHelper} first registers an item as being moved or swiped. 31 | * Implementations should update the item view to indicate it's active state. 32 | */ 33 | void onItemSelected(); 34 | 35 | 36 | /** 37 | * Called when the {@link ItemTouchHelper} has completed the move or swipe, and the active item 38 | * state should be cleared. 39 | */ 40 | void onItemClear(); 41 | } 42 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/java/com/v2ray/ang/helper/OnStartDragListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.v2ray.ang.helper; 18 | 19 | import androidx.recyclerview.widget.RecyclerView; 20 | 21 | /** 22 | * Listener for manual initiation of a drag. 23 | */ 24 | public interface OnStartDragListener { 25 | 26 | /** 27 | * Called when a view is requesting a start of a drag. 28 | * 29 | * @param viewHolder The holder of the view to drag. 30 | */ 31 | void onStartDrag(RecyclerView.ViewHolder viewHolder); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang 2 | 3 | import androidx.multidex.MultiDexApplication 4 | import androidx.preference.PreferenceManager 5 | import com.tencent.mmkv.MMKV 6 | 7 | class AngApplication : MultiDexApplication() { 8 | companion object { 9 | const val PREF_LAST_VERSION = "pref_last_version" 10 | } 11 | 12 | var firstRun = false 13 | private set 14 | 15 | override fun onCreate() { 16 | super.onCreate() 17 | 18 | // LeakCanary.install(this) 19 | 20 | val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) 21 | firstRun = defaultSharedPreferences.getInt(PREF_LAST_VERSION, 0) != BuildConfig.VERSION_CODE 22 | if (firstRun) 23 | defaultSharedPreferences.edit().putInt(PREF_LAST_VERSION, BuildConfig.VERSION_CODE).apply() 24 | 25 | //Logger.init().logLevel(if (BuildConfig.DEBUG) LogLevel.FULL else LogLevel.NONE) 26 | MMKV.initialize(this) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AngConfig.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class AngConfig( 4 | var index: Int, 5 | var vmess: ArrayList, 6 | var subItem: ArrayList 7 | ) { 8 | data class VmessBean(var guid: String = "123456", 9 | var address: String = "v2ray.cool", 10 | var port: Int = 10086, 11 | var id: String = "a3482e88-686a-4a58-8126-99c9df64b7bf", 12 | var alterId: Int = 64, 13 | var security: String = "aes-128-cfb", 14 | var network: String = "tcp", 15 | var remarks: String = "def", 16 | var headerType: String = "", 17 | var requestHost: String = "", 18 | var path: String = "", 19 | var streamSecurity: String = "", 20 | var allowInsecure: String = "", 21 | var configType: Int = 1, 22 | var configVersion: Int = 1, 23 | var testResult: String = "", 24 | var subid: String = "", 25 | var flow: String = "", 26 | var sni: String = "") 27 | 28 | data class SubItemBean(var id: String = "", 29 | var remarks: String = "", 30 | var url: String = "", 31 | var enabled: Boolean = true) 32 | } 33 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AppInfo.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | import android.graphics.drawable.Drawable 4 | 5 | data class AppInfo(val appName: String, 6 | val packageName: String, 7 | val appIcon: Drawable, 8 | val isSystemApp: Boolean, 9 | var isSelected: Int) -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ConfigResult.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class ConfigResult ( 4 | var status: Boolean, 5 | var guid: String? = null, 6 | var content: String = "", 7 | var domainPort: String? = null, 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | enum class EConfigType(val value: Int, val protocolScheme: String) { 4 | VMESS(1, "vmess://"), 5 | CUSTOM(2, ""), 6 | SHADOWSOCKS(3, "ss://"), 7 | SOCKS(4, "socks://"), 8 | VLESS(5, "vless://"), 9 | TROJAN(6, "trojan://"), 10 | WIREGUARD(7, "wireguard://"); 11 | 12 | companion object { 13 | fun fromInt(value: Int) = values().firstOrNull { it.value == value } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ERoutingMode.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | enum class ERoutingMode(val value: String ) { 4 | GLOBAL_PROXY("0"), 5 | BYPASS_LAN("1"), 6 | BYPASS_MAINLAND("2"), 7 | BYPASS_LAN_MAINLAND("3"), 8 | GLOBAL_DIRECT("4"); 9 | } 10 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/Hysteria2Bean.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class Hysteria2Bean( 4 | val server: String?, 5 | val auth: String?, 6 | val lazy: Boolean? = true, 7 | val obfs: ObfsBean? = null, 8 | val socks5: Socks5Bean? = null, 9 | val http: Socks5Bean? = null, 10 | val tls: TlsBean? = null, 11 | ) { 12 | data class ObfsBean( 13 | val type: String?, 14 | val salamander: SalamanderBean? 15 | ) { 16 | data class SalamanderBean( 17 | val password: String?, 18 | ) 19 | } 20 | 21 | data class Socks5Bean( 22 | val listen: String?, 23 | ) 24 | 25 | data class TlsBean( 26 | val sni: String?, 27 | val insecure: Boolean?, 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerAffiliationInfo.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class ServerAffiliationInfo(var testDelayMillis: Long = 0L) { 4 | fun getTestDelayString(): String { 5 | if (testDelayMillis == 0L) { 6 | return "" 7 | } 8 | return testDelayMillis.toString() + "ms" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServersCache.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class ServersCache(val guid: String, 4 | val config: ServerConfig) -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/SubscriptionItem.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class SubscriptionItem( 4 | var remarks: String = "", 5 | var url: String = "", 6 | var enabled: Boolean = true, 7 | val addedTime: Long = System.currentTimeMillis()) { 8 | } 9 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.dto 2 | 3 | data class VmessQRCode(var v: String = "", 4 | var ps: String = "", 5 | var add: String = "", 6 | var port: String = "", 7 | var id: String = "", 8 | var aid: String = "0", 9 | var scy: String = "", 10 | var net: String = "", 11 | var type: String = "", 12 | var host: String = "", 13 | var path: String = "", 14 | var tls: String = "", 15 | var sni: String = "", 16 | var alpn: String = "", 17 | var fp: String = "") -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.extension 2 | 3 | import android.content.Context 4 | import android.os.Build 5 | import android.widget.Toast 6 | import com.v2ray.ang.AngApplication 7 | import me.drakeet.support.toast.ToastCompat 8 | import org.json.JSONObject 9 | import java.net.URI 10 | import java.net.URLConnection 11 | 12 | /** 13 | * Some extensions 14 | */ 15 | 16 | val Context.v2RayApplication: AngApplication 17 | get() = applicationContext as AngApplication 18 | 19 | fun Context.toast(message: Int): Toast = ToastCompat 20 | .makeText(this, message, Toast.LENGTH_SHORT) 21 | .apply { 22 | show() 23 | } 24 | 25 | fun Context.toast(message: CharSequence): Toast = ToastCompat 26 | .makeText(this, message, Toast.LENGTH_SHORT) 27 | .apply { 28 | show() 29 | } 30 | 31 | fun JSONObject.putOpt(pair: Pair) = putOpt(pair.first, pair.second) 32 | fun JSONObject.putOpt(pairs: Map) = pairs.forEach { putOpt(it.key to it.value) } 33 | 34 | const val threshold = 1000 35 | const val divisor = 1024F 36 | 37 | fun Long.toSpeedString() = toTrafficString() + "/s" 38 | 39 | fun Long.toTrafficString(): String { 40 | if (this == 0L) 41 | return "\t\t\t0\t B" 42 | 43 | if (this < threshold) 44 | return "${this.toFloat().toShortString()}\t B" 45 | 46 | val kib = this / divisor 47 | if (kib < threshold) 48 | return "${kib.toShortString()}\t KB" 49 | 50 | val mib = kib / divisor 51 | if (mib < threshold) 52 | return "${mib.toShortString()}\t MB" 53 | 54 | val gib = mib / divisor 55 | if (gib < threshold) 56 | return "${gib.toShortString()}\t GB" 57 | 58 | val tib = gib / divisor 59 | if (tib < threshold) 60 | return "${tib.toShortString()}\t TB" 61 | 62 | val pib = tib / divisor 63 | if (pib < threshold) 64 | return "${pib.toShortString()}\t PB" 65 | 66 | return "∞" 67 | } 68 | 69 | private fun Float.toShortString(): String { 70 | val s = "%.2f".format(this) 71 | if (s.length <= 4) 72 | return s 73 | return s.substring(0, 4).removeSuffix(".") 74 | } 75 | 76 | val URLConnection.responseLength: Long 77 | get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) contentLengthLong else contentLength.toLong() 78 | 79 | val URI.idnHost: String 80 | get() = (host!!).replace("[", "").replace("]", "") -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/gfwknocker/BackServ.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.gfwknocker 2 | 3 | import android.app.Service 4 | import android.content.Context 5 | import com.v2ray.ang.AppConfig 6 | import com.v2ray.ang.R 7 | import com.v2ray.ang.util.MessageUtil 8 | 9 | 10 | class backServ(ctx1 : Context , svc1 : Service , target_ip : String , target_port : Int , nfrag : Int , sleepfrag : Double , is_youtube : Boolean ){ 11 | private var DoH_service: DoH_over_Fragment? = null 12 | private var HTTPS_serv: HTTPS_Fragmentor? = null 13 | private var TLS_serv: TLS_Fragmentor? = null 14 | private var ctx = ctx1 15 | private var svc = svc1 16 | 17 | // constructor 18 | init { 19 | 20 | var mystrg = my_preference_storage(ctx); 21 | var isp = mystrg.get_value("isp","mci") 22 | 23 | 24 | TLS_serv = TLS_Fragmentor( 25 | "127.0.0.1", 2500, 26 | target_ip , target_port, true, 27 | nfrag, sleepfrag 28 | ) 29 | 30 | 31 | 32 | // --------------------- HTTPS and DOH -------------------- 33 | if( is_youtube ) { 34 | val url_remote_config = mystrg.get_value( 35 | "url_remote_config", 36 | ctx.getResources().getString(R.string.remote_config_url) 37 | ) 38 | var cpr = config_pkg_reader(url_remote_config, "mahsa_config.json", ctx) 39 | cpr.fetch_json_config(true) // fetch mahsa config from shared preference or local asset 40 | 41 | 42 | var offline_dns = cpr.get_offline_DNS(isp) 43 | var doh_url = cpr.get_doh_url(isp) 44 | var doh_ip = cpr.get_doh_ip(isp) 45 | var doh_CF_flag = cpr.get_doh_CF_flag(isp) 46 | 47 | if (doh_url.isEmpty()) { 48 | doh_url = "cloudflare" 49 | } 50 | 51 | if (doh_CF_flag) { 52 | doh_ip = target_ip 53 | } 54 | 55 | // DoH service to be used inside code for DNS 56 | DoH_service = DoH_over_Fragment( 57 | doh_url, doh_ip, 443, 58 | true, nfrag, sleepfrag, 59 | offline_dns 60 | ) 61 | 62 | // HTTPS proxy listening on 127.0.0.1:4500 63 | HTTPS_serv = HTTPS_Fragmentor( 64 | "127.0.0.1", 4500, 65 | "", -1, 66 | DoH_service, true, 67 | nfrag, sleepfrag 68 | ) 69 | } 70 | 71 | 72 | // DoH_service!!.query("instagram.com") 73 | // DoH_service!!.query("youtube.com") 74 | // DoH_service!!.query("youtu.be") 75 | // DoH_service!!.query("fb.com") 76 | // DoH_service!!.query("twitter.com") 77 | // DoH_service!!.query("google.com") 78 | // DoH_service!!.query("google.com") 79 | // DoH_service!!.query("fb.com") 80 | // DoH_service!!.query("google.com") 81 | 82 | } 83 | 84 | 85 | fun start_HTTPS_service() { 86 | HTTPS_serv!!.start() 87 | } 88 | 89 | fun stop_HTTPS_service() { 90 | HTTPS_serv!!.safely_stop_server() 91 | DoH_service!!.safely_stop_DoH() 92 | } 93 | 94 | fun start_TLS_service() { 95 | TLS_serv!!.start() 96 | } 97 | 98 | fun stop_TLS_service() { 99 | TLS_serv!!.safely_stop_server() 100 | } 101 | 102 | } 103 | 104 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/plugin/NativePlugin.kt: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * 3 | * Copyright (C) 2021 by nekohasekai * 4 | * Copyright (C) 2021 by Max Lv * 5 | * Copyright (C) 2021 by Mygod Studio * 6 | * * 7 | * This program is free software: you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation, either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see . * 19 | * * 20 | ******************************************************************************/ 21 | 22 | package com.v2ray.ang.plugin 23 | 24 | import android.content.pm.ResolveInfo 25 | 26 | class NativePlugin(resolveInfo: ResolveInfo) : ResolvedPlugin(resolveInfo) { 27 | init { 28 | check(resolveInfo.providerInfo != null) 29 | } 30 | 31 | override val componentInfo get() = resolveInfo.providerInfo!! 32 | } 33 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/plugin/Plugin.kt: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * 3 | * Copyright (C) 2021 by nekohasekai * 4 | * Copyright (C) 2021 by Max Lv * 5 | * Copyright (C) 2021 by Mygod Studio * 6 | * * 7 | * This program is free software: you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation, either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see . * 19 | * * 20 | ******************************************************************************/ 21 | 22 | package com.v2ray.ang.plugin 23 | 24 | import android.graphics.drawable.Drawable 25 | 26 | abstract class Plugin { 27 | abstract val id: String 28 | abstract val label: CharSequence 29 | abstract val version: Int 30 | abstract val versionName: String 31 | open val icon: Drawable? get() = null 32 | open val defaultConfig: String? get() = null 33 | open val packageName: String get() = "" 34 | open val directBootAware: Boolean get() = true 35 | 36 | override fun equals(other: Any?): Boolean { 37 | if (this === other) return true 38 | if (javaClass != other?.javaClass) return false 39 | return id == (other as Plugin).id 40 | } 41 | 42 | override fun hashCode() = id.hashCode() 43 | } 44 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/plugin/PluginContract.kt: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * 3 | * Copyright (C) 2021 by nekohasekai * 4 | * * 5 | * This program is free software: you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation, either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program. If not, see . * 17 | * * 18 | ******************************************************************************/ 19 | 20 | package com.v2ray.ang.plugin 21 | 22 | object PluginContract { 23 | 24 | const val ACTION_NATIVE_PLUGIN = "io.nekohasekai.sagernet.plugin.ACTION_NATIVE_PLUGIN" 25 | const val EXTRA_ENTRY = "io.nekohasekai.sagernet.plugin.EXTRA_ENTRY" 26 | const val METADATA_KEY_ID = "io.nekohasekai.sagernet.plugin.id" 27 | const val METADATA_KEY_EXECUTABLE_PATH = "io.nekohasekai.sagernet.plugin.executable_path" 28 | const val METHOD_GET_EXECUTABLE = "sagernet:getExecutable" 29 | 30 | const val COLUMN_PATH = "path" 31 | const val COLUMN_MODE = "mode" 32 | const val SCHEME = "plugin" 33 | } 34 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/plugin/PluginList.kt: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * 3 | * Copyright (C) 2021 by nekohasekai * 4 | * Copyright (C) 2021 by Max Lv * 5 | * Copyright (C) 2021 by Mygod Studio * 6 | * * 7 | * This program is free software: you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation, either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see . * 19 | * * 20 | ******************************************************************************/ 21 | 22 | package com.v2ray.ang.plugin 23 | 24 | import android.content.Intent 25 | import android.content.pm.PackageManager 26 | import com.v2ray.ang.AngApplication 27 | 28 | class PluginList : ArrayList() { 29 | init { 30 | addAll( 31 | AngApplication.application.packageManager.queryIntentContentProviders( 32 | Intent(PluginContract.ACTION_NATIVE_PLUGIN), PackageManager.GET_META_DATA) 33 | .filter { it.providerInfo.exported }.map { NativePlugin(it) }) 34 | } 35 | 36 | val lookup = mutableMapOf().apply { 37 | for (plugin in this@PluginList.toList()) { 38 | fun check(old: Plugin?) { 39 | if (old != null && old != plugin) { 40 | this@PluginList.remove(old) 41 | } 42 | /* if (old != null && old !== plugin) { 43 | val packages = this@PluginList.filter { it.id == plugin.id } 44 | .joinToString { it.packageName } 45 | val message = "Conflicting plugins found from: $packages" 46 | Toast.makeText(SagerNet.application, message, Toast.LENGTH_LONG).show() 47 | throw IllegalStateException(message) 48 | }*/ 49 | } 50 | check(put(plugin.id, plugin)) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/plugin/ResolvedPlugin.kt: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * * 3 | * Copyright (C) 2021 by nekohasekai * 4 | * Copyright (C) 2021 by Max Lv * 5 | * Copyright (C) 2021 by Mygod Studio * 6 | * * 7 | * This program is free software: you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation, either version 3 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 | * GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see . * 19 | * * 20 | ******************************************************************************/ 21 | 22 | package com.v2ray.ang.plugin 23 | 24 | import android.content.pm.ComponentInfo 25 | import android.content.pm.ResolveInfo 26 | import android.graphics.drawable.Drawable 27 | import android.os.Build 28 | import com.v2ray.ang.AngApplication 29 | import com.v2ray.ang.plugin.PluginManager.loadString 30 | 31 | abstract class ResolvedPlugin(protected val resolveInfo: ResolveInfo) : Plugin() { 32 | protected abstract val componentInfo: ComponentInfo 33 | 34 | override val id by lazy { componentInfo.loadString(PluginContract.METADATA_KEY_ID)!! } 35 | override val version by lazy { 36 | AngApplication.application.getPackageInfo(componentInfo.packageName).versionCode 37 | } 38 | override val versionName: String by lazy { 39 | AngApplication.application.getPackageInfo(componentInfo.packageName).versionName!! 40 | } 41 | override val label: CharSequence get() = resolveInfo.loadLabel(AngApplication.application.packageManager) 42 | override val icon: Drawable get() = resolveInfo.loadIcon(AngApplication.application.packageManager) 43 | override val packageName: String get() = componentInfo.packageName 44 | override val directBootAware get() = Build.VERSION.SDK_INT < 24 || componentInfo.directBootAware 45 | } 46 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/receiver/TaskerReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.receiver 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.text.TextUtils 7 | import com.tencent.mmkv.MMKV 8 | import com.v2ray.ang.AppConfig 9 | import com.v2ray.ang.service.V2RayServiceManager 10 | import com.v2ray.ang.util.MmkvManager 11 | 12 | import com.v2ray.ang.util.Utils 13 | 14 | class TaskerReceiver : BroadcastReceiver() { 15 | private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } 16 | 17 | override fun onReceive(context: Context, intent: Intent?) { 18 | 19 | try { 20 | val bundle = intent?.getBundleExtra(AppConfig.TASKER_EXTRA_BUNDLE) 21 | val switch = bundle?.getBoolean(AppConfig.TASKER_EXTRA_BUNDLE_SWITCH, false) 22 | val guid = bundle?.getString(AppConfig.TASKER_EXTRA_BUNDLE_GUID, "") 23 | 24 | if (switch == null || guid == null || TextUtils.isEmpty(guid)) { 25 | return 26 | } else if (switch) { 27 | if (guid == AppConfig.TASKER_DEFAULT_GUID) { 28 | Utils.startVServiceFromToggle(context) 29 | } else { 30 | mainStorage?.encode(MmkvManager.KEY_SELECTED_SERVER, guid) 31 | V2RayServiceManager.startV2Ray(context) 32 | } 33 | } else { 34 | Utils.stopVService(context) 35 | } 36 | } catch (e: Exception) { 37 | e.printStackTrace() 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/QSTileService.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.service 2 | 3 | import android.annotation.TargetApi 4 | import android.content.BroadcastReceiver 5 | import android.content.Context 6 | import android.content.Intent 7 | import android.content.IntentFilter 8 | import android.graphics.drawable.Icon 9 | import android.os.Build 10 | import android.service.quicksettings.Tile 11 | import android.service.quicksettings.TileService 12 | import com.v2ray.ang.AppConfig 13 | import com.v2ray.ang.R 14 | import com.v2ray.ang.util.MessageUtil 15 | import com.v2ray.ang.util.Utils 16 | import java.lang.ref.SoftReference 17 | 18 | @TargetApi(Build.VERSION_CODES.N) 19 | class QSTileService : TileService() { 20 | 21 | fun setState(state: Int) { 22 | if (state == Tile.STATE_INACTIVE) { 23 | qsTile?.state = Tile.STATE_INACTIVE 24 | qsTile?.label = getString(R.string.app_name) 25 | qsTile?.icon = Icon.createWithResource(applicationContext, R.drawable.ic_stat_name) 26 | } else if (state == Tile.STATE_ACTIVE) { 27 | qsTile?.state = Tile.STATE_ACTIVE 28 | qsTile?.label = V2RayServiceManager.currentConfig?.remarks 29 | qsTile?.icon = Icon.createWithResource(applicationContext, R.drawable.ic_stat_name) 30 | } 31 | 32 | qsTile?.updateTile() 33 | } 34 | 35 | override fun onStartListening() { 36 | super.onStartListening() 37 | setState(Tile.STATE_INACTIVE) 38 | mMsgReceive = ReceiveMessageHandler(this) 39 | registerReceiver(mMsgReceive, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY)) 40 | MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "") 41 | } 42 | 43 | override fun onStopListening() { 44 | super.onStopListening() 45 | 46 | unregisterReceiver(mMsgReceive) 47 | mMsgReceive = null 48 | } 49 | 50 | override fun onClick() { 51 | super.onClick() 52 | when (qsTile.state) { 53 | Tile.STATE_INACTIVE -> { 54 | Utils.startVServiceFromToggle(this) 55 | } 56 | Tile.STATE_ACTIVE -> { 57 | Utils.stopVService(this) 58 | } 59 | } 60 | } 61 | 62 | private var mMsgReceive: BroadcastReceiver? = null 63 | 64 | private class ReceiveMessageHandler(context: QSTileService) : BroadcastReceiver() { 65 | internal var mReference: SoftReference = SoftReference(context) 66 | override fun onReceive(ctx: Context?, intent: Intent?) { 67 | val context = mReference.get() 68 | when (intent?.getIntExtra("key", 0)) { 69 | AppConfig.MSG_STATE_RUNNING -> { 70 | context?.setState(Tile.STATE_ACTIVE) 71 | } 72 | AppConfig.MSG_STATE_NOT_RUNNING -> { 73 | context?.setState(Tile.STATE_INACTIVE) 74 | } 75 | AppConfig.MSG_STATE_START_SUCCESS -> { 76 | context?.setState(Tile.STATE_ACTIVE) 77 | } 78 | AppConfig.MSG_STATE_START_FAILURE -> { 79 | context?.setState(Tile.STATE_INACTIVE) 80 | } 81 | AppConfig.MSG_STATE_STOP_SUCCESS -> { 82 | context?.setState(Tile.STATE_INACTIVE) 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/ServiceControl.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.service 2 | 3 | import android.app.Service 4 | 5 | interface ServiceControl { 6 | fun getService(): Service 7 | 8 | fun startService() 9 | 10 | fun stopService() 11 | 12 | fun vpnProtect(socket: Int): Boolean 13 | } 14 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayProxyOnlyService.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.service 2 | 3 | import android.app.Service 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.os.Build 7 | import android.os.IBinder 8 | import androidx.annotation.RequiresApi 9 | import com.v2ray.ang.util.MyContextWrapper 10 | import com.v2ray.ang.util.Utils 11 | import java.lang.ref.SoftReference 12 | 13 | class V2RayProxyOnlyService : Service(), ServiceControl { 14 | override fun onCreate() { 15 | super.onCreate() 16 | V2RayServiceManager.serviceControl = SoftReference(this) 17 | } 18 | 19 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 20 | V2RayServiceManager.startV2rayPoint() 21 | return START_STICKY 22 | } 23 | 24 | override fun onDestroy() { 25 | super.onDestroy() 26 | V2RayServiceManager.stopV2rayPoint() 27 | } 28 | 29 | override fun getService(): Service { 30 | return this 31 | } 32 | 33 | override fun startService() { 34 | // do nothing 35 | } 36 | 37 | override fun stopService() { 38 | stopSelf() 39 | } 40 | 41 | override fun vpnProtect(socket: Int): Boolean { 42 | return true 43 | } 44 | 45 | override fun onBind(intent: Intent?): IBinder? { 46 | return null 47 | } 48 | 49 | @RequiresApi(Build.VERSION_CODES.N) 50 | override fun attachBaseContext(newBase: Context?) { 51 | val context = newBase?.let { 52 | MyContextWrapper.wrap(newBase, Utils.getLocale(newBase)) 53 | } 54 | super.attachBaseContext(context) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayTestService.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.service 2 | 3 | import android.app.Service 4 | import android.content.Intent 5 | import android.os.IBinder 6 | import com.v2ray.ang.AppConfig.MSG_MEASURE_CONFIG 7 | import com.v2ray.ang.AppConfig.MSG_MEASURE_CONFIG_CANCEL 8 | import com.v2ray.ang.AppConfig.MSG_MEASURE_CONFIG_SUCCESS 9 | import com.v2ray.ang.util.MessageUtil 10 | import com.v2ray.ang.util.SpeedtestUtil 11 | import com.v2ray.ang.util.Utils 12 | import go.Seq 13 | import kotlinx.coroutines.* 14 | import libv2ray.Libv2ray 15 | import java.util.concurrent.Executors 16 | 17 | class V2RayTestService : Service() { 18 | private val realTestScope by lazy { CoroutineScope(Executors.newFixedThreadPool(10).asCoroutineDispatcher()) } 19 | 20 | override fun onCreate() { 21 | super.onCreate() 22 | Seq.setContext(this) 23 | Libv2ray.initV2Env(Utils.userAssetPath(this)) 24 | } 25 | 26 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 27 | when (intent?.getIntExtra("key", 0)) { 28 | MSG_MEASURE_CONFIG -> { 29 | val contentPair = intent.getSerializableExtra("content") as Pair 30 | realTestScope.launch { 31 | val result = SpeedtestUtil.realPing(contentPair.second) 32 | MessageUtil.sendMsg2UI(this@V2RayTestService, MSG_MEASURE_CONFIG_SUCCESS, Pair(contentPair.first, result)) 33 | } 34 | } 35 | MSG_MEASURE_CONFIG_CANCEL -> { 36 | realTestScope.coroutineContext[Job]?.cancelChildren() 37 | } 38 | } 39 | return super.onStartCommand(intent, flags, startId) 40 | } 41 | 42 | override fun onBind(intent: Intent?): IBinder? { 43 | return null 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import android.content.Context 4 | import android.os.Build 5 | import android.view.MenuItem 6 | import androidx.annotation.RequiresApi 7 | import androidx.appcompat.app.AppCompatActivity 8 | import com.v2ray.ang.util.MyContextWrapper 9 | import com.v2ray.ang.util.Utils 10 | 11 | abstract class BaseActivity : AppCompatActivity() { 12 | override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { 13 | android.R.id.home -> { 14 | onBackPressed() 15 | true 16 | } 17 | else -> super.onOptionsItemSelected(item) 18 | } 19 | 20 | @RequiresApi(Build.VERSION_CODES.N) 21 | override fun attachBaseContext(newBase: Context?) { 22 | val context = newBase?.let { 23 | MyContextWrapper.wrap(newBase, Utils.getLocale(newBase)) 24 | } 25 | super.attachBaseContext(context) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/FragmentAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentActivity 5 | import androidx.viewpager2.adapter.FragmentStateAdapter 6 | 7 | class FragmentAdapter(fragmentActivity: FragmentActivity, private val mFragments: List) : 8 | FragmentStateAdapter(fragmentActivity) { 9 | 10 | override fun createFragment(position: Int): Fragment { 11 | return mFragments[position] 12 | } 13 | 14 | override fun getItemCount(): Int { 15 | return mFragments.size 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import android.os.Bundle 4 | import com.v2ray.ang.R 5 | import androidx.fragment.app.Fragment 6 | import com.google.android.material.tabs.TabLayoutMediator 7 | import com.v2ray.ang.AppConfig 8 | import com.v2ray.ang.databinding.ActivityRoutingSettingsBinding 9 | 10 | class RoutingSettingsActivity : BaseActivity() { 11 | private lateinit var binding: ActivityRoutingSettingsBinding 12 | 13 | private val titles: Array by lazy { 14 | resources.getStringArray(R.array.routing_tag) 15 | } 16 | 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | binding = ActivityRoutingSettingsBinding.inflate(layoutInflater) 20 | val view = binding.root 21 | setContentView(view) 22 | 23 | title = getString(R.string.title_pref_routing_custom) 24 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 25 | 26 | val fragments = ArrayList() 27 | fragments.add(RoutingSettingsFragment().newInstance(AppConfig.PREF_V2RAY_ROUTING_AGENT)) 28 | fragments.add(RoutingSettingsFragment().newInstance(AppConfig.PREF_V2RAY_ROUTING_DIRECT)) 29 | fragments.add(RoutingSettingsFragment().newInstance(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)) 30 | 31 | val adapter = FragmentAdapter(this, fragments) 32 | binding.viewpager.adapter = adapter 33 | //tablayout.setTabTextColors(Color.BLACK, Color.RED) 34 | TabLayoutMediator(binding.tablayout, binding.viewpager) { tab, position -> 35 | tab.text = titles[position] 36 | }.attach() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScScannerActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import android.Manifest 4 | import android.content.* 5 | import com.tbruyelle.rxpermissions.RxPermissions 6 | import com.v2ray.ang.R 7 | import com.v2ray.ang.util.AngConfigManager 8 | import android.os.Bundle 9 | import androidx.activity.result.contract.ActivityResultContracts 10 | import com.v2ray.ang.extension.toast 11 | 12 | class ScScannerActivity : BaseActivity() { 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_none) 17 | importQRcode() 18 | } 19 | 20 | fun importQRcode(): Boolean { 21 | RxPermissions(this) 22 | .request(Manifest.permission.CAMERA) 23 | .subscribe { 24 | if (it) 25 | scanQRCode.launch(Intent(this, ScannerActivity::class.java)) 26 | else 27 | toast(R.string.toast_permission_denied) 28 | } 29 | 30 | return true 31 | } 32 | 33 | private val scanQRCode = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { 34 | if (it.resultCode == RESULT_OK) { 35 | val count = AngConfigManager.importBatchConfig(it.data?.getStringExtra("SCAN_RESULT"), "", false) 36 | if (count > 0) { 37 | toast(R.string.toast_success) 38 | } else { 39 | toast(R.string.toast_failure) 40 | } 41 | startActivity(Intent(this, MainActivity::class.java)) 42 | } 43 | finish() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScSwitchActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import com.v2ray.ang.R 4 | import com.v2ray.ang.util.Utils 5 | import android.os.Bundle 6 | import com.v2ray.ang.service.V2RayServiceManager 7 | 8 | class ScSwitchActivity : BaseActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | moveTaskToBack(true) 12 | 13 | setContentView(R.layout.activity_none) 14 | 15 | if (V2RayServiceManager.v2rayPoint.isRunning) { 16 | Utils.stopVService(this) 17 | } else { 18 | Utils.startVServiceFromToggle(this) 19 | } 20 | finish() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import android.content.Intent 4 | import androidx.recyclerview.widget.LinearLayoutManager 5 | import android.view.Menu 6 | import android.view.MenuItem 7 | import com.v2ray.ang.R 8 | import android.os.Bundle 9 | import com.v2ray.ang.databinding.ActivitySubSettingBinding 10 | import com.v2ray.ang.dto.SubscriptionItem 11 | import com.v2ray.ang.util.MmkvManager 12 | 13 | class SubSettingActivity : BaseActivity() { 14 | private lateinit var binding: ActivitySubSettingBinding 15 | 16 | var subscriptions:List> = listOf() 17 | private val adapter by lazy { SubSettingRecyclerAdapter(this) } 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | binding = ActivitySubSettingBinding.inflate(layoutInflater) 22 | val view = binding.root 23 | setContentView(view) 24 | 25 | title = getString(R.string.title_sub_setting) 26 | 27 | binding.recyclerView.setHasFixedSize(true) 28 | binding.recyclerView.layoutManager = LinearLayoutManager(this) 29 | binding.recyclerView.adapter = adapter 30 | 31 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 32 | } 33 | 34 | override fun onResume() { 35 | super.onResume() 36 | subscriptions = MmkvManager.decodeSubscriptions() 37 | adapter.notifyDataSetChanged() 38 | } 39 | 40 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 41 | menuInflater.inflate(R.menu.action_sub_setting, menu) 42 | menu.findItem(R.id.del_config)?.isVisible = false 43 | menu.findItem(R.id.save_config)?.isVisible = false 44 | 45 | return super.onCreateOptionsMenu(menu) 46 | } 47 | 48 | override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { 49 | R.id.add_config -> { 50 | startActivity(Intent(this, SubEditActivity::class.java)) 51 | true 52 | } 53 | else -> super.onOptionsItemSelected(item) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UrlSchemeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.ui 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import com.v2ray.ang.AppConfig 7 | import com.v2ray.ang.R 8 | import com.v2ray.ang.databinding.ActivityLogcatBinding 9 | import com.v2ray.ang.extension.toast 10 | import com.v2ray.ang.util.AngConfigManager 11 | import java.net.URLDecoder 12 | 13 | class UrlSchemeActivity : BaseActivity() { 14 | private lateinit var binding: ActivityLogcatBinding 15 | 16 | override fun onCreate(savedInstanceState: Bundle?) { 17 | super.onCreate(savedInstanceState) 18 | binding = ActivityLogcatBinding.inflate(layoutInflater) 19 | val view = binding.root 20 | setContentView(view) 21 | 22 | try { 23 | intent.apply { 24 | if (action == Intent.ACTION_SEND) { 25 | if ("text/plain" == type) { 26 | intent.getStringExtra(Intent.EXTRA_TEXT)?.let { 27 | val uri = Uri.parse(it) 28 | if (uri.scheme?.startsWith(AppConfig.HTTPS_PROTOCOL) == true || uri.scheme?.startsWith( 29 | AppConfig.HTTP_PROTOCOL 30 | ) == true 31 | ) { 32 | val name = uri.getQueryParameter("name") ?: "Subscription" 33 | importSubscription(it, name) 34 | } else { 35 | importConfig(it) 36 | } 37 | } 38 | } 39 | } else if (action == Intent.ACTION_VIEW) { 40 | when (data?.host) { 41 | "install-config" -> { 42 | val uri: Uri? = intent.data 43 | val shareUrl: String = uri?.getQueryParameter("url")!! 44 | toast(shareUrl) 45 | importConfig(shareUrl) 46 | } 47 | 48 | "install-sub" -> { 49 | val uri: Uri? = intent.data 50 | val url = uri?.getQueryParameter("url")!! 51 | val name = uri.getQueryParameter("name") ?: "Subscription" 52 | importSubscription(url, name) 53 | } 54 | 55 | else -> { 56 | toast(R.string.toast_failure) 57 | } 58 | } 59 | } 60 | 61 | } 62 | 63 | 64 | startActivity(Intent(this, MainActivity::class.java)) 65 | finish() 66 | } catch (e: Exception) { 67 | e.printStackTrace() 68 | } 69 | } 70 | 71 | private fun importSubscription(url: String, name: String) { 72 | val decodedUrl = URLDecoder.decode(url, "UTF-8") 73 | 74 | val check = AngConfigManager.importSubscription(name, decodedUrl) 75 | if (check) toast(R.string.import_subscription_success) else toast(R.string.import_subscription_failure) 76 | } 77 | 78 | private fun importConfig(shareUrl: String) { 79 | val count = AngConfigManager.importBatchConfig(shareUrl, "", false) 80 | if (count > 0) { 81 | toast(R.string.toast_success) 82 | } else { 83 | toast(R.string.toast_failure) 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AppManagerUtil.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.util 2 | 3 | import android.Manifest 4 | import android.content.Context 5 | import android.content.pm.ApplicationInfo 6 | import android.content.pm.PackageInfo 7 | import android.content.pm.PackageManager 8 | import com.v2ray.ang.dto.AppInfo 9 | import rx.Observable 10 | import java.util.* 11 | 12 | object AppManagerUtil { 13 | fun loadNetworkAppList(ctx: Context): ArrayList { 14 | val packageManager = ctx.packageManager 15 | val packages = packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS) 16 | val apps = ArrayList() 17 | 18 | for (pkg in packages) { 19 | if (!pkg.hasInternetPermission && pkg.packageName != "android") continue 20 | 21 | val applicationInfo = pkg.applicationInfo 22 | 23 | val appName = applicationInfo.loadLabel(packageManager).toString() 24 | val appIcon = applicationInfo.loadIcon(packageManager) 25 | val isSystemApp = (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) > 0 26 | 27 | val appInfo = AppInfo(appName, pkg.packageName, appIcon, isSystemApp, 0) 28 | apps.add(appInfo) 29 | } 30 | 31 | return apps 32 | } 33 | 34 | fun rxLoadNetworkAppList(ctx: Context): Observable> = Observable.unsafeCreate { 35 | it.onNext(loadNetworkAppList(ctx)) 36 | } 37 | 38 | val PackageInfo.hasInternetPermission: Boolean 39 | get() { 40 | val permissions = requestedPermissions 41 | return permissions?.any { it == Manifest.permission.INTERNET } ?: false 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MessageUtil.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.util 2 | 3 | import android.content.ComponentName 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.v2ray.ang.AppConfig 7 | import com.v2ray.ang.service.V2RayTestService 8 | import java.io.Serializable 9 | 10 | 11 | object MessageUtil { 12 | 13 | fun sendMsg2Service(ctx: Context, what: Int, content: Serializable) { 14 | sendMsg(ctx, AppConfig.BROADCAST_ACTION_SERVICE, what, content) 15 | } 16 | 17 | fun sendMsg2UI(ctx: Context, what: Int, content: Serializable) { 18 | sendMsg(ctx, AppConfig.BROADCAST_ACTION_ACTIVITY, what, content) 19 | } 20 | 21 | fun sendMsg2TestService(ctx: Context, what: Int, content: Serializable) { 22 | try { 23 | val intent = Intent() 24 | intent.component = ComponentName(ctx, V2RayTestService::class.java) 25 | intent.putExtra("key", what) 26 | intent.putExtra("content", content) 27 | ctx.startService(intent) 28 | } catch (e: Exception) { 29 | e.printStackTrace() 30 | } 31 | } 32 | 33 | private fun sendMsg(ctx: Context, action: String, what: Int, content: Serializable) { 34 | try { 35 | val intent = Intent() 36 | intent.action = action 37 | intent.`package` = AppConfig.ANG_PACKAGE 38 | intent.putExtra("key", what) 39 | intent.putExtra("content", content) 40 | ctx.sendBroadcast(intent) 41 | } catch (e: Exception) { 42 | e.printStackTrace() 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MyContextWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.util 2 | 3 | import android.content.Context 4 | import android.content.ContextWrapper 5 | import android.content.res.Configuration 6 | import android.content.res.Resources 7 | import android.os.Build 8 | import android.os.LocaleList 9 | import androidx.annotation.RequiresApi 10 | import java.util.* 11 | 12 | open class MyContextWrapper(base: Context?) : ContextWrapper(base) { 13 | companion object { 14 | @RequiresApi(Build.VERSION_CODES.N) 15 | fun wrap(context: Context, newLocale: Locale?): ContextWrapper { 16 | var mContext = context 17 | val res: Resources = mContext.resources 18 | val configuration: Configuration = res.configuration 19 | //注意 Android 7.0 前后的不同处理方法 20 | mContext = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 21 | configuration.setLocale(newLocale) 22 | val localeList = LocaleList(newLocale) 23 | LocaleList.setDefault(localeList) 24 | configuration.setLocales(localeList) 25 | mContext.createConfigurationContext(configuration) 26 | } else { 27 | configuration.setLocale(newLocale) 28 | mContext.createConfigurationContext(configuration) 29 | } 30 | return ContextWrapper(mContext) 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/SocksFmt.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.util.fmt 2 | 3 | import com.v2ray.ang.dto.EConfigType 4 | import com.v2ray.ang.dto.ServerConfig 5 | import com.v2ray.ang.dto.V2rayConfig 6 | import com.v2ray.ang.util.Utils 7 | 8 | object SocksFmt { 9 | fun parseSocks(str: String): ServerConfig? { 10 | val config = ServerConfig.create(EConfigType.SOCKS) 11 | var result = str.replace(EConfigType.SOCKS.protocolScheme, "") 12 | val indexSplit = result.indexOf("#") 13 | 14 | if (indexSplit > 0) { 15 | try { 16 | config.remarks = 17 | Utils.urlDecode(result.substring(indexSplit + 1, result.length)) 18 | } catch (e: Exception) { 19 | e.printStackTrace() 20 | } 21 | 22 | result = result.substring(0, indexSplit) 23 | } 24 | 25 | //part decode 26 | val indexS = result.indexOf("@") 27 | if (indexS > 0) { 28 | result = Utils.decode(result.substring(0, indexS)) + result.substring( 29 | indexS, 30 | result.length 31 | ) 32 | } else { 33 | result = Utils.decode(result) 34 | } 35 | 36 | val legacyPattern = "^(.*):(.*)@(.+?):(\\d+?)$".toRegex() 37 | val match = 38 | legacyPattern.matchEntire(result) ?: return null 39 | 40 | config.outboundBean?.settings?.servers?.get(0)?.let { server -> 41 | server.address = match.groupValues[3].removeSurrounding("[", "]") 42 | server.port = match.groupValues[4].toInt() 43 | val socksUsersBean = 44 | V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean() 45 | socksUsersBean.user = match.groupValues[1] 46 | socksUsersBean.pass = match.groupValues[2] 47 | server.users = listOf(socksUsersBean) 48 | } 49 | 50 | return config 51 | } 52 | 53 | fun toUri(config: ServerConfig): String { 54 | val outbound = config.getProxyOutbound() ?: return "" 55 | val remark = "#" + Utils.urlEncode(config.remarks) 56 | val pw = 57 | if (outbound.settings?.servers?.get(0)?.users?.get(0)?.user != null) 58 | "${outbound.settings?.servers?.get(0)?.users?.get(0)?.user}:${outbound.getPassword()}" 59 | else 60 | ":" 61 | val url = String.format( 62 | "%s@%s:%s", 63 | Utils.encode(pw), 64 | Utils.getIpv6Address(outbound.getServerAddress()), 65 | outbound.getServerPort() 66 | ) 67 | return url + remark 68 | } 69 | } -------------------------------------------------------------------------------- /V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.v2ray.ang.viewmodel 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import android.util.Log 6 | import androidx.lifecycle.AndroidViewModel 7 | import androidx.preference.PreferenceManager 8 | import com.tencent.mmkv.MMKV 9 | import com.v2ray.ang.AppConfig 10 | import com.v2ray.ang.util.MmkvManager 11 | 12 | class SettingsViewModel(application: Application) : AndroidViewModel(application), SharedPreferences.OnSharedPreferenceChangeListener { 13 | 14 | private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } 15 | 16 | fun startListenPreferenceChange() { 17 | PreferenceManager.getDefaultSharedPreferences(getApplication()).registerOnSharedPreferenceChangeListener(this) 18 | } 19 | 20 | override fun onCleared() { 21 | PreferenceManager.getDefaultSharedPreferences(getApplication()).unregisterOnSharedPreferenceChangeListener(this) 22 | Log.i(AppConfig.ANG_PACKAGE, "Settings ViewModel is cleared") 23 | super.onCleared() 24 | } 25 | 26 | override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { 27 | Log.d(AppConfig.ANG_PACKAGE, "Observe settings changed: $key") 28 | when(key) { 29 | AppConfig.PREF_MODE, 30 | AppConfig.PREF_VPN_DNS, 31 | AppConfig.PREF_REMOTE_DNS, 32 | AppConfig.PREF_DOMESTIC_DNS, 33 | AppConfig.PREF_LOCAL_DNS_PORT, 34 | AppConfig.PREF_SOCKS_PORT, 35 | AppConfig.PREF_HTTP_PORT, 36 | AppConfig.PREF_LOGLEVEL, 37 | AppConfig.PREF_LANGUAGE, 38 | AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, 39 | AppConfig.PREF_ROUTING_MODE, 40 | AppConfig.PREF_V2RAY_ROUTING_AGENT, 41 | AppConfig.PREF_V2RAY_ROUTING_BLOCKED, 42 | AppConfig.PREF_V2RAY_ROUTING_DIRECT, -> { 43 | settingsStorage?.encode(key, sharedPreferences.getString(key, "")) 44 | } 45 | AppConfig.PREF_SPEED_ENABLED, 46 | AppConfig.PREF_PROXY_SHARING, 47 | AppConfig.PREF_LOCAL_DNS_ENABLED, 48 | AppConfig.PREF_FAKE_DNS_ENABLED, 49 | AppConfig.PREF_ALLOW_INSECURE, 50 | AppConfig.PREF_PREFER_IPV6, 51 | AppConfig.PREF_PER_APP_PROXY, 52 | AppConfig.PREF_BYPASS_APPS, 53 | AppConfig.PREF_CONFIRM_REMOVE, 54 | AppConfig.PREF_START_SCAN_IMMEDIATE, -> { 55 | settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false)) 56 | } 57 | AppConfig.PREF_SNIFFING_ENABLED -> { 58 | settingsStorage?.encode(key, sharedPreferences.getBoolean(key, true)) 59 | } 60 | AppConfig.PREF_PER_APP_PROXY_SET -> { 61 | settingsStorage?.encode(key, sharedPreferences.getStringSet(key, setOf())) 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/color_highlight_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #009966 4 | #FF0099 5 | #247BA0 6 | #009966 7 | #999999 8 | #CFD8DC 9 | #212121 10 | 11 | 12 | 13 | #2B2B2B 14 | #161616 15 | #D81B60 16 | #FFFFFF 17 | #000000 18 | 19 | #F1F1FF 20 | #FFF1F1 21 | #F1FFF1 22 | #FFFFB3 23 | #FF0000 24 | #363636 25 | #575757 26 | 27 | #1565C0 28 | #C11E1E 29 | #2F6D06 30 | 31 | 32 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 50dp 4 | 16dp 5 | 16dp 6 | 8dp 7 | 50dp 8 | 24dp 9 | 72dp 10 | 60dp 11 | 12 | 16dp 13 | 16dp 14 | 8dp 15 | 160dp 16 | 17 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/ic_banner_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/color/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 17 | 18 | 19 | 25 | 26 | 31 | 32 | 37 | 38 | 14 | 15 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/values-sw360dp-v13/values-preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 0dp 5 | -------------------------------------------------------------------------------- /V2rayNG/app/src/main/res/values-v35/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 25 | 26 | 27 | 35 | 36 | 44 | 45 | 53 | 54 | 12 | 13 | 17 | 18 | 19 | 25 | 26 | 31 | 32 | 37 | 38 |