Skip to content

Commit 9163334

Browse files
Refactor: Added better support for work profiles.
fixed #114 Signed-off-by: HeCodes2Much <wayne6324@gmail.com>
1 parent 7706c93 commit 9163334

File tree

8 files changed

+158
-63
lines changed

8 files changed

+158
-63
lines changed

app/src/main/java/com/github/droidworksstudio/common/ContextExtensions.kt

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.droidworksstudio.common
33
import android.Manifest
44
import android.app.SearchManager
55
import android.content.ActivityNotFoundException
6+
import android.content.ComponentName
67
import android.content.Context
78
import android.content.Intent
89
import android.content.pm.LauncherApps
@@ -33,9 +34,10 @@ import androidx.core.graphics.drawable.toBitmap
3334
import androidx.core.os.ConfigurationCompat
3435
import androidx.lifecycle.LifecycleObserver
3536
import androidx.lifecycle.LifecycleOwner
36-
import com.github.droidworksstudio.launcher.utils.Constants
3737
import com.github.droidworksstudio.launcher.data.entities.AppInfo
3838
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
39+
import com.github.droidworksstudio.launcher.ui.activities.LauncherActivity
40+
import com.github.droidworksstudio.launcher.utils.Constants
3941
import java.util.Calendar
4042
import java.util.Date
4143
import kotlin.math.pow
@@ -184,12 +186,46 @@ fun Context.appInfo(appInfo: AppInfo) {
184186
}
185187

