Skip to content

Commit

Permalink
Created the new PermissionsUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
D4rK7355608 committed Jul 10, 2024
1 parent 3d55396 commit df2193e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 154 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {
applicationId = "com.d4rk.cleaner"
minSdk = 26
targetSdk = 34
versionCode = 85
versionCode = 86
versionName = "2.0.0"
archivesName = "${applicationId}-v${versionName}"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down
141 changes: 5 additions & 136 deletions app/src/main/kotlin/com/d4rk/cleaner/ui/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
package com.d4rk.cleaner.ui.home

import android.Manifest
import android.app.Activity
import android.app.AppOpsManager
import android.app.Application
import android.app.usage.StorageStatsManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.storage.StorageManager
import android.provider.Settings
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.d4rk.cleaner.data.datastore.DataStore
import com.d4rk.cleaner.utils.FileScanner
import com.d4rk.cleaner.utils.PermissionsUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -123,8 +114,8 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
* @param activity The Activity instance required to request permissions.
*/
fun analyze(activity: Activity) {
if (!hasRequiredPermissions()) {
requestPermissions(activity)
if (!PermissionsUtils.hasStoragePermissions(getApplication())) {
PermissionsUtils.requestStoragePermissions(activity)
return
}

Expand Down Expand Up @@ -157,8 +148,8 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
* @param activity The Activity instance required to request permissions.
*/
fun clean(activity: Activity) {
if (!hasRequiredPermissions()) {
requestPermissions(activity)
if (!PermissionsUtils.hasStoragePermissions(getApplication())) {
PermissionsUtils.requestStoragePermissions(activity)
return
}

Expand All @@ -179,126 +170,4 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
}
}
}

/**
* Checks if the app has all the necessary permissions to perform scanning and cleaning.
*
* @return True if all required permissions are granted, false otherwise.
*/
private fun hasRequiredPermissions(): Boolean {
val hasStoragePermissions = when {
Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q ->
ContextCompat.checkSelfPermission(
getApplication(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED

Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2 ->
ContextCompat.checkSelfPermission(
getApplication(),
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED

else -> true
}

val hasManageStoragePermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager()
} else {
true
}

val hasUsageStatsPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
isAccessGranted()
} else {
true
}

val hasMediaPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
getApplication(),
Manifest.permission.READ_MEDIA_AUDIO
) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(
getApplication(),
Manifest.permission.READ_MEDIA_IMAGES
) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(
getApplication(),
Manifest.permission.READ_MEDIA_VIDEO
) == PackageManager.PERMISSION_GRANTED
} else {
true
}

return hasStoragePermissions && hasManageStoragePermission &&
hasUsageStatsPermission && hasMediaPermissions
}

/**
* Checks if the app has access to usage statistics.
*
* @return True if access is granted, false otherwise.
*/
private fun isAccessGranted(): Boolean = try {
val packageManager = getApplication<Application>().packageManager
val applicationInfo =
packageManager.getApplicationInfo(getApplication<Application>().packageName, 0)
val appOpsManager =
getApplication<Application>().getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
@Suppress("DEPRECATION") val mode: Int = appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_GET_USAGE_STATS,
applicationInfo.uid,
applicationInfo.packageName
)
mode == AppOpsManager.MODE_ALLOWED
} catch (e: PackageManager.NameNotFoundException) {
false
}

/**
* Requests necessary permissions for the app to function correctly.
*
* This function checks for and requests the following permissions:
* - WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE: For accessing and managing files.
* - MANAGE_EXTERNAL_STORAGE (Android R and above): For managing all files on external storage.
* - PACKAGE_USAGE_STATS: For gathering app usage statistics.
* - READ_MEDIA_AUDIO, READ_MEDIA_IMAGES, READ_MEDIA_VIDEO (Android Tiramisu and above):
* For accessing media files.
*
* It utilizes ActivityCompat.requestPermissions to initiate the permission request process
* and handles different Android versions to ensure compatibility.
*
* @param activity The Activity instance required to request permissions.
*/
private fun requestPermissions(activity: Activity) {
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", getApplication<Application>().packageName, null)
intent.data = uri
activity.startActivity(intent)
}

if (!isAccessGranted()) {
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
activity.startActivity(intent)
}
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requiredPermissions.addAll(
listOf(
Manifest.permission.READ_MEDIA_AUDIO,
Manifest.permission.READ_MEDIA_IMAGES,
Manifest.permission.READ_MEDIA_VIDEO
)
)
}

ActivityCompat.requestPermissions(activity, requiredPermissions.toTypedArray(), 1)
}
}
21 changes: 4 additions & 17 deletions app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.d4rk.cleaner.ui.settings.display.theme.style.AppTheme
import com.d4rk.cleaner.utils.PermissionsUtils
import com.google.android.ump.ConsentForm
import com.google.android.ump.ConsentInformation
import com.google.android.ump.ConsentRequestParameters
Expand Down Expand Up @@ -38,7 +39,9 @@ class StartupActivity : AppCompatActivity() {
loadForm()
}
} , {})
requestPermissions()
if (!PermissionsUtils.hasNotificationPermission(this)) {
PermissionsUtils.requestNotificationPermission(this)
}
}

/**
Expand All @@ -62,20 +65,4 @@ class StartupActivity : AppCompatActivity() {
}
} , {})
}

/**
* Handles the application's permission requirements.
*
* 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.
*
* @see android.Manifest.permission.POST_NOTIFICATIONS
* @see android.os.Build.VERSION.SDK_INT
* @see android.os.Build.VERSION_CODES.TIRAMISU
*/
private fun requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS) , 1)
}
}
}
Loading

0 comments on commit df2193e

Please sign in to comment.