diff --git a/app/build.gradle b/app/build.gradle index 81aef1f..a110b80 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,13 +3,13 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 27 - buildToolsVersion "27.0.3" + compileSdkVersion 28 + buildToolsVersion "28.0.3" defaultConfig { applicationId "com.simplemobiletools.applauncher" - minSdkVersion 16 - targetSdkVersion 27 + minSdkVersion 21 + targetSdkVersion 28 versionCode 15 versionName "4.1.1" multiDexEnabled true @@ -42,9 +42,9 @@ android { } dependencies { - implementation 'com.simplemobiletools:commons:4.6.7' + implementation 'com.simplemobiletools:commons:5.0.18' implementation 'com.facebook.stetho:stetho:1.5.0' - implementation 'com.android.support:multidex:1.0.3' + implementation 'androidx.multidex:multidex:2.0.0' } Properties props = new Properties() diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt index 8a8c58d..bf394f3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt @@ -1,6 +1,6 @@ package com.simplemobiletools.applauncher -import android.support.multidex.MultiDexApplication +import androidx.multidex.MultiDexApplication import com.facebook.stetho.Stetho import com.simplemobiletools.commons.extensions.checkUseEnglish diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt index 732f533..e6dc9d0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt @@ -17,7 +17,6 @@ import com.simplemobiletools.applauncher.models.AppLauncher import com.simplemobiletools.commons.extensions.appLaunched import com.simplemobiletools.commons.extensions.checkWhatsNew import com.simplemobiletools.commons.extensions.updateTextColors -import com.simplemobiletools.commons.helpers.LICENSE_MULTISELECT import com.simplemobiletools.commons.helpers.LICENSE_STETHO import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.models.FAQItem @@ -94,7 +93,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun launchAbout() { - val licenses = LICENSE_MULTISELECT or LICENSE_STETHO + val licenses = LICENSE_STETHO val faqItems = arrayListOf( FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons) diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt index ab040b1..1560282 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt @@ -17,7 +17,6 @@ import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.views.FastScroller import com.simplemobiletools.commons.views.MyRecyclerView import kotlinx.android.synthetic.main.item_app_launcher.view.* -import java.util.* class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList, val listener: RefreshRecyclerViewListener?, recyclerView: MyRecyclerView, fastScroller: FastScroller, itemClick: (Any) -> Unit) : @@ -29,26 +28,6 @@ class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList - setupView(itemView, launcher) - } - bindViewHolder(holder, position, view) - } - - override fun getItemCount() = launchers.size - override fun prepareActionMode(menu: Menu) { menu.apply { findItem(R.id.cab_edit).isVisible = isOneItemSelected() @@ -56,18 +35,40 @@ class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList showEditDialog() R.id.cab_remove -> tryRemoveLauncher() } } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_app_launcher, parent) + + override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) { + val launcher = launchers[position] + holder.bindView(launcher, true, true) { itemView, adapterPosition -> + setupView(itemView, launcher, isKeySelected(launcher.packageName.hashCode())) + } + bindViewHolder(holder) + } + + override fun getItemCount() = launchers.size + + private fun getItemWithKey(key: Int): AppLauncher? = launchers.firstOrNull { it.packageName.hashCode() == key } + override fun getSelectableItemCount() = launchers.size override fun getIsItemSelectable(position: Int) = true + override fun getItemSelectionKey(position: Int) = launchers.getOrNull(position)?.packageName?.hashCode() + + override fun getItemKeyPosition(key: Int) = launchers.indexOfFirst { it.packageName.hashCode() == key } + private fun showEditDialog() { - EditDialog(activity, launchers[selectedPositions.first()]) { + EditDialog(activity, getItemWithKey(selectedKeys.first())!!) { finishActMode() listener?.refreshItems() } @@ -89,24 +90,38 @@ class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList(selectedPositions.size) - val removeLaunchers = ArrayList(selectedPositions.size) - selectedPositions.sortedDescending().forEach { - val launcher = launchers[it] + val removeIds = ArrayList(selectedKeys.size) + val removeLaunchers = ArrayList(selectedKeys.size) + val positions = ArrayList(selectedKeys.size) + + for (key in selectedKeys) { + val launcher = getItemWithKey(key) ?: continue removeIds.add(launcher.id.toString()) removeLaunchers.add(launcher) + + val position = launchers.indexOfFirst { it.packageName.hashCode() == key } + if (position != -1) { + positions.add(position) + } } launchers.removeAll(removeLaunchers) activity.dbHelper.deleteLaunchers(removeIds) - removeSelectedItems() + positions.sortDescending() + removeSelectedItems(positions) } - private fun setupView(view: View, launcher: AppLauncher) { + private fun setupView(view: View, launcher: AppLauncher, isSelected: Boolean) { view.apply { + // setup check icon + launcher_check?.beInvisibleIf(!isSelected) launcher_label.text = launcher.name launcher_label.setTextColor(textColor) launcher_icon.setImageDrawable(launcher.drawable!!) + + if (isSelected) { + launcher_check?.background?.applyColorFilter(primaryColor) + } } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersDialogAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersDialogAdapter.kt index e2e5b65..96b9813 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersDialogAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersDialogAdapter.kt @@ -1,87 +1,74 @@ package com.simplemobiletools.applauncher.adapters import android.app.Activity -import android.support.v7.widget.RecyclerView -import android.util.SparseArray import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView import com.simplemobiletools.applauncher.R import com.simplemobiletools.applauncher.extensions.config import com.simplemobiletools.applauncher.models.AppLauncher import com.simplemobiletools.commons.extensions.applyColorFilter import com.simplemobiletools.commons.extensions.beInvisibleIf -import com.simplemobiletools.commons.interfaces.MyAdapterListener import kotlinx.android.synthetic.main.item_app_launcher.view.* import java.util.* class LaunchersDialogAdapter(activity: Activity, val launchers: ArrayList) : RecyclerView.Adapter() { private val config = activity.config private var primaryColor = config.primaryColor - private var itemViews = SparseArray() - private val selectedPositions = HashSet() private var textColor = config.textColor + private var selectedKeys = HashSet() fun toggleItemSelection(select: Boolean, pos: Int) { + val itemKey = launchers.getOrNull(pos)?.packageName?.hashCode() ?: return + if (select) { - if (itemViews[pos] != null) { - itemViews[pos].launcher_check?.background?.applyColorFilter(primaryColor) - selectedPositions.add(pos) - } + selectedKeys.add(itemKey) } else { - selectedPositions.remove(pos) + selectedKeys.remove(itemKey) } - itemViews[pos]?.launcher_check?.beInvisibleIf(!select) + notifyItemChanged(pos) } - fun getSelectedLaunchers(): ArrayList { - val selectedLaunchers = ArrayList() - selectedPositions.forEach { - selectedLaunchers.add(launchers[it]) - } - return selectedLaunchers - } - - private val adapterListener = object : MyAdapterListener { - override fun itemLongClicked(position: Int) { - } - - override fun toggleItemSelectionAdapter(select: Boolean, position: Int) { - toggleItemSelection(select, position) - } - - override fun getSelectedPositions(): HashSet = selectedPositions - } + fun getSelectedLaunchers() = launchers.filter { selectedKeys.contains(it.packageName.hashCode()) } as ArrayList override fun onBindViewHolder(holder: ViewHolder, position: Int) { - itemViews.put(position, holder.bindView(launchers[position], textColor)) - toggleItemSelection(selectedPositions.contains(position), position) + holder.bindView(launchers[position]) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_app_launcher, parent, false) - return ViewHolder(view, adapterListener) + return ViewHolder(view) } override fun getItemCount() = launchers.size - class ViewHolder(view: View, val adapterListener: MyAdapterListener) : RecyclerView.ViewHolder(view) { - fun bindView(launcher: AppLauncher, textColor: Int): View { + private fun isKeySelected(key: Int) = selectedKeys.contains(key) + + inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + fun bindView(launcher: AppLauncher): View { + val isSelected = isKeySelected(launcher.packageName.hashCode()) itemView.apply { + launcher_check?.beInvisibleIf(!isSelected) launcher_label.text = launcher.name launcher_label.setTextColor(textColor) launcher_icon.setImageDrawable(launcher.drawable!!) - setOnClickListener { viewClicked() } - setOnLongClickListener { viewClicked(); true } + if (isSelected) { + launcher_check?.background?.applyColorFilter(primaryColor) + } + + setOnClickListener { viewClicked(launcher) } + setOnLongClickListener { viewClicked(launcher); true } } + return itemView } - private fun viewClicked() { - val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition) - adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition) + private fun viewClicked(launcher: AppLauncher) { + val isSelected = selectedKeys.contains(launcher.packageName.hashCode()) + toggleItemSelection(!isSelected, adapterPosition) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/AddAppLauncherDialog.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/AddAppLauncherDialog.kt index 01f5ee7..71b6397 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/AddAppLauncherDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/AddAppLauncherDialog.kt @@ -1,8 +1,8 @@ package com.simplemobiletools.applauncher.dialogs import android.app.Activity -import android.support.v7.app.AlertDialog import android.view.ViewGroup +import androidx.appcompat.app.AlertDialog import com.simplemobiletools.applauncher.R import com.simplemobiletools.applauncher.adapters.LaunchersDialogAdapter import com.simplemobiletools.applauncher.extensions.dbHelper @@ -16,7 +16,7 @@ class AddAppLauncherDialog(val activity: Activity, val notDisplayedLaunchers: Ar init { AlertDialog.Builder(activity) - .setPositiveButton(R.string.ok, { dialogInterface, i -> confirmSelection() }) + .setPositiveButton(R.string.ok) { dialogInterface, i -> confirmSelection() } .setNegativeButton(R.string.cancel, null) .create().apply { activity.setupDialogStuff(view, this) { diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/EditDialog.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/EditDialog.kt index 99d3949..8b84946 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/EditDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/dialogs/EditDialog.kt @@ -1,8 +1,8 @@ package com.simplemobiletools.applauncher.dialogs import android.app.Activity -import android.support.v7.app.AlertDialog import android.view.ViewGroup +import androidx.appcompat.app.AlertDialog import com.simplemobiletools.applauncher.R import com.simplemobiletools.applauncher.extensions.dbHelper import com.simplemobiletools.applauncher.models.AppLauncher diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/extensions/Context.kt index a9ed1b1..929061b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/extensions/Context.kt @@ -1,22 +1,18 @@ package com.simplemobiletools.applauncher.extensions -import android.annotation.TargetApi import android.content.Context import android.content.Intent import android.content.pm.LauncherApps import android.content.pm.PackageManager import android.graphics.drawable.Drawable -import android.os.Build import com.simplemobiletools.applauncher.helpers.Config import com.simplemobiletools.applauncher.helpers.DBHelper import com.simplemobiletools.applauncher.models.AppLauncher -import com.simplemobiletools.commons.helpers.isLollipopPlus val Context.config: Config get() = Config.newInstance(applicationContext) val Context.dbHelper: DBHelper get() = DBHelper.newInstance(applicationContext) -@TargetApi(Build.VERSION_CODES.LOLLIPOP) fun Context.getNotDisplayedLaunchers(displayedLaunchers: ArrayList): ArrayList { val allApps = ArrayList() val intent = Intent(Intent.ACTION_MAIN, null) @@ -28,14 +24,12 @@ fun Context.getNotDisplayedLaunchers(displayedLaunchers: ArrayList) val packageName = componentInfo.packageName var drawable: Drawable? = null - if (isLollipopPlus()) { - try { - // try getting the properly colored launcher icons - val launcher = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps - val activityList = launcher.getActivityList(packageName, android.os.Process.myUserHandle())[0] - drawable = activityList.getBadgedIcon(0) - } catch (e: Exception) { - } + try { + // try getting the properly colored launcher icons + val launcher = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps + val activityList = launcher.getActivityList(packageName, android.os.Process.myUserHandle())[0] + drawable = activityList.getBadgedIcon(0) + } catch (e: Exception) { } if (drawable == null) { diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/helpers/DBHelper.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/helpers/DBHelper.kt index 1f04950..b9da862 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/helpers/DBHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/helpers/DBHelper.kt @@ -1,6 +1,5 @@ package com.simplemobiletools.applauncher.helpers -import android.annotation.TargetApi import android.content.ContentValues import android.content.Context import android.content.pm.LauncherApps @@ -8,7 +7,6 @@ import android.content.pm.PackageManager import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper import android.graphics.drawable.Drawable -import android.os.Build import android.text.TextUtils import com.simplemobiletools.applauncher.R import com.simplemobiletools.applauncher.extensions.getLauncherDrawable @@ -16,7 +14,6 @@ import com.simplemobiletools.applauncher.extensions.isAPredefinedApp import com.simplemobiletools.applauncher.models.AppLauncher import com.simplemobiletools.commons.extensions.getIntValue import com.simplemobiletools.commons.extensions.getStringValue -import com.simplemobiletools.commons.helpers.isLollipopPlus import java.util.* class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) { @@ -123,7 +120,6 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont return mDb.update(MAIN_TABLE_NAME, values, selection, selectionArgs) == 1 } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) fun getLaunchers(): ArrayList { val resources = context.resources val packageManager = context.packageManager @@ -139,18 +135,16 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont val wasRenamed = cursor.getIntValue(COL_WAS_RENAMED) == 1 var drawable: Drawable? = null - if (isLollipopPlus()) { - try { - // try getting the properly colored launcher icons - val launcher = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps - val activityList = launcher.getActivityList(packageName, android.os.Process.myUserHandle())[0] - drawable = activityList.getBadgedIcon(0) + try { + // try getting the properly colored launcher icons + val launcher = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps + val activityList = launcher.getActivityList(packageName, android.os.Process.myUserHandle())[0] + drawable = activityList.getBadgedIcon(0) - if (!wasRenamed) { - name = activityList.label.toString() - } - } catch (e: Exception) { + if (!wasRenamed) { + name = activityList.label.toString() } + } catch (e: Exception) { } if (drawable == null) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 492fbcf..7ea2c98 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/dialog_pick_launchers.xml b/app/src/main/res/layout/dialog_pick_launchers.xml index 3c36d9d..0fb8c02 100644 --- a/app/src/main/res/layout/dialog_pick_launchers.xml +++ b/app/src/main/res/layout/dialog_pick_launchers.xml @@ -1,5 +1,5 @@ -