186188
fun Context.launchApp(appInfo: AppInfo) {
187-
val intent = this.packageManager.getLaunchIntentForPackage(appInfo.packageName)
188-
if (intent != null) {
189-
this.startActivity(intent)
189+
val packageName = appInfo.packageName
190+
val primaryUserHandle = android.os.Process.myUserHandle()
191+
val userHandle = getUserHandleFromId(appInfo.userHandle) ?: primaryUserHandle // Fallback to current user if not provided
192+
193+
// Get the LauncherApps service
194+
val launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
195+
196+
// Attempt to get the launch intent for the package
197+
val activityList = launcherApps.getActivityList(packageName, userHandle)
198+
199+
Log.d("launchApp", "launchApp: $packageName - $activityList")
200+
if (activityList.isNotEmpty()) {
201+
val componentName = ComponentName(packageName, activityList[0].name)
202+
try {
203+
// Start the app's main activity
204+
launcherApps.startMainActivity(componentName, userHandle, null, null)
205+
} catch (e: SecurityException) {
206+
Log.e("launchApp", "SecurityException: ${e.message}")
207+
showLongToast("Unable to launch app due to security restrictions")
208+
} catch (e: Exception) {
209+
Log.e("launchApp", "Exception: ${e.message}")
210+
showLongToast("Unable to launch app")
211+
}
190212
} else {
191-
showLongToast("Failed to open the application")
213+
showLongToast("Failed to find the application activity")
214+
}
215+
}
216+
217+
fun Context.getUserHandleFromId(userId: Int): UserHandle? {
218+
val userManager = getSystemService(Context.USER_SERVICE) as UserManager
219+
// Get all available UserHandles
220+
val userProfiles = userManager.userProfiles
221+
// Iterate over user profiles
222+
for (userProfile in userProfiles) {
223+
// Check if the UserHandle matches the provided user ID
224+
if (userProfile.hashCode() == userId) {
225+
return userProfile
226+
}
192227
}
228+
return null
193229
}
194230

195231
fun Context.launchClock() {
@@ -212,11 +248,11 @@ fun Context.launchCalendar() {
212248
this.startActivity(Intent(Intent.ACTION_VIEW, builder.build()))
213249
} catch (e: Exception) {
214250
try {
215-
val intent = Intent(Intent.ACTION_MAIN)
251+
val intent = Intent(this, LauncherActivity::class.java)
216252
intent.addCategory(Intent.CATEGORY_APP_CALENDAR)
217253
this.startActivity(intent)
218254
} catch (e: Exception) {
219-
Log.d("openCalendar", e.toString())
255+
Log.e("openCalendar", e.toString())
220256
}
221257
}
222258
}

app/src/main/java/com/github/droidworksstudio/launcher/Application.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Application
44
import android.content.Context
55
import android.graphics.Typeface
66
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
7+
import com.github.droidworksstudio.launcher.helper.contextProvider.kt.ContextProvider
78
import dagger.hilt.android.HiltAndroidApp
89
import org.acra.ACRA
910
import org.acra.ReportField
@@ -23,6 +24,8 @@ class Application : Application() {
2324
override fun onCreate() {
2425
super.onCreate()
2526

27+
ContextProvider.init(this)
28+
2629
setCustomFont(applicationContext)
2730

2831
val pkgName = getString(R.string.app_name)

app/src/main/java/com/github/droidworksstudio/launcher/data/dao/AppInfoDAO.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package com.github.droidworksstudio.launcher.data.dao
22

33
import android.util.Log
4-
import androidx.room.*
4+
import androidx.room.Dao
5+
import androidx.room.Delete
6+
import androidx.room.Insert
7+
import androidx.room.OnConflictStrategy
8+
import androidx.room.Query
9+
import androidx.room.Transaction
10+
import androidx.room.Update
511
import com.github.droidworksstudio.launcher.data.entities.AppInfo
612
import kotlinx.coroutines.flow.Flow
713

@@ -73,10 +79,10 @@ interface AppInfoDAO {
7379
@Query("SELECT * FROM app WHERE is_favorite = 1")
7480
fun getFavoriteAppInfo(): List<AppInfo>
7581

76-
@Query("SELECT * FROM app WHERE package_name = :packageName AND is_work = 0")
82+
@Query("SELECT * FROM app WHERE package_name = :packageName AND user_handle = 0")
7783
suspend fun getAppByPackageName(packageName: String): AppInfo?
7884

79-
@Query("SELECT * FROM app WHERE package_name = :packageName AND is_work = 1")
85+
@Query("SELECT * FROM app WHERE package_name = :packageName AND user_handle != 0")
8086
suspend fun getAppByPackageNameWork(packageName: String): AppInfo?
8187

8288
private fun logUpdate(message: String, appInfo: AppInfo) {

app/src/main/java/com/github/droidworksstudio/launcher/data/entities/AppInfo.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ data class AppInfo(
2626
@ColumnInfo(name = "is_lock")
2727
var lock: Boolean,
2828

29-
@ColumnInfo(name = "is_work")
30-
var work: Boolean,
29+
@ColumnInfo(name = "user_handle")
30+
var userHandle: Int,
3131

3232
@ColumnInfo(name = "create_time")
3333
var createTime: String,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.github.droidworksstudio.launcher.helper.contextProvider.kt
2+
3+
import android.content.Context
4+
5+
object ContextProvider {
6+
lateinit var applicationContext: Context
7+
private set
8+
9+
fun init(context: Context) {
10+
applicationContext = context
11+
}
12+
}
13+
14+

app/src/main/java/com/github/droidworksstudio/launcher/repository/AppInfoRepository.kt

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import android.os.UserHandle
88
import android.os.UserManager
99
import android.util.Log
1010
import androidx.annotation.RequiresApi
11-
import com.github.droidworksstudio.launcher.utils.Constants
1211
import com.github.droidworksstudio.launcher.data.dao.AppInfoDAO
1312
import com.github.droidworksstudio.launcher.data.entities.AppInfo
13+
import com.github.droidworksstudio.launcher.helper.contextProvider.kt.ContextProvider
14+
import com.github.droidworksstudio.launcher.utils.Constants
1415
import kotlinx.coroutines.Dispatchers
1516
import kotlinx.coroutines.flow.Flow
1617
import kotlinx.coroutines.flow.firstOrNull
@@ -24,6 +25,9 @@ class AppInfoRepository @Inject constructor(
2425
private val appDao: AppInfoDAO,
2526
) {
2627

28+
private val context: Context
29+
get() = ContextProvider.applicationContext
30+
2731
@Inject
2832
lateinit var packageManager: PackageManager
2933

@@ -93,16 +97,32 @@ class AppInfoRepository @Inject constructor(
9397
appDao.updateLockApp(appInfo, appLock)
9498
}
9599

100+
@RequiresApi(Build.VERSION_CODES.R)
96101
private suspend fun getInstalledPackages(): Set<String> = withContext(Dispatchers.IO) {
97-
98-
val packages = HashSet<String>()
99-
val apps = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
100-
for (app in apps) {
101-
packages.add(app.packageName)
102+
val packages = mutableSetOf<String>()
103+
104+
// Obtain UserManager and LauncherApps services
105+
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
106+
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
107+
108+
// Iterate through each user profile
109+
for (userHandle in userManager.userProfiles) {
110+
try {
111+
// Get the package list for the user profile
112+
val apps = launcherApps.getActivityList(null, userHandle)
113+
for (app in apps) {
114+
packages.add(app.applicationInfo.packageName)
115+
}
116+
} catch (e: Exception) {
117+
// Handle potential exceptions
118+
Log.e("AppInfoRepository", "Error retrieving packages for user $userHandle", e)
119+
}
102120
}
121+
103122
packages
104123
}
105124

125+
106126
@RequiresApi(Build.VERSION_CODES.O)
107127
suspend fun initInstalledAppInfo(context: Context): List<AppInfo> =
108128
withContext(Dispatchers.IO) {
@@ -125,9 +145,7 @@ class AppInfoRepository @Inject constructor(
125145
val newAppList: List<AppInfo> = userManager.userProfiles
126146
.flatMap { profile ->
127147
// Invoke the getIdentifier method on the UserHandle instance
128-
val userId = getIdentifierMethod.invoke(profile) as Int
129-
130-
when (userId) {
148+
when (val userId = getIdentifierMethod.invoke(profile) as Int) {
131149
0 -> {
132150
// Handle the case when profile is UserHandle{0}
133151
launcherApps.getActivityList(null, profile)
@@ -142,7 +160,7 @@ class AppInfoRepository @Inject constructor(
142160
hidden = false,
143161
lock = false,
144162
createTime = currentDateTime.toString(),
145-
work = false,
163+
userHandle = userId,
146164
)
147165
} else {
148166
val existingApp = getAppByPackageName(packageName)
@@ -166,7 +184,7 @@ class AppInfoRepository @Inject constructor(
166184
hidden = false,
167185
lock = false,
168186
createTime = currentDateTime.toString(),
169-
work = true,
187+
userHandle = userId,
170188
)
171189
} else {
172190
val existingApp = getAppByPackageNameWork(packageName)

0 commit comments

Comments
 (0)