Skip to content

Commit c072588

Browse files
Feat: Added the start of Private Spaces
I will look into maybe having a 2nd app list for private space apps in the feature. closes #611
1 parent 25955a9 commit c072588

File tree

15 files changed

+285
-118
lines changed

15 files changed

+285
-118
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
tools:ignore="QueryAllPackagesPermission" />
1515
<!--For opening alarm app-->
1616
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
17+
<uses-permission android:name="android.permission.ACCESS_HIDDEN_PROFILES" />
1718
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
1819

1920
<application
@@ -86,7 +87,6 @@
8687
<action android:name="android.accessibilityservice.AccessibilityService" />
8788
</intent-filter>
8889
</service>
89-
9090
</application>
9191

9292
</manifest>

app/src/main/java/com/github/droidworksstudio/mlauncher/MainActivity.kt

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import android.os.Build
99
import android.os.Bundle
1010
import android.os.Handler
1111
import android.os.Looper
12-
import android.provider.Settings
1312
import android.view.KeyEvent
1413
import android.view.View
1514
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
@@ -18,7 +17,6 @@ import androidx.appcompat.app.AppCompatDelegate
1817
import androidx.lifecycle.ViewModelProvider
1918
import androidx.navigation.NavController
2019
import androidx.navigation.Navigation
21-
import com.github.droidworksstudio.common.showLongToast
2220
import com.github.droidworksstudio.mlauncher.data.Constants
2321
import com.github.droidworksstudio.mlauncher.data.Migration
2422
import com.github.droidworksstudio.mlauncher.data.Prefs
@@ -150,12 +148,6 @@ class MainActivity : AppCompatActivity() {
150148
@Deprecated("Deprecated in Java")
151149
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
152150
super.onActivityResult(requestCode, resultCode, data)
153-
154-
if (resultCode != RESULT_OK) {
155-
showLongToast("Intent Error")
156-
return
157-
}
158-
159151
when (requestCode) {
160152
Constants.REQUEST_CODE_ENABLE_ADMIN -> {
161153
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P)
@@ -235,9 +227,6 @@ class MainActivity : AppCompatActivity() {
235227
}
236228

237229
private fun initObservers(viewModel: MainViewModel) {
238-
viewModel.launcherResetFailed.observe(this) {
239-
openLauncherChooser(it)
240-
}
241230
viewModel.showMessageDialog.observe(this) {
242231
showMessage(it)
243232
}
@@ -258,13 +247,6 @@ class MainActivity : AppCompatActivity() {
258247
navController.popBackStack(R.id.mainFragment, false)
259248
}
260249

261-
private fun openLauncherChooser(resetFailed: Boolean) {
262-
if (resetFailed) {
263-
val intent = Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
264-
startActivity(intent)
265-
}
266-
}
267-
268250
private fun showMessage(message: String) {
269251
if (message.isEmpty()) return
270252
binding.messageTextView.text = message

app/src/main/java/com/github/droidworksstudio/mlauncher/MainViewModel.kt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ import com.github.droidworksstudio.mlauncher.data.Constants.AppDrawerFlag
1414
import com.github.droidworksstudio.mlauncher.data.Prefs
1515
import com.github.droidworksstudio.mlauncher.helper.AppUsageTracker
1616
import com.github.droidworksstudio.mlauncher.helper.getAppsList
17-
import com.github.droidworksstudio.mlauncher.helper.getDefaultLauncherPackage
1817
import com.github.droidworksstudio.mlauncher.helper.ismlauncherDefault
19-
import com.github.droidworksstudio.mlauncher.helper.resetDefaultLauncher
18+
import com.github.droidworksstudio.mlauncher.helper.setDefaultHomeScreen
2019
import kotlinx.coroutines.launch
2120

2221
class MainViewModel(application: Application) : AndroidViewModel(application) {
@@ -30,7 +29,6 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
3029
val appList = MutableLiveData<List<AppListItem>?>() // TODO why maybe?
3130
val hiddenApps = MutableLiveData<List<AppListItem>?>()
3231
private val launcherDefault = MutableLiveData<Boolean>()
33-
val launcherResetFailed = MutableLiveData<Boolean>()
3432

3533
val showDate = MutableLiveData(prefs.showDate)
3634
val showClock = MutableLiveData(prefs.showClock)
@@ -49,11 +47,11 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
4947

5048
fun selectedApp(app: AppListItem, flag: AppDrawerFlag, n: Int = 0) {
5149
when (flag) {
52-
AppDrawerFlag.LaunchApp, AppDrawerFlag.HiddenApps -> {
50+
AppDrawerFlag.LaunchApp, AppDrawerFlag.HiddenApps, AppDrawerFlag.PrivateApps -> {
5351
launchApp(app)
5452
}
5553

56-
AppDrawerFlag.SetHomeApp, AppDrawerFlag.ReorderApps -> {
54+
AppDrawerFlag.SetHomeApp -> {
5755
prefs.setHomeAppModel(n, app)
5856
}
5957

@@ -148,10 +146,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
148146
}
149147

150148
fun resetDefaultLauncherApp(context: Context) {
151-
resetDefaultLauncher(context)
152-
launcherResetFailed.value = getDefaultLauncherPackage(
153-
appContext
154-
).contains(".")
149+
setDefaultHomeScreen(context)
155150
}
156151

157152
fun updateDrawerAlignment(gravity: Constants.Gravity) {

app/src/main/java/com/github/droidworksstudio/mlauncher/data/Constants.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface EnumOption {
1919
object Constants {
2020

2121
const val REQUEST_CODE_ENABLE_ADMIN = 666
22+
const val REQUEST_SET_DEFAULT_HOME = 777
2223

2324
const val TRIPLE_TAP_DELAY_MS = 300
2425
const val LONG_PRESS_DELAY_MS = 500
@@ -98,7 +99,7 @@ object Constants {
9899
enum class AppDrawerFlag {
99100
LaunchApp,
100101
HiddenApps,
101-
ReorderApps,
102+
PrivateApps,
102103
SetHomeApp,
103104
SetShortSwipeUp,
104105
SetShortSwipeDown,
@@ -264,6 +265,7 @@ object Constants {
264265

265266
enum class Action : EnumOption {
266267
OpenApp,
268+
TogglePrivateSpace,
267269
LockScreen,
268270
ShowNotification,
269271
ShowAppList,
@@ -280,6 +282,7 @@ object Constants {
280282
return when (this) {
281283
OpenApp -> context.getString(R.string.open_app)
282284
LockScreen -> context.getString(R.string.lock_screen)
285+
TogglePrivateSpace -> context.getString(R.string.private_space)
283286
ShowNotification -> context.getString(R.string.show_notifications)
284287
ShowAppList -> context.getString(R.string.show_app_list)
285288
OpenQuickSettings -> context.getString(R.string.open_quick_settings)
@@ -298,6 +301,7 @@ object Constants {
298301
return when (this) {
299302
OpenApp -> stringResource(R.string.open_app)
300303
LockScreen -> stringResource(R.string.lock_screen)
304+
TogglePrivateSpace -> stringResource(R.string.private_space)
301305
ShowNotification -> stringResource(R.string.show_notifications)
302306
ShowAppList -> stringResource(R.string.show_app_list)
303307
OpenQuickSettings -> stringResource(R.string.open_quick_settings)

app/src/main/java/com/github/droidworksstudio/mlauncher/helper/BatteryReceiver.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class BatteryReceiver : BroadcastReceiver() {
5555
}
5656
}
5757

58-
var batteryLevelInt = batteryLevel.toInt()
58+
val batteryLevelInt = batteryLevel.toInt()
5959
batteryTextView?.text = buildString {
6060
append(batteryLevelInt)
6161
append("%")
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.github.droidworksstudio.mlauncher.helper
2+
3+
import android.content.ActivityNotFoundException
4+
import android.content.Context
5+
import android.content.pm.LauncherApps
6+
import android.os.Build
7+
import android.os.Handler
8+
import android.os.Looper
9+
import android.os.UserHandle
10+
import android.os.UserManager
11+
import android.util.Log
12+
import com.github.droidworksstudio.common.showLongToast
13+
import com.github.droidworksstudio.mlauncher.MainViewModel
14+
import com.github.droidworksstudio.mlauncher.R
15+
16+
private lateinit var viewModel: MainViewModel
17+
18+
/*
19+
* Checks whether the device supports private space.
20+
*/
21+
fun isPrivateSpaceSupported(): Boolean {
22+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
23+
}
24+
25+
fun getPrivateSpaceUser(context: Context): UserHandle? {
26+
if (!isPrivateSpaceSupported()) {
27+
return null
28+
}
29+
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
30+
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
31+
return userManager.userProfiles.firstOrNull { u ->
32+
launcherApps.getLauncherUserInfo(u)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE
33+
}
34+
}
35+
36+
/**
37+
* Check if the given user profile is the private space.
38+
*/
39+
fun isPrivateSpaceProfile(context: Context, userHandle: UserHandle): Boolean {
40+
if (!isPrivateSpaceSupported()) {
41+
return false
42+
}
43+
44+
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
45+
try {
46+
val userType = launcherApps.getLauncherUserInfo(userHandle)?.userType
47+
return userType == UserManager.USER_TYPE_PROFILE_PRIVATE
48+
} catch (e: Exception) {
49+
Log.e("PrivateSpace", "Failed to retrieve launcher user info", e)
50+
return false
51+
}
52+
}
53+
54+
55+
/**
56+
* Check whether the user has created a private space and whether mLauncher can access it.
57+
*/
58+
fun isPrivateSpaceSetUp(
59+
context: Context,
60+
showToast: Boolean = false,
61+
launchSettings: Boolean = false
62+
): Boolean {
63+
if (!isPrivateSpaceSupported()) {
64+
if (showToast) {
65+
context.showLongToast(context.getString(R.string.alert_requires_android_v))
66+
}
67+
return false
68+
}
69+
val privateSpaceUser = getPrivateSpaceUser(context)
70+
if (privateSpaceUser != null) {
71+
return true
72+
}
73+
if (!ismlauncherDefault(context)) {
74+
if (showToast) {
75+
context.showLongToast(context.getString(R.string.toast_private_space_default_home_screen))
76+
}
77+
if (launchSettings) {
78+
viewModel.resetDefaultLauncherApp(context)
79+
}
80+
} else {
81+
if (showToast) {
82+
context.showLongToast(context.getString(R.string.toast_private_space_not_available))
83+
}
84+
if (launchSettings) {
85+
try {
86+
viewModel.resetDefaultLauncherApp(context)
87+
} catch (_: ActivityNotFoundException) {
88+
}
89+
}
90+
}
91+
return false
92+
}
93+
94+
fun isPrivateSpaceLocked(context: Context): Boolean {
95+
if (!isPrivateSpaceSupported()) {
96+
return false
97+
}
98+
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
99+
val privateSpaceUser = getPrivateSpaceUser(context) ?: return false
100+
return userManager.isQuietModeEnabled(privateSpaceUser)
101+
}
102+
103+
fun lockPrivateSpace(context: Context, lock: Boolean) {
104+
if (!isPrivateSpaceSupported()) {
105+
return
106+
}
107+
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
108+
val privateSpaceUser = getPrivateSpaceUser(context) ?: return
109+
userManager.requestQuietModeEnabled(lock, privateSpaceUser)
110+
}
111+
112+
fun togglePrivateSpaceLock(context: Context) {
113+
if (!isPrivateSpaceSetUp(context, showToast = true, launchSettings = true)) {
114+
return
115+
}
116+
if (!ismlauncherDefault(context)) {
117+
context.showLongToast(context.getString(R.string.toast_private_space_default_home_screen))
118+
return
119+
}
120+
121+
val lock = isPrivateSpaceLocked(context)
122+
lockPrivateSpace(context, !lock)
123+
124+
Handler(Looper.getMainLooper()).post {
125+
if (isPrivateSpaceLocked(context) == !lock) {
126+
context.showLongToast(context.getString(R.string.toast_private_space_locked))
127+
}
128+
}
129+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.github.droidworksstudio.mlauncher.helper
2+
3+
import android.content.BroadcastReceiver
4+
import android.content.Context
5+
import android.content.Intent
6+
import com.github.droidworksstudio.common.showLongToast
7+
import com.github.droidworksstudio.mlauncher.R
8+
9+
class PrivateSpaceReceiver : BroadcastReceiver() {
10+
override fun onReceive(context: Context, intent: Intent?) {
11+
// Check if the received action is for managed profile availability
12+
if (intent?.action == Intent.ACTION_PROFILE_AVAILABLE) {
13+
// Handle the event when the managed profile is available
14+
context.showLongToast(context.getString(R.string.toast_private_space_unlocked))
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)