diff --git a/README.md b/README.md
index 2e25e3e..51ae856 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ This is a fork of [finnmglas's app Launcher][original-repo].
## Notable changes:
* Edge gestures: There is a setting to allow distinguishing swiping at the edges of the screen from swiping in the center.
+* Compatible with [work profile](https://www.android.com/enterprise/work-profile/), so apps like [Shelter](https://gitea.angry.im/PeterCxy/Shelter) can be used.
### Visual
* This app uses the system wallpaper instead of a custom solution.
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ec99e9b..5df0438 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
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 a9d7f6c..dd70db0 100644
--- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt
@@ -67,6 +67,8 @@ const val PREF_STARTED_TIME = "firstStartup"
const val PREF_VERSION = "version"
+const val INVALID_USER = -1
+
/* Objects used by multiple activities */
val appsList: MutableList = ArrayList()
@@ -153,14 +155,15 @@ private fun getIntent(packageName: String, context: Context): Intent? {
}
fun launch(
- data: String, activity: Activity,
+ data: String, user: Int?,
+ activity: Activity,
animationIn: Int = android.R.anim.fade_in, animationOut: Int = android.R.anim.fade_out
) {
if (LauncherAction.isOtherAction(data)) { // [type]:[info]
LauncherAction.byId(data)?.let {it.launch(activity) }
}
- else launchApp(data, activity) // app
+ else launchApp(data, user, activity) // app
activity.overridePendingTransition(animationIn, animationOut)
}
@@ -217,7 +220,20 @@ fun audioVolumeDown(activity: Activity) {
/* --- */
-fun launchApp(packageName: String, context: Context) {
+fun launchApp(packageName: String, user: Int?, context: Context) {
+ 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
+
+ }
+ }
+ }
+
val intent = getIntent(packageName, context)
if (intent != null) {
@@ -327,25 +343,57 @@ fun openAppsList(activity: Activity){
activity.startActivity(intent)
}
+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 {
+ userHandle -> launcherApps.getActivityList(packageName, userHandle).firstOrNull()?.let {
+ app -> return app.getBadgedIcon(0)
+ }
+ }
+ }
+ return context.packageManager.getApplicationIcon(packageName)
+}
+
/**
* [loadApps] is used to speed up the [AppsRecyclerAdapter] loading time,
* as it caches all the apps and allows for fast access to the data.
*/
-fun loadApps(packageManager: PackageManager) {
+fun loadApps(packageManager: PackageManager, context: Context) {
val loadList = mutableListOf()
- val i = Intent(Intent.ACTION_MAIN, null)
- i.addCategory(Intent.CATEGORY_LAUNCHER)
- val allApps = packageManager.queryIntentActivities(i, 0)
- for (ri in allApps) {
- val app = AppInfo()
- app.label = ri.loadLabel(packageManager)
- app.packageName = ri.activityInfo.packageName
- app.icon = ri.activityInfo.loadIcon(packageManager)
- loadList.add(app)
- }
- loadList.sortBy { it.label.toString() }
+ val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
+ val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
+ // TODO: shortcuts - launcherApps.getShortcuts()
+ val users = userManager.userProfiles
+ for(user in users) {
+ for (activityInfo in launcherApps.getActivityList(null,user)) {
+ val app = AppInfo()
+ app.label = activityInfo.label
+ app.packageName = activityInfo.applicationInfo.packageName
+ app.icon = activityInfo.getBadgedIcon(0)
+ app.user = user.hashCode()
+ loadList.add(app)
+ }
+ }
+
+
+ // fallback option
+ if(loadList.isEmpty()){
+ Log.i("Launcher", "using fallback option to load packages")
+ val i = Intent(Intent.ACTION_MAIN, null)
+ i.addCategory(Intent.CATEGORY_LAUNCHER)
+ val allApps = packageManager.queryIntentActivities(i, 0)
+ for (ri in allApps) {
+ val app = AppInfo()
+ app.label = ri.loadLabel(packageManager)
+ app.packageName = ri.activityInfo.packageName
+ app.icon = ri.activityInfo.loadIcon(packageManager)
+ loadList.add(app)
+ }
+ }
appsList.clear()
appsList.addAll(loadList)
}
@@ -404,9 +452,12 @@ fun setWindowFlags(window: Window) {
// Used in Tutorial and Settings `ActivityOnResult`
fun saveListActivityChoice(context: Context, data: Intent?) {
val value = data?.getStringExtra("value")
+ var user = data?.getIntExtra("user", INVALID_USER)
+ user = user?.let{ if(it == INVALID_USER) null else it }
+
val forGesture = data?.getStringExtra("forGesture") ?: return
- Gesture.byId(forGesture)?.setApp(context, value.toString())
+ Gesture.byId(forGesture)?.setApp(context, value.toString(), user)
loadSettings(context)
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/Gesture.kt b/app/src/main/java/de/jrpie/android/launcher/Gesture.kt
index 8d70340..fc48d1d 100644
--- a/app/src/main/java/de/jrpie/android/launcher/Gesture.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/Gesture.kt
@@ -41,8 +41,12 @@ enum class Gesture (val id: String, private val labelResource: Int,
TOP, BOTTOM, LEFT, RIGHT
}
- fun getApp(context: Context): String {
- return getPreferences(context).getString(this.id, "")!!
+ fun getApp(context: Context): Pair {
+ val preferences = getPreferences(context)
+ var packageName = preferences.getString(this.id, "")!!
+ var u: Int? = preferences.getInt(this.id + "_user", INVALID_USER)
+ u = if(u == INVALID_USER) null else u
+ return Pair(packageName,u)
}
fun removeApp(context: Context) {
@@ -51,10 +55,15 @@ enum class Gesture (val id: String, private val labelResource: Int,
.apply()
}
- fun setApp(context: Context, app: String) {
+ fun setApp(context: Context, app: String, user: Int?) {
getPreferences(context).edit()
.putString(this.id, app)
.apply()
+
+ val u = user?: INVALID_USER
+ getPreferences(context).edit()
+ .putInt(this.id + "_user", u)
+ .apply()
}
fun getLabel(context: Context): String {
@@ -132,7 +141,8 @@ enum class Gesture (val id: String, private val labelResource: Int,
}
operator fun invoke(activity: Activity) {
- launch(this.getApp(activity), activity, this.animationIn, this.animationOut)
+ val app = this.getApp(activity)
+ launch(app.first, app.second, activity, this.animationIn, this.animationOut)
}
companion object {
diff --git a/app/src/main/java/de/jrpie/android/launcher/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/HomeActivity.kt
index 10529ed..fd20091 100644
--- a/app/src/main/java/de/jrpie/android/launcher/HomeActivity.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/HomeActivity.kt
@@ -87,7 +87,7 @@ class HomeActivity: UIObject, AppCompatActivity(),
}
// Preload apps to speed up the Apps Recycler
- AsyncTask.execute { loadApps(packageManager) }
+ AsyncTask.execute { loadApps(packageManager, applicationContext) }
// Initialise layout
binding = HomeBinding.inflate(layoutInflater)
diff --git a/app/src/main/java/de/jrpie/android/launcher/list/apps/AppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/list/apps/AppInfo.kt
index 0c99757..f19fd0e 100644
--- a/app/src/main/java/de/jrpie/android/launcher/list/apps/AppInfo.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/list/apps/AppInfo.kt
@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable
* Represents an app installed on the users device.
*/
class AppInfo {
+ var user: Int? = null
var label: CharSequence? = null
var packageName: CharSequence? = null
var icon: Drawable? = null
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 a0c76da..d0d70b5 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
@@ -21,6 +21,7 @@ import de.jrpie.android.launcher.appsList
import de.jrpie.android.launcher.getPreferences
import de.jrpie.android.launcher.getSavedTheme
import de.jrpie.android.launcher.launch
+import de.jrpie.android.launcher.launchApp
import de.jrpie.android.launcher.list.ListActivity
import de.jrpie.android.launcher.list.intendedChoosePause
import de.jrpie.android.launcher.loadApps
@@ -54,9 +55,10 @@ class AppsRecyclerAdapter(val activity: Activity,
val pos = adapterPosition
val context: Context = v.context
val appPackageName = appsListDisplayed[pos].packageName.toString()
-
+ val appUser = appsListDisplayed[pos].user
when (intention){
ListActivity.ListActivityIntention.VIEW -> {
+ launchApp(appPackageName, appUser, activity)
val launchIntent: Intent = context.packageManager
.getLaunchIntentForPackage(appPackageName)!!
context.startActivity(launchIntent)
@@ -64,6 +66,7 @@ class AppsRecyclerAdapter(val activity: Activity,
ListActivity.ListActivityIntention.PICK -> {
val returnIntent = Intent()
returnIntent.putExtra("value", appPackageName)
+ appUser?.let{ returnIntent.putExtra("user", it) }
returnIntent.putExtra("forGesture", forGesture)
activity.setResult(REQUEST_CHOOSE_APP, returnIntent)
activity.finish()
@@ -152,9 +155,9 @@ class AppsRecyclerAdapter(val activity: Activity,
init {
// Load the apps
if (appsList.size == 0)
- loadApps(activity.packageManager)
+ loadApps(activity.packageManager, activity)
else {
- AsyncTask.execute { loadApps(activity.packageManager) }
+ AsyncTask.execute { loadApps(activity.packageManager, activity) }
notifyDataSetChanged()
}
@@ -193,7 +196,8 @@ class AppsRecyclerAdapter(val activity: Activity,
// modifiable at some later point.
if (appsListDisplayed.size == 1 && intention == ListActivity.ListActivityIntention.VIEW
&& getPreferences(activity).getBoolean(PREF_SEARCH_AUTO_LAUNCH, false)) {
- launch(appsListDisplayed[0].packageName.toString(), activity)
+ val info = appsListDisplayed[0]
+ launch(info.packageName.toString(), info.user, activity)
val inputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(View(activity).windowToken, 0)
diff --git a/app/src/main/java/de/jrpie/android/launcher/list/other/OtherRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/list/other/OtherRecyclerAdapter.kt
index 1e04a0d..0b54fa6 100644
--- a/app/src/main/java/de/jrpie/android/launcher/list/other/OtherRecyclerAdapter.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/list/other/OtherRecyclerAdapter.kt
@@ -8,6 +8,7 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
+import de.jrpie.android.launcher.INVALID_USER
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.REQUEST_CHOOSE_APP
import de.jrpie.android.launcher.list.forGesture
@@ -56,10 +57,11 @@ class OtherRecyclerAdapter(val activity: Activity):
return ViewHolder(view)
}
- private fun returnChoiceIntent(forApp: String, value: String) {
+ private fun returnChoiceIntent(forGesture: String, value: String) {
val returnIntent = Intent()
returnIntent.putExtra("value", value)
- returnIntent.putExtra("forGesture", forApp)
+ returnIntent.putExtra("forGesture", forGesture)
+ returnIntent.putExtra("user", INVALID_USER)
activity.setResult(REQUEST_CHOOSE_APP, returnIntent)
activity.finish()
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActionsRecycler.kt b/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActionsRecycler.kt
index 0685a87..3e609c4 100644
--- a/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActionsRecycler.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/settings/actions/SettingsFragmentActionsRecycler.kt
@@ -80,7 +80,8 @@ class ActionsRecyclerAdapter(val activity: Activity):
viewHolder.img
)
fun updateViewHolder() {
- val content = gesture.getApp(activity)
+ val app = gesture.getApp(activity)
+ val content = app.first
if (content == ""){
viewHolder.img.visibility = View.INVISIBLE
viewHolder.removeAction.visibility = View.GONE
@@ -93,7 +94,7 @@ class ActionsRecyclerAdapter(val activity: Activity):
} else {
// Set image icon (by packageName)
try {
- viewHolder.img.setImageDrawable(activity.packageManager.getApplicationIcon(content))
+ viewHolder.img.setImageDrawable(getAppIcon(activity, content, app.second))
} catch (e : Exception) {
// the button is shown, user asked to select an action
viewHolder.img.visibility = View.INVISIBLE