refresh icons on uninstall

This commit is contained in:
tibbi 2022-09-19 18:44:30 +02:00
parent d3bdfbf1af
commit ed9fc728ee
6 changed files with 105 additions and 74 deletions

View File

@ -1,10 +1,12 @@
package com.simplemobiletools.launcher.activities package com.simplemobiletools.launcher.activities
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@ -14,6 +16,7 @@ import android.view.*
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import androidx.core.view.marginLeft import androidx.core.view.marginLeft
import androidx.core.view.marginTop import androidx.core.view.marginTop
@ -21,15 +24,14 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.launcher.BuildConfig import com.simplemobiletools.launcher.BuildConfig
import com.simplemobiletools.launcher.R import com.simplemobiletools.launcher.R
import com.simplemobiletools.launcher.extensions.config import com.simplemobiletools.launcher.extensions.*
import com.simplemobiletools.launcher.extensions.handleAppIconPopupMenu
import com.simplemobiletools.launcher.extensions.homeScreenGridItemsDB
import com.simplemobiletools.launcher.extensions.launchApp
import com.simplemobiletools.launcher.fragments.AllAppsFragment import com.simplemobiletools.launcher.fragments.AllAppsFragment
import com.simplemobiletools.launcher.fragments.MyFragment import com.simplemobiletools.launcher.fragments.MyFragment
import com.simplemobiletools.launcher.fragments.WidgetsFragment import com.simplemobiletools.launcher.fragments.WidgetsFragment
import com.simplemobiletools.launcher.helpers.ROW_COUNT import com.simplemobiletools.launcher.helpers.ROW_COUNT
import com.simplemobiletools.launcher.helpers.UNINSTALL_APP_REQUEST_CODE
import com.simplemobiletools.launcher.interfaces.FlingListener import com.simplemobiletools.launcher.interfaces.FlingListener
import com.simplemobiletools.launcher.models.AppLauncher
import com.simplemobiletools.launcher.models.HomeScreenGridItem import com.simplemobiletools.launcher.models.HomeScreenGridItem
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
@ -41,6 +43,8 @@ class MainActivity : SimpleActivity(), FlingListener {
private var mScreenHeight = 0 private var mScreenHeight = 0
private var mIgnoreUpEvent = false private var mIgnoreUpEvent = false
private var mIgnoreMoveEvents = false private var mIgnoreMoveEvents = false
private var mCachedLaunchers = ArrayList<AppLauncher>()
private lateinit var mDetector: GestureDetectorCompat private lateinit var mDetector: GestureDetectorCompat
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -81,6 +85,15 @@ class MainActivity : SimpleActivity(), FlingListener {
updateStatusbarColor(Color.TRANSPARENT) updateStatusbarColor(Color.TRANSPARENT)
(all_apps_fragment as AllAppsFragment).setupViews() (all_apps_fragment as AllAppsFragment).setupViews()
(widgets_fragment as WidgetsFragment).setupViews() (widgets_fragment as WidgetsFragment).setupViews()
ensureBackgroundThread {
if (mCachedLaunchers.isEmpty()) {
mCachedLaunchers = launchersDB.getAppLaunchers() as ArrayList<AppLauncher>
(all_apps_fragment as AllAppsFragment).gotLaunchers(mCachedLaunchers)
}
refetchLaunchers()
}
} }
override fun onBackPressed() { override fun onBackPressed() {
@ -93,6 +106,15 @@ class MainActivity : SimpleActivity(), FlingListener {
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == UNINSTALL_APP_REQUEST_CODE) {
ensureBackgroundThread {
refetchLaunchers()
}
}
}
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
(all_apps_fragment as AllAppsFragment).onConfigurationChanged() (all_apps_fragment as AllAppsFragment).onConfigurationChanged()
@ -133,6 +155,19 @@ class MainActivity : SimpleActivity(), FlingListener {
return true return true
} }
private fun refetchLaunchers() {
val launchers = getAllAppLaunchers()
(all_apps_fragment as AllAppsFragment).gotLaunchers(launchers)
mCachedLaunchers.map { it.packageName }.forEach { packageName ->
if (!launchers.map { it.packageName }.contains(packageName)) {
launchersDB.deleteApp(packageName)
}
}
mCachedLaunchers = launchers
}
fun startHandlingTouches(touchDownY: Int) { fun startHandlingTouches(touchDownY: Int) {
mTouchDownY = touchDownY mTouchDownY = touchDownY
mCurrentFragmentY = all_apps_fragment.y.toInt() mCurrentFragmentY = all_apps_fragment.y.toInt()
@ -240,6 +275,30 @@ class MainActivity : SimpleActivity(), FlingListener {
hideFragment(all_apps_fragment) hideFragment(all_apps_fragment)
} }
@SuppressLint("WrongConstant")
fun getAllAppLaunchers(): ArrayList<AppLauncher> {
val allApps = ArrayList<AppLauncher>()
val allPackageNames = ArrayList<String>()
val intent = Intent(Intent.ACTION_MAIN, null)
intent.addCategory(Intent.CATEGORY_LAUNCHER)
val list = packageManager.queryIntentActivities(intent, PackageManager.PERMISSION_GRANTED)
for (info in list) {
val componentInfo = info.activityInfo.applicationInfo
val label = info.loadLabel(packageManager).toString()
val packageName = componentInfo.packageName
val drawable = getDrawableForPackageName(packageName) ?: continue
val placeholderColor = calculateAverageColor(drawable.toBitmap())
allPackageNames.add(packageName)
allApps.add(AppLauncher(null, label, packageName, 0, placeholderColor, drawable))
}
val launchers = allApps.distinctBy { it.packageName } as ArrayList<AppLauncher>
launchersDB.insertAll(launchers)
return launchers
}
private fun getDefaultAppPackages() { private fun getDefaultAppPackages() {
val homeScreenGridItems = ArrayList<HomeScreenGridItem>() val homeScreenGridItems = ArrayList<HomeScreenGridItem>()
try { try {
@ -286,4 +345,27 @@ class MainActivity : SimpleActivity(), FlingListener {
homeScreenGridItemsDB.insertAll(homeScreenGridItems) homeScreenGridItemsDB.insertAll(homeScreenGridItems)
} }
// taken from https://gist.github.com/maxjvh/a6ab15cbba9c82a5065d
private fun calculateAverageColor(bitmap: Bitmap): Int {
var red = 0
var green = 0
var blue = 0
val height = bitmap.height
val width = bitmap.width
var n = 0
val pixels = IntArray(width * height)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
var i = 0
while (i < pixels.size) {
val color = pixels[i]
red += Color.red(color)
green += Color.green(color)
blue += Color.blue(color)
n++
i += 1
}
return Color.rgb(red / n, green / n, blue / n)
}
} }

View File

@ -18,7 +18,6 @@ import com.simplemobiletools.launcher.activities.SimpleActivity
import com.simplemobiletools.launcher.extensions.getColumnCount import com.simplemobiletools.launcher.extensions.getColumnCount
import com.simplemobiletools.launcher.interfaces.AllAppsListener import com.simplemobiletools.launcher.interfaces.AllAppsListener
import com.simplemobiletools.launcher.models.AppLauncher import com.simplemobiletools.launcher.models.AppLauncher
import com.simplemobiletools.launcher.models.HomeScreenGridItem
import kotlinx.android.synthetic.main.item_launcher_label.view.* import kotlinx.android.synthetic.main.item_launcher_label.view.*
class LaunchersAdapter( class LaunchersAdapter(
@ -32,6 +31,7 @@ class LaunchersAdapter(
private var textColor = activity.getProperTextColor() private var textColor = activity.getProperTextColor()
private var iconPadding = 0 private var iconPadding = 0
private var wasManualScrollPositionSet = false private var wasManualScrollPositionSet = false
private var wereFreshIconsLoaded = false
init { init {
calculateIconWidth() calculateIconWidth()
@ -60,9 +60,12 @@ class LaunchersAdapter(
} }
fun updateItems(newItems: ArrayList<AppLauncher>) { fun updateItems(newItems: ArrayList<AppLauncher>) {
if (newItems.hashCode() != launchers.hashCode()) { val oldSum = launchers.sumOf { it.getHashToCompare() }
val newSum = newItems.sumOf { it.getHashToCompare() }
if (oldSum != newSum || !wereFreshIconsLoaded) {
launchers = newItems launchers = newItems
notifyDataSetChanged() notifyDataSetChanged()
wereFreshIconsLoaded = true
} }
} }

View File

@ -11,6 +11,7 @@ import android.widget.PopupMenu
import com.simplemobiletools.commons.extensions.getPopupMenuTheme import com.simplemobiletools.commons.extensions.getPopupMenuTheme
import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.launcher.R import com.simplemobiletools.launcher.R
import com.simplemobiletools.launcher.helpers.UNINSTALL_APP_REQUEST_CODE
fun Activity.launchApp(packageName: String) { fun Activity.launchApp(packageName: String) {
val launchIntent = packageManager.getLaunchIntentForPackage(packageName) val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
@ -31,7 +32,7 @@ fun Activity.launchAppInfo(packageName: String) {
fun Activity.uninstallApp(packageName: String) { fun Activity.uninstallApp(packageName: String) {
Intent(Intent.ACTION_DELETE).apply { Intent(Intent.ACTION_DELETE).apply {
data = Uri.fromParts("package", packageName, null) data = Uri.fromParts("package", packageName, null)
startActivity(this) startActivityForResult(this, UNINSTALL_APP_REQUEST_CODE)
} }
} }

View File

@ -2,23 +2,19 @@ package com.simplemobiletools.launcher.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.Surface import android.view.Surface
import android.view.WindowManager import android.view.WindowManager
import androidx.core.graphics.drawable.toBitmap
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isRPlus import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.commons.views.MyGridLayoutManager import com.simplemobiletools.commons.views.MyGridLayoutManager
import com.simplemobiletools.launcher.R import com.simplemobiletools.launcher.R
import com.simplemobiletools.launcher.activities.MainActivity import com.simplemobiletools.launcher.activities.MainActivity
import com.simplemobiletools.launcher.adapters.LaunchersAdapter import com.simplemobiletools.launcher.adapters.LaunchersAdapter
import com.simplemobiletools.launcher.extensions.* import com.simplemobiletools.launcher.extensions.getColumnCount
import com.simplemobiletools.launcher.extensions.handleAppIconPopupMenu
import com.simplemobiletools.launcher.extensions.launchApp
import com.simplemobiletools.launcher.interfaces.AllAppsListener import com.simplemobiletools.launcher.interfaces.AllAppsListener
import com.simplemobiletools.launcher.models.AppLauncher import com.simplemobiletools.launcher.models.AppLauncher
import kotlinx.android.synthetic.main.all_apps_fragment.view.* import kotlinx.android.synthetic.main.all_apps_fragment.view.*
@ -31,7 +27,6 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
this.activity = activity this.activity = activity
background.applyColorFilter(activity.getProperBackgroundColor()) background.applyColorFilter(activity.getProperBackgroundColor())
setPadding(0, activity.statusBarHeight, 0, 0) setPadding(0, activity.statusBarHeight, 0, 0)
getLaunchers()
all_apps_grid.setOnTouchListener { v, event -> all_apps_grid.setOnTouchListener { v, event ->
if (event.actionMasked == MotionEvent.ACTION_UP || event.actionMasked == MotionEvent.ACTION_CANCEL) { if (event.actionMasked == MotionEvent.ACTION_UP || event.actionMasked == MotionEvent.ACTION_CANCEL) {
@ -68,42 +63,7 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
return shouldIntercept return shouldIntercept
} }
@SuppressLint("WrongConstant") fun gotLaunchers(appLaunchers: ArrayList<AppLauncher>) {
private fun getLaunchers() {
ensureBackgroundThread {
val cachedLaunchers = context.launchersDB.getAppLaunchers() as ArrayList<AppLauncher>
gotLaunchers(cachedLaunchers)
val allApps = ArrayList<AppLauncher>()
val allPackageNames = ArrayList<String>()
val intent = Intent(Intent.ACTION_MAIN, null)
intent.addCategory(Intent.CATEGORY_LAUNCHER)
val list = context.packageManager.queryIntentActivities(intent, PackageManager.PERMISSION_GRANTED)
for (info in list) {
val componentInfo = info.activityInfo.applicationInfo
val label = info.loadLabel(context.packageManager).toString()
val packageName = componentInfo.packageName
val drawable = context.getDrawableForPackageName(packageName) ?: continue
val placeholderColor = calculateAverageColor(drawable.toBitmap())
allPackageNames.add(packageName)
allApps.add(AppLauncher(null, label, packageName, 0, placeholderColor, drawable))
}
val launchers = allApps.distinctBy { it.packageName } as ArrayList<AppLauncher>
context.launchersDB.insertAll(launchers)
gotLaunchers(launchers)
cachedLaunchers.map { it.packageName }.forEach { packageName ->
if (!launchers.map { it.packageName }.contains(packageName)) {
context.launchersDB.deleteApp(packageName)
}
}
}
}
private fun gotLaunchers(appLaunchers: ArrayList<AppLauncher>) {
val sorted = appLaunchers.sortedBy { it.title.normalizeString().lowercase() }.toMutableList() as ArrayList<AppLauncher> val sorted = appLaunchers.sortedBy { it.title.normalizeString().lowercase() }.toMutableList() as ArrayList<AppLauncher>
setupAdapter(sorted) setupAdapter(sorted)
} }
@ -166,27 +126,4 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
all_apps_popup_menu_anchor.y = y all_apps_popup_menu_anchor.y = y
activity?.handleAppIconPopupMenu(all_apps_popup_menu_anchor, packageName) activity?.handleAppIconPopupMenu(all_apps_popup_menu_anchor, packageName)
} }
// taken from https://gist.github.com/maxjvh/a6ab15cbba9c82a5065d
private fun calculateAverageColor(bitmap: Bitmap): Int {
var red = 0
var green = 0
var blue = 0
val height = bitmap.height
val width = bitmap.width
var n = 0
val pixels = IntArray(width * height)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
var i = 0
while (i < pixels.size) {
val color = pixels[i]
red += Color.red(color)
green += Color.green(color)
blue += Color.blue(color)
n++
i += 1
}
return Color.rgb(red / n, green / n, blue / n)
}
} }

View File

@ -9,3 +9,5 @@ const val WAS_HOME_SCREEN_INIT = "was_home_screen_init"
// default home screen grid size // default home screen grid size
const val ROW_COUNT = 6 const val ROW_COUNT = 6
const val COLUMN_COUNT = 5 const val COLUMN_COUNT = 5
const val UNINSTALL_APP_REQUEST_CODE = 50

View File

@ -29,6 +29,12 @@ data class AppLauncher(
fun getBubbleText() = title fun getBubbleText() = title
fun getHashToCompare() = getStringToCompare().hashCode()
fun getStringToCompare(): String {
return copy(id = null, drawable = null).toString()
}
override fun compareTo(other: AppLauncher): Int { override fun compareTo(other: AppLauncher): Int {
var result = when { var result = when {
sorting and SORT_BY_TITLE != 0 -> title.normalizeString().lowercase().compareTo(other.title.normalizeString().lowercase()) sorting and SORT_BY_TITLE != 0 -> title.normalizeString().lowercase().compareTo(other.title.normalizeString().lowercase())