From 1b4bee03738ddc5ab952ddbbf821b001a63557c0 Mon Sep 17 00:00:00 2001 From: D4rK7355608 Date: Tue, 18 Jun 2024 09:26:12 +0300 Subject: [PATCH] Updated the startup screen --- .../cleaner/ui/startup/StartupActivity.kt | 80 ++++--------------- .../cleaner/ui/startup/StartupComposable.kt | 68 ++++++++++------ 2 files changed, 59 insertions(+), 89 deletions(-) diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupActivity.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupActivity.kt index c4072af..e0552c6 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupActivity.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupActivity.kt @@ -1,37 +1,31 @@ package com.d4rk.cleaner.ui.startup import android.Manifest -import android.app.AppOpsManager -import android.content.Intent -import android.net.Uri import android.os.Build import android.os.Bundle -import android.os.Environment -import android.provider.Settings -import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier -import androidx.core.app.ActivityCompat import com.d4rk.cleaner.ui.settings.display.theme.style.AppTheme import com.google.android.ump.ConsentForm import com.google.android.ump.ConsentInformation import com.google.android.ump.ConsentRequestParameters import com.google.android.ump.UserMessagingPlatform -class StartupActivity : ComponentActivity() { - private lateinit var consentInformation: ConsentInformation - private lateinit var consentForm: ConsentForm - override fun onCreate(savedInstanceState: Bundle?) { +class StartupActivity : AppCompatActivity() { + private lateinit var consentInformation : ConsentInformation + private lateinit var consentForm : ConsentForm + override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { AppTheme { Surface( - modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background + modifier = Modifier.fillMaxSize() , color = MaterialTheme.colorScheme.background ) { StartupComposable() } @@ -39,11 +33,11 @@ class StartupActivity : ComponentActivity() { } val params = ConsentRequestParameters.Builder().setTagForUnderAgeOfConsent(false).build() consentInformation = UserMessagingPlatform.getConsentInformation(this) - consentInformation.requestConsentInfoUpdate(this, params, { + consentInformation.requestConsentInfoUpdate(this , params , { if (consentInformation.isConsentFormAvailable) { loadForm() } - }, {}) + } , {}) requestPermissions() } @@ -59,69 +53,29 @@ class StartupActivity : ComponentActivity() { * @see com.google.ads.consent.ConsentInformation */ private fun loadForm() { - UserMessagingPlatform.loadConsentForm(this, { consentForm -> + UserMessagingPlatform.loadConsentForm(this , { consentForm -> this.consentForm = consentForm if (consentInformation.consentStatus == ConsentInformation.ConsentStatus.REQUIRED) { consentForm.show(this) { loadForm() } } - }, {}) + } , {}) } /** - * Checks if the access to usage statistics is granted for the application. + * Handles the application's permission requirements. * - * This property retrieves the current access status for usage statistics based on the app's UID. - * It uses deprecated methods due to the nature of permissions and operations involved. - * The property determines if the access to usage statistics is allowed (`true`) or not (`false`). + * This function is responsible for checking and requesting the necessary permissions for the application. It takes into account the Android version to manage specific permission scenarios. + * For Android versions Tiramisu or later, it requests the POST_NOTIFICATIONS permission. * - * @return `true` if access to usage statistics is granted, `false` otherwise. - * @suppress Use of deprecated methods for checking usage statistics access. - */ - @Suppress("DEPRECATION") - private val isAccessGranted: Boolean - get() { - val packageManager = packageManager - val applicationInfo = packageManager.getApplicationInfo(packageName, 0) - val appOpsManager = getSystemService(APP_OPS_SERVICE) as AppOpsManager - @Suppress("DEPRECATION") val mode: Int = appOpsManager.checkOpNoThrow( - AppOpsManager.OPSTR_GET_USAGE_STATS, - applicationInfo.uid, - applicationInfo.packageName - ) - return mode == AppOpsManager.MODE_ALLOWED - } - - /** - * Requests necessary permissions required for the application. - * - * This function checks and requests permissions required for the application, particularly for storage access. - * It checks the Android version to handle specific permission scenarios. - * If running on Android 11 or later, it directs the user to manage app storage access settings if not granted. - * Additionally, it prompts for usage access settings if usage access is not granted. - * - * @see android.Manifest.permission.WRITE_EXTERNAL_STORAGE - * @see android.Manifest.permission.READ_EXTERNAL_STORAGE + * @see android.Manifest.permission.POST_NOTIFICATIONS * @see android.os.Build.VERSION.SDK_INT - * @see android.os.Build.VERSION_CODES.R + * @see android.os.Build.VERSION_CODES.TIRAMISU */ private fun requestPermissions() { - val requiredPermissions = mutableListOf( - Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE - ) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!Environment.isExternalStorageManager()) { - val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) - val uri = Uri.fromParts("package", packageName, null) - intent.data = uri - startActivity(intent) - } - if (!isAccessGranted) { - val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS) - startActivity(intent) - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS) , 1) } - ActivityCompat.requestPermissions(this, requiredPermissions.toTypedArray(), 1) } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt index 1e1ed15..a76274a 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.text.ClickableText import androidx.compose.material.icons.Icons @@ -13,6 +14,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults @@ -24,7 +26,10 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import com.d4rk.cleaner.MainActivity import com.d4rk.cleaner.R @@ -36,60 +41,71 @@ import com.d4rk.cleaner.utils.bounceClick fun StartupComposable() { val context = LocalContext.current val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) - Scaffold(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { - LargeTopAppBar( - title = { Text(stringResource(R.string.welcome)) }, - scrollBehavior = scrollBehavior - ) + Scaffold(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) , topBar = { + LargeTopAppBar(title = { Text(stringResource(R.string.welcome)) } , + scrollBehavior = scrollBehavior) }) { innerPadding -> Box( modifier = Modifier .fillMaxSize() .padding(24.dp) + .safeDrawingPadding() ) { LazyColumn( modifier = Modifier .fillMaxSize() - .padding(innerPadding), + .padding(innerPadding) , ) { item { Image( - painter = painterResource(id = R.drawable.il_startup), + painter = painterResource(id = R.drawable.il_startup) , contentDescription = null ) - Image( - Icons.Outlined.Info, contentDescription = null + Icon( + Icons.Outlined.Info , contentDescription = null ) } item { Text( - text = stringResource(R.string.summary_browse_terms_of_service_and_privacy_policy), - modifier = Modifier.padding(top = 24.dp, bottom = 24.dp) + text = stringResource(R.string.summary_browse_terms_of_service_and_privacy_policy) , + modifier = Modifier.padding(top = 24.dp , bottom = 24.dp) ) - ClickableText( - text = AnnotatedString(stringResource(R.string.browse_terms_of_service_and_privacy_policy)), - onClick = { - Utils.openUrl( - context, - "https://sites.google.com/view/d4rk7355608/more/apps/privacy-policy" + val annotatedString = buildAnnotatedString { + withStyle( + style = SpanStyle( + color = MaterialTheme.colorScheme.primary , + textDecoration = TextDecoration.Underline ) - - }, - ) + ) { + append(stringResource(R.string.browse_terms_of_service_and_privacy_policy)) + } + addStringAnnotation( + tag = "URL" , + annotation = "https://sites.google.com/view/d4rk7355608/more/apps/privacy-policy" , + start = 0 , + end = stringResource(R.string.browse_terms_of_service_and_privacy_policy).length + ) + } + ClickableText(text = annotatedString , onClick = { offset -> + annotatedString.getStringAnnotations("URL" , offset , offset).firstOrNull() + ?.let { annotation -> + Utils.openUrl(context , annotation.item) + } + }) } } ExtendedFloatingActionButton(modifier = Modifier .align(Alignment.BottomEnd) - .bounceClick(), - text = { Text(stringResource(R.string.agree)) }, + .bounceClick() , + text = { Text(stringResource(R.string.agree)) } , onClick = { Utils.openActivity( - context, MainActivity::class.java + context , MainActivity::class.java ) - }, + } , icon = { Icon( - Icons.Outlined.CheckCircle, + Icons.Outlined.CheckCircle , contentDescription = null ) })