Refactoring to import custom configuration function

Most of the functions have been merged into the existing menu, only the local import function needs to be added.
The code is temporarily commented and will be deleted after user testing.
This commit is contained in:
2dust
2025-03-20 15:36:06 +08:00
parent e819798d80
commit 9bee5fbe99
12 changed files with 195 additions and 168 deletions
@@ -8,11 +8,9 @@ import android.net.Uri
import android.net.VpnService
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
@@ -38,14 +36,12 @@ import com.v2ray.ang.handler.MigrateManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
import com.v2ray.ang.service.V2RayServiceManager
import com.v2ray.ang.util.HttpUtil
import com.v2ray.ang.util.Utils
import com.v2ray.ang.viewmodel.MainViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.drakeet.support.toast.ToastCompat
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
private val binding by lazy {
@@ -87,13 +83,16 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
when (pendingAction) {
Action.IMPORT_QR_CODE_CONFIG ->
scanQRCodeForConfig.launch(Intent(this, ScannerActivity::class.java))
Action.IMPORT_QR_CODE_URL ->
scanQRCodeForUrlToCustomConfig.launch(Intent(this, ScannerActivity::class.java))
// Action.IMPORT_QR_CODE_URL ->
// scanQRCodeForUrlToCustomConfig.launch(Intent(this, ScannerActivity::class.java))
Action.READ_CONTENT_FROM_URI ->
chooseFileForCustomConfig.launch(Intent.createChooser(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "*/*"
addCategory(Intent.CATEGORY_OPENABLE)
}, getString(R.string.title_file_chooser)))
Action.POST_NOTIFICATIONS -> {}
else -> {}
}
@@ -108,7 +107,8 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
enum class Action {
NONE,
IMPORT_QR_CODE_CONFIG,
IMPORT_QR_CODE_URL,
//IMPORT_QR_CODE_URL,
READ_CONTENT_FROM_URI,
POST_NOTIFICATIONS
}
@@ -126,11 +126,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
}
private val scanQRCodeForUrlToCustomConfig = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
importConfigCustomUrl(it.data?.getStringExtra("SCAN_RESULT"))
}
}
// private val scanQRCodeForUrlToCustomConfig = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
// if (it.resultCode == RESULT_OK) {
// importConfigCustomUrl(it.data?.getStringExtra("SCAN_RESULT"))
// }
// }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -326,6 +326,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
true
}
R.id.import_local -> {
importConfigLocal()
true
}
R.id.import_manually_vmess -> {
importManually(EConfigType.VMESS.value)
true
@@ -366,25 +371,25 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
true
}
R.id.import_config_custom_clipboard -> {
importConfigCustomClipboard()
true
}
R.id.import_config_custom_local -> {
importConfigCustomLocal()
true
}
R.id.import_config_custom_url -> {
importConfigCustomUrlClipboard()
true
}
R.id.import_config_custom_url_scan -> {
importQRcode(false)
true
}
// R.id.import_config_custom_clipboard -> {
// importConfigCustomClipboard()
// true
// }
//
// R.id.import_config_custom_local -> {
// importConfigCustomLocal()
// true
// }
//
// R.id.import_config_custom_url -> {
// importConfigCustomUrlClipboard()
// true
// }
//
// R.id.import_config_custom_url_scan -> {
// importQRcode(false)
// true
// }
R.id.sub_update -> {
importConfigViaSub()
@@ -517,10 +522,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
if (forConfig) {
scanQRCodeForConfig.launch(Intent(this, ScannerActivity::class.java))
} else {
scanQRCodeForUrlToCustomConfig.launch(Intent(this, ScannerActivity::class.java))
//scanQRCodeForUrlToCustomConfig.launch(Intent(this, ScannerActivity::class.java))
}
} else {
pendingAction = if (forConfig) Action.IMPORT_QR_CODE_CONFIG else Action.IMPORT_QR_CODE_URL
pendingAction = Action.IMPORT_QR_CODE_CONFIG//if (forConfig) Action.IMPORT_QR_CODE_CONFIG else Action.IMPORT_QR_CODE_URL
requestPermissionLauncher.launch(permission)
}
return true
@@ -570,27 +575,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
}
private fun importConfigCustomClipboard()
: Boolean {
try {
val configText = Utils.getClipboard(this)
if (TextUtils.isEmpty(configText)) {
toast(R.string.toast_none_data_clipboard)
return false
}
importCustomizeConfig(configText)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
/**
* import config from local config file
*/
private fun importConfigCustomLocal(): Boolean {
private fun importConfigLocal(): Boolean {
try {
showFileChooser()
} catch (e: Exception) {
@@ -600,47 +585,77 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
return true
}
private fun importConfigCustomUrlClipboard()
: Boolean {
try {
val url = Utils.getClipboard(this)
if (TextUtils.isEmpty(url)) {
toast(R.string.toast_none_data_clipboard)
return false
}
return importConfigCustomUrl(url)
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
// private fun importConfigCustomClipboard()
// : Boolean {
// try {
// val configText = Utils.getClipboard(this)
// if (TextUtils.isEmpty(configText)) {
// toast(R.string.toast_none_data_clipboard)
// return false
// }
// importCustomizeConfig(configText)
// return true
// } catch (e: Exception) {
// e.printStackTrace()
// return false
// }
// }
/**
* import config from local config file
*/
// private fun importConfigCustomLocal(): Boolean {
// try {
// showFileChooser()
// } catch (e: Exception) {
// e.printStackTrace()
// return false
// }
// return true
// }
//
// private fun importConfigCustomUrlClipboard()
// : Boolean {
// try {
// val url = Utils.getClipboard(this)
// if (TextUtils.isEmpty(url)) {
// toast(R.string.toast_none_data_clipboard)
// return false
// }
// return importConfigCustomUrl(url)
// } catch (e: Exception) {
// e.printStackTrace()
// return false
// }
// }
/**
* import config from url
*/
private fun importConfigCustomUrl(url: String?): Boolean {
try {
if (!Utils.isValidUrl(url)) {
toast(R.string.toast_invalid_url)
return false
}
lifecycleScope.launch(Dispatchers.IO) {
val configText = try {
HttpUtil.getUrlContentWithUserAgent(url)
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
importCustomizeConfig(configText)
}
}
} catch (e: Exception) {
e.printStackTrace()
return false
}
return true
}
// private fun importConfigCustomUrl(url: String?): Boolean {
// try {
// if (!Utils.isValidUrl(url)) {
// toast(R.string.toast_invalid_url)
// return false
// }
// lifecycleScope.launch(Dispatchers.IO) {
// val configText = try {
// HttpUtil.getUrlContentWithUserAgent(url)
// } catch (e: Exception) {
// e.printStackTrace()
// ""
// }
// launch(Dispatchers.Main) {
// importCustomizeConfig(configText)
// }
// }
// } catch (e: Exception) {
// e.printStackTrace()
// return false
// }
// return true
// }
/**
* import config from sub
@@ -699,7 +714,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
try {
contentResolver.openInputStream(uri).use { input ->
importCustomizeConfig(input?.bufferedReader()?.readText())
importBatchConfig(input?.bufferedReader()?.readText())
}
} catch (e: Exception) {
e.printStackTrace()
@@ -709,28 +724,28 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
}
/**
* import customize config
*/
private fun importCustomizeConfig(server: String?) {
try {
if (server == null || TextUtils.isEmpty(server)) {
toast(R.string.toast_none_data)
return
}
if (mainViewModel.appendCustomConfigServer(server)) {
mainViewModel.reloadServerList()
toast(R.string.toast_success)
} else {
toast(R.string.toast_failure)
}
//adapter.notifyItemInserted(mainViewModel.serverList.lastIndex)
} catch (e: Exception) {
ToastCompat.makeText(this, "${getString(R.string.toast_malformed_josn)} ${e.cause?.message}", Toast.LENGTH_LONG).show()
e.printStackTrace()
return
}
}
// /**
// * import customize config
// */
// private fun importCustomizeConfig(server: String?) {
// try {
// if (server == null || TextUtils.isEmpty(server)) {
// toast(R.string.toast_none_data)
// return
// }
// if (mainViewModel.appendCustomConfigServer(server)) {
// mainViewModel.reloadServerList()
// toast(R.string.toast_success)
// } else {
// toast(R.string.toast_failure)
// }
// //adapter.notifyItemInserted(mainViewModel.serverList.lastIndex)
// } catch (e: Exception) {
// ToastCompat.makeText(this, "${getString(R.string.toast_malformed_josn)} ${e.cause?.message}", Toast.LENGTH_LONG).show()
// e.printStackTrace()
// return
// }
// }
private fun setTestState(content: String?) {
binding.tvTestState.text = content
@@ -19,7 +19,6 @@ import com.v2ray.ang.dto.ProfileItem
import com.v2ray.ang.dto.ServersCache
import com.v2ray.ang.extension.serializable
import com.v2ray.ang.extension.toast
import com.v2ray.ang.fmt.CustomFmt
import com.v2ray.ang.handler.AngConfigManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsManager
@@ -89,37 +88,37 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
}
}
/**
* Appends a custom configuration server.
* @param server The server configuration to append.
* @return True if the server was successfully appended, false otherwise.
*/
fun appendCustomConfigServer(server: String): Boolean {
if (server.contains("inbounds")
&& server.contains("outbounds")
&& server.contains("routing")
) {
try {
val config = CustomFmt.parse(server) ?: return false
config.subscriptionId = subscriptionId
val key = MmkvManager.encodeServerConfig("", config)
MmkvManager.encodeServerRaw(key, server)
serverList.add(0, key)
// val profile = ProfileLiteItem(
// configType = config.configType,
// subscriptionId = config.subscriptionId,
// remarks = config.remarks,
// server = config.getProxyOutbound()?.getServerAddress(),
// serverPort = config.getProxyOutbound()?.getServerPort(),
// )
serversCache.add(0, ServersCache(key, config))
return true
} catch (e: Exception) {
e.printStackTrace()
}
}
return false
}
// /**
// * Appends a custom configuration server.
// * @param server The server configuration to append.
// * @return True if the server was successfully appended, false otherwise.
// */
// fun appendCustomConfigServer(server: String): Boolean {
// if (server.contains("inbounds")
// && server.contains("outbounds")
// && server.contains("routing")
// ) {
// try {
// val config = CustomFmt.parse(server) ?: return false
// config.subscriptionId = subscriptionId
// val key = MmkvManager.encodeServerConfig("", config)
// MmkvManager.encodeServerRaw(key, server)
// serverList.add(0, key)
//// val profile = ProfileLiteItem(
//// configType = config.configType,
//// subscriptionId = config.subscriptionId,
//// remarks = config.remarks,
//// server = config.getProxyOutbound()?.getServerAddress(),
//// serverPort = config.getProxyOutbound()?.getServerPort(),
//// )
// serversCache.add(0, ServersCache(key, config))
// return true
// } catch (e: Exception) {
// e.printStackTrace()
// }
// }
// return false
// }
/**
* Swaps the positions of two servers.
+26 -22
View File
@@ -20,6 +20,10 @@
android:id="@+id/import_clipboard"
android:title="@string/menu_item_import_config_clipboard"
app:showAsAction="never" />
<item
android:id="@+id/import_local"
android:title="@string/menu_item_import_config_local"
app:showAsAction="never" />
<item
android:id="@+id/import_manually_vmess"
android:title="@string/menu_item_import_config_manually_vmess"
@@ -53,28 +57,28 @@
android:title="@string/menu_item_import_config_manually_hysteria2"
app:showAsAction="never" />
<item
android:title="@string/menu_item_import_config_custom"
app:showAsAction="ifRoom">
<menu>
<item
android:id="@+id/import_config_custom_clipboard"
android:title="@string/menu_item_import_config_custom_clipboard"
app:showAsAction="never" />
<item
android:id="@+id/import_config_custom_local"
android:title="@string/menu_item_import_config_custom_local"
app:showAsAction="never" />
<item
android:id="@+id/import_config_custom_url"
android:title="@string/menu_item_import_config_custom_url"
app:showAsAction="never" />
<item
android:id="@+id/import_config_custom_url_scan"
android:title="@string/menu_item_import_config_custom_url_scan"
app:showAsAction="never" />
</menu>
</item>
<!-- <item-->
<!-- android:title="@string/menu_item_import_config_custom"-->
<!-- app:showAsAction="ifRoom">-->
<!-- <menu>-->
<!-- <item-->
<!-- android:id="@+id/import_config_custom_clipboard"-->
<!-- android:title="@string/menu_item_import_config_custom_clipboard"-->
<!-- app:showAsAction="never" />-->
<!-- <item-->
<!-- android:id="@+id/import_config_custom_local"-->
<!-- android:title="@string/menu_item_import_config_custom_local"-->
<!-- app:showAsAction="never" />-->
<!-- <item-->
<!-- android:id="@+id/import_config_custom_url"-->
<!-- android:title="@string/menu_item_import_config_custom_url"-->
<!-- app:showAsAction="never" />-->
<!-- <item-->
<!-- android:id="@+id/import_config_custom_url_scan"-->
<!-- android:title="@string/menu_item_import_config_custom_url_scan"-->
<!-- app:showAsAction="never" />-->
<!-- </menu>-->
<!-- </item>-->
</menu>
</item>
<item
@@ -27,6 +27,7 @@
<string name="menu_item_del_config">حذف التكوين</string>
<string name="menu_item_import_config_qrcode">استيراد التكوين من رمز الاستجابة السريعة (QRcode)</string>
<string name="menu_item_import_config_clipboard">استيراد التكوين من الحافظة</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">الكتابة يدويًا [VMess]</string>
<string name="menu_item_import_config_manually_vless">الكتابة يدويًا [VLESS]</string>
<string name="menu_item_import_config_manually_ss">الكتابة يدويًا [Shadowsocks]</string>
@@ -27,6 +27,7 @@
<string name="menu_item_del_config">কনফিগারেশন মুছুন</string>
<string name="menu_item_import_config_qrcode">QR কোড থেকে কনফিগারেশন আমদানি করুন</string>
<string name="menu_item_import_config_clipboard">ক্লিপবোর্ড থেকে কনফিগারেশন আমদানি করুন</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">ম্যানুয়ালি টাইপ করুন [VMess]</string>
<string name="menu_item_import_config_manually_vless">ম্যানুয়ালি টাইপ করুন [VLESS]</string>
<string name="menu_item_import_config_manually_ss">ম্যানুয়ালি টাইপ করুন [Shadowsocks]</string>
@@ -27,6 +27,7 @@
<string name="menu_item_del_config">پاک کردن کانفیگ</string>
<string name="menu_item_import_config_qrcode">و من ٱووردن کانفیگ ز QRcode</string>
<string name="menu_item_import_config_clipboard">و من ٱووردن کانفیگ ز کلیپ بورد</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">هؽل دستی[VMess]</string>
<string name="menu_item_import_config_manually_vless">هؽل دستی[VLESS]</string>
<string name="menu_item_import_config_manually_ss">هؽل دستی[Shadowsocks]</string>
@@ -27,6 +27,7 @@
<string name="menu_item_del_config">حذف کانفیگ</string>
<string name="menu_item_import_config_qrcode">کانفیگ را از QRcode وارد کنید</string>
<string name="menu_item_import_config_clipboard">کانفیگ را از کلیپ ‌بورد وارد کنید</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">تایپ دستی[VMESS]</string>
<string name="menu_item_import_config_manually_vless">تایپ دستی[VLESS]</string>
<string name="menu_item_import_config_manually_ss">تایپ دستی[SHADOWSOCKS]</string>
@@ -26,6 +26,7 @@
<string name="menu_item_del_config">Удалить профиль</string>
<string name="menu_item_import_config_qrcode">Импорт из QR-кода</string>
<string name="menu_item_import_config_clipboard">Импорт из буфера обмена</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">Ручной ввод VMess</string>
<string name="menu_item_import_config_manually_vless">Ручной ввод VLESS</string>
<string name="menu_item_import_config_manually_ss">Ручной ввод Shadowsocks</string>
@@ -26,6 +26,7 @@
<string name="menu_item_del_config">Xoá cấu hình</string>
<string name="menu_item_import_config_qrcode">Nhập cấu hình từ mã QR</string>
<string name="menu_item_import_config_clipboard">Nhập cấu hình từ Clipboard</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">Nhập thủ công [VMess]</string>
<string name="menu_item_import_config_manually_vless">Nhập thủ công [VLESS]</string>
<string name="menu_item_import_config_manually_ss">Nhập thủ công [ShadowSocks]</string>
@@ -26,6 +26,7 @@
<string name="menu_item_del_config">删除配置</string>
<string name="menu_item_import_config_qrcode">扫描二维码</string>
<string name="menu_item_import_config_clipboard">从剪贴板导入</string>
<string name="menu_item_import_config_local">从本地导入</string>
<string name="menu_item_import_config_manually_vmess">手动输入[VMess]</string>
<string name="menu_item_import_config_manually_vless">手动输入[VLESS]</string>
<string name="menu_item_import_config_manually_ss">手动输入[Shadowsocks]</string>
@@ -26,6 +26,7 @@
<string name="menu_item_del_config">刪除設定</string>
<string name="menu_item_import_config_qrcode">從 QR Code 匯入設定</string>
<string name="menu_item_import_config_clipboard">從剪貼簿匯入設定</string>
<string name="menu_item_import_config_local">從本地匯入</string>
<string name="menu_item_import_config_manually_vmess">手動鍵入 [VMess]</string>
<string name="menu_item_import_config_manually_vless">手動鍵入 [VLESS]</string>
<string name="menu_item_import_config_manually_ss">手動鍵入 [Shadowsocks]</string>
@@ -27,6 +27,7 @@
<string name="menu_item_del_config">Delete config</string>
<string name="menu_item_import_config_qrcode">Import config from QRcode</string>
<string name="menu_item_import_config_clipboard">Import config from Clipboard</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_manually_vmess">Type manually[VMess]</string>
<string name="menu_item_import_config_manually_vless">Type manually[VLESS]</string>
<string name="menu_item_import_config_manually_ss">Type manually[Shadowsocks]</string>