Skip to content

Commit 515b5c4

Browse files
committed
feat: 添加首次使用引导页及电池优化设置
1 parent 29766da commit 515b5c4

7 files changed

Lines changed: 343 additions & 82 deletions

File tree

‎app/src/main/AndroidManifest.xml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
1111
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
1212
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
13+
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
1314

1415
<application
1516
android:allowBackup="true"
@@ -23,6 +24,7 @@
2324
<activity
2425
android:name=".ConfigActivity"
2526
android:windowSoftInputMode="adjustResize" />
27+
<activity android:name=".OnboardingActivity" />
2628
<activity android:name=".AboutActivity" />
2729
<activity android:name=".SettingsActivity" />
2830

‎app/src/main/java/io/github/acedroidx/frp/MainActivity.kt‎

Lines changed: 8 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
package io.github.acedroidx.frp
22

3-
import android.Manifest
43
import android.app.NotificationChannel
54
import android.app.NotificationManager
65
import android.content.ComponentName
76
import android.content.Intent
87
import android.content.ServiceConnection
98
import android.content.SharedPreferences
10-
import android.content.pm.PackageManager
11-
import android.net.Uri
12-
import android.provider.Settings
139
import android.os.Build
1410
import android.os.Bundle
1511
import android.os.IBinder
@@ -55,7 +51,6 @@ import androidx.compose.runtime.getValue
5551
import androidx.compose.runtime.LaunchedEffect
5652
import androidx.compose.runtime.mutableStateOf
5753
import androidx.compose.runtime.remember
58-
import androidx.compose.runtime.rememberCoroutineScope
5954
import androidx.compose.ui.Alignment
6055
import androidx.compose.ui.Modifier
6156
import androidx.compose.ui.res.painterResource
@@ -71,14 +66,12 @@ import androidx.compose.animation.fadeIn
7166
import androidx.compose.animation.fadeOut
7267
import androidx.compose.animation.core.tween
7368
import androidx.compose.animation.core.FastOutSlowInEasing
74-
import androidx.core.content.ContextCompat
7569
import androidx.lifecycle.compose.collectAsStateWithLifecycle
7670
import androidx.lifecycle.lifecycleScope
7771
import io.github.acedroidx.frp.ui.theme.FrpTheme
7872
import io.github.acedroidx.frp.ui.theme.ThemeModeKeys
7973
import kotlinx.coroutines.flow.MutableStateFlow
8074
import kotlinx.coroutines.launch
81-
import androidx.compose.material3.SnackbarResult
8275
import java.io.File
8376
import java.text.SimpleDateFormat
8477
import java.util.Date
@@ -93,25 +86,12 @@ class MainActivity : ComponentActivity() {
9386
private val runningConfigList = MutableStateFlow<List<FrpConfig>>(emptyList())
9487
private val frpVersion = MutableStateFlow("")
9588
private val themeMode = MutableStateFlow("")
96-
private val permissionGranted = MutableStateFlow(true)
9789

9890
private lateinit var preferences: SharedPreferences
9991

10092
private lateinit var mService: ShellService
10193
private var mBound: Boolean = false
10294

103-
// 权限请求启动器
104-
private val notificationPermissionLauncher = registerForActivityResult(
105-
ActivityResultContracts.RequestPermission()
106-
) { isGranted: Boolean ->
107-
permissionGranted.value = isGranted
108-
if (!isGranted) {
109-
Log.w("adx", "Notification permission denied")
110-
} else {
111-
Log.d("adx", "Notification permission granted")
112-
}
113-
}
114-
11595
/** Defines callbacks for service binding, passed to bindService() */
11696
private val connection = object : ServiceConnection {
11797

@@ -173,6 +153,14 @@ class MainActivity : ComponentActivity() {
173153

174154
preferences = getSharedPreferences("data", MODE_PRIVATE)
175155

156+
// 首次启动引导页
157+
val isFirstLaunch = !preferences.getBoolean(PreferencesKey.FIRST_LAUNCH_DONE, false)
158+
if (isFirstLaunch) {
159+
startActivity(Intent(this, OnboardingActivity::class.java))
160+
finish()
161+
return
162+
}
163+
176164
// 应用"最近任务中排除"设置
177165
val excludeFromRecents = preferences.getBoolean(PreferencesKey.EXCLUDE_FROM_RECENTS, false)
178166
try {
@@ -197,7 +185,6 @@ class MainActivity : ComponentActivity() {
197185
checkConfig()
198186
updateConfigList()
199187
createBGNotificationChannel()
200-
checkAndRequestPermissions()
201188

202189
if (preferences.getBoolean(PreferencesKey.AUTO_START_LAUNCH, false)) {
203190
maybeAutoStartOnLaunch()
@@ -208,7 +195,6 @@ class MainActivity : ComponentActivity() {
208195
val currentTheme by themeMode.collectAsStateWithLifecycle(themeMode.collectAsState().value)
209196
val openDialog = remember { mutableStateOf(false) }
210197
val snackbarHostState = remember { SnackbarHostState() }
211-
val permissionGranted by permissionGranted.collectAsStateWithLifecycle(true)
212198

213199
FrpTheme(themeMode = currentTheme) {
214200
val frpVersion by frpVersion.collectAsStateWithLifecycle(frpVersion.collectAsState().value.ifEmpty { loadingText })
@@ -265,32 +251,6 @@ class MainActivity : ComponentActivity() {
265251
if (openDialog.value) {
266252
CreateConfigDialog { openDialog.value = false }
267253
}
268-
269-
// 显示权限提示
270-
val scope = rememberCoroutineScope()
271-
val notificationPermissionMessage =
272-
stringResource(R.string.notification_permission_denied_message)
273-
val notificationPermissionAction =
274-
stringResource(R.string.notification_permission_action_settings)
275-
LaunchedEffect(permissionGranted) {
276-
if (!permissionGranted && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
277-
scope.launch {
278-
val result = snackbarHostState.showSnackbar(
279-
message = notificationPermissionMessage,
280-
actionLabel = notificationPermissionAction,
281-
withDismissAction = true
282-
)
283-
if (result == SnackbarResult.ActionPerformed) {
284-
// 跳转到应用设置页面
285-
val intent =
286-
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
287-
data = Uri.fromParts("package", packageName, null)
288-
}
289-
startActivity(intent)
290-
}
291-
}
292-
}
293-
}
294254
}
295255
}
296256

@@ -581,14 +541,6 @@ class MainActivity : ComponentActivity() {
581541
} catch (e: Exception) {
582542
Log.e("MainActivity", "Failed to set excludeFromRecents in onResume: ${e.message}")
583543
}
584-
585-
// 重新检查权限状态(用户可能从设置页面返回)
586-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
587-
val hasNotificationPermission = ContextCompat.checkSelfPermission(
588-
this, Manifest.permission.POST_NOTIFICATIONS
589-
) == PackageManager.PERMISSION_GRANTED
590-
permissionGranted.value = hasNotificationPermission
591-
}
592544
}
593545

594546
override fun onDestroy() {
@@ -671,32 +623,6 @@ class MainActivity : ComponentActivity() {
671623
startService(intent)
672624
}
673625

674-
/**
675-
* 检查并请求必要的运行时权限
676-
*/
677-
private fun checkAndRequestPermissions() {
678-
// Android 13 及以上需要通知权限
679-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
680-
val hasNotificationPermission = ContextCompat.checkSelfPermission(
681-
this, Manifest.permission.POST_NOTIFICATIONS
682-
) == PackageManager.PERMISSION_GRANTED
683-
684-
permissionGranted.value = hasNotificationPermission
685-
686-
if (!hasNotificationPermission) {
687-
// 检查是否应该显示权限说明
688-
if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
689-
Log.d("adx", "Should show permission rationale")
690-
}
691-
// 请求权限
692-
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
693-
}
694-
} else {
695-
// Android 13 以下不需要动态请求通知权限
696-
permissionGranted.value = true
697-
}
698-
}
699-
700626
private fun createBGNotificationChannel() {
701627
// Create the NotificationChannel, but only on API 26+ because
702628
// the NotificationChannel class is new and not in the support library

0 commit comments

Comments
 (0)