Don't store compat themed icons in database
This commit is contained in:
parent
59b8f17fc4
commit
23252726b0
@ -16,9 +16,6 @@ interface IconDao {
|
||||
@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?
|
||||
|
||||
@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')")
|
||||
suspend fun getIconsFromAllPacks(componentName: String): List<IconEntity>
|
||||
|
||||
@ -80,9 +77,6 @@ interface IconDao {
|
||||
@Query("DELETE FROM IconPack WHERE packageName NOT IN (:packs)")
|
||||
fun deleteAllPacksExcept(packs: List<String>)
|
||||
|
||||
@Query("DELETE FROM Icons WHERE type = 'themed-compat'")
|
||||
fun deleteAllCompatThemedIcons()
|
||||
|
||||
@Transaction
|
||||
fun uninstallIconPacksExcept(packs: List<String>) {
|
||||
deleteAllIconsPackIconsExcept(packs)
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
package de.mm20.launcher2.ktx
|
||||
|
||||
import android.util.Log
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
|
||||
fun XmlPullParser.skipToNextTag(): Boolean {
|
||||
while (next() != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) return true
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -3,6 +3,8 @@ 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.compat.AdaptiveIconDrawableCompat
|
||||
import de.mm20.launcher2.icons.compat.toLauncherIcon
|
||||
import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -25,66 +27,30 @@ internal class DynamicCalendarIcon(
|
||||
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()
|
||||
)
|
||||
val adaptiveIcon = AdaptiveIconDrawableCompat.from(resources, resId)
|
||||
|
||||
var icon = when {
|
||||
isThemed && drawable is AdaptiveIconDrawable -> {
|
||||
if (isAtLeastApiLevel(33) && drawable.monochrome != null) {
|
||||
return@withContext StaticLauncherIcon(
|
||||
var icon = if (adaptiveIcon != null) {
|
||||
adaptiveIcon.toLauncherIcon(themed = isThemed)
|
||||
} else {
|
||||
try {
|
||||
val drawable = ResourcesCompat.getDrawable(resources, resId, null)
|
||||
|
||||
when {
|
||||
drawable is AdaptiveIconDrawable -> AdaptiveIconDrawableCompat.from(drawable).toLauncherIcon(themed = isThemed)
|
||||
drawable != null -> StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
icon = drawable.monochrome!!,
|
||||
icon = drawable,
|
||||
scale = 1f,
|
||||
),
|
||||
backgroundLayer = ColorLayer()
|
||||
)
|
||||
} else {
|
||||
return@withContext StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
icon = drawable.foreground!!,
|
||||
scale = 1.5f,
|
||||
),
|
||||
backgroundLayer = ColorLayer()
|
||||
backgroundLayer = TransparentLayer,
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
isThemed -> {
|
||||
StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
icon = drawable,
|
||||
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
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
null
|
||||
} ?: return@withContext StaticLauncherIcon(
|
||||
foregroundLayer = TextLayer(day.toString()),
|
||||
backgroundLayer = ColorLayer()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
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.IconPackInstaller
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
@ -55,7 +54,6 @@ class IconPackManager(
|
||||
withContext(Dispatchers.IO) {
|
||||
IconPackInstaller(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> {
|
||||
val iconDao = appDatabase.iconDao()
|
||||
return iconDao.getIconsFromAllPacks(componentName.flattenToString())
|
||||
@ -301,7 +268,7 @@ class IconPackManager(
|
||||
iconPack: String,
|
||||
baseIconName: String,
|
||||
themed: Boolean,
|
||||
): DynamicCalendarIcon? {
|
||||
): LauncherIcon? {
|
||||
val resources = try {
|
||||
context.packageManager.getResourcesForApplication(iconPack)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
@ -313,10 +280,16 @@ class IconPackManager(
|
||||
if (id == 0) return null
|
||||
id
|
||||
}.toIntArray()
|
||||
|
||||
if (themed) {
|
||||
return ThemedDynamicCalendarIcon(
|
||||
resources = resources,
|
||||
resourceIds = drawableIds,
|
||||
)
|
||||
}
|
||||
return DynamicCalendarIcon(
|
||||
resources = resources,
|
||||
resourceIds = drawableIds,
|
||||
isThemed = themed,
|
||||
)
|
||||
}
|
||||
|
||||
@ -444,12 +417,11 @@ class IconPackManager(
|
||||
val array = resources.obtainTypedArrayOrNull(resId) ?: return null
|
||||
if (array.length() != 31) return null
|
||||
|
||||
return DynamicCalendarIcon(
|
||||
return ThemedDynamicCalendarIcon(
|
||||
resources = resources,
|
||||
resourceIds = IntArray(31) {
|
||||
array.getResourceId(it, 0).takeIf { it != 0 } ?: return null
|
||||
},
|
||||
isThemed = true
|
||||
)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import de.mm20.launcher2.data.customattrs.DefaultPlaceholderIcon
|
||||
import de.mm20.launcher2.data.customattrs.ForceThemedIcon
|
||||
import de.mm20.launcher2.data.customattrs.UnmodifiedSystemDefaultIcon
|
||||
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.CustomThemedIconProvider
|
||||
import de.mm20.launcher2.icons.providers.GoogleClockIconProvider
|
||||
@ -106,14 +106,14 @@ class IconRepository(
|
||||
Log.w("MM20", "Icon pack ${settings.iconPack} not found")
|
||||
}
|
||||
}
|
||||
providers.add(GoogleClockIconProvider(context))
|
||||
providers.add(CalendarIconProvider(context))
|
||||
if (settings.themedIcons) {
|
||||
if (!isAtLeastApiLevel(33)) {
|
||||
providers.add(CompatThemedIconProvider(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(placeholderProvider)
|
||||
cache.evictAll()
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package de.mm20.launcher2.icons
|
||||
|
||||
import de.mm20.launcher2.icons.compat.ThemedIconsCompatManager
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
) {
|
||||
|
||||
|
||||
}
|
||||
@ -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 }
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ import de.mm20.launcher2.ktx.obtainTypedArrayOrNull
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
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? {
|
||||
if(searchable !is LauncherApp) return null
|
||||
val component = ComponentName(searchable.`package`, searchable.activity)
|
||||
@ -40,7 +40,8 @@ class CalendarIconProvider(val context: Context): IconProvider {
|
||||
typedArray.recycle()
|
||||
return DynamicCalendarIcon(
|
||||
resources = resources,
|
||||
resourceIds = drawableIds
|
||||
resourceIds = drawableIds,
|
||||
isThemed = themed
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user