diff --git a/app/src/main/java/com/github/kr328/clash/AppSettingsActivity.kt b/app/src/main/java/com/github/kr328/clash/AppSettingsActivity.kt index 7348642d..2b4ed2cd 100644 --- a/app/src/main/java/com/github/kr328/clash/AppSettingsActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/AppSettingsActivity.kt @@ -2,7 +2,6 @@ package com.github.kr328.clash import android.content.ComponentName import android.content.pm.PackageManager -import androidx.core.content.pm.ShortcutManagerCompat import com.github.kr328.clash.common.util.componentName import com.github.kr328.clash.design.AppSettingsDesign import com.github.kr328.clash.design.model.Behavior @@ -75,9 +74,5 @@ class AppSettingsActivity : BaseActivity(), Behavior { newState, PackageManager.DONT_KILL_APP ) - if (hide) { - // Prevent launcher activity not found. - ShortcutManagerCompat.removeAllDynamicShortcuts(this) - } } } diff --git a/app/src/main/java/com/github/kr328/clash/MainActivity.kt b/app/src/main/java/com/github/kr328/clash/MainActivity.kt index 62f2a1aa..5c616528 100644 --- a/app/src/main/java/com/github/kr328/clash/MainActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/MainActivity.kt @@ -1,5 +1,6 @@ package com.github.kr328.clash +import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.Bundle @@ -8,6 +9,10 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts.RequestPermission import androidx.core.app.ActivityCompat 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.ticker import com.github.kr328.clash.design.MainDesign @@ -22,7 +27,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 +import com.github.kr328.clash.design.R as DesignR class MainActivity : BaseActivity() { override suspend fun main() { @@ -111,8 +116,8 @@ class MainActivity : BaseActivity() { val active = withProfile { queryActive() } if (active == null || !active.imported) { - showToast(R.string.no_profile_selected, ToastDuration.Long) { - setAction(R.string.profiles) { + showToast(DesignR.string.no_profile_selected, ToastDuration.Long) { + setAction(DesignR.string.profiles) { startActivity(ProfilesActivity::class.intent) } } @@ -133,7 +138,7 @@ class MainActivity : BaseActivity() { startClashService() } } 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() { 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)) } } diff --git a/app/src/main/java/com/github/kr328/clash/MainApplication.kt b/app/src/main/java/com/github/kr328/clash/MainApplication.kt index 60c890ef..93f9b74b 100644 --- a/app/src/main/java/com/github/kr328/clash/MainApplication.kt +++ b/app/src/main/java/com/github/kr328/clash/MainApplication.kt @@ -2,26 +2,17 @@ package com.github.kr328.clash import android.app.Application 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.compat.currentProcessName -import com.github.kr328.clash.common.constants.Intents 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.service.util.sendServiceRecreated import com.github.kr328.clash.util.clashDir import java.io.File import java.io.FileOutputStream -import com.github.kr328.clash.design.R as DesignR - @Suppress("unused") class MainApplication : Application() { - private val uiStore by lazy(LazyThreadSafetyMode.NONE) { UiStore(this) } override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) @@ -39,63 +30,11 @@ class MainApplication : Application() { if (processName == packageName) { Remote.launch() - setupShortcuts() } else { 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() { clashDir.mkdirs()