From 2759f5902915631ecf2dc7fe19e653f706d2b1a7 Mon Sep 17 00:00:00 2001 From: Kr328 <39107975+Kr328@users.noreply.github.com> Date: Mon, 8 Jun 2020 00:22:14 +0800 Subject: [PATCH] refactor clash bridge --- .../com/github/kr328/clash/ProxiesActivity.kt | 11 ++--- .../github/kr328/clash/remote/ClashClient.kt | 10 ++-- .../com/github/kr328/clash/remote/Remote.kt | 2 +- .../github/kr328/clash/utils/ProxySorter.kt | 13 +---- app/src/main/res/menu/proxies.xml | 1 - core/src/main/cpp/main.cpp | 47 ++++++++++--------- core/src/main/cpp/patch.cpp | 8 ++-- core/src/main/golang/main.go | 4 +- core/src/main/golang/proxies.go | 18 +++---- .../java/com/github/kr328/clash/core/Clash.kt | 24 ++-------- .../kr328/clash/core/bridge/Bridge.java | 2 +- .../kr328/clash/core/bridge/LogCallback.java | 7 +++ .../github/kr328/clash/core/event/LogEvent.kt | 4 ++ service/build.gradle.kts | 1 + .../github/kr328/clash/core/model/Packet.aidl | 2 +- .../kr328/clash/service/IClashManager.aidl | 6 +-- .../kr328/clash/service/ClashManager.kt | 10 ++-- .../kr328/clash/service/ProfileProcessor.kt | 13 +++-- .../service/clash/module/ReloadModule.kt | 1 + 19 files changed, 89 insertions(+), 95 deletions(-) create mode 100644 core/src/main/java/com/github/kr328/clash/core/bridge/LogCallback.java diff --git a/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt b/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt index 8200b8a..a984e76 100644 --- a/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/ProxiesActivity.kt @@ -119,11 +119,6 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback { put(UiSettings.PROXY_GROUP_SORT, UiSettings.PROXY_SORT_NAME) } } - R.id.groupDelay -> { - uiSettings.commit { - put(UiSettings.PROXY_GROUP_SORT, UiSettings.PROXY_SORT_DELAY) - } - } R.id.proxyDefault -> { uiSettings.commit { put(UiSettings.PROXY_PROXY_SORT, UiSettings.PROXY_SORT_DEFAULT) @@ -186,7 +181,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback { UiSettings.PROXY_SORT_NAME -> findItem(R.id.groupName).isChecked = true UiSettings.PROXY_SORT_DELAY -> - findItem(R.id.proxyDelay).isChecked = true + findItem(R.id.proxyDefault).isChecked = true } when (uiSettings.get(UiSettings.PROXY_PROXY_SORT)) { UiSettings.PROXY_SORT_DEFAULT -> @@ -206,7 +201,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback { private fun setGroupSelected(group: String, select: String) { launch { withClash { - setSelectProxy(group, select) + setSelector(group, select) } } } @@ -240,7 +235,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback { queryGeneral() } val proxies = withClash { - queryAllProxyGroups() + queryProxyGroups() } val merged = Pipeline(proxies, uiSettings).mergePrefix() diff --git a/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt b/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt index 5588420..202f48f 100644 --- a/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt +++ b/app/src/main/java/com/github/kr328/clash/remote/ClashClient.kt @@ -11,13 +11,13 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class ClashClient(val service: IClashManager) { - suspend fun setSelectProxy(name: String, proxy: String): Boolean = withContext(Dispatchers.IO) { - service.setSelectProxy(name, proxy) + suspend fun setSelector(group: String, selected: String) = withContext(Dispatchers.IO) { + service.setSelector(group, selected) } suspend fun startHealthCheck(group: String) = withContext(Dispatchers.IO) { CompletableDeferred().apply { - service.startHealthCheck(group, object : IStreamCallback.Stub() { + service.performHealthCheck(group, object : IStreamCallback.Stub() { override fun complete() { this@apply.complete(Unit) } @@ -31,8 +31,8 @@ class ClashClient(val service: IClashManager) { } }.await() - suspend fun queryAllProxyGroups(): List = withContext(Dispatchers.IO) { - service.queryAllProxies().list + suspend fun queryProxyGroups(): List = withContext(Dispatchers.IO) { + service.queryProxyGroups().list } suspend fun queryGeneral(): General = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/com/github/kr328/clash/remote/Remote.kt b/app/src/main/java/com/github/kr328/clash/remote/Remote.kt index 01d5726..9bc9242 100644 --- a/app/src/main/java/com/github/kr328/clash/remote/Remote.kt +++ b/app/src/main/java/com/github/kr328/clash/remote/Remote.kt @@ -190,7 +190,7 @@ object Remote { val sources = info.splitSourceDirs ?: arrayOf(info.sourceDir) ?: return false - val regexNativeLibrary = Regex("lib/(\\S+)/libgojni.so") + val regexNativeLibrary = Regex("lib/(\\S+)/libclash.so") val availableAbi = Build.SUPPORTED_ABIS.toSet() val apkAbi = sources diff --git a/app/src/main/java/com/github/kr328/clash/utils/ProxySorter.kt b/app/src/main/java/com/github/kr328/clash/utils/ProxySorter.kt index af5a4c4..9f43268 100644 --- a/app/src/main/java/com/github/kr328/clash/utils/ProxySorter.kt +++ b/app/src/main/java/com/github/kr328/clash/utils/ProxySorter.kt @@ -24,10 +24,9 @@ class ProxySorter(private val groupOrder: Order, private val proxyOrder: Order) val sortedGroup = when (groupOrder) { Order.DEFAULT -> groupSortWithDefault(global, other) - Order.DELAY_INCREASE -> groupSortWithDelay(true, other) - Order.DELAY_DECREASE -> groupSortWithDelay(false, other) Order.NAME_INCREASE -> groupSortWithName(true, other) Order.NAME_DECREASE -> groupSortWithName(false, other) + else -> groupSortWithDefault(global, other) } val sorted = if (global == null) @@ -73,16 +72,6 @@ class ProxySorter(private val groupOrder: Order, private val proxyOrder: Order) proxyGroup.sortedByDescending { it.name } } - private fun groupSortWithDelay( - increase: Boolean, - proxyGroup: List - ): List { - return if (increase) - proxyGroup.sortedBy { it.delay } - else - proxyGroup.sortedByDescending { it.delay } - } - private fun proxySortWithName( increase: Boolean, proxies: List diff --git a/app/src/main/res/menu/proxies.xml b/app/src/main/res/menu/proxies.xml index cdb246d..0fabf90 100644 --- a/app/src/main/res/menu/proxies.xml +++ b/app/src/main/res/menu/proxies.xml @@ -15,7 +15,6 @@ - diff --git a/core/src/main/cpp/main.cpp b/core/src/main/cpp/main.cpp index cd60471..ad0af54 100644 --- a/core/src/main/cpp/main.cpp +++ b/core/src/main/cpp/main.cpp @@ -2,16 +2,21 @@ Master *Master::master = nullptr; +template +inline T g(JNIEnv *env, T object) { + return reinterpret_cast(env->NewGlobalRef(object)); +} + Master::Master(JavaVM *vm, JNIEnv *env): vm(vm) { master = this; - cClashException = env->FindClass("com/github/kr328/clash/core/bridge/ClashException"); - cTraffic = env->FindClass("com/github/kr328/clash/core/model/Traffic"); - cGeneral = env->FindClass("com/github/kr328/clash/core/model/General"); - cCompletableFuture = env->FindClass("java/util/concurrent/CompletableFuture"); - cProxyGroup = env->FindClass("com/github/kr328/clash/core/model/ProxyGroup"); - cProxy = env->FindClass("com/github/kr328/clash/core/model/Proxy"); - iTunCallback = env->FindClass("com/github/kr328/clash/core/bridge/TunCallback"); + cClashException = g(env, env->FindClass("com/github/kr328/clash/core/bridge/ClashException")); + cTraffic = g(env, env->FindClass("com/github/kr328/clash/core/model/Traffic")); + cGeneral = g(env, env->FindClass("com/github/kr328/clash/core/model/General")); + cCompletableFuture = g(env, env->FindClass("java/util/concurrent/CompletableFuture")); + cProxyGroup = g(env, env->FindClass("com/github/kr328/clash/core/model/ProxyGroup")); + cProxy = g(env, env->FindClass("com/github/kr328/clash/core/model/Proxy")); + iTunCallback = g(env, env->FindClass("com/github/kr328/clash/core/bridge/TunCallback")); cClashExceptionConstructor = env->GetMethodID(cClashException, "", "(Ljava/lang/String;)V"); cTrafficConstructor = env->GetMethodID(cTraffic, "", "(JJ)V"); @@ -27,20 +32,20 @@ Master::Master(JavaVM *vm, JNIEnv *env): vm(vm) { mTunCallbackOnNewSocket = env->GetMethodID(iTunCallback, "onNewSocket", "(I)V"); mTunCallbackOnStop = env->GetMethodID(iTunCallback, "onStop", "()V"); - sDirect = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Direct"))); - sReject = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Reject"))); - sShadowsocks = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Shadowsocks"))); - sSnell = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Snell"))); - sSocks5 = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Socks5"))); - sHttp = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Http"))); - sVmess = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Vmess"))); - sTrojan = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Trojan"))); - sRelay = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Relay"))); - sSelector = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Selector"))); - sFallback = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Fallback"))); - sURLTest = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("URLTest"))); - sLoadBalance = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("LoadBalance"))); - sUnknown = reinterpret_cast(env->NewGlobalRef(env->NewStringUTF("Unknown"))); + sDirect = g(env, env->NewStringUTF("Direct")); + sReject = g(env, env->NewStringUTF("Reject")); + sShadowsocks = g(env, env->NewStringUTF("Shadowsocks")); + sSnell = g(env, env->NewStringUTF("Snell")); + sSocks5 = g(env, env->NewStringUTF("Socks5")); + sHttp = g(env, env->NewStringUTF("Http")); + sVmess = g(env, env->NewStringUTF("Vmess")); + sTrojan = g(env, env->NewStringUTF("Trojan")); + sRelay = g(env, env->NewStringUTF("Relay")); + sSelector = g(env, env->NewStringUTF("Selector")); + sFallback = g(env, env->NewStringUTF("Fallback")); + sURLTest = g(env, env->NewStringUTF("URLTest")); + sLoadBalance = g(env, env->NewStringUTF("LoadBalance")); + sUnknown = g(env, env->NewStringUTF("Unknown")); } Master::Context::Context(JNIEnv *env) { diff --git a/core/src/main/cpp/patch.cpp b/core/src/main/cpp/patch.cpp index 6ea0d16..45ce871 100644 --- a/core/src/main/cpp/patch.cpp +++ b/core/src/main/cpp/patch.cpp @@ -51,18 +51,20 @@ Java_com_github_kr328_clash_core_bridge_Bridge_setDnsOverride(JNIEnv *env, jclas } extern "C" -JNIEXPORT void JNICALL +JNIEXPORT jboolean JNICALL Java_com_github_kr328_clash_core_bridge_Bridge_setSelector(JNIEnv *env, jclass clazz, jstring group, jstring selected) { UNUSED(clazz); - Master::runWithContext(env, [&](Master::Context *context) { + return Master::runWithContext(env, [&](Master::Context *context) -> bool { const char *g = context->getString(group); const char *s = context->getString(selected); - setSelector(g, s); + int r = setSelector(g, s); context->releaseString(group, g); context->releaseString(selected, s); + + return r == 0; }); } \ No newline at end of file diff --git a/core/src/main/golang/main.go b/core/src/main/golang/main.go index f4bdcdb..5fd7fe0 100644 --- a/core/src/main/golang/main.go +++ b/core/src/main/golang/main.go @@ -32,6 +32,8 @@ func init() { sub := log.Subscribe() defer log.UnSubscribe(sub) + close(r) + for item := range sub { msg := item.(*log.Event) @@ -56,8 +58,6 @@ func init() { C.free(unsafe.Pointer(cPayload)) } - - r <- struct{}{} }() <- r diff --git a/core/src/main/golang/proxies.go b/core/src/main/golang/proxies.go index ed1ef67..d9f87c6 100644 --- a/core/src/main/golang/proxies.go +++ b/core/src/main/golang/proxies.go @@ -16,7 +16,7 @@ import ( #include static proxy_group_list_t *new_proxy_group_list_t(int size) { - proxy_group_list_t *result = malloc(sizeof(proxy_group_list_t) + size * sizeof(proxy_group_t*)); + proxy_group_list_t *result = (proxy_group_list_t *) malloc(sizeof(proxy_group_list_t) + size * sizeof(proxy_group_t*)); result->size = size; @@ -24,7 +24,7 @@ static proxy_group_list_t *new_proxy_group_list_t(int size) { } static proxy_group_t *new_proxy_group_t(int proxies_size) { - proxy_group_t *result = malloc(sizeof(proxy_group_t) + proxies_size * sizeof(proxy_t)); + proxy_group_t *result = (proxy_group_t *) malloc(sizeof(proxy_group_t) + proxies_size * sizeof(proxy_t)); result->proxies_size = proxies_size; @@ -42,7 +42,7 @@ static void proxy_group_list_set(proxy_group_list_t *list, int index, proxy_grou import "C" //export setSelector -func setSelector(group C.const_string_t, selected C.const_string_t) { +func setSelector(group C.const_string_t, selected C.const_string_t) C.int { g := C.GoString(group) s := C.GoString(selected) @@ -50,37 +50,39 @@ func setSelector(group C.const_string_t, selected C.const_string_t) { if p == nil { log.Warnln("Set selector failure: %s not found", g) - return + return -1 } pw, ok := p.(*outbound.Proxy) if !ok { log.Warnln("Set selector failure: %s not valid group", g) - return + return -1 } adapter, ok := pw.ProxyAdapter.(outboundgroup.ProxyGroup) if !ok { log.Warnln("Set selector failure: %s not valid group", g) - return + return -1 } selector, ok := adapter.(*outboundgroup.Selector) if !ok { log.Warnln("Set selector failure: %s not selector", g) - return + return -1 } if err := selector.Set(s); err != nil { log.Warnln("Set selector failure: %s not in %s", s, g) - return + return -1 } log.Infoln("Set %s -> %s", g, s) + + return 0 } //export queryProxyGroups diff --git a/core/src/main/java/com/github/kr328/clash/core/Clash.kt b/core/src/main/java/com/github/kr328/clash/core/Clash.kt index dd22c7a..677fa2d 100644 --- a/core/src/main/java/com/github/kr328/clash/core/Clash.kt +++ b/core/src/main/java/com/github/kr328/clash/core/Clash.kt @@ -2,6 +2,7 @@ package com.github.kr328.clash.core import android.os.ParcelFileDescriptor import com.github.kr328.clash.common.Global +import com.github.kr328.clash.common.utils.Log import com.github.kr328.clash.core.bridge.Bridge import com.github.kr328.clash.core.bridge.TunCallback import com.github.kr328.clash.core.event.LogEvent @@ -13,8 +14,6 @@ import java.io.InputStream import java.util.concurrent.CompletableFuture object Clash { - private val logReceivers = mutableMapOf Unit>() - init { val context = Global.application @@ -23,6 +22,8 @@ object Clash { Bridge.initialize(bytes, context.cacheDir.absolutePath, BuildConfig.VERSION_NAME) Bridge.reset() + + Log.i("Clash core initialized") } fun start() { @@ -76,7 +77,7 @@ object Clash { return Bridge.queryProxyGroups().toList() } - fun setSelector(name: String, selected: String) { + fun setSelector(name: String, selected: String): Boolean { return Bridge.setSelector(name, selected) } @@ -101,27 +102,10 @@ object Clash { } fun registerLogReceiver(key: String, receiver: (LogEvent) -> Unit) { - synchronized(logReceivers) { - logReceivers[key] = receiver - Bridge.setLogCallback(this::onLogEvent) - } } fun unregisterLogReceiver(key: String) { - synchronized(logReceivers) { - logReceivers.remove(key) - if (logReceivers.isEmpty()) - Bridge.setLogCallback(null) - } - } - - private fun onLogEvent(level: String, payload: String) { - synchronized(logReceivers) { - logReceivers.forEach { - it.value(LogEvent(LogEvent.Level.fromString(level), payload)) - } - } } } \ No newline at end of file diff --git a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.java b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.java index 4c27222..8e67d6d 100644 --- a/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.java +++ b/core/src/main/java/com/github/kr328/clash/core/bridge/Bridge.java @@ -31,7 +31,7 @@ public final class Bridge { public static native void setDnsOverride(boolean overrideDns, String appendNameservers); public static native void setProxyMode(String mode); - public static native void setSelector(String group, String selected); + public static native boolean setSelector(String group, String selected); public static native CompletableFuture downloadProfile(String url, String base, String output); public static native CompletableFuture downloadProfile(int fd, String base, String output); diff --git a/core/src/main/java/com/github/kr328/clash/core/bridge/LogCallback.java b/core/src/main/java/com/github/kr328/clash/core/bridge/LogCallback.java new file mode 100644 index 0000000..cdfa0a2 --- /dev/null +++ b/core/src/main/java/com/github/kr328/clash/core/bridge/LogCallback.java @@ -0,0 +1,7 @@ +package com.github.kr328.clash.core.bridge; + +import com.github.kr328.clash.core.event.LogEvent; + +interface LogCallback { + void onMessage(LogEvent event); +} diff --git a/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt b/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt index 63ff6af..18cd607 100644 --- a/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt +++ b/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt @@ -2,6 +2,7 @@ package com.github.kr328.clash.core.event import android.os.Parcel import android.os.Parcelable +import androidx.annotation.Keep import com.github.kr328.clash.common.serialization.Parcels import kotlinx.serialization.Serializable @@ -12,6 +13,9 @@ data class LogEvent( val message: String, val time: Long = System.currentTimeMillis() ) : Parcelable { + @Keep + constructor(level: String, message: String): this(Level.fromString(level), message) + companion object { const val DEBUG_VALUE = "debug" const val INFO_VALUE = "info" diff --git a/service/build.gradle.kts b/service/build.gradle.kts index abcfb51..609be6c 100644 --- a/service/build.gradle.kts +++ b/service/build.gradle.kts @@ -66,6 +66,7 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$gKotlinSerializationVersion") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$gKotlinVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$gKotlinCoroutineVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$gKotlinCoroutineVersion") implementation("androidx.room:room-runtime:$gRoomVersion") implementation("androidx.room:room-ktx:$gRoomVersion") implementation("androidx.core:core-ktx:$gAndroidKtxVersion") diff --git a/service/src/main/aidl/com/github/kr328/clash/core/model/Packet.aidl b/service/src/main/aidl/com/github/kr328/clash/core/model/Packet.aidl index 2cdcbd7..7c69387 100644 --- a/service/src/main/aidl/com/github/kr328/clash/core/model/Packet.aidl +++ b/service/src/main/aidl/com/github/kr328/clash/core/model/Packet.aidl @@ -1,4 +1,4 @@ package com.github.kr328.clash.core.model; -parcelable ProxyGroupList; +parcelable ProxyGroupWrapper; parcelable General; \ No newline at end of file diff --git a/service/src/main/aidl/com/github/kr328/clash/service/IClashManager.aidl b/service/src/main/aidl/com/github/kr328/clash/service/IClashManager.aidl index c8c7913..bb3df8c 100644 --- a/service/src/main/aidl/com/github/kr328/clash/service/IClashManager.aidl +++ b/service/src/main/aidl/com/github/kr328/clash/service/IClashManager.aidl @@ -5,12 +5,12 @@ import com.github.kr328.clash.core.model.Packet; interface IClashManager { // Control - boolean setSelectProxy(String proxy, String selected); - void startHealthCheck(String group, IStreamCallback callback); + void setSelector(String group, String selected); + void performHealthCheck(String group, IStreamCallback callback); void setProxyMode(String mode); // Query - ProxyGroupList queryAllProxies(); + ProxyGroupWrapper queryProxyGroups(); General queryGeneral(); long queryBandwidth(); diff --git a/service/src/main/java/com/github/kr328/clash/service/ClashManager.kt b/service/src/main/java/com/github/kr328/clash/service/ClashManager.kt index c86b0f9..46d4236 100644 --- a/service/src/main/java/com/github/kr328/clash/service/ClashManager.kt +++ b/service/src/main/java/com/github/kr328/clash/service/ClashManager.kt @@ -18,7 +18,7 @@ class ClashManager(parent: CoroutineScope) : Clash.setProxyMode(requireNotNull(mode)) } - override fun queryAllProxies(): ProxyGroupWrapper { + override fun queryProxyGroups(): ProxyGroupWrapper { return ProxyGroupWrapper(Clash.queryProxyGroups()) } @@ -26,7 +26,7 @@ class ClashManager(parent: CoroutineScope) : return Clash.queryGeneral() } - override fun setSelectProxy(proxy: String?, selected: String?): Boolean { + override fun setSelector(proxy: String?, selected: String?) { require(proxy != null && selected != null) launch { @@ -35,7 +35,7 @@ class ClashManager(parent: CoroutineScope) : SelectedProxyDao.setSelectedForProfile(SelectedProxyEntity(current.id, proxy, selected)) } - return Clash.setSelector(proxy, selected) + Clash.setSelector(proxy, selected) } override fun queryBandwidth(): Long { @@ -44,10 +44,10 @@ class ClashManager(parent: CoroutineScope) : return data.download + data.upload } - override fun startHealthCheck(group: String?, callback: IStreamCallback?) { + override fun performHealthCheck(group: String?, callback: IStreamCallback?) { require(group != null && callback != null) - Clash.performHealthCheck(group).invokeOnCompletion { u -> + Clash.performHealthCheck(group).whenComplete { _, u -> if (u != null) callback.completeExceptionally(u.message) else diff --git a/service/src/main/java/com/github/kr328/clash/service/ProfileProcessor.kt b/service/src/main/java/com/github/kr328/clash/service/ProfileProcessor.kt index 4673d4c..67c1c28 100644 --- a/service/src/main/java/com/github/kr328/clash/service/ProfileProcessor.kt +++ b/service/src/main/java/com/github/kr328/clash/service/ProfileProcessor.kt @@ -13,10 +13,12 @@ import com.github.kr328.clash.service.model.asEntity import com.github.kr328.clash.service.util.resolveBaseDir import com.github.kr328.clash.service.util.resolveProfileFile import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.future.await import kotlinx.coroutines.withContext import java.io.File import java.io.FileNotFoundException import java.lang.Exception +import java.lang.NullPointerException import java.util.* object ProfileProcessor { @@ -56,14 +58,17 @@ object ProfileProcessor { source: Uri, target: File, baseDir: File - ) = withContext(Dispatchers.IO) { + ) { when (source.scheme?.toLowerCase(Locale.getDefault())) { "http", "https" -> Clash.downloadProfile(source.toString(), target, baseDir) "content", "file", "resource" -> { - val fd = context.contentResolver.openFileDescriptor(source, "r") - ?: throw FileNotFoundException("$source not found") - Clash.downloadProfile(fd.detachFd(), target, baseDir) + val fd = withContext(Dispatchers.IO) { + @Suppress("BlockingMethodInNonBlockingContext") + context.contentResolver.openFileDescriptor(source, "r") + } ?: throw FileNotFoundException("$source not found") + + Clash.downloadProfile(fd, target, baseDir) } else -> throw IllegalArgumentException("Invalid uri type") }.await() diff --git a/service/src/main/java/com/github/kr328/clash/service/clash/module/ReloadModule.kt b/service/src/main/java/com/github/kr328/clash/service/clash/module/ReloadModule.kt index 512512d..8084a2f 100644 --- a/service/src/main/java/com/github/kr328/clash/service/clash/module/ReloadModule.kt +++ b/service/src/main/java/com/github/kr328/clash/service/clash/module/ReloadModule.kt @@ -9,6 +9,7 @@ import com.github.kr328.clash.service.data.ProfileDao import com.github.kr328.clash.service.data.SelectedProxyDao import com.github.kr328.clash.service.util.resolveBaseDir import com.github.kr328.clash.service.util.resolveProfileFile +import kotlinx.coroutines.future.await import kotlinx.coroutines.sync.Mutex class ReloadModule(private val context: Context) : Module() {