From 08e004a8190e2f6b48e619ef3e3061eab9f54546 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 7 Jan 2025 17:55:25 +0530 Subject: [PATCH] Fixed: Application crash while adding application shortcuts. * Using the `ShortcutManagerCompat` class to add dynamic shortcuts instead of directly using the `ShortcutManager` class, as it provides better handling for adding shortcuts. * The issue occurred because these shortcuts were defined in the manifest, which treated them as immutable and unable to be updated. We removed them from the manifest and added them as dynamic shortcuts. On some devices (e.g., Honor devices), it takes time to remove these shortcuts from the static shortcut list after the user updates the app, causing them to be treated as immutable and unable to be updated. This led to the crash. To fix this, we updated our shortcut IDs so that when the previous static shortcuts are removed by the OS, it will not affect the creation of the new dynamic shortcuts. * For previously added dynamic shortcuts on other devices, we implemented a removeOutdatedIdShortcuts() method, which removes the old dynamic shortcuts. --- .../kiwixmobile/main/KiwixMainActivity.kt | 37 ++++++++++++++----- .../kiwixmobile/core/main/CoreMainActivity.kt | 1 + .../custom/main/CustomMainActivity.kt | 32 +++++++++++----- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt index ee63d58e96..e207c6f81c 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt @@ -19,16 +19,16 @@ package org.kiwix.kiwixmobile.main import android.content.Intent -import android.content.pm.ShortcutInfo -import android.content.pm.ShortcutManager import android.content.res.Configuration -import android.graphics.drawable.Icon import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat import androidx.core.os.ConfigurationCompat import androidx.core.os.bundleOf import androidx.core.view.isVisible @@ -45,8 +45,8 @@ import eu.mhutti1.utils.storage.StorageDeviceUtils import kotlinx.coroutines.launch import org.kiwix.kiwixmobile.BuildConfig import org.kiwix.kiwixmobile.R -import org.kiwix.kiwixmobile.core.R.id import org.kiwix.kiwixmobile.core.R.drawable +import org.kiwix.kiwixmobile.core.R.id import org.kiwix.kiwixmobile.core.R.mipmap import org.kiwix.kiwixmobile.core.R.string import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions @@ -56,6 +56,7 @@ import org.kiwix.kiwixmobile.core.extensions.applyEdgeToEdgeInsets import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID import org.kiwix.kiwixmobile.core.main.ZIM_FILE_URI_KEY import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.databinding.ActivityKiwixMainBinding @@ -66,6 +67,7 @@ import javax.inject.Inject const val NAVIGATE_TO_ZIM_HOST_FRAGMENT = "navigate_to_zim_host_fragment" const val ACTION_GET_CONTENT = "GET_CONTENT" const val OPENING_ZIM_FILE_DELAY = 300L +const val GET_CONTENT_SHORTCUT_ID = "get_content_shortcut" class KiwixMainActivity : CoreMainActivity() { private var actionMode: ActionMode? = null @@ -324,13 +326,27 @@ class KiwixMainActivity : CoreMainActivity() { override fun getIconResId() = mipmap.ic_launcher override fun createApplicationShortcuts() { - val shortcutManager = getSystemService(ShortcutManager::class.java) + // Remove previously added dynamic shortcuts for old ids if any found. + removeOutdatedIdShortcuts() + ShortcutManagerCompat.addDynamicShortcuts(this, dynamicShortcutList()) + } + + // Outdated shortcut ids(new_tab, get_content) + // Remove if the application has the outdated shortcuts. + private fun removeOutdatedIdShortcuts() { + ShortcutManagerCompat.getDynamicShortcuts(this).forEach { + if (it.id == "new_tab" || it.id == "get_content") { + ShortcutManagerCompat.removeDynamicShortcuts(this, arrayListOf(it.id)) + } + } + } + private fun dynamicShortcutList(): List { // Create a shortcut for opening the "New tab" - val newTabShortcut = ShortcutInfo.Builder(this, "new_tab") + val newTabShortcut = ShortcutInfoCompat.Builder(this, NEW_TAB_SHORTCUT_ID) .setShortLabel(getString(string.new_tab_shortcut_label)) .setLongLabel(getString(string.new_tab_shortcut_label)) - .setIcon(Icon.createWithResource(this, drawable.ic_shortcut_new_tab)) + .setIcon(IconCompat.createWithResource(this, drawable.ic_shortcut_new_tab)) .setDisabledMessage(getString(string.shortcut_disabled_message)) .setIntent( Intent(this, KiwixMainActivity::class.java).apply { @@ -340,10 +356,10 @@ class KiwixMainActivity : CoreMainActivity() { .build() // create a shortCut for opening the online fragment. - val getContentShortcut = ShortcutInfo.Builder(this, "get_content") + val getContentShortcut = ShortcutInfoCompat.Builder(this, GET_CONTENT_SHORTCUT_ID) .setShortLabel(getString(string.get_content_shortcut_label)) .setLongLabel(getString(string.get_content_shortcut_label)) - .setIcon(Icon.createWithResource(this, drawable.ic_shortcut_get_content)) + .setIcon(IconCompat.createWithResource(this, drawable.ic_shortcut_get_content)) .setDisabledMessage(getString(string.shortcut_disabled_message)) .setIntent( Intent(this, KiwixMainActivity::class.java).apply { @@ -351,6 +367,7 @@ class KiwixMainActivity : CoreMainActivity() { } ) .build() - shortcutManager.dynamicShortcuts = listOf(newTabShortcut, getContentShortcut) + + return listOf(newTabShortcut, getContentShortcut) } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index 858f6e06a7..2daf681c54 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -77,6 +77,7 @@ const val FIND_IN_PAGE_SEARCH_STRING = "findInPageSearchString" const val ZIM_FILE_URI_KEY = "zimFileUri" const val KIWIX_INTERNAL_ERROR = 10 const val ACTION_NEW_TAB = "NEW_TAB" +const val NEW_TAB_SHORTCUT_ID = "new_tab_shortcut" abstract class CoreMainActivity : BaseActivity(), WebViewProvider { diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt index f9a41b7aa6..813bdd9977 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt @@ -19,26 +19,27 @@ package org.kiwix.kiwixmobile.custom.main import android.content.Intent -import android.content.pm.ShortcutInfo -import android.content.pm.ShortcutManager -import android.graphics.drawable.Icon import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat import androidx.core.net.toUri import androidx.drawerlayout.widget.DrawerLayout import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import com.google.android.material.navigation.NavigationView +import org.kiwix.kiwixmobile.core.R.drawable +import org.kiwix.kiwixmobile.core.R.string +import org.kiwix.kiwixmobile.core.extensions.applyEdgeToEdgeInsets import org.kiwix.kiwixmobile.core.extensions.browserIntent import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB import org.kiwix.kiwixmobile.core.main.CoreMainActivity +import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID import org.kiwix.kiwixmobile.custom.BuildConfig import org.kiwix.kiwixmobile.custom.R -import org.kiwix.kiwixmobile.core.R.string -import org.kiwix.kiwixmobile.core.R.drawable -import org.kiwix.kiwixmobile.core.extensions.applyEdgeToEdgeInsets import org.kiwix.kiwixmobile.custom.customActivityComponent import org.kiwix.kiwixmobile.custom.databinding.ActivityCustomMainBinding @@ -192,12 +193,13 @@ class CustomMainActivity : CoreMainActivity() { override fun getIconResId() = R.mipmap.ic_launcher override fun createApplicationShortcuts() { - val shortcutManager = getSystemService(ShortcutManager::class.java) + // Remove previously added dynamic shortcuts for old ids if any found. + removeOutdatedIdShortcuts() // Create a shortcut for opening the "New tab" - val newTabShortcut = ShortcutInfo.Builder(this, "new_tab") + val newTabShortcut = ShortcutInfoCompat.Builder(this, NEW_TAB_SHORTCUT_ID) .setShortLabel(getString(string.new_tab_shortcut_label)) .setLongLabel(getString(string.new_tab_shortcut_label)) - .setIcon(Icon.createWithResource(this, drawable.ic_shortcut_new_tab)) + .setIcon(IconCompat.createWithResource(this, drawable.ic_shortcut_new_tab)) .setDisabledMessage(getString(string.shortcut_disabled_message)) .setIntent( Intent(this, CustomMainActivity::class.java).apply { @@ -205,6 +207,16 @@ class CustomMainActivity : CoreMainActivity() { } ) .build() - shortcutManager.dynamicShortcuts = listOf(newTabShortcut) + ShortcutManagerCompat.addDynamicShortcuts(this, listOf(newTabShortcut)) + } + + // Outdated shortcut id(new_tab) + // Remove if the application has the outdated shortcut. + private fun removeOutdatedIdShortcuts() { + ShortcutManagerCompat.getDynamicShortcuts(this).forEach { + if (it.id == "new_tab") { + ShortcutManagerCompat.removeDynamicShortcuts(this, arrayListOf(it.id)) + } + } } }