mirror of
https://github.com/MetaCubeX/ClashMetaForAndroid.git
synced 2025-02-19 16:23:14 +03:00
Update app (#428)
This commit is contained in:
parent
3100e1700c
commit
e8e00108e6
4
.github/workflows/build-debug.yaml
vendored
4
.github/workflows/build-debug.yaml
vendored
@ -20,8 +20,8 @@ jobs:
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
distribution: "temurin"
|
||||
java-version: 21
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
4
.github/workflows/build-pre-release.yaml
vendored
4
.github/workflows/build-pre-release.yaml
vendored
@ -19,8 +19,8 @@ jobs:
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
distribution: "temurin"
|
||||
java-version: 21
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
4
.github/workflows/build-release.yaml
vendored
4
.github/workflows/build-release.yaml
vendored
@ -22,8 +22,8 @@ jobs:
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
distribution: "temurin"
|
||||
java-version: 21
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
4
.github/workflows/update-dependencies.yaml
vendored
4
.github/workflows/update-dependencies.yaml
vendored
@ -18,8 +18,8 @@ jobs:
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
distribution: "temurin"
|
||||
java-version: 21
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.github.kr328.clash">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
@ -16,6 +15,8 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
@ -172,7 +173,11 @@
|
||||
<service
|
||||
android:name=".LogcatService"
|
||||
android:exported="false"
|
||||
android:label="@string/clash_logcat" />
|
||||
android:label="@string/clash_logcat"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="explanation_for_special_use"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".TileService"
|
||||
android:exported="true"
|
||||
|
@ -120,6 +120,9 @@ class AccessControlActivity : BaseActivity<AccessControlDesign>() {
|
||||
.filter {
|
||||
it.packageName == "android" || it.requestedPermissions?.contains(INTERNET) == true
|
||||
}
|
||||
.filter {
|
||||
it.applicationInfo != null
|
||||
}
|
||||
.filter {
|
||||
systemApp || !it.isSystemApp
|
||||
}
|
||||
@ -132,6 +135,6 @@ class AccessControlActivity : BaseActivity<AccessControlDesign>() {
|
||||
|
||||
private val PackageInfo.isSystemApp: Boolean
|
||||
get() {
|
||||
return applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
|
||||
return applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM) != 0
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
abstract class BaseActivity<D : Design<*>> : AppCompatActivity(),
|
||||
CoroutineScope by MainScope(),
|
||||
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -28,6 +28,7 @@ import kotlinx.coroutines.withContext
|
||||
import java.io.OutputStreamWriter
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class LogcatActivity : BaseActivity<LogcatDesign>() {
|
||||
private var conn: ServiceConnection? = null
|
||||
|
@ -14,6 +14,7 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.github.kr328.clash.common.compat.getColorCompat
|
||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
||||
import com.github.kr328.clash.common.compat.startForegroundCompat
|
||||
import com.github.kr328.clash.common.log.Log
|
||||
import com.github.kr328.clash.common.util.intent
|
||||
import com.github.kr328.clash.core.model.LogMessage
|
||||
@ -130,17 +131,17 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De
|
||||
NotificationChannelCompat.Builder(
|
||||
CHANNEL_ID,
|
||||
NotificationManagerCompat.IMPORTANCE_DEFAULT
|
||||
).setName(getString(R.string.clash_logcat)).build()
|
||||
).setName(getString(com.github.kr328.clash.design.R.string.clash_logcat)).build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun showNotification() {
|
||||
val notification = NotificationCompat
|
||||
.Builder(this, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_logo_service)
|
||||
.setColor(getColorCompat(R.color.color_clash_light))
|
||||
.setContentTitle(getString(R.string.clash_logcat))
|
||||
.setContentText(getString(R.string.running))
|
||||
.setSmallIcon(com.github.kr328.clash.service.R.drawable.ic_logo_service)
|
||||
.setColor(getColorCompat(com.github.kr328.clash.design.R.color.color_clash_light))
|
||||
.setContentTitle(getString(com.github.kr328.clash.design.R.string.clash_logcat))
|
||||
.setContentText(getString(com.github.kr328.clash.design.R.string.running))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
@ -152,7 +153,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De
|
||||
)
|
||||
.build()
|
||||
|
||||
startForeground(R.id.nf_logcat_status, notification)
|
||||
startForegroundCompat(R.id.nf_logcat_status, notification)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -1,6 +1,13 @@
|
||||
package com.github.kr328.clash
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.PersistableBundle
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.github.kr328.clash.common.util.intent
|
||||
import com.github.kr328.clash.common.util.ticker
|
||||
import com.github.kr328.clash.design.MainDesign
|
||||
@ -15,6 +22,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.selects.select
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class MainActivity : BaseActivity<MainDesign>() {
|
||||
override suspend fun main() {
|
||||
@ -129,4 +137,20 @@ class MainActivity : BaseActivity<MainDesign>() {
|
||||
packageManager.getPackageInfo(packageName, 0).versionName + "\n" + Bridge.nativeCoreVersion().replace("_", "-")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val requestPermissionLauncher =
|
||||
registerForActivityResult(RequestPermission()
|
||||
) { isGranted: Boolean ->
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
android.Manifest.permission.POST_NOTIFICATIONS
|
||||
) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import kotlinx.coroutines.selects.select
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
|
||||
class MetaFeatureSettingsActivity : BaseActivity<MetaFeatureSettingsDesign>() {
|
||||
|
@ -18,6 +18,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.selects.select
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class NewProfileActivity : BaseActivity<NewProfileDesign>() {
|
||||
private val self: NewProfileActivity
|
||||
|
@ -9,7 +9,6 @@ import com.github.kr328.clash.common.util.setUUID
|
||||
import com.github.kr328.clash.common.util.ticker
|
||||
import com.github.kr328.clash.design.ProfilesDesign
|
||||
import com.github.kr328.clash.design.ui.ToastDuration
|
||||
import com.github.kr328.clash.R
|
||||
import com.github.kr328.clash.service.model.Profile
|
||||
import com.github.kr328.clash.util.withProfile
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -19,6 +18,7 @@ import kotlinx.coroutines.selects.select
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class ProfilesActivity : BaseActivity<ProfilesDesign>() {
|
||||
override suspend fun main() {
|
||||
|
@ -12,9 +12,11 @@ import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.selects.select
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
||||
private var canceled: Boolean = false
|
||||
private lateinit var original: Profile
|
||||
|
||||
override suspend fun main() {
|
||||
setResult(RESULT_CANCELED)
|
||||
@ -22,7 +24,7 @@ class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
||||
val uuid = intent.uuid ?: return finish()
|
||||
val design = PropertiesDesign(this)
|
||||
|
||||
val original = withProfile { queryByUUID(uuid) } ?: return finish()
|
||||
original = withProfile { queryByUUID(uuid) } ?: return finish()
|
||||
|
||||
design.profile = original
|
||||
|
||||
@ -71,7 +73,7 @@ class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
||||
design?.apply {
|
||||
launch {
|
||||
if (!progressing) {
|
||||
if (requestExitWithoutSaving())
|
||||
if (original == profile || requestExitWithoutSaving())
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.selects.select
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.github.kr328.clash.design.R
|
||||
|
||||
class ProvidersActivity : BaseActivity<ProvidersDesign>() {
|
||||
override suspend fun main() {
|
||||
|
@ -9,11 +9,13 @@ import android.os.Build
|
||||
import android.service.quicksettings.Tile
|
||||
import android.service.quicksettings.TileService
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.github.kr328.clash.common.compat.registerReceiverCompat
|
||||
import com.github.kr328.clash.common.constants.Intents
|
||||
import com.github.kr328.clash.common.constants.Permissions
|
||||
import com.github.kr328.clash.remote.StatusClient
|
||||
import com.github.kr328.clash.util.startClashService
|
||||
import com.github.kr328.clash.util.stopClashService
|
||||
import com.github.kr328.clash.service.R
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
class TileService : TileService() {
|
||||
@ -36,7 +38,7 @@ class TileService : TileService() {
|
||||
override fun onStartListening() {
|
||||
super.onStartListening()
|
||||
|
||||
registerReceiver(
|
||||
registerReceiverCompat(
|
||||
receiver,
|
||||
IntentFilter().apply {
|
||||
addAction(Intents.ACTION_CLASH_STARTED)
|
||||
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.github.kr328.clash.common.compat.registerReceiverCompat
|
||||
import com.github.kr328.clash.common.constants.Intents
|
||||
import com.github.kr328.clash.common.log.Log
|
||||
import java.util.*
|
||||
@ -88,7 +89,7 @@ class Broadcasts(private val context: Application) {
|
||||
return
|
||||
|
||||
try {
|
||||
context.registerReceiver(broadcastReceiver, IntentFilter().apply {
|
||||
context.registerReceiverCompat(broadcastReceiver, IntentFilter().apply {
|
||||
addAction(Intents.ACTION_SERVICE_RECREATED)
|
||||
addAction(Intents.ACTION_CLASH_STARTED)
|
||||
addAction(Intents.ACTION_CLASH_STOPPED)
|
||||
|
@ -7,16 +7,12 @@ import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ActivityResultLifecycle : LifecycleOwner {
|
||||
private val lifecycle = LifecycleRegistry(this)
|
||||
override val lifecycle = LifecycleRegistry(this)
|
||||
|
||||
init {
|
||||
lifecycle.currentState = Lifecycle.State.INITIALIZED
|
||||
}
|
||||
|
||||
override fun getLifecycle(): Lifecycle {
|
||||
return lifecycle
|
||||
}
|
||||
|
||||
suspend fun <T> use(block: suspend (lifecycle: ActivityResultLifecycle, start: () -> Unit) -> T): T {
|
||||
return try {
|
||||
markCreated()
|
||||
|
@ -32,13 +32,19 @@ subprojects {
|
||||
apply(plugin = if (isApp) "com.android.application" else "com.android.library")
|
||||
|
||||
extensions.configure<BaseExtension> {
|
||||
buildFeatures.buildConfig = true
|
||||
defaultConfig {
|
||||
if (isApp) {
|
||||
applicationId = "com.github.metacubex.clash"
|
||||
}
|
||||
|
||||
project.name.let { name ->
|
||||
namespace = if (name == "app") "com.github.kr328.clash"
|
||||
else "com.github.kr328.clash.$name"
|
||||
}
|
||||
|
||||
minSdk = 21
|
||||
targetSdk = 31
|
||||
targetSdk = 35
|
||||
|
||||
versionName = "2.11.5"
|
||||
versionCode = 211005
|
||||
@ -59,7 +65,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
ndkVersion = "23.0.7599858"
|
||||
ndkVersion = "27.2.12479018"
|
||||
|
||||
compileSdkVersion(defaultConfig.targetSdk!!)
|
||||
|
||||
@ -134,7 +140,7 @@ subprojects {
|
||||
named("release") {
|
||||
isMinifyEnabled = isApp
|
||||
isShrinkResources = isApp
|
||||
signingConfig = signingConfigs.findByName("release")
|
||||
signingConfig = signingConfigs.findByName("release") ?: signingConfigs["debug"]
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
@ -161,6 +167,11 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.kr328.clash.common">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<permission
|
||||
android:name="${applicationId}.permission.RECEIVE_BROADCASTS"
|
||||
|
@ -2,8 +2,13 @@
|
||||
|
||||
package com.github.kr328.clash.common.compat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -14,4 +19,19 @@ fun Context.getColorCompat(@ColorRes id: Int): Int {
|
||||
|
||||
fun Context.getDrawableCompat(@DrawableRes id: Int): Drawable? {
|
||||
return ContextCompat.getDrawable(this, id)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||
fun Context.registerReceiverCompat(
|
||||
receiver: BroadcastReceiver,
|
||||
filter: IntentFilter,
|
||||
permission: String? = null,
|
||||
handler: Handler? = null
|
||||
) =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
registerReceiver(receiver, filter, permission, handler,
|
||||
if (permission == null) Context.RECEIVER_EXPORTED else Context.RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
else
|
||||
registerReceiver(receiver, filter, permission, handler)
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
package com.github.kr328.clash.common.compat
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
|
||||
fun Context.startForegroundServiceCompat(intent: Intent) {
|
||||
@ -10,4 +13,12 @@ fun Context.startForegroundServiceCompat(intent: Intent) {
|
||||
} else {
|
||||
startService(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Service.startForegroundCompat(id: Int, notification: Notification) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
|
||||
} else {
|
||||
startForeground(id, notification)
|
||||
}
|
||||
}
|
||||
|
1
core/.gitignore
vendored
Normal file
1
core/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/src/main/cpp/version.h
|
@ -1,8 +1,6 @@
|
||||
import android.databinding.tool.ext.capitalizeUS
|
||||
import com.github.kr328.golang.GolangBuildTask
|
||||
import com.github.kr328.golang.GolangPlugin
|
||||
import java.io.FileOutputStream
|
||||
import java.net.URL
|
||||
import java.time.Duration
|
||||
|
||||
plugins {
|
||||
kotlin("android")
|
||||
@ -62,4 +60,15 @@ afterEvaluate {
|
||||
tasks.withType(GolangBuildTask::class.java).forEach {
|
||||
it.inputs.dir(golangSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val abis = listOf("armeabi-v7a" to "ArmeabiV7a", "arm64-v8a" to "Arm64V8a", "x86_64" to "X8664", "x86" to "X86")
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
afterEvaluate {
|
||||
for ((abi, goAbi) in abis) {
|
||||
val cmakeName = if (variant.buildType == "debug") "Debug" else "RelWithDebInfo"
|
||||
tasks.getByName("buildCMake$cmakeName[$abi]").dependsOn(tasks.getByName("externalGolangBuild${variant.name.capitalizeUS()}$goAbi"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.kr328.clash.core">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
|
@ -61,7 +61,7 @@ object Bridge {
|
||||
.detachFd()
|
||||
|
||||
val home = ctx.filesDir.resolve("clash").apply { mkdirs() }.absolutePath
|
||||
val versionName = ctx.packageManager.getPackageInfo(ctx.packageName, 0).versionName
|
||||
val versionName = ctx.packageManager.getPackageInfo(ctx.packageName, 0).versionName ?: "unknown"
|
||||
val sdkVersion = Build.VERSION.SDK_INT
|
||||
|
||||
Log.d("Home = $home")
|
||||
|
@ -1 +1 @@
|
||||
<manifest package="com.github.kr328.clash.design" />
|
||||
<manifest />
|
||||
|
@ -81,7 +81,7 @@ class MainDesign(context: Context) : Design<MainDesign.Request>(context) {
|
||||
init {
|
||||
binding.self = this
|
||||
|
||||
binding.colorClashStarted = context.resolveThemedColor(R.attr.colorPrimary)
|
||||
binding.colorClashStarted = context.resolveThemedColor(com.google.android.material.R.attr.colorPrimary)
|
||||
binding.colorClashStopped = context.resolveThemedColor(R.attr.colorClashStopped)
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ class ProxyDesign(
|
||||
binding.urlTestFloatView.visibility = View.GONE
|
||||
} else {
|
||||
binding.urlTestFloatView.supportImageTintList = ColorStateList.valueOf(
|
||||
context.resolveThemedColor(R.attr.colorOnPrimary)
|
||||
context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||
)
|
||||
|
||||
binding.pagesView.apply {
|
||||
|
@ -15,9 +15,9 @@ class PopupListAdapter(
|
||||
private val texts: List<CharSequence>,
|
||||
private val selected: Int,
|
||||
) : BaseAdapter() {
|
||||
private val colorPrimary = context.resolveThemedColor(R.attr.colorPrimary)
|
||||
private val colorOnPrimary = context.resolveThemedColor(R.attr.colorOnPrimary)
|
||||
private val colorControlNormal = context.resolveThemedColor(R.attr.colorControlNormal)
|
||||
private val colorPrimary = context.resolveThemedColor(com.google.android.material.R.attr.colorPrimary)
|
||||
private val colorOnPrimary = context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||
private val colorControlNormal = context.resolveThemedColor(com.google.android.material.R.attr.colorControlNormal)
|
||||
|
||||
override fun getCount(): Int {
|
||||
return texts.size
|
||||
|
@ -8,15 +8,15 @@ import com.github.kr328.clash.design.util.resolveThemedColor
|
||||
import com.github.kr328.clash.design.util.resolveThemedResourceId
|
||||
|
||||
class ProxyViewConfig(val context: Context, var proxyLine: Int) {
|
||||
private val colorSurface = context.resolveThemedColor(R.attr.colorSurface)
|
||||
private val colorSurface = context.resolveThemedColor(com.google.android.material.R.attr.colorSurface)
|
||||
|
||||
val clickableBackground =
|
||||
context.resolveThemedResourceId(android.R.attr.selectableItemBackground)
|
||||
|
||||
val selectedControl = context.resolveThemedColor(R.attr.colorOnPrimary)
|
||||
val selectedBackground = context.resolveThemedColor(R.attr.colorPrimary)
|
||||
val selectedControl = context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||
val selectedBackground = context.resolveThemedColor(com.google.android.material.R.attr.colorPrimary)
|
||||
|
||||
val unselectedControl = context.resolveThemedColor(R.attr.colorOnSurface)
|
||||
val unselectedControl = context.resolveThemedColor(com.google.android.material.R.attr.colorOnSurface)
|
||||
val unselectedBackground: Int
|
||||
get() = if (proxyLine==1) Color.TRANSPARENT else colorSurface
|
||||
|
||||
|
@ -8,8 +8,8 @@ import com.github.kr328.clash.design.model.AppInfo
|
||||
fun PackageInfo.toAppInfo(pm: PackageManager): AppInfo {
|
||||
return AppInfo(
|
||||
packageName = packageName,
|
||||
icon = applicationInfo.loadIcon(pm).foreground(),
|
||||
label = applicationInfo.loadLabel(pm).toString(),
|
||||
icon = applicationInfo!!.loadIcon(pm).foreground(),
|
||||
label = applicationInfo!!.loadLabel(pm).toString(),
|
||||
installTime = firstInstallTime,
|
||||
updateDate = lastUpdateTime,
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ fun View.setOnInsertsChangedListener(adaptLandscape: Boolean = true, listener: (
|
||||
|
||||
listener(if (adaptLandscape) rInsets.landscape(v.context) else rInsets)
|
||||
|
||||
compat.toWindowInsets()
|
||||
compat.toWindowInsets()!!
|
||||
}
|
||||
|
||||
requestApplyInsets()
|
||||
|
@ -14,12 +14,4 @@ class AppRecyclerView @JvmOverloads constructor(
|
||||
init {
|
||||
isFocusable = false
|
||||
}
|
||||
|
||||
override fun onDraw(c: Canvas?) {
|
||||
super.onDraw(c)
|
||||
}
|
||||
|
||||
override fun dispatchDraw(canvas: Canvas?) {
|
||||
super.dispatchDraw(canvas)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,6 @@ class LargeActionCard @JvmOverloads constructor(
|
||||
minimumHeight = context.getPixels(R.dimen.large_action_card_min_height)
|
||||
radius = context.getPixels(R.dimen.large_action_card_radius).toFloat()
|
||||
elevation = context.getPixels(R.dimen.large_action_card_elevation).toFloat()
|
||||
setCardBackgroundColor(context.resolveThemedColor(R.attr.colorSurface))
|
||||
setCardBackgroundColor(context.resolveThemedColor(com.google.android.material.R.attr.colorSurface))
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="geofile_import_failed">Nhập thất bại</string>
|
||||
<string name="toast_profile_updated_complete">Cập nhật thành công</string>
|
||||
<string name="toast_profile_updated_failed">Cập nhật không thành công</string>
|
||||
<string name="toast_profile_updated_complete">Cập nhật thành công %s</string>
|
||||
<string name="toast_profile_updated_failed">Cập nhật không thành công %1$s %2$s</string>
|
||||
<string name="press_to_import">Chạm để nhập...</string>
|
||||
<string name="meta_features">Tính năng của Clash Meta</string>
|
||||
<string name="allow_ipv6">Cho phép Ipv6</string>
|
||||
|
43
gradle/libs.versions.toml
Normal file
43
gradle/libs.versions.toml
Normal file
@ -0,0 +1,43 @@
|
||||
[versions]
|
||||
agp = "8.8.0"
|
||||
kotlin = "2.1.0"
|
||||
ksp = "2.1.0-1.0.29"
|
||||
golang = "1.0.4"
|
||||
coroutine = "1.10.1"
|
||||
coreKtx = "1.8.0"
|
||||
activity = "1.5.0"
|
||||
fragment = "1.5.0"
|
||||
appcompat = "1.4.2"
|
||||
coordinator = "1.2.0"
|
||||
recyclerview = "1.2.1"
|
||||
viewpager = "1.0.0"
|
||||
material = "1.6.1"
|
||||
serialization = "1.3.3"
|
||||
kaidl = "1.15"
|
||||
room = "2.4.2"
|
||||
multiprocess = "1.0.0"
|
||||
|
||||
[libraries]
|
||||
build-android = { module = "com.android.tools.build:gradle", version.ref = "agp" }
|
||||
build-kotlin-common = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
build-kotlin-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
|
||||
build-ksp = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" }
|
||||
build-golang = { module = "com.github.kr328.golang:gradle-plugin", version.ref = "golang" }
|
||||
kotlin-coroutine = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutine" }
|
||||
kotlin-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||
androidx-core = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
||||
androidx-activity = { module = "androidx.activity:activity", version.ref = "activity" }
|
||||
androidx-fragment = { module = "androidx.fragment:fragment", version.ref = "fragment" }
|
||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
||||
androidx-coordinator = { module = "androidx.coordinatorlayout:coordinatorlayout", version.ref = "coordinator" }
|
||||
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
|
||||
androidx-viewpager = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||
google-material = { module = "com.google.android.material:material", version.ref = "material" }
|
||||
kaidl-compiler = { module = "com.github.kr328.kaidl:kaidl", version.ref = "kaidl" }
|
||||
kaidl-runtime = { module = "com.github.kr328.kaidl:kaidl-runtime", version.ref = "kaidl" }
|
||||
rikkax-multiprocess = { module = "dev.rikka.rikkax.preference:multiprocess", version.ref = "multiprocess" }
|
||||
|
||||
[plugins]
|
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,8 +1,6 @@
|
||||
#Tue Jan 14 14:06:42 CST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip
|
||||
networkTimeout=10000
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
@ -1,2 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.github.kr328.clash.hideapi" />
|
||||
<manifest />
|
@ -19,7 +19,7 @@ dependencies {
|
||||
implementation(libs.androidx.room.ktx)
|
||||
implementation(libs.kaidl.runtime)
|
||||
implementation(libs.rikkax.multiprocess)
|
||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
|
||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
|
||||
|
||||
// define any required OkHttp artifacts without version
|
||||
implementation("com.squareup.okhttp3:okhttp")
|
||||
|
@ -1,6 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.github.kr328.clash.service">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
@ -9,19 +8,27 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name=".ClashService"
|
||||
android:exported="false"
|
||||
android:label="@string/clash_meta_for_android"
|
||||
android:process=":background" />
|
||||
android:process=":background"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="explanation_for_special_use"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".TunService"
|
||||
android:exported="false"
|
||||
android:label="@string/clash_meta_for_android"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:process=":background">
|
||||
android:process=":background"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="explanation_for_special_use"/>
|
||||
<intent-filter>
|
||||
<action android:name="android.net.VpnService" />
|
||||
</intent-filter>
|
||||
@ -33,7 +40,11 @@
|
||||
<service
|
||||
android:name=".ProfileWorker"
|
||||
android:exported="false"
|
||||
android:process=":background" />
|
||||
android:process=":background"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="explanation_for_special_use"/>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name=".FilesProvider"
|
||||
|
@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.github.kr328.clash.common.compat.getColorCompat
|
||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
||||
import com.github.kr328.clash.common.compat.startForegroundCompat
|
||||
import com.github.kr328.clash.common.constants.Components
|
||||
import com.github.kr328.clash.common.constants.Intents
|
||||
import com.github.kr328.clash.common.id.UndefinedIds
|
||||
@ -123,7 +124,7 @@ class ProfileWorker : BaseService() {
|
||||
.setOnlyAlertOnce(true)
|
||||
.build()
|
||||
|
||||
startForeground(R.id.nf_profile_worker, notification)
|
||||
startForegroundCompat(R.id.nf_profile_worker, notification)
|
||||
}
|
||||
|
||||
private suspend inline fun processing(name: String, block: () -> Unit) {
|
||||
|
@ -11,10 +11,11 @@ import java.util.concurrent.TimeUnit
|
||||
|
||||
class AppListCacheModule(service: Service) : Module<Unit>(service) {
|
||||
private fun PackageInfo.uniqueUidName(): String =
|
||||
if (sharedUserId != null && sharedUserId.isNotBlank()) sharedUserId else packageName
|
||||
if (sharedUserId?.isNotBlank() == true) sharedUserId!! else packageName
|
||||
|
||||
private fun reload() {
|
||||
val packages = service.packageManager.getInstalledPackages(0)
|
||||
.filter { it.applicationInfo != null }
|
||||
.groupBy { it.uniqueUidName() }
|
||||
.map { (_, v) ->
|
||||
val info = v[0]
|
||||
@ -23,9 +24,9 @@ class AppListCacheModule(service: Service) : Module<Unit>(service) {
|
||||
// Force use package name if only one app in a single sharedUid group
|
||||
// Example: firefox
|
||||
|
||||
info.applicationInfo.uid to info.packageName
|
||||
info.applicationInfo!!.uid to info.packageName
|
||||
} else {
|
||||
info.applicationInfo.uid to info.uniqueUidName()
|
||||
info.applicationInfo!!.uid to info.uniqueUidName()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.github.kr328.clash.common.compat.registerReceiverCompat
|
||||
import com.github.kr328.clash.common.constants.Permissions
|
||||
import com.github.kr328.clash.common.log.Log
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
@ -44,9 +45,9 @@ abstract class Module<E>(val service: Service) {
|
||||
}
|
||||
|
||||
if (requireSelf) {
|
||||
service.registerReceiver(receiver, filter, Permissions.RECEIVE_SELF_BROADCASTS, null)
|
||||
service.registerReceiverCompat(receiver, filter, Permissions.RECEIVE_SELF_BROADCASTS, null)
|
||||
} else {
|
||||
service.registerReceiver(receiver, filter)
|
||||
service.registerReceiverCompat(receiver, filter)
|
||||
}
|
||||
|
||||
receivers.add(receiver)
|
||||
|
@ -8,6 +8,7 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.github.kr328.clash.common.compat.getColorCompat
|
||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
||||
import com.github.kr328.clash.common.compat.startForegroundCompat
|
||||
import com.github.kr328.clash.common.constants.Components
|
||||
import com.github.kr328.clash.common.constants.Intents
|
||||
import com.github.kr328.clash.service.R
|
||||
@ -47,7 +48,7 @@ class StaticNotificationModule(service: Service) : Module<Unit>(service) {
|
||||
.setContentText(service.getText(R.string.running))
|
||||
.build()
|
||||
|
||||
service.startForeground(R.id.nf_clash_status, notification)
|
||||
service.startForegroundCompat(R.id.nf_clash_status, notification)
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +75,7 @@ class StaticNotificationModule(service: Service) : Module<Unit>(service) {
|
||||
.setContentTitle(service.getText(R.string.loading))
|
||||
.build()
|
||||
|
||||
service.startForeground(R.id.nf_clash_status, notification)
|
||||
service.startForegroundCompat(R.id.nf_clash_status, notification)
|
||||
}
|
||||
}
|
||||
}
|
@ -14,49 +14,3 @@ pluginManagement {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
create("libs") {
|
||||
val agp = "7.2.1"
|
||||
val kotlin = "1.7.0"
|
||||
val ksp = "$kotlin-1.0.6"
|
||||
val golang = "1.0.4"
|
||||
val coroutine = "1.7.3"
|
||||
val coreKtx = "1.8.0"
|
||||
val activity = "1.5.0"
|
||||
val fragment = "1.5.0"
|
||||
val appcompat = "1.4.2"
|
||||
val coordinator = "1.2.0"
|
||||
val recyclerview = "1.2.1"
|
||||
val viewpager = "1.0.0"
|
||||
val material = "1.6.1"
|
||||
val serialization = "1.3.3"
|
||||
val kaidl = "1.15"
|
||||
val room = "2.4.2"
|
||||
val multiprocess = "1.0.0"
|
||||
|
||||
library("build-android", "com.android.tools.build:gradle:$agp")
|
||||
library("build-kotlin-common", "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin")
|
||||
library("build-kotlin-serialization", "org.jetbrains.kotlin:kotlin-serialization:$kotlin")
|
||||
library("build-ksp", "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp")
|
||||
library("build-golang", "com.github.kr328.golang:gradle-plugin:$golang")
|
||||
library("kotlin-coroutine", "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine")
|
||||
library("kotlin-serialization-json", "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization")
|
||||
library("androidx-core", "androidx.core:core-ktx:$coreKtx")
|
||||
library("androidx-activity", "androidx.activity:activity:$activity")
|
||||
library("androidx-fragment", "androidx.fragment:fragment:$fragment")
|
||||
library("androidx-appcompat", "androidx.appcompat:appcompat:$appcompat")
|
||||
library("androidx-coordinator", "androidx.coordinatorlayout:coordinatorlayout:$coordinator")
|
||||
library("androidx-recyclerview", "androidx.recyclerview:recyclerview:$recyclerview")
|
||||
library("androidx-viewpager", "androidx.viewpager2:viewpager2:$viewpager")
|
||||
library("androidx-room-compiler", "androidx.room:room-compiler:$room")
|
||||
library("androidx-room-runtime", "androidx.room:room-runtime:$room")
|
||||
library("androidx-room-ktx", "androidx.room:room-ktx:$room")
|
||||
library("google-material", "com.google.android.material:material:$material")
|
||||
library("kaidl-compiler", "com.github.kr328.kaidl:kaidl:$kaidl")
|
||||
library("kaidl-runtime", "com.github.kr328.kaidl:kaidl-runtime:$kaidl")
|
||||
library("rikkax-multiprocess", "dev.rikka.rikkax.preference:multiprocess:$multiprocess")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user