diff --git a/app/src/main/java/de/jrpie/android/launcher/Application.kt b/app/src/main/java/de/jrpie/android/launcher/Application.kt index 6e924c2..e3e5f7c 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -1,9 +1,5 @@ package de.jrpie.android.launcher -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter import android.content.SharedPreferences import android.content.pm.LauncherApps import android.content.pm.ShortcutInfo @@ -11,7 +7,6 @@ import android.os.AsyncTask import android.os.Build import android.os.Build.VERSION_CODES import android.os.UserHandle -import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData import androidx.preference.PreferenceManager import de.jrpie.android.launcher.actions.TorchManager @@ -24,14 +19,6 @@ import de.jrpie.android.launcher.preferences.resetPreferences class Application : android.app.Application() { val apps = MutableLiveData>() - private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - // TODO: only update specific apps - // use Intent.EXTRA_USER - loadApps() - } - } - // TODO: only update specific apps private val launcherAppsCallback = object : LauncherApps.Callback() { override fun onPackageRemoved(p0: String?, p1: UserHandle?) { @@ -120,21 +107,6 @@ class Application : android.app.Application() { val launcherApps = getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps launcherApps.registerCallback(launcherAppsCallback) - if (Build.VERSION.SDK_INT >= VERSION_CODES.N) { - val filter = IntentFilter().also { - if (Build.VERSION.SDK_INT >= VERSION_CODES.VANILLA_ICE_CREAM) { - it.addAction(Intent.ACTION_PROFILE_AVAILABLE) - it.addAction(Intent.ACTION_PROFILE_UNAVAILABLE) - } else { - it.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) - it.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) - } - } - ContextCompat.registerReceiver(this, profileAvailabilityBroadcastReceiver, filter, - ContextCompat.RECEIVER_EXPORTED - ) - } - loadApps() } diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 48b5028..e8d3851 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -18,7 +18,6 @@ import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.DetailedAppInfo -import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity @@ -31,36 +30,31 @@ const val REQUEST_SET_DEFAULT_HOME = 42 const val LOG_TAG = "Launcher" -fun isDefaultHomeScreen(context: Context): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { +fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) { + + if (checkDefault + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + && context is Activity + ) { val roleManager = context.getSystemService(RoleManager::class.java) - return roleManager.isRoleHeld(RoleManager.ROLE_HOME) - } else { + if (!roleManager.isRoleHeld(RoleManager.ROLE_HOME)) { + context.startActivityForResult( + roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME), + REQUEST_SET_DEFAULT_HOME + ) + } + return + } + + if (checkDefault) { val testIntent = Intent(Intent.ACTION_MAIN) testIntent.addCategory(Intent.CATEGORY_HOME) val defaultHome = testIntent.resolveActivity(context.packageManager)?.packageName - return defaultHome == context.packageName + if (defaultHome == context.packageName) { + // Launcher is already the default home app + return + } } -} - -fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) { - if (checkDefault && isDefaultHomeScreen(context)) { - // Launcher is already the default home app - return - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q - && context is Activity - && checkDefault // using role manager only works when µLauncher is not already the default. - ) { - val roleManager = context.getSystemService(RoleManager::class.java) - context.startActivityForResult( - roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME), - REQUEST_SET_DEFAULT_HOME - ) - return - } - val intent = Intent(Settings.ACTION_HOME_SETTINGS) context.startActivity(intent) } @@ -100,21 +94,6 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList= Build.VERSION_CODES.N) { - if (userManager.isQuietModeEnabled(user)) { - // hide paused apps - if (LauncherPreferences.apps().hidePausedApps()) { - continue - } - // hide apps from private space - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && - launcherApps.getLauncherUserInfo(user)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE - ) { - continue - } - } - } launcherApps.getActivityList(null, user).forEach { loadList.add(DetailedAppInfo(it)) } diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt index 2eddf16..3c641ff 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt @@ -1,22 +1,17 @@ package de.jrpie.android.launcher.actions -import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent -import android.content.pm.LauncherApps import android.graphics.Rect import android.graphics.drawable.Drawable import android.media.AudioManager import android.os.Build import android.os.SystemClock -import android.os.UserManager -import android.provider.Settings import android.view.KeyEvent import android.widget.Toast import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.R import de.jrpie.android.launcher.apps.AppFilter -import de.jrpie.android.launcher.isDefaultHomeScreen import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.list.ListActivity import de.jrpie.android.launcher.ui.settings.SettingsActivity @@ -38,8 +33,7 @@ enum class LauncherAction( val id: String, val label: Int, val icon: Int, - val launch: (Context) -> Unit, - val available: (Context) -> Boolean = { true } + val launch: (Context) -> Unit ) : Action { SETTINGS( "settings", @@ -59,13 +53,6 @@ enum class LauncherAction( R.drawable.baseline_favorite_24, { context -> openAppsList(context, true) } ), - TOGGLE_PRIVATE_SPACE_LOCK( - "toggle_private_space_lock", - R.string.list_other_toggle_private_space_lock, - R.drawable.baseline_security_24, - ::togglePrivateSpaceLock, - available = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM } - ), VOLUME_UP( "volume_up", R.string.list_other_volume_up, @@ -220,46 +207,6 @@ private fun expandNotificationsPanel(context: Context) { } } -private fun togglePrivateSpaceLock(context: Context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { - Toast.makeText( - context, - context.getString(R.string.alert_requires_android_v), - Toast.LENGTH_LONG - ).show() - return - } - val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager - val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps - val privateSpaceUser = userManager.userProfiles.firstOrNull { u -> - launcherApps.getLauncherUserInfo(u)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE - } - if (privateSpaceUser == null) { - Toast.makeText(context, context.getString(R.string.toast_private_space_not_available), Toast.LENGTH_LONG).show() - - if (!isDefaultHomeScreen(context)) { - Toast.makeText(context, context.getString(R.string.toast_private_space_default_home_screen), Toast.LENGTH_LONG).show() - return - } - - try { - context.startActivity(Intent(Settings.ACTION_PRIVACY_SETTINGS)) - } catch (_: ActivityNotFoundException) {} - return - } - if (userManager.isQuietModeEnabled(privateSpaceUser)) { - userManager.requestQuietModeEnabled(false, privateSpaceUser) - Toast.makeText( - context, - context.getString(R.string.toast_private_space_unlocked), - Toast.LENGTH_LONG - ).show() - return - } - userManager.requestQuietModeEnabled(true, privateSpaceUser) - Toast.makeText(context, context.getString(R.string.toast_private_space_locked), Toast.LENGTH_LONG).show() -} - private fun expandSettingsPanel(context: Context) { /* https://stackoverflow.com/a/31898506 */ try { @@ -313,7 +260,6 @@ private class LauncherActionSerializer : KSerializer { ) { element("value", String.serializer().descriptor) } - override fun deserialize(decoder: Decoder): LauncherAction { val s = decoder.decodeStructure(descriptor) { decodeElementIndex(descriptor) diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java index 98496ce..640e6ce 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java @@ -5,8 +5,8 @@ import java.util.Set; import de.jrpie.android.launcher.R; import de.jrpie.android.launcher.actions.lock.LockMethod; -import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer; import de.jrpie.android.launcher.preferences.serialization.SetAppInfoPreferenceSerializer; +import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer; import de.jrpie.android.launcher.preferences.theme.Background; import de.jrpie.android.launcher.preferences.theme.ColorTheme; import de.jrpie.android.launcher.preferences.theme.Font; @@ -29,7 +29,6 @@ import eu.jonahbauer.android.preference.annotations.Preferences; @Preference(name = "hidden", type = Set.class, serializer = SetAppInfoPreferenceSerializer.class), @Preference(name = "custom_names", type = HashMap.class, serializer = MapAppInfoStringPreferenceSerializer.class), @Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"), - @Preference(name = "hide_paused_apps", type = boolean.class, defaultValue = "false"), }), @PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = { @Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT") diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt index 816d94f..8cef124 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt @@ -2,8 +2,8 @@ package de.jrpie.android.launcher.preferences.theme import android.content.Context import android.content.res.Resources -import com.google.android.material.color.DynamicColors import de.jrpie.android.launcher.R +import com.google.android.material.color.DynamicColors @Suppress("unused") enum class ColorTheme( diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt index 1d5381d..5633113 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt @@ -3,6 +3,7 @@ package de.jrpie.android.launcher.ui import android.annotation.SuppressLint import android.content.SharedPreferences import android.content.res.Resources +import android.os.AsyncTask import android.os.Build import android.os.Bundle import android.util.DisplayMetrics @@ -19,8 +20,13 @@ import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.databinding.HomeBinding +import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.LauncherPreferences +import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion +import de.jrpie.android.launcher.preferences.resetPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity +import java.text.SimpleDateFormat +import java.util.Date import java.util.Locale import java.util.Timer import kotlin.concurrent.fixedRateTimer @@ -63,6 +69,8 @@ class HomeActivity : UIObject, AppCompatActivity(), private lateinit var mDetector: GestureDetectorCompat + // timers + private var clockTimer = Timer() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -96,24 +104,30 @@ class HomeActivity : UIObject, AppCompatActivity(), } - private fun initClock() { + private fun updateClock() { + clockTimer.cancel() val locale = Locale.getDefault() val dateVisible = LauncherPreferences.clock().dateVisible() val timeVisible = LauncherPreferences.clock().timeVisible() var dateFMT = "yyyy-MM-dd" var timeFMT = "HH:mm" + val period = 100L if (LauncherPreferences.clock().showSeconds()) { timeFMT += ":ss" } - + /* + I thought about adding an option to show microseconds as well ( timeFMT += ".SSS" ). + However setting period ot 1L (or even 10L) causes high CPU load, + so that doesn't seem to be a good idea. + */ if (LauncherPreferences.clock().localized()) { dateFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, dateFMT) timeFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, timeFMT) } - var upperFormat = dateFMT - var lowerFormat = timeFMT + var upperFormat = SimpleDateFormat(dateFMT, locale) + var lowerFormat = SimpleDateFormat(timeFMT, locale) var upperVisible = dateVisible var lowerVisible = timeVisible @@ -128,10 +142,21 @@ class HomeActivity : UIObject, AppCompatActivity(), binding.homeUpperView.setTextColor(LauncherPreferences.clock().color()) binding.homeLowerView.setTextColor(LauncherPreferences.clock().color()) - binding.homeLowerView.format24Hour = lowerFormat - binding.homeUpperView.format24Hour = upperFormat - binding.homeLowerView.format12Hour = lowerFormat - binding.homeUpperView.format12Hour = upperFormat + + clockTimer = fixedRateTimer("clockTimer", true, 0L, period) { + this@HomeActivity.runOnUiThread { + if (lowerVisible) { + val t = lowerFormat.format(Date()) + if (binding.homeLowerView.text != t) + binding.homeLowerView.text = t + } + if (upperVisible) { + val d = upperFormat.format(Date()) + if (binding.homeUpperView.text != d) + binding.homeUpperView.text = d + } + } + } } override fun getTheme(): Resources.Theme { @@ -151,7 +176,12 @@ class HomeActivity : UIObject, AppCompatActivity(), edgeWidth = LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f - initClock() + updateClock() + } + + override fun onPause() { + super.onPause() + clockTimer.cancel() } override fun onDestroy() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt index 97d1c84..ddfcfd1 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt @@ -23,8 +23,7 @@ import de.jrpie.android.launcher.ui.list.forGesture class OtherRecyclerAdapter(val activity: Activity) : RecyclerView.Adapter() { - private val othersList: Array = - LauncherAction.entries.filter { it.isAvailable(activity) }.toTypedArray() + private val othersList: Array = LauncherAction.values() inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt index a8efb43..0b054ce 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt @@ -40,11 +40,6 @@ class SettingsFragmentLauncher : PreferenceFragmentCompat() { ) val lightTheme = LauncherPreferences.theme().colorTheme() == ColorTheme.LIGHT background?.isVisible = !lightTheme - - val hidePausedApps = findPreference( - LauncherPreferences.apps().keys().hidePausedApps() - ) - hidePausedApps?.isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N } override fun onStart() { diff --git a/app/src/main/res/drawable/baseline_security_24.xml b/app/src/main/res/drawable/baseline_security_24.xml deleted file mode 100644 index 3c260ff..0000000 --- a/app/src/main/res/drawable/baseline_security_24.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/app/src/main/res/layout/home.xml b/app/src/main/res/layout/home.xml index f59b211..5f34412 100644 --- a/app/src/main/res/layout/home.xml +++ b/app/src/main/res/layout/home.xml @@ -10,7 +10,7 @@ android:fitsSystemWindows="true" tools:context=".ui.HomeActivity"> - - apps.hidden apps.custom_names apps.hide_bound_apps - apps.hide_paused_apps list.layout general.select_launcher diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4cdebb1..5bb2c61 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -145,7 +145,6 @@ Apps Hidden apps Don\'t show apps that are bound to a gesture in the app list - Hide paused apps Layout of app list Default @@ -208,7 +207,6 @@ µLauncher Settings All Applications Favorite Applications - Toggle Private Space Lock Music: Louder Music: Quieter Music: Next @@ -247,7 +245,6 @@ More options Error: Can\'t expand status bar. This action is using functionality that is not part of the published Android API. Unfortunately, it does not seem to work on your device. This functionality requires Android 6.0 or later. - This functionality requires Android 15.0 or later. App hidden. You can make it visible again in settings. Undo Quick Settings @@ -258,10 +255,6 @@ Error: Can\'t access torch. Error: Failed to lock screen. (If you just upgraded the app, try to disable and re-enable the accessibility service in phone settings) μLauncher\'s accessibility service is not enabled. Please enable it in settings - Private space locked - Private space unlocked - Private space is not available - µLauncher needs to be the default home screen to access private space. Error: Locking the screen using accessibility is not supported on this device. Please use device admin instead. µLauncher - lock screen diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 57e50df..d1dcbe6 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -145,11 +145,6 @@ android:title="@string/settings_apps_hide_bound_apps" android:defaultValue="false" /> - -