mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 09:49:25 +02:00
Self grant runtime permissions
This commit is contained in:
parent
82e8f65f0d
commit
141c967b74
7 changed files with 87 additions and 9 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,4 +25,7 @@ interface DeviceOwnerApi {
|
||||||
fun setOrganizationName(name: String)
|
fun setOrganizationName(name: String)
|
||||||
|
|
||||||
fun transferOwnership(packageName: String, dryRun: Boolean = false)
|
fun transferOwnership(packageName: String, dryRun: Boolean = false)
|
||||||
|
|
||||||
|
// returns true on success; never throws
|
||||||
|
fun grantLocationAccess(): Boolean
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package io.timelimit.android.integration.platform.android
|
package io.timelimit.android.integration.platform.android
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.admin.DeviceAdminReceiver
|
import android.app.admin.DeviceAdminReceiver
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
@ -124,4 +125,14 @@ class AndroidDeviceOwnerApi(
|
||||||
devicePolicyManager.setDelegatedScopes(componentName, packageName, emptyList())
|
devicePolicyManager.setDelegatedScopes(componentName, packageName, emptyList())
|
||||||
devicePolicyManager.transferOwnership(componentName, targetComponentName, null)
|
devicePolicyManager.transferOwnership(componentName, targetComponentName, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun grantLocationAccess(): Boolean {
|
||||||
|
if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) return false
|
||||||
|
if (!devicePolicyManager.isDeviceOwnerApp(componentName.packageName)) return false
|
||||||
|
|
||||||
|
return devicePolicyManager.setPermissionGrantState(
|
||||||
|
componentName, componentName.packageName, Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package io.timelimit.android.integration.platform.android
|
package io.timelimit.android.integration.platform.android
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
@ -40,6 +41,7 @@ import android.widget.Toast
|
||||||
import androidx.collection.LruCache
|
import androidx.collection.LruCache
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import io.timelimit.android.BuildConfig
|
import io.timelimit.android.BuildConfig
|
||||||
|
@ -511,6 +513,40 @@ class AndroidIntegration(context: Context): PlatformIntegration(maximumProtectio
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
policyManager.addUserRestriction(deviceAdmin, UserManager.DISALLOW_SAFE_BOOT)
|
policyManager.addUserRestriction(deviceAdmin, UserManager.DISALLOW_SAFE_BOOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policyManager.getPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
).let {
|
||||||
|
if (it == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|
||||||
|
else
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.CALL_PHONE,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|
||||||
|
)
|
||||||
|
}
|
||||||
} else /* disable lockdown */ {
|
} else /* disable lockdown */ {
|
||||||
// enable problematic features
|
// enable problematic features
|
||||||
policyManager.clearUserRestriction(deviceAdmin, UserManager.DISALLOW_ADD_USER)
|
policyManager.clearUserRestriction(deviceAdmin, UserManager.DISALLOW_ADD_USER)
|
||||||
|
@ -520,6 +556,29 @@ class AndroidIntegration(context: Context): PlatformIntegration(maximumProtectio
|
||||||
policyManager.clearUserRestriction(deviceAdmin, UserManager.DISALLOW_SAFE_BOOT)
|
policyManager.clearUserRestriction(deviceAdmin, UserManager.DISALLOW_SAFE_BOOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT
|
||||||
|
)
|
||||||
|
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.CALL_PHONE,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
policyManager.setPermissionGrantState(
|
||||||
|
deviceAdmin,
|
||||||
|
context.packageName,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS,
|
||||||
|
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
enableSystemApps()
|
enableSystemApps()
|
||||||
stopSuspendingForAllApps()
|
stopSuspendingForAllApps()
|
||||||
setBlockedFeatures(emptySet())
|
setBlockedFeatures(emptySet())
|
||||||
|
|
|
@ -207,5 +207,7 @@ class DummyIntegration(
|
||||||
override fun setOrganizationName(name: String) = throw SecurityException()
|
override fun setOrganizationName(name: String) = throw SecurityException()
|
||||||
|
|
||||||
override fun transferOwnership(packageName: String, dryRun: Boolean) = throw IllegalStateException("unsupported operation")
|
override fun transferOwnership(packageName: String, dryRun: Boolean) = throw IllegalStateException("unsupported operation")
|
||||||
|
|
||||||
|
override fun grantLocationAccess(): Boolean = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -124,7 +124,7 @@ class LockActionFragment : Fragment() {
|
||||||
override fun setThisDeviceAsCurrentDevice() = this@LockActionFragment.setThisDeviceAsCurrentDevice()
|
override fun setThisDeviceAsCurrentDevice() = this@LockActionFragment.setThisDeviceAsCurrentDevice()
|
||||||
|
|
||||||
override fun requestLocationPermission() {
|
override fun requestLocationPermission() {
|
||||||
RequestWifiPermission.doRequest(this@LockActionFragment, LOCATION_REQUEST_CODE)
|
RequestWifiPermission.doRequest(this@LockActionFragment, LOCATION_REQUEST_CODE, auth.logic.platformIntegration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun disableLimitsTemporarily() {
|
override fun disableLimitsTemporarily() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -117,7 +117,7 @@ object ManageCategoryNetworksView {
|
||||||
}
|
}
|
||||||
|
|
||||||
view.grantPermissionButton.setOnClickListener {
|
view.grantPermissionButton.setOnClickListener {
|
||||||
RequestWifiPermission.doRequest(fragment, permissionRequestCode)
|
RequestWifiPermission.doRequest(fragment, permissionRequestCode, auth.logic.platformIntegration)
|
||||||
}
|
}
|
||||||
|
|
||||||
isFullVersionLive.observe(lifecycleOwner, Observer { isFullVersion ->
|
isFullVersionLive.observe(lifecycleOwner, Observer { isFullVersion ->
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2020 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -26,6 +26,7 @@ import android.widget.Toast
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import io.timelimit.android.R
|
import io.timelimit.android.R
|
||||||
|
import io.timelimit.android.integration.platform.PlatformIntegration
|
||||||
|
|
||||||
object RequestWifiPermission {
|
object RequestWifiPermission {
|
||||||
private fun isLocationEnabled(context: Context): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
|
private fun isLocationEnabled(context: Context): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
|
||||||
|
@ -36,8 +37,10 @@ object RequestWifiPermission {
|
||||||
locationManager.isLocationEnabled
|
locationManager.isLocationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doRequest(fragment: Fragment, permissionRequestCode: Int) {
|
fun doRequest(fragment: Fragment, permissionRequestCode: Int, platformIntegration: PlatformIntegration) {
|
||||||
if (ContextCompat.checkSelfPermission(fragment.requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(fragment.requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
if (platformIntegration.deviceOwner.grantLocationAccess()) return
|
||||||
|
|
||||||
fragment.requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), permissionRequestCode)
|
fragment.requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), permissionRequestCode)
|
||||||
} else if (!isLocationEnabled(fragment.requireContext())) {
|
} else if (!isLocationEnabled(fragment.requireContext())) {
|
||||||
Toast.makeText(fragment.requireContext(), R.string.category_networks_toast_enable_location_service, Toast.LENGTH_SHORT).show()
|
Toast.makeText(fragment.requireContext(), R.string.category_networks_toast_enable_location_service, Toast.LENGTH_SHORT).show()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue