Don't store compat themed icons in database

This commit is contained in:
MM20 2023-02-15 18:41:30 +01:00
parent 59b8f17fc4
commit 23252726b0
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
13 changed files with 289 additions and 259 deletions

View File

@ -16,9 +16,6 @@ interface IconDao {
@Query("SELECT * FROM Icons WHERE componentName = :componentName AND iconPack = :iconPack AND (type = 'app' OR type = 'calendar') LIMIT 1") @Query("SELECT * FROM Icons WHERE componentName = :componentName AND iconPack = :iconPack AND (type = 'app' OR type = 'calendar') LIMIT 1")
suspend fun getIcon(componentName: String, iconPack: String): IconEntity? suspend fun getIcon(componentName: String, iconPack: String): IconEntity?
@Query("SELECT * FROM Icons WHERE componentName = :componentName AND (type = 'themed-compat') LIMIT 1")
suspend fun getCompatThemedIcon(componentName: String): IconEntity?
@Query("SELECT * FROM Icons WHERE componentName = :componentName AND (type = 'app' OR type = 'calendar')") @Query("SELECT * FROM Icons WHERE componentName = :componentName AND (type = 'app' OR type = 'calendar')")
suspend fun getIconsFromAllPacks(componentName: String): List<IconEntity> suspend fun getIconsFromAllPacks(componentName: String): List<IconEntity>
@ -80,9 +77,6 @@ interface IconDao {
@Query("DELETE FROM IconPack WHERE packageName NOT IN (:packs)") @Query("DELETE FROM IconPack WHERE packageName NOT IN (:packs)")
fun deleteAllPacksExcept(packs: List<String>) fun deleteAllPacksExcept(packs: List<String>)
@Query("DELETE FROM Icons WHERE type = 'themed-compat'")
fun deleteAllCompatThemedIcons()
@Transaction @Transaction
fun uninstallIconPacksExcept(packs: List<String>) { fun uninstallIconPacksExcept(packs: List<String>) {
deleteAllIconsPackIconsExcept(packs) deleteAllIconsPackIconsExcept(packs)

View File

@ -1,10 +1,13 @@
package de.mm20.launcher2.ktx package de.mm20.launcher2.ktx
import android.util.Log
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
fun XmlPullParser.skipToNextTag(): Boolean { fun XmlPullParser.skipToNextTag(): Boolean {
while (next() != XmlPullParser.END_DOCUMENT) { while (next() != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) return true if (eventType == XmlPullParser.START_TAG) {
return true
}
} }
return false return false
} }

View File

@ -3,6 +3,8 @@ package de.mm20.launcher2.icons
import android.content.res.Resources import android.content.res.Resources
import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.AdaptiveIconDrawable
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import de.mm20.launcher2.icons.compat.AdaptiveIconDrawableCompat
import de.mm20.launcher2.icons.compat.toLauncherIcon
import de.mm20.launcher2.icons.transformations.LauncherIconTransformation import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.isAtLeastApiLevel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -25,66 +27,30 @@ internal class DynamicCalendarIcon(
val day = Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault()).dayOfMonth val day = Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault()).dayOfMonth
val resId = resourceIds[day - 1] val resId = resourceIds[day - 1]
val drawable = try { val adaptiveIcon = AdaptiveIconDrawableCompat.from(resources, resId)
ResourcesCompat.getDrawable(resources, resId, null)
} catch (e: Resources.NotFoundException) {
null
} ?: return@withContext StaticLauncherIcon(
foregroundLayer = TextLayer(day.toString()),
backgroundLayer = ColorLayer()
)
var icon = when { var icon = if (adaptiveIcon != null) {
isThemed && drawable is AdaptiveIconDrawable -> { adaptiveIcon.toLauncherIcon(themed = isThemed)
if (isAtLeastApiLevel(33) && drawable.monochrome != null) { } else {
return@withContext StaticLauncherIcon( try {
val drawable = ResourcesCompat.getDrawable(resources, resId, null)
when {
drawable is AdaptiveIconDrawable -> AdaptiveIconDrawableCompat.from(drawable).toLauncherIcon(themed = isThemed)
drawable != null -> StaticLauncherIcon(
foregroundLayer = TintedIconLayer( foregroundLayer = TintedIconLayer(
icon = drawable.monochrome!!, icon = drawable,
scale = 1f, scale = 1f,
), ),
backgroundLayer = ColorLayer() backgroundLayer = TransparentLayer,
)
} else {
return@withContext StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
icon = drawable.foreground!!,
scale = 1.5f,
),
backgroundLayer = ColorLayer()
) )
else -> null
} }
} } catch (e: Resources.NotFoundException) {
isThemed -> { null
StaticLauncherIcon( } ?: return@withContext StaticLauncherIcon(
foregroundLayer = TintedIconLayer( foregroundLayer = TextLayer(day.toString()),
icon = drawable, backgroundLayer = ColorLayer()
scale = 0.5f,
),
backgroundLayer = ColorLayer()
)
}
drawable is AdaptiveIconDrawable -> {
return@withContext StaticLauncherIcon(
foregroundLayer = drawable.foreground?.let {
StaticIconLayer(
icon = it,
scale = 1.5f,
)
} ?: TransparentLayer,
backgroundLayer = drawable.background?.let {
StaticIconLayer(
icon = it,
scale = 1.5f,
)
} ?: TransparentLayer,
)
}
else -> StaticLauncherIcon(
foregroundLayer = StaticIconLayer(
icon = drawable,
scale = 1f,
),
backgroundLayer = TransparentLayer
) )
} }

View File

@ -20,7 +20,6 @@ import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.icons.loaders.CompatThemedIconInstaller
import de.mm20.launcher2.icons.loaders.GrayscaleMapInstaller import de.mm20.launcher2.icons.loaders.GrayscaleMapInstaller
import de.mm20.launcher2.icons.loaders.IconPackInstaller import de.mm20.launcher2.icons.loaders.IconPackInstaller
import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.isAtLeastApiLevel
@ -55,7 +54,6 @@ class IconPackManager(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
IconPackInstaller(context, appDatabase).installIcons() IconPackInstaller(context, appDatabase).installIcons()
GrayscaleMapInstaller(context, appDatabase).installIcons() GrayscaleMapInstaller(context, appDatabase).installIcons()
CompatThemedIconInstaller(context, appDatabase).installIcons()
} }
} }
@ -236,37 +234,6 @@ class IconPackManager(
) )
} }
suspend fun getCompatThemedIcon(componentName: ComponentName): LauncherIcon? {
val iconDao = appDatabase.iconDao()
val icon = iconDao.getCompatThemedIcon(componentName.flattenToString())
?: return null
val drawableName = icon.drawable ?: return null
val res = try {
context.packageManager.getResourcesForApplication(componentName.packageName)
} catch (e: Resources.NotFoundException) {
return null
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val resourceId = res.getIdentifier(drawableName, null, null)
val drawable = try {
ResourcesCompat.getDrawable(res, resourceId, null)
} catch (e: Resources.NotFoundException) {
return null
} ?: return null
return StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
icon = drawable,
scale = 1f,
),
backgroundLayer = ColorLayer()
)
}
suspend fun getAllIconPackIcons(componentName: ComponentName): List<IconPackIcon> { suspend fun getAllIconPackIcons(componentName: ComponentName): List<IconPackIcon> {
val iconDao = appDatabase.iconDao() val iconDao = appDatabase.iconDao()
return iconDao.getIconsFromAllPacks(componentName.flattenToString()) return iconDao.getIconsFromAllPacks(componentName.flattenToString())
@ -301,7 +268,7 @@ class IconPackManager(
iconPack: String, iconPack: String,
baseIconName: String, baseIconName: String,
themed: Boolean, themed: Boolean,
): DynamicCalendarIcon? { ): LauncherIcon? {
val resources = try { val resources = try {
context.packageManager.getResourcesForApplication(iconPack) context.packageManager.getResourcesForApplication(iconPack)
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
@ -313,10 +280,16 @@ class IconPackManager(
if (id == 0) return null if (id == 0) return null
id id
}.toIntArray() }.toIntArray()
if (themed) {
return ThemedDynamicCalendarIcon(
resources = resources,
resourceIds = drawableIds,
)
}
return DynamicCalendarIcon( return DynamicCalendarIcon(
resources = resources, resources = resources,
resourceIds = drawableIds, resourceIds = drawableIds,
isThemed = themed,
) )
} }
@ -444,12 +417,11 @@ class IconPackManager(
val array = resources.obtainTypedArrayOrNull(resId) ?: return null val array = resources.obtainTypedArrayOrNull(resId) ?: return null
if (array.length() != 31) return null if (array.length() != 31) return null
return DynamicCalendarIcon( return ThemedDynamicCalendarIcon(
resources = resources, resources = resources,
resourceIds = IntArray(31) { resourceIds = IntArray(31) {
array.getResourceId(it, 0).takeIf { it != 0 } ?: return null array.getResourceId(it, 0).takeIf { it != 0 } ?: return null
}, },
isThemed = true
) )
} catch (e: Resources.NotFoundException) { } catch (e: Resources.NotFoundException) {
} }

View File

@ -16,7 +16,7 @@ import de.mm20.launcher2.data.customattrs.DefaultPlaceholderIcon
import de.mm20.launcher2.data.customattrs.ForceThemedIcon import de.mm20.launcher2.data.customattrs.ForceThemedIcon
import de.mm20.launcher2.data.customattrs.UnmodifiedSystemDefaultIcon import de.mm20.launcher2.data.customattrs.UnmodifiedSystemDefaultIcon
import de.mm20.launcher2.icons.providers.CalendarIconProvider import de.mm20.launcher2.icons.providers.CalendarIconProvider
import de.mm20.launcher2.icons.providers.CompatThemedIconProvider import de.mm20.launcher2.icons.providers.CompatIconProvider
import de.mm20.launcher2.icons.providers.CustomIconPackIconProvider import de.mm20.launcher2.icons.providers.CustomIconPackIconProvider
import de.mm20.launcher2.icons.providers.CustomThemedIconProvider import de.mm20.launcher2.icons.providers.CustomThemedIconProvider
import de.mm20.launcher2.icons.providers.GoogleClockIconProvider import de.mm20.launcher2.icons.providers.GoogleClockIconProvider
@ -106,14 +106,14 @@ class IconRepository(
Log.w("MM20", "Icon pack ${settings.iconPack} not found") Log.w("MM20", "Icon pack ${settings.iconPack} not found")
} }
} }
providers.add(GoogleClockIconProvider(context))
providers.add(CalendarIconProvider(context))
if (settings.themedIcons) { if (settings.themedIcons) {
if (!isAtLeastApiLevel(33)) {
providers.add(CompatThemedIconProvider(iconPackManager))
}
providers.add(ThemedIconProvider(iconPackManager)) providers.add(ThemedIconProvider(iconPackManager))
} }
providers.add(GoogleClockIconProvider(context))
providers.add(CalendarIconProvider(context, settings.themedIcons))
if (!isAtLeastApiLevel(33)) {
providers.add(CompatIconProvider(context, settings.themedIcons))
}
providers.add(SystemIconProvider(context, settings.themedIcons)) providers.add(SystemIconProvider(context, settings.themedIcons))
providers.add(placeholderProvider) providers.add(placeholderProvider)
cache.evictAll() cache.evictAll()

View File

@ -1,6 +1,5 @@
package de.mm20.launcher2.icons package de.mm20.launcher2.icons
import de.mm20.launcher2.icons.compat.ThemedIconsCompatManager
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module import org.koin.dsl.module

View File

@ -0,0 +1,58 @@
package de.mm20.launcher2.icons
import android.content.res.Resources
import android.graphics.drawable.AdaptiveIconDrawable
import androidx.core.content.res.ResourcesCompat
import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.Instant
import java.time.ZoneId
internal class ThemedDynamicCalendarIcon(
val resources: Resources,
val resourceIds: IntArray,
private var transformations: List<LauncherIconTransformation> = emptyList(),
) : DynamicLauncherIcon, TransformableDynamicLauncherIcon {
override suspend fun getIcon(time: Long): StaticLauncherIcon = withContext(Dispatchers.IO) {
val day = Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault()).dayOfMonth
val resId = resourceIds[day - 1]
val drawable = try {
ResourcesCompat.getDrawable(resources, resId, null)
} catch (e: Resources.NotFoundException) {
null
} ?: return@withContext StaticLauncherIcon(
foregroundLayer = TextLayer(day.toString()),
backgroundLayer = ColorLayer()
)
var icon = when (drawable) {
is AdaptiveIconDrawable -> StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
icon = drawable.foreground,
scale = 1.5f,
),
backgroundLayer = ColorLayer()
)
else -> StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
icon = drawable,
scale = 0.5f,
),
backgroundLayer = ColorLayer()
)
}
for (transformation in transformations) {
icon = transformation.transform(icon)
}
return@withContext icon
}
override fun setTransformations(transformations: List<LauncherIconTransformation>) {
this.transformations = transformations
}
}

