From e9c7ec1031edec09d4669a981ef896ebd8f78212 Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Mon, 11 Apr 2022 23:21:01 +0800 Subject: [PATCH 1/6] Fix adding shortcuts in Android 12.1+ --- .../island/shortcut/IslandAppShortcut.kt | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index 8198b2e44..cefc101d1 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -31,6 +31,7 @@ import android.util.Log import android.widget.Toast import android.widget.Toast.LENGTH_LONG import androidx.annotation.RequiresApi +import androidx.core.content.LocusIdCompat import androidx.core.content.getSystemService import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat @@ -76,14 +77,12 @@ object IslandAppShortcut { /** @return true if launcher supports shortcut pinning, false for failure, or null if legacy shortcut installation broadcast is sent. */ @OwnerUser @ProfileUser @JvmStatic fun requestPinAsUser(context: Context, app: ApplicationInfo, dynamic: Boolean) { - if (SDK_INT < O) return requestLegacyPin(context, app) + val shortcut = buildShortcutInfo(context, app, dynamic) - val sm: ShortcutManager = context.getSystemService() ?: return showToastForShortcutFailure(context) - val info = buildShortcutInfo(context, app, dynamic) - try { sm.addDynamicShortcuts(listOf(info)) } + try { ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) } catch (e: RuntimeException) { Log.e(TAG, "Error adding dynamic shortcut", e) } - try { sm.requestPinShortcut(info, null) } // FIXME: Deal with rate limit + try { ShortcutManagerCompat.requestPinShortcut(context, shortcut, null) } // FIXME: Deal with rate limit catch (e: RuntimeException) { showToastForShortcutFailure(context); analytics().report(e) } } @@ -124,10 +123,10 @@ object IslandAppShortcut { update(context, app, dynamic) } } - @OwnerUser @RequiresApi(O) private fun update(context: Context, app: ApplicationInfo, dynamic: Boolean) { + @OwnerUser private fun update(context: Context, app: ApplicationInfo, dynamic: Boolean) { Log.i(TAG, "Updating shortcut for ${app.packageName} in profile ${app.userId}") val shortcut = buildShortcutInfo(context, app, dynamic) - context.getSystemService()?.updateShortcuts(listOf(shortcut)) + ShortcutManagerCompat.updateShortcuts(context, listOf(shortcut)) } private fun buildLabel(context: Context, app: ApplicationInfo, dynamic: Boolean) @@ -142,16 +141,16 @@ object IslandAppShortcut { private fun getDynamicPrefix(context: Context, app: ApplicationInfo) = if (app.hidden) context.getString(R.string.default_launch_shortcut_prefix) else null - @RequiresApi(O) private fun buildShortcutInfo(context: Context, app: ApplicationInfo, dynamic: Boolean): ShortcutInfo { + private fun buildShortcutInfo(context: Context, app: ApplicationInfo, dynamic: Boolean): ShortcutInfoCompat { + val settings = IslandSettings(context) val pkg = app.packageName; val userId = app.userId; val isCrossProfile = isCrossProfile(userId) val shortcutId = getShortcutId(pkg, userId, isCrossProfile) val label = buildLabel(context, app, dynamic) val intent = buildShortcutIntent(context, pkg, userId) val drawable = getAppIconDrawable(context, context.getSystemService()!!, app) - val sm = context.getSystemService()!! - return ShortcutInfo.Builder(context, shortcutId).setIntent(intent).setShortLabel(label).apply { - setIcon(Icon.createWithAdaptiveBitmap(drawable.toBitmap(sm.iconMaxWidth, sm.iconMaxHeight))) - if (SDK_INT >= Q) setLocusId(LocusId(shortcutId)) + return ShortcutInfoCompat.Builder(context, shortcutId).setIntent(intent).setShortLabel(label).apply { + setIcon(IconCompat.createWithAdaptiveBitmap(drawable.toBitmap(ShortcutManagerCompat.getIconMaxWidth(context), ShortcutManagerCompat.getIconMaxHeight(context)))) + if (SDK_INT >= Q) setLocusId(LocusIdCompat(shortcutId)) }.build() } From 147181b6b67d74e8134592b4db68f01b29f96e0c Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Mon, 11 Apr 2022 23:28:17 +0800 Subject: [PATCH 2/6] Remove unused imports --- .../java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index cefc101d1..12b1223ae 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -8,7 +8,6 @@ import android.content.pm.ApplicationInfo import android.content.pm.LauncherApps import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES import android.content.pm.PackageManager.NameNotFoundException -import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager import android.content.res.Resources import android.graphics.Bitmap @@ -17,7 +16,6 @@ import android.graphics.Canvas import android.graphics.Color import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.Drawable -import android.graphics.drawable.Icon import android.net.Uri import android.os.Binder import android.os.Build.VERSION.SDK_INT From 77419245f0162b59a07faef57704348e5bd0b114 Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Mon, 11 Apr 2022 23:31:47 +0800 Subject: [PATCH 3/6] Remove unused variable --- .../main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index 12b1223ae..42f372f66 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -140,7 +140,6 @@ object IslandAppShortcut { = if (app.hidden) context.getString(R.string.default_launch_shortcut_prefix) else null private fun buildShortcutInfo(context: Context, app: ApplicationInfo, dynamic: Boolean): ShortcutInfoCompat { - val settings = IslandSettings(context) val pkg = app.packageName; val userId = app.userId; val isCrossProfile = isCrossProfile(userId) val shortcutId = getShortcutId(pkg, userId, isCrossProfile) val label = buildLabel(context, app, dynamic) From 861eb5ce7e44f8395b41b4aac2e59c67e4a239c4 Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Sat, 28 May 2022 11:05:09 +0800 Subject: [PATCH 4/6] Fix sdk version matching --- .../java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index 42f372f66..67a9d2b72 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -75,6 +75,8 @@ object IslandAppShortcut { /** @return true if launcher supports shortcut pinning, false for failure, or null if legacy shortcut installation broadcast is sent. */ @OwnerUser @ProfileUser @JvmStatic fun requestPinAsUser(context: Context, app: ApplicationInfo, dynamic: Boolean) { + if (SDK_INT < O) return requestLegacyPin(context, app) + val shortcut = buildShortcutInfo(context, app, dynamic) try { ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) } @@ -121,7 +123,7 @@ object IslandAppShortcut { update(context, app, dynamic) } } - @OwnerUser private fun update(context: Context, app: ApplicationInfo, dynamic: Boolean) { + @OwnerUser @RequiresApi(O) private fun update(context: Context, app: ApplicationInfo, dynamic: Boolean) { Log.i(TAG, "Updating shortcut for ${app.packageName} in profile ${app.userId}") val shortcut = buildShortcutInfo(context, app, dynamic) ShortcutManagerCompat.updateShortcuts(context, listOf(shortcut)) @@ -139,7 +141,7 @@ object IslandAppShortcut { private fun getDynamicPrefix(context: Context, app: ApplicationInfo) = if (app.hidden) context.getString(R.string.default_launch_shortcut_prefix) else null - private fun buildShortcutInfo(context: Context, app: ApplicationInfo, dynamic: Boolean): ShortcutInfoCompat { + @RequiresApi(O) private fun buildShortcutInfo(context: Context, app: ApplicationInfo, dynamic: Boolean): ShortcutInfoCompat { val pkg = app.packageName; val userId = app.userId; val isCrossProfile = isCrossProfile(userId) val shortcutId = getShortcutId(pkg, userId, isCrossProfile) val label = buildLabel(context, app, dynamic) From 14d40bce9f62959dc19d8c86a7662866b8cada65 Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Sat, 28 May 2022 11:05:23 +0800 Subject: [PATCH 5/6] Fix adding shortcuts in Android 12.1+ --- .../java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt index 67a9d2b72..00f6f36b7 100644 --- a/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt +++ b/mobile/src/main/java/com/oasisfeng/island/shortcut/IslandAppShortcut.kt @@ -67,10 +67,7 @@ object IslandAppShortcut { @OwnerUser @JvmStatic fun requestPin(context: Context, app: ApplicationInfo) { val dynamic = isDynamicLabelEnabled(context) - val profile = app.user - if (IslandManager.isReady(context, profile)) - Shuttle(context, profile).launchNoThrows { requestPinAsUser(this, app, dynamic) } - else requestPinAsUser(context, app, dynamic) // Create cross-profile shortcut in Mainland if Island is not ready (probably deactivated) + requestPinAsUser(context, app, dynamic) } /** @return true if launcher supports shortcut pinning, false for failure, or null if legacy shortcut installation broadcast is sent. */ From 7829ea511be87ec84c918107a5fb8ab06d6d610f Mon Sep 17 00:00:00 2001 From: proletarius101 Date: Wed, 14 Sep 2022 22:55:48 +0800 Subject: [PATCH 6/6] fix: `Max number of dynamic shortcuts exceeded` use Google Shortcuts Integration Library (https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#gsi-library) to bypass the maximum shortcut limit --- mobile/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mobile/build.gradle b/mobile/build.gradle index 05bb89023..e482183be 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -43,6 +43,9 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlin_coroutine_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutine_version" implementation 'androidx.core:core-ktx:1.7.0' + implementation('androidx.core:core-google-shortcuts:1.1.0-alpha01') { + exclude group:'com.google.android.gms' + } implementation "androidx.fragment:fragment-ktx:1.4.0" implementation 'androidx.lifecycle:lifecycle-common-java8:2.4.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'