diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/UrlContentRequest.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/UrlContentRequest.kt new file mode 100644 index 00000000..03fbaa31 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/UrlContentRequest.kt @@ -0,0 +1,10 @@ +package com.v2ray.ang.dto + +data class UrlContentRequest( + val url: String?, + val timeout: Int = 15000, + val httpPort: Int = 0, + val proxyUsername: String? = null, + val proxyPassword: String? = null, + val userAgent: String? = null +) \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt index 14d86326..fdcfaf52 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt @@ -11,6 +11,7 @@ import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.SubscriptionCache import com.v2ray.ang.dto.SubscriptionItem import com.v2ray.ang.dto.SubscriptionUpdateResult +import com.v2ray.ang.dto.UrlContentRequest import com.v2ray.ang.enums.EConfigType import com.v2ray.ang.extension.isNotNullEmpty import com.v2ray.ang.fmt.CustomFmt @@ -535,14 +536,28 @@ object AngConfigManager { var configText = try { val httpPort = SettingsManager.getHttpPort() - HttpUtil.getUrlContentWithUserAgent(url, userAgent, 15000, httpPort, proxyUsername, proxyPassword) + HttpUtil.getUrlContentWithUserAgent( + UrlContentRequest( + url = url, + userAgent = userAgent, + timeout = 15000, + httpPort = httpPort, + proxyUsername = proxyUsername, + proxyPassword = proxyPassword + ) + ) } catch (e: Exception) { LogUtil.e(AppConfig.ANG_PACKAGE, "Update subscription: proxy not ready or other error", e) "" } if (configText.isEmpty()) { configText = try { - HttpUtil.getUrlContentWithUserAgent(url, userAgent) + HttpUtil.getUrlContentWithUserAgent( + UrlContentRequest( + url = url, + userAgent = userAgent + ) + ) } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "Update subscription: Failed to get URL content with user agent", e) "" diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt index 35f567d6..8cd9467e 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt @@ -2,6 +2,7 @@ package com.v2ray.ang.handler import com.v2ray.ang.AppConfig import com.v2ray.ang.dto.IPAPIInfo +import com.v2ray.ang.dto.UrlContentRequest import com.v2ray.ang.util.HttpUtil import com.v2ray.ang.util.JsonUtil import com.v2ray.ang.util.LogUtil @@ -88,7 +89,15 @@ object SpeedtestManager { val proxyPassword = SettingsManager.getSocksPassword() val httpPort = SettingsManager.getHttpPort() if (httpPort == 0) return null - val content = HttpUtil.getUrlContent(url, 5000, httpPort, proxyUsername, proxyPassword) ?: return null + val content = HttpUtil.getUrlContent( + UrlContentRequest( + url = url, + timeout = 5000, + httpPort = httpPort, + proxyUsername = proxyUsername, + proxyPassword = proxyPassword + ) + ) ?: return null val ipInfo = JsonUtil.fromJson(content, IPAPIInfo::class.java) ?: return null val ip = listOf( diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt index caa87256..f498eb28 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt @@ -5,6 +5,7 @@ import com.v2ray.ang.AppConfig import com.v2ray.ang.BuildConfig import com.v2ray.ang.dto.CheckUpdateResult import com.v2ray.ang.dto.GitHubRelease +import com.v2ray.ang.dto.UrlContentRequest import com.v2ray.ang.extension.concatUrl import com.v2ray.ang.util.HttpUtil import com.v2ray.ang.util.JsonUtil @@ -23,10 +24,23 @@ object UpdateCheckerManager { val proxyUsername = SettingsManager.getSocksUsername() val proxyPassword = SettingsManager.getSocksPassword() - var response = HttpUtil.getUrlContent(url, 5000) + var response = HttpUtil.getUrlContent( + UrlContentRequest( + url = url, + timeout = 5000 + ) + ) if (response.isNullOrEmpty()) { val httpPort = SettingsManager.getHttpPort() - response = HttpUtil.getUrlContent(url, 5000, httpPort, proxyUsername, proxyPassword) + response = HttpUtil.getUrlContent( + UrlContentRequest( + url = url, + timeout = 5000, + httpPort = httpPort, + proxyUsername = proxyUsername, + proxyPassword = proxyPassword + ) + ) ?: throw IllegalStateException("Failed to get response") } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt index 460de6b4..9a8e2206 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/PerAppProxyActivity.kt @@ -14,6 +14,7 @@ import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityBypassListBinding import com.v2ray.ang.dto.AppInfo +import com.v2ray.ang.dto.UrlContentRequest import com.v2ray.ang.extension.toast import com.v2ray.ang.extension.toastSuccess import com.v2ray.ang.extension.v2RayApplication @@ -189,12 +190,25 @@ class PerAppProxyActivity : BaseActivity() { val url = AppConfig.ANDROID_PACKAGE_NAME_LIST_URL lifecycleScope.launch(Dispatchers.IO) { - var content = HttpUtil.getUrlContent(url, 5000) + var content = HttpUtil.getUrlContent( + UrlContentRequest( + url = url, + timeout = 5000 + ) + ) if (content.isNullOrEmpty()) { val proxyUsername = SettingsManager.getSocksUsername() val proxyPassword = SettingsManager.getSocksPassword() val httpPort = SettingsManager.getHttpPort() - content = HttpUtil.getUrlContent(url, 5000, httpPort, proxyUsername, proxyPassword) ?: "" + content = HttpUtil.getUrlContent( + UrlContentRequest( + url = url, + timeout = 5000, + httpPort = httpPort, + proxyUsername = proxyUsername, + proxyPassword = proxyPassword + ) + ) ?: "" } launch(Dispatchers.Main) { //LogUtil.i(AppConfig.TAG, content) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/util/HttpUtil.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/util/HttpUtil.kt index c693253c..4282801d 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/util/HttpUtil.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/util/HttpUtil.kt @@ -3,6 +3,7 @@ package com.v2ray.ang.util import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.LOOPBACK import com.v2ray.ang.BuildConfig +import com.v2ray.ang.dto.UrlContentRequest import okhttp3.Credentials import okhttp3.OkHttpClient import okhttp3.Request @@ -108,20 +109,15 @@ object HttpUtil { * @param httpPort The HTTP port to use. * @return The content of the URL as a string. */ - fun getUrlContent( - url: String, - timeout: Int, - httpPort: Int = 0, - proxyUsername: String? = null, - proxyPassword: String? = null - ): String? { - val client = buildOkHttpClient(timeout, httpPort, proxyUsername, proxyPassword, followRedirects = true) + fun getUrlContent(request: UrlContentRequest): String? { + val url = request.url ?: return null + val client = buildOkHttpClient(request.timeout, request.httpPort, request.proxyUsername, request.proxyPassword, followRedirects = true) val requestBuilder = Request.Builder() .url(url) .get() .header("Connection", "close") - if (httpPort != 0 && !proxyUsername.isNullOrBlank() && !proxyPassword.isNullOrBlank()) { - requestBuilder.header("Proxy-Authorization", Credentials.basic(proxyUsername, proxyPassword)) + if (request.httpPort != 0 && !request.proxyUsername.isNullOrBlank() && !request.proxyPassword.isNullOrBlank()) { + requestBuilder.header("Proxy-Authorization", Credentials.basic(request.proxyUsername, request.proxyPassword)) } try { client.newCall(requestBuilder.build()).execute().use { response -> @@ -147,25 +143,18 @@ object HttpUtil { * @throws IOException If an I/O error occurs. */ @Throws(IOException::class) - fun getUrlContentWithUserAgent( - url: String?, - userAgent: String?, - timeout: Int = 15000, - httpPort: Int = 0, - proxyUsername: String? = null, - proxyPassword: String? = null - ): String { - var currentUrl = url + fun getUrlContentWithUserAgent(request: UrlContentRequest): String { + var currentUrl = request.url var redirects = 0 val maxRedirects = 3 while (redirects++ < maxRedirects) { if (currentUrl == null) continue - val client = buildOkHttpClient(timeout, httpPort, proxyUsername, proxyPassword, followRedirects = false) - val finalUserAgent = if (userAgent.isNullOrBlank()) { + val client = buildOkHttpClient(request.timeout, request.httpPort, request.proxyUsername, request.proxyPassword, followRedirects = false) + val finalUserAgent = if (request.userAgent.isNullOrBlank()) { "v2rayNG/${BuildConfig.VERSION_NAME}" } else { - userAgent + request.userAgent } val requestBuilder = Request.Builder() .url(currentUrl) @@ -175,8 +164,8 @@ object HttpUtil { applyEmbeddedBasicAuthHeader(currentUrl, requestBuilder) - if (httpPort != 0 && !proxyUsername.isNullOrBlank() && !proxyPassword.isNullOrBlank()) { - requestBuilder.header("Proxy-Authorization", Credentials.basic(proxyUsername, proxyPassword)) + if (request.httpPort != 0 && !request.proxyUsername.isNullOrBlank() && !request.proxyPassword.isNullOrBlank()) { + requestBuilder.header("Proxy-Authorization", Credentials.basic(request.proxyUsername, request.proxyPassword)) } client.newCall(requestBuilder.build()).execute().use { response -> @@ -271,20 +260,17 @@ object HttpUtil { } fun downloadToFile( - url: String, - targetFile: File, - timeout: Int = 15000, - httpPort: Int = 0, - proxyUsername: String? = null, - proxyPassword: String? = null + request: UrlContentRequest, + targetFile: File ): Boolean { - val client = buildOkHttpClient(timeout, httpPort, proxyUsername, proxyPassword, followRedirects = true) + val url = request.url ?: return false + val client = buildOkHttpClient(request.timeout, request.httpPort, request.proxyUsername, request.proxyPassword, followRedirects = true) val requestBuilder = Request.Builder() .url(url) .get() .header("Connection", "close") - if (httpPort != 0 && !proxyUsername.isNullOrBlank() && !proxyPassword.isNullOrBlank()) { - requestBuilder.header("Proxy-Authorization", Credentials.basic(proxyUsername, proxyPassword)) + if (request.httpPort != 0 && !request.proxyUsername.isNullOrBlank() && !request.proxyPassword.isNullOrBlank()) { + requestBuilder.header("Proxy-Authorization", Credentials.basic(request.proxyUsername, request.proxyPassword)) } return try { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt index 3799cd52..6cef5f98 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/UserAssetViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel import com.v2ray.ang.AppConfig import com.v2ray.ang.dto.AssetUrlCache import com.v2ray.ang.dto.AssetUrlItem +import com.v2ray.ang.dto.UrlContentRequest import com.v2ray.ang.extension.concatUrl import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.util.HttpUtil @@ -92,7 +93,18 @@ class UserAssetViewModel : ViewModel() { val targetTemp = File(extDir, item.remarks + "_temp") val target = File(extDir, item.remarks) try { - if (HttpUtil.downloadToFile(item.url, targetTemp, 15000, httpPort, proxyUsername, proxyPassword)) { + if ( + HttpUtil.downloadToFile( + UrlContentRequest( + url = item.url, + timeout = 15000, + httpPort = httpPort, + proxyUsername = proxyUsername, + proxyPassword = proxyPassword + ), + targetTemp + ) + ) { targetTemp.renameTo(target) return true }