View File

@ -0,0 +1,150 @@
package de.mm20.launcher2.icons.compat
import android.content.res.Resources
import android.content.res.XmlResourceParser
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.util.Xml
import android.view.InflateException
import androidx.core.content.res.ResourcesCompat
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.icons.ColorLayer
import de.mm20.launcher2.icons.StaticIconLayer
import de.mm20.launcher2.icons.StaticLauncherIcon
import de.mm20.launcher2.icons.TintedIconLayer
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.ktx.skipToNextTag
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
data class AdaptiveIconDrawableCompat(
val background: Drawable,
val foreground: Drawable,
val monochrome: Drawable?,
) {
companion object {
fun from(adaptiveIconDrawable: AdaptiveIconDrawable): AdaptiveIconDrawableCompat {
return AdaptiveIconDrawableCompat(
background = adaptiveIconDrawable.background,
foreground = adaptiveIconDrawable.foreground,
monochrome = if (isAtLeastApiLevel(33)) adaptiveIconDrawable.monochrome else null,
)
}
fun from(resources: Resources, resId: Int): AdaptiveIconDrawableCompat? {
var xmlParser: XmlResourceParser? = null
try {
xmlParser = resources.getXml(resId)
val attrs = Xml.asAttributeSet(xmlParser)
if (!xmlParser.skipToNextTag()) return null
Log.d("MM20", "xmlParser.name: ${xmlParser.name}")
if (xmlParser.name != "adaptive-icon") {
return null
}
var background: Drawable? = null
var foreground: Drawable? = null
var monochrome: Drawable? = null
while (xmlParser.skipToNextTag()) {
when (xmlParser.name) {
"monochrome" -> {
monochrome = parseLayer(resources, xmlParser, attrs)
}
"background" -> {
background = parseLayer(resources, xmlParser, attrs)
}
"foreground" -> {
foreground = parseLayer(resources, xmlParser, attrs)
}
}
}
Log.d(
"MM20",
"background: $background, foreground: $foreground, monochrome: $monochrome"
)
if (foreground != null && background != null) {
return AdaptiveIconDrawableCompat(
background = background,
foreground = foreground,
monochrome = monochrome,
)
}
} catch (e: Resources.NotFoundException) {
CrashReporter.logException(e)
return null
} catch (e: IOException) {
CrashReporter.logException(e)
return null
} catch (e: XmlPullParserException) {
CrashReporter.logException(e)
return null
} finally {
xmlParser?.close()
}
return null
}
@Throws(
XmlPullParserException::class,
IOException::class,
Resources.NotFoundException::class
)
private fun parseLayer(
resources: Resources,
parser: XmlResourceParser,
attrs: AttributeSet
): Drawable? {
val drawableId = parser.getAttributeResourceValue(
"http://schemas.android.com/apk/res/android",
"drawable",
0
)
if (drawableId != 0) {
return ResourcesCompat.getDrawable(resources, drawableId, null)
}
if (!parser.skipToNextTag()) return null
return try {
Drawable.createFromXmlInner(resources, parser, attrs)
} catch (e: InflateException) {
CrashReporter.logException(e)
null
}
}
}
}
fun AdaptiveIconDrawableCompat.toLauncherIcon(
themed: Boolean = false,
): StaticLauncherIcon {
if (themed && this.monochrome != null) {
return StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
scale = 1f,
icon = this.monochrome,
),
backgroundLayer = ColorLayer()
)
} else {
return StaticLauncherIcon(
foregroundLayer = StaticIconLayer(
scale = 1.5f,
icon = this.foreground,
),
backgroundLayer = StaticIconLayer(
scale = 1.5f,
icon = this.background,
)
)
}
}

View File

@ -1,26 +0,0 @@
package de.mm20.launcher2.icons.compat
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Resources
import android.content.res.XmlResourceParser
import android.util.Log
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.icons.IconPackIcon
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.ktx.skipToNextTag
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
internal class ThemedIconsCompatManager(
private val context: Context,
) {
}

View File

