mirror of
https://github.com/MetaCubeX/ClashMetaForAndroid.git
synced 2026-05-09 18:11:26 +08:00
@@ -2,7 +2,6 @@ package com.github.kr328.clash
|
|||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
|
||||||
import com.github.kr328.clash.common.util.componentName
|
import com.github.kr328.clash.common.util.componentName
|
||||||
import com.github.kr328.clash.design.AppSettingsDesign
|
import com.github.kr328.clash.design.AppSettingsDesign
|
||||||
import com.github.kr328.clash.design.model.Behavior
|
import com.github.kr328.clash.design.model.Behavior
|
||||||
@@ -75,9 +74,5 @@ class AppSettingsActivity : BaseActivity<AppSettingsDesign>(), Behavior {
|
|||||||
newState,
|
newState,
|
||||||
PackageManager.DONT_KILL_APP
|
PackageManager.DONT_KILL_APP
|
||||||
)
|
)
|
||||||
if (hide) {
|
|
||||||
// Prevent launcher activity not found.
|
|
||||||
ShortcutManagerCompat.removeAllDynamicShortcuts(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.github.kr328.clash
|
package com.github.kr328.clash
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -8,6 +9,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.pm.ShortcutInfoCompat
|
||||||
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
|
import com.github.kr328.clash.common.constants.Intents
|
||||||
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
|
||||||
@@ -22,7 +27,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
|
import com.github.kr328.clash.design.R as DesignR
|
||||||
|
|
||||||
class MainActivity : BaseActivity<MainDesign>() {
|
class MainActivity : BaseActivity<MainDesign>() {
|
||||||
override suspend fun main() {
|
override suspend fun main() {
|
||||||
@@ -111,8 +116,8 @@ class MainActivity : BaseActivity<MainDesign>() {
|
|||||||
val active = withProfile { queryActive() }
|
val active = withProfile { queryActive() }
|
||||||
|
|
||||||
if (active == null || !active.imported) {
|
if (active == null || !active.imported) {
|
||||||
showToast(R.string.no_profile_selected, ToastDuration.Long) {
|
showToast(DesignR.string.no_profile_selected, ToastDuration.Long) {
|
||||||
setAction(R.string.profiles) {
|
setAction(DesignR.string.profiles) {
|
||||||
startActivity(ProfilesActivity::class.intent)
|
startActivity(ProfilesActivity::class.intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +138,7 @@ class MainActivity : BaseActivity<MainDesign>() {
|
|||||||
startClashService()
|
startClashService()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
design?.showToast(R.string.unable_to_start_vpn, ToastDuration.Long)
|
design?.showToast(DesignR.string.unable_to_start_vpn, ToastDuration.Long)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,5 +162,54 @@ class MainActivity : BaseActivity<MainDesign>() {
|
|||||||
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
|
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setupShortcuts()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupShortcuts() {
|
||||||
|
// Skip dynamic shortcut setup when the app icon is hidden.
|
||||||
|
if (uiStore.hideAppIcon) return
|
||||||
|
|
||||||
|
val icon = IconCompat.createWithResource(this, R.mipmap.ic_launcher)
|
||||||
|
val flags = Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||||
|
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or
|
||||||
|
Intent.FLAG_ACTIVITY_NO_ANIMATION
|
||||||
|
|
||||||
|
val toggle = ShortcutInfoCompat.Builder(this, "toggle_clash")
|
||||||
|
.setShortLabel(getString(DesignR.string.shortcut_toggle_short))
|
||||||
|
.setLongLabel(getString(DesignR.string.shortcut_toggle_long))
|
||||||
|
.setIcon(icon)
|
||||||
|
.setIntent(
|
||||||
|
Intent(Intents.ACTION_TOGGLE_CLASH)
|
||||||
|
.setClassName(this, ExternalControlActivity::class.java.name)
|
||||||
|
.addFlags(flags)
|
||||||
|
)
|
||||||
|
.setRank(0)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val start = ShortcutInfoCompat.Builder(this, "start_clash")
|
||||||
|
.setShortLabel(getString(DesignR.string.shortcut_start_short))
|
||||||
|
.setLongLabel(getString(DesignR.string.shortcut_start_long))
|
||||||
|
.setIcon(icon)
|
||||||
|
.setIntent(
|
||||||
|
Intent(Intents.ACTION_START_CLASH)
|
||||||
|
.setClassName(this, ExternalControlActivity::class.java.name)
|
||||||
|
.addFlags(flags)
|
||||||
|
)
|
||||||
|
.setRank(1)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val stop = ShortcutInfoCompat.Builder(this, "stop_clash")
|
||||||
|
.setShortLabel(getString(DesignR.string.shortcut_stop_short))
|
||||||
|
.setLongLabel(getString(DesignR.string.shortcut_stop_long))
|
||||||
|
.setIcon(icon)
|
||||||
|
.setIntent(
|
||||||
|
Intent(Intents.ACTION_STOP_CLASH)
|
||||||
|
.setClassName(this, ExternalControlActivity::class.java.name)
|
||||||
|
.addFlags(flags)
|
||||||
|
)
|
||||||
|
.setRank(2)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
ShortcutManagerCompat.setDynamicShortcuts(this, listOf(toggle, start, stop))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,17 @@ package com.github.kr328.clash
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import androidx.core.content.pm.ShortcutInfoCompat
|
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import com.github.kr328.clash.common.Global
|
import com.github.kr328.clash.common.Global
|
||||||
import com.github.kr328.clash.common.compat.currentProcessName
|
import com.github.kr328.clash.common.compat.currentProcessName
|
||||||
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 com.github.kr328.clash.design.store.UiStore
|
|
||||||
import com.github.kr328.clash.remote.Remote
|
import com.github.kr328.clash.remote.Remote
|
||||||
import com.github.kr328.clash.service.util.sendServiceRecreated
|
import com.github.kr328.clash.service.util.sendServiceRecreated
|
||||||
import com.github.kr328.clash.util.clashDir
|
import com.github.kr328.clash.util.clashDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import com.github.kr328.clash.design.R as DesignR
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class MainApplication : Application() {
|
class MainApplication : Application() {
|
||||||
private val uiStore by lazy(LazyThreadSafetyMode.NONE) { UiStore(this) }
|
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context?) {
|
override fun attachBaseContext(base: Context?) {
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
@@ -39,63 +30,11 @@ class MainApplication : Application() {
|
|||||||
|
|
||||||
if (processName == packageName) {
|
if (processName == packageName) {
|
||||||
Remote.launch()
|
Remote.launch()
|
||||||
setupShortcuts()
|
|
||||||
} else {
|
} else {
|
||||||
sendServiceRecreated()
|
sendServiceRecreated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupShortcuts() {
|
|
||||||
if (uiStore.hideAppIcon) {
|
|
||||||
// Prevent launcher activity not found.
|
|
||||||
ShortcutManagerCompat.removeAllDynamicShortcuts(this)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val icon = IconCompat.createWithResource(this, R.mipmap.ic_launcher)
|
|
||||||
val flags = Intent.FLAG_ACTIVITY_NEW_TASK or
|
|
||||||
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or
|
|
||||||
Intent.FLAG_ACTIVITY_NO_ANIMATION
|
|
||||||
|
|
||||||
val toggle = ShortcutInfoCompat.Builder(this, "toggle_clash")
|
|
||||||
.setShortLabel(getString(DesignR.string.shortcut_toggle_short))
|
|
||||||
.setLongLabel(getString(DesignR.string.shortcut_toggle_long))
|
|
||||||
.setIcon(icon)
|
|
||||||
.setIntent(
|
|
||||||
Intent(Intents.ACTION_TOGGLE_CLASH)
|
|
||||||
.setClassName(this, ExternalControlActivity::class.java.name)
|
|
||||||
.addFlags(flags)
|
|
||||||
)
|
|
||||||
.setRank(0)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val start = ShortcutInfoCompat.Builder(this, "start_clash")
|
|
||||||
.setShortLabel(getString(DesignR.string.shortcut_start_short))
|
|
||||||
.setLongLabel(getString(DesignR.string.shortcut_start_long))
|
|
||||||
.setIcon(icon)
|
|
||||||
.setIntent(
|
|
||||||
Intent(Intents.ACTION_START_CLASH)
|
|
||||||
.setClassName(this, ExternalControlActivity::class.java.name)
|
|
||||||
.addFlags(flags)
|
|
||||||
)
|
|
||||||
.setRank(1)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val stop = ShortcutInfoCompat.Builder(this, "stop_clash")
|
|
||||||
.setShortLabel(getString(DesignR.string.shortcut_stop_short))
|
|
||||||
.setLongLabel(getString(DesignR.string.shortcut_stop_long))
|
|
||||||
.setIcon(icon)
|
|
||||||
.setIntent(
|
|
||||||
Intent(Intents.ACTION_STOP_CLASH)
|
|
||||||
.setClassName(this, ExternalControlActivity::class.java.name)
|
|
||||||
.addFlags(flags)
|
|
||||||
)
|
|
||||||
.setRank(2)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
ShortcutManagerCompat.setDynamicShortcuts(this, listOf(toggle, start, stop))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractGeoFiles() {
|
private fun extractGeoFiles() {
|
||||||
clashDir.mkdirs()
|
clashDir.mkdirs()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user