Fix android vpn close issues

Add requests page

Fix checkUpdate dark mode style error

Fix quickStart error open app

Add memory proxies tab index

Support hidden group

Optimize logs
This commit is contained in:
chen08209
2024-06-13 23:43:42 +08:00
parent 5ab4dd0cbd
commit f7abf6446c
56 changed files with 1437 additions and 496 deletions

View File

@@ -15,7 +15,6 @@ enum class RunState {
class GlobalState {
companion object {
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
var runTime: Date? = null
var flutterEngine: FlutterEngine? = null
fun getCurrentTilePlugin(): TilePlugin? =
flutterEngine?.plugins?.get(TilePlugin::class.java) as TilePlugin?

View File

@@ -1,17 +1,18 @@
package com.follow.clash.extensions
import java.net.InetSocketAddress
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.system.OsConstants.IPPROTO_TCP
import android.system.OsConstants.IPPROTO_UDP
import android.util.Base64
import java.net.URL
import androidx.core.graphics.drawable.toBitmap
import com.follow.clash.models.Metadata
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.net.InetAddress
import java.net.InetSocketAddress
suspend fun Drawable.getBase64(): String {
@@ -29,3 +30,8 @@ fun Metadata.getProtocol(): Int? {
if (network.startsWith("udp")) return IPPROTO_UDP
return null
}
fun String.getInetSocketAddress(): InetSocketAddress {
val url = URL("https://$this")
return InetSocketAddress(InetAddress.getByName(url.host), url.port)
}

View File

@@ -1,11 +1,15 @@
package com.follow.clash.models
data class Process(
val id: Int,
val metadata: Metadata,
)
data class Metadata(
val network: String,
val sourceIP: String,
val sourcePort: Int,
val destinationIP: String,
val destinationPort: Int,
val remoteDestination: String,
val host: String
)

View File

@@ -6,13 +6,16 @@ import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toBitmap
import com.follow.clash.extensions.getBase64
import com.follow.clash.extensions.getInetSocketAddress
import com.follow.clash.extensions.getProtocol
import com.follow.clash.models.Metadata
import com.follow.clash.models.Process
import com.follow.clash.models.Package
import com.google.gson.Gson
import io.flutter.embedding.engine.plugins.FlutterPlugin
@@ -78,21 +81,34 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
"getPackageIcon" -> {
scope.launch {
val packageName = call.argument<String>("packageName")
if (packageName != null) {
result.success(getPackageIcon(packageName))
} else {
if (packageName == null) {
result.success(null)
return@launch
}
val packageIcon = getPackageIcon(packageName)
packageIcon.let {
if (it != null) {
result.success(it)
return@launch
}
if (iconMap["default"] == null) {
iconMap["default"] =
context?.packageManager?.defaultActivityIcon?.getBase64()
}
result.success(iconMap["default"])
return@launch
}
}
}
"getPackageName" -> {
"resolverProcess" -> {
val data = call.argument<String>("data")
val metadata =
val process =
if (data != null) Gson().fromJson(
data,
Metadata::class.java
Process::class.java
) else null
val metadata = process?.metadata
val protocol = metadata?.getProtocol()
if (protocol == null) {
result.success(null)
@@ -100,17 +116,27 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
}
scope.launch {
withContext(Dispatchers.Default) {
if (context == null) result.success(null)
val source = InetSocketAddress(metadata.sourceIP, metadata.sourcePort)
val target = InetSocketAddress(
metadata.host.ifEmpty { metadata.destinationIP },
metadata.destinationPort
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
result.success(null)
return@withContext
}
if (context == null) {
result.success(null)
return@withContext
}
if (connectivity == null) {
connectivity = context!!.getSystemService<ConnectivityManager>()
}
val uid =
connectivity?.getConnectionOwnerUid(protocol, source, target)
val src = InetSocketAddress(metadata.sourceIP, metadata.sourcePort)
val dst = InetSocketAddress(
metadata.destinationIP.ifEmpty { metadata.host },
metadata.destinationPort
)
val uid = try {
connectivity?.getConnectionOwnerUid(protocol, src, dst)
} catch (_: Exception) {
null
}
if (uid == null || uid == -1) {
result.success(null)
return@withContext
@@ -137,7 +163,12 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
private suspend fun getPackageIcon(packageName: String): String? {
val packageManager = context?.packageManager
if (iconMap[packageName] == null) {
iconMap[packageName] = packageManager?.getApplicationIcon(packageName)?.getBase64()
iconMap[packageName] = try {
packageManager?.getApplicationIcon(packageName)?.getBase64()
} catch (_: Exception) {
null
}
}
return iconMap[packageName]
}
@@ -163,7 +194,7 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
}
fun requestGc() {
channel.invokeMethod("gc",null)
channel.invokeMethod("gc", null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {

View File

@@ -16,7 +16,6 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.follow.clash.GlobalState
import com.follow.clash.RunState
import com.follow.clash.models.AccessControl
import com.follow.clash.models.Props
import com.follow.clash.services.FlClashVpnService
import com.google.gson.Gson
@@ -26,7 +25,6 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.util.Date
class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
@@ -95,10 +93,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
}
}
"GetRunTimeStamp" -> {
result.success(GlobalState.runTime?.time)
}
"startForeground" -> {
title = call.argument<String>("title") as String
content = call.argument<String>("content") as String
@@ -124,7 +118,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
if (GlobalState.runState.value == RunState.START) return;
flClashVpnService?.start(port, props)
GlobalState.runState.value = RunState.START
GlobalState.runTime = Date()
startAfter()
}
@@ -133,7 +126,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
flClashVpnService?.stop()
unbindService()
GlobalState.runState.value = RunState.STOP;
GlobalState.runTime = null;
}
@SuppressLint("ForegroundServiceType")

View File

@@ -44,7 +44,7 @@ class FlClashTileService : TileService() {
private fun activityTransfer() {
val intent = Intent(this, TempActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
PendingIntent.getActivity(
this,