@ -1,109 +0,0 @@
package de.mm20.launcher2.icons.loaders
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Resources
import android.content.res.XmlResourceParser
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.icons.IconPackIcon
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.ktx.skipToNextTag
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
class CompatThemedIconInstaller(
private val context: Context,
private val database: AppDatabase,
) {
fun installIcons() {
if (isAtLeastApiLevel(33)) return
val launcherActivities = getLauncherActivities()
val dao = database.iconDao()
val icons = mutableListOf<IconPackIcon>()
database.runInTransaction {
dao.deleteAllCompatThemedIcons()
for (activity in launcherActivities) {
val componentName = ComponentName(activity.applicationInfo.packageName, activity.name)
val monochromeIcon = getMonochromeIconResource(activity)
if (monochromeIcon != null) {
val icon = IconPackIcon(
type = "themed-compat",
componentName = componentName,
name = null,
drawable = monochromeIcon,
iconPack = componentName.packageName
)
icons.add(icon)
}
if (icons.size > 100) {
dao.insertAll(icons.map { it.toDatabaseEntity() })
icons.clear()
}
}
if (icons.isNotEmpty()) {
dao.insertAll(icons.map { it.toDatabaseEntity() })
}
}
}
private fun getMonochromeIconResource(activityInfo: ActivityInfo): String? {
val iconResource = activityInfo.iconResource
val resources = try {
context.packageManager.getResourcesForApplication(activityInfo.packageName)
} catch (e: PackageManager.NameNotFoundException) {
CrashReporter.logException(e)
return null
}
var xmlParser: XmlResourceParser? = null
try {
xmlParser = resources.getXml(iconResource)
if (!xmlParser.skipToNextTag()) return null
if (xmlParser.name != "adaptive-icon") {
return null
}
while (xmlParser.skipToNextTag()) {
if (xmlParser.name == "monochrome") {
val drawable = xmlParser.getAttributeResourceValue(
"http://schemas.android.com/apk/res/android",
"drawable",
0
)
if (drawable == 0) return null
return resources.getResourceName(drawable)
}
}
} catch (e: Resources.NotFoundException) {
CrashReporter.logException(e)
return null
} catch (e: IOException) {
CrashReporter.logException(e)
return null
} catch (e: XmlPullParserException) {
CrashReporter.logException(e)
return null
} finally {
xmlParser?.close()
}
return null
}
private fun getLauncherActivities(): List<ActivityInfo> {
val resolveInfos = context.packageManager.queryIntentActivities(
Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER), 0
)
return resolveInfos.mapNotNull { it.activityInfo }
}
}

View File

@ -9,7 +9,7 @@ import de.mm20.launcher2.ktx.obtainTypedArrayOrNull
import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.search.data.LauncherApp import de.mm20.launcher2.search.data.LauncherApp
class CalendarIconProvider(val context: Context): IconProvider { class CalendarIconProvider(val context: Context, val themed: Boolean): IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
if(searchable !is LauncherApp) return null if(searchable !is LauncherApp) return null
val component = ComponentName(searchable.`package`, searchable.activity) val component = ComponentName(searchable.`package`, searchable.activity)
@ -40,7 +40,8 @@ class CalendarIconProvider(val context: Context): IconProvider {
typedArray.recycle() typedArray.recycle()
return DynamicCalendarIcon( return DynamicCalendarIcon(
resources = resources, resources = resources,
resourceIds = drawableIds resourceIds = drawableIds,
isThemed = themed
) )
} }
} }

View File

@ -0,0 +1,39 @@
package de.mm20.launcher2.icons.providers
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.icons.compat.AdaptiveIconDrawableCompat
import de.mm20.launcher2.icons.compat.toLauncherIcon
import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.search.data.LauncherApp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class CompatIconProvider(
private val context: Context,
private val themed: Boolean = false,
) : IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
if (searchable !is LauncherApp) return null
val component = ComponentName(searchable.`package`, searchable.activity)
val activityInfo = try {
context.packageManager.getActivityInfo(component, 0)
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val iconRes = activityInfo.iconResource
val resources = try {
context.packageManager.getResourcesForApplication(activityInfo.packageName)
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val icon = withContext(Dispatchers.IO) {
AdaptiveIconDrawableCompat.from(resources, iconRes)
} ?: return null
return icon.toLauncherIcon(themed = themed)
}
}

View File

@ -1,17 +0,0 @@
package de.mm20.launcher2.icons.providers
import android.content.ComponentName
import de.mm20.launcher2.icons.IconPackManager
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.search.data.LauncherApp
class CompatThemedIconProvider(
private val iconPackManager: IconPackManager,
): IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
if (searchable !is LauncherApp) return null
val component = ComponentName(searchable.`package`, searchable.activity)
return iconPackManager.getCompatThemedIcon(component)
}
}