fix: popup menu for work profile apps

This commit is contained in:
Josia Pietsch 2024-08-05 15:08:41 +02:00
parent bf4298ea58
commit 5e841a9106
Signed by: jrpie
GPG key ID: E70B571D66986A2D
6 changed files with 77 additions and 57 deletions

View file

@ -4,6 +4,14 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2024-08-03T23:51:52.680101889Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/home/jrpie/.config/.android/avd/Medium_Phone_API_35.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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()
)
}

View file

@ -13,13 +13,6 @@
android:paddingRight="32sp"
tools:context=".settings.meta.SettingsFragmentMeta">
<Button
android:id="@+id/settings_meta_button_select_launcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_meta_select_launcher"
android:textAllCaps="false" />
<Button
android:id="@+id/settings_meta_button_view_tutorial"
android:layout_width="match_parent"