mirror of
https://github.com/MetaCubeX/ClashMetaForAndroid.git
synced 2025-02-22 01:33:16 +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
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 21
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
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
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 21
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
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
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 21
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
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
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "temurin"
|
||||||
java-version: 17
|
java-version: 21
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
package="com.github.kr328.clash">
|
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.software.leanback"
|
android:name="android.software.leanback"
|
||||||
@ -16,6 +15,8 @@
|
|||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="QueryAllPackagesPermission" />
|
tools:ignore="QueryAllPackagesPermission" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
@ -172,7 +173,11 @@
|
|||||||
<service
|
<service
|
||||||
android:name=".LogcatService"
|
android:name=".LogcatService"
|
||||||
android:exported="false"
|
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
|
<service
|
||||||
android:name=".TileService"
|
android:name=".TileService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -120,6 +120,9 @@ class AccessControlActivity : BaseActivity<AccessControlDesign>() {
|
|||||||
.filter {
|
.filter {
|
||||||
it.packageName == "android" || it.requestedPermissions?.contains(INTERNET) == true
|
it.packageName == "android" || it.requestedPermissions?.contains(INTERNET) == true
|
||||||
}
|
}
|
||||||
|
.filter {
|
||||||
|
it.applicationInfo != null
|
||||||
|
}
|
||||||
.filter {
|
.filter {
|
||||||
systemApp || !it.isSystemApp
|
systemApp || !it.isSystemApp
|
||||||
}
|
}
|
||||||
@ -132,6 +135,6 @@ class AccessControlActivity : BaseActivity<AccessControlDesign>() {
|
|||||||
|
|
||||||
private val PackageInfo.isSystemApp: Boolean
|
private val PackageInfo.isSystemApp: Boolean
|
||||||
get() {
|
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 java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
abstract class BaseActivity<D : Design<*>> : AppCompatActivity(),
|
abstract class BaseActivity<D : Design<*>> : AppCompatActivity(),
|
||||||
CoroutineScope by MainScope(),
|
CoroutineScope by MainScope(),
|
||||||
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -28,6 +28,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import java.io.OutputStreamWriter
|
import java.io.OutputStreamWriter
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class LogcatActivity : BaseActivity<LogcatDesign>() {
|
class LogcatActivity : BaseActivity<LogcatDesign>() {
|
||||||
private var conn: ServiceConnection? = null
|
private var conn: ServiceConnection? = null
|
||||||
|
@ -14,6 +14,7 @@ import androidx.core.app.NotificationCompat
|
|||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import com.github.kr328.clash.common.compat.getColorCompat
|
import com.github.kr328.clash.common.compat.getColorCompat
|
||||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
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.log.Log
|
||||||
import com.github.kr328.clash.common.util.intent
|
import com.github.kr328.clash.common.util.intent
|
||||||
import com.github.kr328.clash.core.model.LogMessage
|
import com.github.kr328.clash.core.model.LogMessage
|
||||||
@ -130,17 +131,17 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De
|
|||||||
NotificationChannelCompat.Builder(
|
NotificationChannelCompat.Builder(
|
||||||
CHANNEL_ID,
|
CHANNEL_ID,
|
||||||
NotificationManagerCompat.IMPORTANCE_DEFAULT
|
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() {
|
private fun showNotification() {
|
||||||
val notification = NotificationCompat
|
val notification = NotificationCompat
|
||||||
.Builder(this, CHANNEL_ID)
|
.Builder(this, CHANNEL_ID)
|
||||||
.setSmallIcon(R.drawable.ic_logo_service)
|
.setSmallIcon(com.github.kr328.clash.service.R.drawable.ic_logo_service)
|
||||||
.setColor(getColorCompat(R.color.color_clash_light))
|
.setColor(getColorCompat(com.github.kr328.clash.design.R.color.color_clash_light))
|
||||||
.setContentTitle(getString(R.string.clash_logcat))
|
.setContentTitle(getString(com.github.kr328.clash.design.R.string.clash_logcat))
|
||||||
.setContentText(getString(R.string.running))
|
.setContentText(getString(com.github.kr328.clash.design.R.string.running))
|
||||||
.setContentIntent(
|
.setContentIntent(
|
||||||
PendingIntent.getActivity(
|
PendingIntent.getActivity(
|
||||||
this,
|
this,
|
||||||
@ -152,7 +153,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De
|
|||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
startForeground(R.id.nf_logcat_status, notification)
|
startForegroundCompat(R.id.nf_logcat_status, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
package com.github.kr328.clash
|
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
|
||||||
|
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.intent
|
||||||
import com.github.kr328.clash.common.util.ticker
|
import com.github.kr328.clash.common.util.ticker
|
||||||
import com.github.kr328.clash.design.MainDesign
|
import com.github.kr328.clash.design.MainDesign
|
||||||
@ -15,6 +22,7 @@ import kotlinx.coroutines.isActive
|
|||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class MainActivity : BaseActivity<MainDesign>() {
|
class MainActivity : BaseActivity<MainDesign>() {
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
@ -129,4 +137,20 @@ class MainActivity : BaseActivity<MainDesign>() {
|
|||||||
packageManager.getPackageInfo(packageName, 0).versionName + "\n" + Bridge.nativeCoreVersion().replace("_", "-")
|
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 kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
|
|
||||||
class MetaFeatureSettingsActivity : BaseActivity<MetaFeatureSettingsDesign>() {
|
class MetaFeatureSettingsActivity : BaseActivity<MetaFeatureSettingsDesign>() {
|
||||||
|
@ -18,6 +18,7 @@ import kotlinx.coroutines.isActive
|
|||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class NewProfileActivity : BaseActivity<NewProfileDesign>() {
|
class NewProfileActivity : BaseActivity<NewProfileDesign>() {
|
||||||
private val self: NewProfileActivity
|
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.common.util.ticker
|
||||||
import com.github.kr328.clash.design.ProfilesDesign
|
import com.github.kr328.clash.design.ProfilesDesign
|
||||||
import com.github.kr328.clash.design.ui.ToastDuration
|
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.service.model.Profile
|
||||||
import com.github.kr328.clash.util.withProfile
|
import com.github.kr328.clash.util.withProfile
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -19,6 +18,7 @@ import kotlinx.coroutines.selects.select
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class ProfilesActivity : BaseActivity<ProfilesDesign>() {
|
class ProfilesActivity : BaseActivity<ProfilesDesign>() {
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
|
@ -12,9 +12,11 @@ import kotlinx.coroutines.coroutineScope
|
|||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
||||||
private var canceled: Boolean = false
|
private var canceled: Boolean = false
|
||||||
|
private lateinit var original: Profile
|
||||||
|
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
@ -22,7 +24,7 @@ class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
|||||||
val uuid = intent.uuid ?: return finish()
|
val uuid = intent.uuid ?: return finish()
|
||||||
val design = PropertiesDesign(this)
|
val design = PropertiesDesign(this)
|
||||||
|
|
||||||
val original = withProfile { queryByUUID(uuid) } ?: return finish()
|
original = withProfile { queryByUUID(uuid) } ?: return finish()
|
||||||
|
|
||||||
design.profile = original
|
design.profile = original
|
||||||
|
|
||||||
@ -71,7 +73,7 @@ class PropertiesActivity : BaseActivity<PropertiesDesign>() {
|
|||||||
design?.apply {
|
design?.apply {
|
||||||
launch {
|
launch {
|
||||||
if (!progressing) {
|
if (!progressing) {
|
||||||
if (requestExitWithoutSaving())
|
if (original == profile || requestExitWithoutSaving())
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.isActive
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import com.github.kr328.clash.design.R
|
||||||
|
|
||||||
class ProvidersActivity : BaseActivity<ProvidersDesign>() {
|
class ProvidersActivity : BaseActivity<ProvidersDesign>() {
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
|
@ -9,11 +9,13 @@ import android.os.Build
|
|||||||
import android.service.quicksettings.Tile
|
import android.service.quicksettings.Tile
|
||||||
import android.service.quicksettings.TileService
|
import android.service.quicksettings.TileService
|
||||||
import androidx.annotation.RequiresApi
|
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.Intents
|
||||||
import com.github.kr328.clash.common.constants.Permissions
|
import com.github.kr328.clash.common.constants.Permissions
|
||||||
import com.github.kr328.clash.remote.StatusClient
|
import com.github.kr328.clash.remote.StatusClient
|
||||||
import com.github.kr328.clash.util.startClashService
|
import com.github.kr328.clash.util.startClashService
|
||||||
import com.github.kr328.clash.util.stopClashService
|
import com.github.kr328.clash.util.stopClashService
|
||||||
|
import com.github.kr328.clash.service.R
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
class TileService : TileService() {
|
class TileService : TileService() {
|
||||||
@ -36,7 +38,7 @@ class TileService : TileService() {
|
|||||||
override fun onStartListening() {
|
override fun onStartListening() {
|
||||||
super.onStartListening()
|
super.onStartListening()
|
||||||
|
|
||||||
registerReceiver(
|
registerReceiverCompat(
|
||||||
receiver,
|
receiver,
|
||||||
IntentFilter().apply {
|
IntentFilter().apply {
|
||||||
addAction(Intents.ACTION_CLASH_STARTED)
|
addAction(Intents.ACTION_CLASH_STARTED)
|
||||||
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
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.constants.Intents
|
||||||
import com.github.kr328.clash.common.log.Log
|
import com.github.kr328.clash.common.log.Log
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -88,7 +89,7 @@ class Broadcasts(private val context: Application) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.registerReceiver(broadcastReceiver, IntentFilter().apply {
|
context.registerReceiverCompat(broadcastReceiver, IntentFilter().apply {
|
||||||
addAction(Intents.ACTION_SERVICE_RECREATED)
|
addAction(Intents.ACTION_SERVICE_RECREATED)
|
||||||
addAction(Intents.ACTION_CLASH_STARTED)
|
addAction(Intents.ACTION_CLASH_STARTED)
|
||||||
addAction(Intents.ACTION_CLASH_STOPPED)
|
addAction(Intents.ACTION_CLASH_STOPPED)
|
||||||
|
@ -7,16 +7,12 @@ import kotlinx.coroutines.NonCancellable
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class ActivityResultLifecycle : LifecycleOwner {
|
class ActivityResultLifecycle : LifecycleOwner {
|
||||||
private val lifecycle = LifecycleRegistry(this)
|
override val lifecycle = LifecycleRegistry(this)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lifecycle.currentState = Lifecycle.State.INITIALIZED
|
lifecycle.currentState = Lifecycle.State.INITIALIZED
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLifecycle(): Lifecycle {
|
|
||||||
return lifecycle
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <T> use(block: suspend (lifecycle: ActivityResultLifecycle, start: () -> Unit) -> T): T {
|
suspend fun <T> use(block: suspend (lifecycle: ActivityResultLifecycle, start: () -> Unit) -> T): T {
|
||||||
return try {
|
return try {
|
||||||
markCreated()
|
markCreated()
|
||||||
|
@ -32,13 +32,19 @@ subprojects {
|
|||||||
apply(plugin = if (isApp) "com.android.application" else "com.android.library")
|
apply(plugin = if (isApp) "com.android.application" else "com.android.library")
|
||||||
|
|
||||||
extensions.configure<BaseExtension> {
|
extensions.configure<BaseExtension> {
|
||||||
|
buildFeatures.buildConfig = true
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
if (isApp) {
|
if (isApp) {
|
||||||
applicationId = "com.github.metacubex.clash"
|
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
|
minSdk = 21
|
||||||
targetSdk = 31
|
targetSdk = 35
|
||||||
|
|
||||||
versionName = "2.11.5"
|
versionName = "2.11.5"
|
||||||
versionCode = 211005
|
versionCode = 211005
|
||||||
@ -59,7 +65,7 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ndkVersion = "23.0.7599858"
|
ndkVersion = "27.2.12479018"
|
||||||
|
|
||||||
compileSdkVersion(defaultConfig.targetSdk!!)
|
compileSdkVersion(defaultConfig.targetSdk!!)
|
||||||
|
|
||||||
@ -134,7 +140,7 @@ subprojects {
|
|||||||
named("release") {
|
named("release") {
|
||||||
isMinifyEnabled = isApp
|
isMinifyEnabled = isApp
|
||||||
isShrinkResources = isApp
|
isShrinkResources = isApp
|
||||||
signingConfig = signingConfigs.findByName("release")
|
signingConfig = signingConfigs.findByName("release") ?: signingConfigs["debug"]
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"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"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="com.github.kr328.clash.common">
|
|
||||||
|
|
||||||
<permission
|
<permission
|
||||||
android:name="${applicationId}.permission.RECEIVE_BROADCASTS"
|
android:name="${applicationId}.permission.RECEIVE_BROADCASTS"
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
package com.github.kr328.clash.common.compat
|
package com.github.kr328.clash.common.compat
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.IntentFilter
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -15,3 +20,18 @@ fun Context.getColorCompat(@ColorRes id: Int): Int {
|
|||||||
fun Context.getDrawableCompat(@DrawableRes id: Int): Drawable? {
|
fun Context.getDrawableCompat(@DrawableRes id: Int): Drawable? {
|
||||||
return ContextCompat.getDrawable(this, id)
|
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
|
package com.github.kr328.clash.common.compat
|
||||||
|
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ServiceInfo
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
|
||||||
fun Context.startForegroundServiceCompat(intent: Intent) {
|
fun Context.startForegroundServiceCompat(intent: Intent) {
|
||||||
@ -11,3 +14,11 @@ fun Context.startForegroundServiceCompat(intent: Intent) {
|
|||||||
startService(intent)
|
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.GolangBuildTask
|
||||||
import com.github.kr328.golang.GolangPlugin
|
import com.github.kr328.golang.GolangPlugin
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.net.URL
|
|
||||||
import java.time.Duration
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("android")
|
kotlin("android")
|
||||||
@ -63,3 +61,14 @@ afterEvaluate {
|
|||||||
it.inputs.dir(golangSource)
|
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"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
package="com.github.kr328.clash.core">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -61,7 +61,7 @@ object Bridge {
|
|||||||
.detachFd()
|
.detachFd()
|
||||||
|
|
||||||
val home = ctx.filesDir.resolve("clash").apply { mkdirs() }.absolutePath
|
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
|
val sdkVersion = Build.VERSION.SDK_INT
|
||||||
|
|
||||||
Log.d("Home = $home")
|
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 {
|
init {
|
||||||
binding.self = this
|
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)
|
binding.colorClashStopped = context.resolveThemedColor(R.attr.colorClashStopped)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ class ProxyDesign(
|
|||||||
binding.urlTestFloatView.visibility = View.GONE
|
binding.urlTestFloatView.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
binding.urlTestFloatView.supportImageTintList = ColorStateList.valueOf(
|
binding.urlTestFloatView.supportImageTintList = ColorStateList.valueOf(
|
||||||
context.resolveThemedColor(R.attr.colorOnPrimary)
|
context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.pagesView.apply {
|
binding.pagesView.apply {
|
||||||
|
@ -15,9 +15,9 @@ class PopupListAdapter(
|
|||||||
private val texts: List<CharSequence>,
|
private val texts: List<CharSequence>,
|
||||||
private val selected: Int,
|
private val selected: Int,
|
||||||
) : BaseAdapter() {
|
) : BaseAdapter() {
|
||||||
private val colorPrimary = context.resolveThemedColor(R.attr.colorPrimary)
|
private val colorPrimary = context.resolveThemedColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
private val colorOnPrimary = context.resolveThemedColor(R.attr.colorOnPrimary)
|
private val colorOnPrimary = context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||||
private val colorControlNormal = context.resolveThemedColor(R.attr.colorControlNormal)
|
private val colorControlNormal = context.resolveThemedColor(com.google.android.material.R.attr.colorControlNormal)
|
||||||
|
|
||||||
override fun getCount(): Int {
|
override fun getCount(): Int {
|
||||||
return texts.size
|
return texts.size
|
||||||
|
@ -8,15 +8,15 @@ import com.github.kr328.clash.design.util.resolveThemedColor
|
|||||||
import com.github.kr328.clash.design.util.resolveThemedResourceId
|
import com.github.kr328.clash.design.util.resolveThemedResourceId
|
||||||
|
|
||||||
class ProxyViewConfig(val context: Context, var proxyLine: Int) {
|
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 =
|
val clickableBackground =
|
||||||
context.resolveThemedResourceId(android.R.attr.selectableItemBackground)
|
context.resolveThemedResourceId(android.R.attr.selectableItemBackground)
|
||||||
|
|
||||||
val selectedControl = context.resolveThemedColor(R.attr.colorOnPrimary)
|
val selectedControl = context.resolveThemedColor(com.google.android.material.R.attr.colorOnPrimary)
|
||||||
val selectedBackground = context.resolveThemedColor(R.attr.colorPrimary)
|
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
|
val unselectedBackground: Int
|
||||||
get() = if (proxyLine==1) Color.TRANSPARENT else colorSurface
|
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 {
|
fun PackageInfo.toAppInfo(pm: PackageManager): AppInfo {
|
||||||
return AppInfo(
|
return AppInfo(
|
||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
icon = applicationInfo.loadIcon(pm).foreground(),
|
icon = applicationInfo!!.loadIcon(pm).foreground(),
|
||||||
label = applicationInfo.loadLabel(pm).toString(),
|
label = applicationInfo!!.loadLabel(pm).toString(),
|
||||||
installTime = firstInstallTime,
|
installTime = firstInstallTime,
|
||||||
updateDate = lastUpdateTime,
|
updateDate = lastUpdateTime,
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,7 @@ fun View.setOnInsertsChangedListener(adaptLandscape: Boolean = true, listener: (
|
|||||||
|
|
||||||
listener(if (adaptLandscape) rInsets.landscape(v.context) else rInsets)
|
listener(if (adaptLandscape) rInsets.landscape(v.context) else rInsets)
|
||||||
|
|
||||||
compat.toWindowInsets()
|
compat.toWindowInsets()!!
|
||||||
}
|
}
|
||||||
|
|
||||||
requestApplyInsets()
|
requestApplyInsets()
|
||||||
|
@ -14,12 +14,4 @@ class AppRecyclerView @JvmOverloads constructor(
|
|||||||
init {
|
init {
|
||||||
isFocusable = false
|
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)
|
minimumHeight = context.getPixels(R.dimen.large_action_card_min_height)
|
||||||
radius = context.getPixels(R.dimen.large_action_card_radius).toFloat()
|
radius = context.getPixels(R.dimen.large_action_card_radius).toFloat()
|
||||||
elevation = context.getPixels(R.dimen.large_action_card_elevation).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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="geofile_import_failed">Nhập thất bại</string>
|
<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_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</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="press_to_import">Chạm để nhập...</string>
|
||||||
<string name="meta_features">Tính năng của Clash Meta</string>
|
<string name="meta_features">Tính năng của Clash Meta</string>
|
||||||
<string name="allow_ipv6">Cho phép Ipv6</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
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip
|
|
||||||
networkTimeout=10000
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
|
@ -1,2 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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.androidx.room.ktx)
|
||||||
implementation(libs.kaidl.runtime)
|
implementation(libs.kaidl.runtime)
|
||||||
implementation(libs.rikkax.multiprocess)
|
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
|
// define any required OkHttp artifacts without version
|
||||||
implementation("com.squareup.okhttp3:okhttp")
|
implementation("com.squareup.okhttp3:okhttp")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
package="com.github.kr328.clash.service">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
@ -9,19 +8,27 @@
|
|||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="QueryAllPackagesPermission" />
|
tools:ignore="QueryAllPackagesPermission" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<service
|
<service
|
||||||
android:name=".ClashService"
|
android:name=".ClashService"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/clash_meta_for_android"
|
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
|
<service
|
||||||
android:name=".TunService"
|
android:name=".TunService"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/clash_meta_for_android"
|
android:label="@string/clash_meta_for_android"
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
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>
|
<intent-filter>
|
||||||
<action android:name="android.net.VpnService" />
|
<action android:name="android.net.VpnService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
@ -33,7 +40,11 @@
|
|||||||
<service
|
<service
|
||||||
android:name=".ProfileWorker"
|
android:name=".ProfileWorker"
|
||||||
android:exported="false"
|
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
|
<provider
|
||||||
android:name=".FilesProvider"
|
android:name=".FilesProvider"
|
||||||
|
@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat
|
|||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import com.github.kr328.clash.common.compat.getColorCompat
|
import com.github.kr328.clash.common.compat.getColorCompat
|
||||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
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.Components
|
||||||
import com.github.kr328.clash.common.constants.Intents
|
import com.github.kr328.clash.common.constants.Intents
|
||||||
import com.github.kr328.clash.common.id.UndefinedIds
|
import com.github.kr328.clash.common.id.UndefinedIds
|
||||||
@ -123,7 +124,7 @@ class ProfileWorker : BaseService() {
|
|||||||
.setOnlyAlertOnce(true)
|
.setOnlyAlertOnce(true)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
startForeground(R.id.nf_profile_worker, notification)
|
startForegroundCompat(R.id.nf_profile_worker, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend inline fun processing(name: String, block: () -> Unit) {
|
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) {
|
class AppListCacheModule(service: Service) : Module<Unit>(service) {
|
||||||
private fun PackageInfo.uniqueUidName(): String =
|
private fun PackageInfo.uniqueUidName(): String =
|
||||||
if (sharedUserId != null && sharedUserId.isNotBlank()) sharedUserId else packageName
|
if (sharedUserId?.isNotBlank() == true) sharedUserId!! else packageName
|
||||||
|
|
||||||
private fun reload() {
|
private fun reload() {
|
||||||
val packages = service.packageManager.getInstalledPackages(0)
|
val packages = service.packageManager.getInstalledPackages(0)
|
||||||
|
.filter { it.applicationInfo != null }
|
||||||
.groupBy { it.uniqueUidName() }
|
.groupBy { it.uniqueUidName() }
|
||||||
.map { (_, v) ->
|
.map { (_, v) ->
|
||||||
val info = v[0]
|
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
|
// Force use package name if only one app in a single sharedUid group
|
||||||
// Example: firefox
|
// Example: firefox
|
||||||
|
|
||||||
info.applicationInfo.uid to info.packageName
|
info.applicationInfo!!.uid to info.packageName
|
||||||
} else {
|
} 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.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
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.constants.Permissions
|
||||||
import com.github.kr328.clash.common.log.Log
|
import com.github.kr328.clash.common.log.Log
|
||||||
import kotlinx.coroutines.NonCancellable
|
import kotlinx.coroutines.NonCancellable
|
||||||
@ -44,9 +45,9 @@ abstract class Module<E>(val service: Service) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (requireSelf) {
|
if (requireSelf) {
|
||||||
service.registerReceiver(receiver, filter, Permissions.RECEIVE_SELF_BROADCASTS, null)
|
service.registerReceiverCompat(receiver, filter, Permissions.RECEIVE_SELF_BROADCASTS, null)
|
||||||
} else {
|
} else {
|
||||||
service.registerReceiver(receiver, filter)
|
service.registerReceiverCompat(receiver, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
receivers.add(receiver)
|
receivers.add(receiver)
|
||||||
|
@ -8,6 +8,7 @@ import androidx.core.app.NotificationCompat
|
|||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import com.github.kr328.clash.common.compat.getColorCompat
|
import com.github.kr328.clash.common.compat.getColorCompat
|
||||||
import com.github.kr328.clash.common.compat.pendingIntentFlags
|
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.Components
|
||||||
import com.github.kr328.clash.common.constants.Intents
|
import com.github.kr328.clash.common.constants.Intents
|
||||||
import com.github.kr328.clash.service.R
|
import com.github.kr328.clash.service.R
|
||||||
@ -47,7 +48,7 @@ class StaticNotificationModule(service: Service) : Module<Unit>(service) {
|
|||||||
.setContentText(service.getText(R.string.running))
|
.setContentText(service.getText(R.string.running))
|
||||||
.build()
|
.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))
|
.setContentTitle(service.getText(R.string.loading))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
service.startForeground(R.id.nf_clash_status, notification)
|
service.startForegroundCompat(R.id.nf_clash_status, notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,49 +14,3 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
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