diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index b268ef3..81acdf9 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,6 +4,14 @@
+
+
+
+
+
+
+
+
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 648894d..aa5193a 100644
--- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt
@@ -1,12 +1,15 @@
package de.jrpie.android.launcher
import android.app.Activity
+import android.app.ActivityOptions
import android.app.AlertDialog
import android.app.Service
import android.app.role.RoleManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
+import android.content.pm.ActivityInfo
+import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.graphics.BlendMode
@@ -15,12 +18,14 @@ import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
+import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.media.AudioManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.SystemClock
+import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
import android.util.DisplayMetrics
@@ -39,10 +44,12 @@ import android.widget.Toast
import de.jrpie.android.launcher.list.ListActivity
import de.jrpie.android.launcher.list.apps.AppInfo
import de.jrpie.android.launcher.list.apps.AppsRecyclerAdapter
+import de.jrpie.android.launcher.list.intendedChoosePause
import de.jrpie.android.launcher.list.other.LauncherAction
import de.jrpie.android.launcher.settings.SettingsActivity
import de.jrpie.android.launcher.settings.intendedSettingsPause
import de.jrpie.android.launcher.tutorial.TutorialActivity
+import kotlin.contracts.contract
/* Preference Key Constants */
@@ -220,17 +227,37 @@ fun audioVolumeDown(activity: Activity) {
/* --- */
-fun launchApp(packageName: String, user: Int?, context: Context) {
+fun getUserFromId(user: Int?, context: Context): UserHandle? {
+ val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
+ return userManager.userProfiles.firstOrNull { it.hashCode() == user }
+}
+fun getLauncherActivityInfo(packageName: String, user: Int?, context: Context): LauncherActivityInfo? {
+ val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
+ return getUserFromId(user,context)?.let {
+ userHandle -> launcherApps.getActivityList(packageName, userHandle).firstOrNull()
+ }
+}
+fun uninstallApp(packageName: String, user: Int?, activity: Activity) {
+ Log.i("Launcher", "uninstalling $packageName ($user)")
+ val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE)
+ intent.data = Uri.parse("package:$packageName")
+ getUserFromId(user, activity)?.let {
+ user -> intent.putExtra(Intent.EXTRA_USER, user)
+ }
+
+ intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)
+ activity.startActivityForResult(intent,
+ REQUEST_UNINSTALL
+ )
+}
+
+fun launchApp(packageName: String, user: Int?, context: Context, rect: Rect? = null) {
Log.i("Launcher", "Starting: " + packageName + " (user " +user.toString()+ ")")
if (user != null) {
val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
- val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
- userManager.userProfiles.firstOrNull { it.hashCode() == user }?.let {
- userHandle -> launcherApps.getActivityList(packageName, userHandle).firstOrNull()?.let {
- app -> launcherApps.startMainActivity(app.componentName, userHandle, null, null)
- return
-
- }
+ getLauncherActivityInfo(packageName,user,context)?.let {
+ app -> launcherApps.startMainActivity(app.componentName, app.user, rect, null)
+ return
}
}
@@ -251,6 +278,7 @@ fun launchApp(packageName: String, user: Int?, context: Context) {
) { _, _ ->
openAppSettings(
packageName,
+ user,
context
)
}
@@ -322,10 +350,11 @@ fun resetToDarkTheme(activity: Activity) {
}
-fun openAppSettings(pkg: String, context: Context) {
- val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
- intent.data = Uri.parse("package:$pkg")
- context.startActivity(intent)
+fun openAppSettings(packageName: String, user: Int?, context: Context, sourceBounds: Rect? = null, opts: Bundle? = null) {
+ val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
+ getLauncherActivityInfo(packageName, user, context)?.let {
+ app -> launcherApps.startAppDetailsActivity(app.componentName, app.user, sourceBounds, opts)
+ }
}
fun openSettings(activity: Activity) {
@@ -346,8 +375,7 @@ fun openAppsList(activity: Activity){
fun getAppIcon(context: Context, packageName: String, user: Int?): Drawable {
if (user != null) {
val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
- val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
- userManager.userProfiles.firstOrNull { it.hashCode() == user }?.let {
+ getUserFromId(user,context)?.let {
userHandle -> launcherApps.getActivityList(packageName, userHandle).firstOrNull()?.let {
app -> return app.getBadgedIcon(0)
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/list/apps/AppsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/list/apps/AppsRecyclerAdapter.kt
index 490d264..042c71c 100644
--- a/app/src/main/java/de/jrpie/android/launcher/list/apps/AppsRecyclerAdapter.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/list/apps/AppsRecyclerAdapter.kt
@@ -3,6 +3,7 @@ package de.jrpie.android.launcher.list.apps
import android.app.Activity
import android.content.Context
import android.content.Intent
+import android.graphics.Rect
import android.net.Uri
import android.os.AsyncTask
import android.view.LayoutInflater
@@ -27,6 +28,7 @@ import de.jrpie.android.launcher.list.intendedChoosePause
import de.jrpie.android.launcher.loadApps
import de.jrpie.android.launcher.openAppSettings
import de.jrpie.android.launcher.transformGrayscale
+import de.jrpie.android.launcher.uninstallApp
import java.util.*
/**
@@ -58,8 +60,9 @@ class AppsRecyclerAdapter(val activity: Activity,
val appUser = appsListDisplayed[pos].user
when (intention){
ListActivity.ListActivityIntention.VIEW -> {
- launchApp(appPackageName, appUser, activity)
-
+ val rect = Rect()
+ img.getGlobalVisibleRect(rect)
+ launchApp(appPackageName, appUser, activity, rect)
}
ListActivity.ListActivityIntention.PICK -> {
val returnIntent = Intent()
@@ -78,6 +81,7 @@ class AppsRecyclerAdapter(val activity: Activity,
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
val appLabel = appsListDisplayed[i].label.toString()
val appPackageName = appsListDisplayed[i].packageName.toString()
+ val appUser = appsListDisplayed[i].user
val appIcon = appsListDisplayed[i].icon
val isSystemApp = appsListDisplayed[i].isSystemApp
@@ -95,10 +99,10 @@ class AppsRecyclerAdapter(val activity: Activity,
else {
viewHolder.menuDots.visibility = View.VISIBLE
- viewHolder.menuDots.setOnClickListener{ showOptionsPopup(viewHolder, appPackageName) }
- viewHolder.menuDots.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName) }
- viewHolder.textView.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName) }
- viewHolder.img.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName) }
+ viewHolder.menuDots.setOnClickListener{ showOptionsPopup(viewHolder, appPackageName, appUser) }
+ viewHolder.menuDots.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName, appUser) }
+ viewHolder.textView.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName, appUser) }
+ viewHolder.img.setOnLongClickListener{ showOptionsPopup(viewHolder, appPackageName, appUser) }
// ensure onClicks are actually caught
viewHolder.textView.setOnClickListener{ viewHolder.onClick(viewHolder.textView) }
@@ -106,9 +110,8 @@ class AppsRecyclerAdapter(val activity: Activity,
}
}
- // TODO fixme: handle work profile apps
@Suppress("SameReturnValue")
- private fun showOptionsPopup(viewHolder: ViewHolder, appPackageName: String): Boolean {
+ private fun showOptionsPopup(viewHolder: ViewHolder, appPackageName: String, user: Int?): Boolean {
//create the popup menu
val popup = PopupMenu(activity, viewHolder.menuDots)
@@ -116,23 +119,14 @@ class AppsRecyclerAdapter(val activity: Activity,
popup.setOnMenuItemClickListener {
when (it.itemId) {
- R.id.app_menu_delete -> { // delete
+ R.id.app_menu_delete -> {
intendedChoosePause = true
- val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE)
- intent.data = Uri.parse("package:$appPackageName")
- intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)
- activity.startActivityForResult(intent,
- REQUEST_UNINSTALL
- )
-
+ uninstallApp(appPackageName, user, activity)
true
}
- R.id.app_menu_info -> { // open app settings
+ R.id.app_menu_info -> {
intendedChoosePause = true
- openAppSettings(
- appPackageName,
- activity
- )
+ openAppSettings(appPackageName, user, activity)
true
}
else -> false
diff --git a/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActions.kt b/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActions.kt
index 62b4758..5bfe246 100644
--- a/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActions.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActions.kt
@@ -2,7 +2,6 @@ package de.jrpie.android.launcher.settings.actions
import android.content.ActivityNotFoundException
import android.content.Intent
-import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.net.Uri
import android.os.Bundle
@@ -11,10 +10,14 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
-import de.jrpie.android.launcher.*
+import de.jrpie.android.launcher.R
+import de.jrpie.android.launcher.UIObject
import de.jrpie.android.launcher.databinding.SettingsActionsBinding
+import de.jrpie.android.launcher.getPreferences
import de.jrpie.android.launcher.list.ListActivity
+import de.jrpie.android.launcher.setButtonColor
import de.jrpie.android.launcher.settings.intendedSettingsPause
+import de.jrpie.android.launcher.vibrantColor
/**
@@ -25,7 +28,8 @@ import de.jrpie.android.launcher.settings.intendedSettingsPause
* It also allows the user to view all apps ([ListActivity]) or install new ones.
*/
-class SettingsFragmentActions : Fragment(), UIObject {
+class
+SettingsFragmentActions : Fragment(), UIObject {
private var binding: SettingsActionsBinding? = null
diff --git a/app/src/main/java/de/jrpie/android/launcher/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/settings/meta/SettingsFragmentMeta.kt
index 463b7f3..90a04c9 100644
--- a/app/src/main/java/de/jrpie/android/launcher/settings/meta/SettingsFragmentMeta.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/settings/meta/SettingsFragmentMeta.kt
@@ -50,7 +50,7 @@ class SettingsFragmentMeta : Fragment(), UIObject {
private fun rateIntentForUrl(url: String): Intent {
val intent = Intent(
Intent.ACTION_VIEW,
- Uri.parse(String.format("%s?id=%s", url, this.context!!.packageName))
+ Uri.parse(String.format("%s?id=%s", url, this.requireContext().packageName))
)
var flags = Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
flags = flags or Intent.FLAG_ACTIVITY_NEW_DOCUMENT
@@ -59,7 +59,6 @@ class SettingsFragmentMeta : Fragment(), UIObject {
}
override fun applyTheme() {
- setButtonColor(binding.settingsMetaButtonSelectLauncher, vibrantColor)
setButtonColor(binding.settingsMetaButtonViewTutorial, vibrantColor)
setButtonColor(binding.settingsMetaButtonResetSettings, vibrantColor)
setButtonColor(binding.settingsMetaButtonReportBug, vibrantColor)
@@ -70,12 +69,6 @@ class SettingsFragmentMeta : Fragment(), UIObject {
override fun setOnClicks() {
- binding.settingsMetaButtonSelectLauncher.setOnClickListener {
- intendedSettingsPause = true
- val callHomeSettingIntent = Intent(Settings.ACTION_HOME_SETTINGS)
- startActivity(callHomeSettingIntent)
- }
-
binding.settingsMetaButtonViewTutorial.setOnClickListener {
intendedSettingsPause = true
startActivity(Intent(this.context, TutorialActivity::class.java))
@@ -102,7 +95,7 @@ class SettingsFragmentMeta : Fragment(), UIObject {
intendedSettingsPause = true
openNewTabWindow(
getString(R.string.settings_meta_report_bug_link),
- context!!
+ requireContext()
)
}
@@ -113,7 +106,7 @@ class SettingsFragmentMeta : Fragment(), UIObject {
intendedSettingsPause = true
openNewTabWindow(
getString(R.string.settings_meta_contact_url),
- context!!
+ requireContext()
)
}
@@ -122,7 +115,7 @@ class SettingsFragmentMeta : Fragment(), UIObject {
intendedSettingsPause = true
openNewTabWindow(
getString(R.string.settings_meta_fork_contact_url),
- context!!
+ requireContext()
)
}
@@ -131,7 +124,7 @@ class SettingsFragmentMeta : Fragment(), UIObject {
intendedSettingsPause = true
openNewTabWindow(
getString(R.string.settings_meta_privacy_url),
- context!!
+ requireContext()
)
}
diff --git a/app/src/main/res/layout/settings_meta.xml b/app/src/main/res/layout/settings_meta.xml
index 8cb9802..af9633a 100644
--- a/app/src/main/res/layout/settings_meta.xml
+++ b/app/src/main/res/layout/settings_meta.xml
@@ -13,13 +13,6 @@
android:paddingRight="32sp"
tools:context=".settings.meta.SettingsFragmentMeta">
-
-