diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6b0959c..160e535 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,9 @@ tools:ignore="GoogleAppIndexingWarning"> + android:label="@string/app_name" + android:screenOrientation="portrait" + android:launchMode="singleInstance"> @@ -25,17 +27,25 @@ + android:exported="false" + android:screenOrientation="portrait" /> + android:exported="false" + android:screenOrientation="portrait"/> + android:exported="false" + android:screenOrientation="portrait"/> + android:exported="false" + android:screenOrientation="portrait"/> + diff --git a/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt b/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt new file mode 100644 index 0000000..692ac78 --- /dev/null +++ b/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt @@ -0,0 +1,5 @@ +package com.github.kr328.clash + +class ProxyActivity : BaseActivity() { + +} \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_proxy_group.xml b/app/src/main/res/layout/adapter_proxy_group.xml new file mode 100644 index 0000000..aa1b0cb --- /dev/null +++ b/app/src/main/res/layout/adapter_proxy_group.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eabcb4f..d1a86c7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,11 +6,11 @@ Running %s Forwarded - Proxy + Proxies %d Items - Profile - %s Active + Profiles + %s Activated Unselected Logs 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 e0ef6e0..1382225 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 @@ -9,6 +9,7 @@ import com.github.kr328.clash.core.event.ProcessEvent import com.github.kr328.clash.core.event.ProxyChangedEvent import com.github.kr328.clash.core.event.TrafficEvent import com.github.kr328.clash.core.model.Proxy +import com.github.kr328.clash.core.model.ProxyPacket import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import org.json.JSONObject @@ -56,14 +57,14 @@ class Clash( } } - fun queryProxies(): Proxy.Packet { + fun queryProxies(): ProxyPacket { return runControl(COMMAND_QUERY_PROXIES) { _, input, _ -> val data = input.readString() Log.d(TAG, data) Json(JsonConfiguration.Stable.copy(strictMode = false)) - .parse(Proxy.Packet.serializer(), data) + .parse(ProxyPacket.serializer(), data) } } diff --git a/core/src/main/java/com/github/kr328/clash/core/event/ErrorEvent.kt b/core/src/main/java/com/github/kr328/clash/core/event/ErrorEvent.kt index 877de56..5bfa236 100644 --- a/core/src/main/java/com/github/kr328/clash/core/event/ErrorEvent.kt +++ b/core/src/main/java/com/github/kr328/clash/core/event/ErrorEvent.kt @@ -8,7 +8,8 @@ import kotlinx.serialization.Serializable @Serializable data class ErrorEvent(val type: Type, val message: String) : Event, Parcelable { enum class Type { - START_FAILURE + START_FAILURE, + QUERY_PROXY_FAILURE } override fun writeToParcel(parcel: Parcel, flags: Int) { diff --git a/core/src/main/java/com/github/kr328/clash/core/model/Proxy.kt b/core/src/main/java/com/github/kr328/clash/core/model/Proxy.kt index 4022580..6e704a7 100644 --- a/core/src/main/java/com/github/kr328/clash/core/model/Proxy.kt +++ b/core/src/main/java/com/github/kr328/clash/core/model/Proxy.kt @@ -6,25 +6,7 @@ import com.github.kr328.clash.core.serialization.Parcels import kotlinx.serialization.Serializable @Serializable -data class Proxy(val type: String) : Parcelable { - @Serializable - data class Packet(val proxies: Map) - - override fun writeToParcel(parcel: Parcel, flags: Int) { - Parcels.dump(serializer(), this, parcel) - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): Proxy { - return Parcels.load(serializer(), parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } -} \ No newline at end of file +data class Proxy(val type: String, + val all: List = emptyList(), + val now: String = "", + val history: List = emptyList()) \ No newline at end of file diff --git a/core/src/main/java/com/github/kr328/clash/core/model/ProxyPacket.kt b/core/src/main/java/com/github/kr328/clash/core/model/ProxyPacket.kt new file mode 100644 index 0000000..3aa1167 --- /dev/null +++ b/core/src/main/java/com/github/kr328/clash/core/model/ProxyPacket.kt @@ -0,0 +1,28 @@ +package com.github.kr328.clash.core.model + +import android.os.Parcel +import android.os.Parcelable +import com.github.kr328.clash.core.serialization.Parcels +import kotlinx.serialization.Serializable + +@Serializable +data class ProxyPacket(val proxies: Map) : Parcelable { + override fun writeToParcel(parcel: Parcel, flags: Int) { + Parcels.dump(serializer(), this, parcel) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ProxyPacket { + return Parcels.load(serializer(), parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + +} \ No newline at end of file diff --git a/service/src/main/aidl/com/github/kr328/clash/core/model/ProxyPacket.aidl b/service/src/main/aidl/com/github/kr328/clash/core/model/ProxyPacket.aidl new file mode 100644 index 0000000..9e3d5fe --- /dev/null +++ b/service/src/main/aidl/com/github/kr328/clash/core/model/ProxyPacket.aidl @@ -0,0 +1,3 @@ +package com.github.kr328.clash.core.model; + +parcelable ProxyPacket; diff --git a/service/src/main/aidl/com/github/kr328/clash/service/IClashService.aidl b/service/src/main/aidl/com/github/kr328/clash/service/IClashService.aidl index fd81da8..96a0048 100644 --- a/service/src/main/aidl/com/github/kr328/clash/service/IClashService.aidl +++ b/service/src/main/aidl/com/github/kr328/clash/service/IClashService.aidl @@ -4,6 +4,7 @@ import com.github.kr328.clash.service.IClashEventObserver; import com.github.kr328.clash.service.IClashEventService; import com.github.kr328.clash.service.IClashProfileService; import com.github.kr328.clash.core.event.Event; +import com.github.kr328.clash.core.model.ProxyPacket; interface IClashService { // Services @@ -18,4 +19,7 @@ interface IClashService { void stopTunDevice(); void start(); void stop(); + + // Query + ProxyPacket queryAllProxies(); } diff --git a/service/src/main/java/com/github/kr328/clash/service/ClashService.kt b/service/src/main/java/com/github/kr328/clash/service/ClashService.kt index 1c0fa42..c63849f 100644 --- a/service/src/main/java/com/github/kr328/clash/service/ClashService.kt +++ b/service/src/main/java/com/github/kr328/clash/service/ClashService.kt @@ -11,8 +11,10 @@ import android.os.IInterface import android.os.ParcelFileDescriptor import com.github.kr328.clash.core.Clash import com.github.kr328.clash.core.event.* +import com.github.kr328.clash.core.model.ProxyPacket import com.github.kr328.clash.core.utils.Log import com.github.kr328.clash.service.data.ClashDatabase +import java.io.EOFException import java.io.File import java.io.IOException import java.util.concurrent.Executors @@ -36,10 +38,24 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master, clash.stopTunDevice() } + override fun queryAllProxies(): ProxyPacket { + return try { + ProxyPacket(clash.queryProxies().proxies.mapValues { + it.value.copy(history = it.value.history.take(1)) + }) + } catch (e: Exception) { + this@ClashService.eventService.preformErrorEvent( + ErrorEvent(ErrorEvent.Type.QUERY_PROXY_FAILURE, e.toString()) + ) + + ProxyPacket(emptyMap()) + } + } + override fun start() { try { clash.process.start() - } catch (e: IOException) { + } catch (e: Exception) { Log.e("Start failure", e) this@ClashService.eventService.preformErrorEvent( @@ -58,7 +74,7 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master, clash.startTunDevice(fd.fileDescriptor, mtu) fd.close() - } catch (e: IOException) { + } catch (e: Exception) { Log.e("Start tun failure", e) this@ClashService.eventService.preformErrorEvent( diff --git a/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt b/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt index af69472..3a7b544 100644 --- a/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt +++ b/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt @@ -49,15 +49,10 @@ class DefaultNetworkObserver(val context: Context, val listener: (Network?) -> U private fun rebuildNetworkList(): Network? { return try { connectivity.allNetworks - .map { - connectivity.getNetworkCapabilities(it) to it - } - .filter { - it.first != null - } - .map { - it.first!! to it.second + .flatMap { network -> + connectivity.getNetworkCapabilities(network)?.let { listOf(it to network) } ?: emptyList() } + .asSequence() .filterNot { it.first.hasTransport(NetworkCapabilities.TRANSPORT_VPN) || !it.first.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)