Rename
This commit is contained in:
1 parent
b86d90021c
commit
6c0757c91b
972 files changed
+6885
-7321
No files matched your search
@@ -0,0 +1,7 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
interface OnErrorCallback {
|
||||
|
||||
fun onError(e: Exception)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
interface OnPermissionsDeniedCallback {
|
||||
|
||||
fun onPermissionsDenied(deniedPermissions: Array<String>)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
interface OnPermissionsGrantedCallback {
|
||||
|
||||
fun onPermissionsGranted()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
interface OnPermissionsResultCallback {
|
||||
|
||||
fun onPermissionsGranted()
|
||||
|
||||
fun onPermissionsDenied(deniedPermissions: Array<String>?)
|
||||
|
||||
fun onError(e: Exception)
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
interface OnRequestPermissionsResultCallback {
|
||||
|
||||
fun onRequestPermissionsResult(permissions: Array<String>, grantResults: IntArray)
|
||||
|
||||
fun onSettingActivityResult()
|
||||
|
||||
fun onError(e: Exception)
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.constant.AppLog
|
||||
import io.legato.kazusa.exception.NoStackTraceException
|
||||
import io.legato.kazusa.utils.registerForActivityResult
|
||||
import io.legato.kazusa.utils.toastOnUi
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PermissionActivity : AppCompatActivity() {
|
||||
|
||||
private var rationaleDialog: AlertDialog? = null
|
||||
|
||||
private val settingActivityResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
onRequestPermissionFinish()
|
||||
}
|
||||
private val settingActivityResultAwait =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
|
||||
private val requestPermissionResult =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission())
|
||||
private val requestPermissionsResult =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions())
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val rationale = intent.getStringExtra(KEY_RATIONALE)
|
||||
val requestCode = intent.getIntExtra(KEY_INPUT_PERMISSIONS_CODE, 1000)
|
||||
val permissions = intent.getStringArrayExtra(KEY_INPUT_PERMISSIONS)!!
|
||||
when (intent.getIntExtra(KEY_INPUT_REQUEST_TYPE, Request.TYPE_REQUEST_PERMISSION)) {
|
||||
//权限请求
|
||||
Request.TYPE_REQUEST_PERMISSION -> showSettingDialog(permissions, rationale) {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val result = requestPermissionsResult.launch(permissions)
|
||||
if (result.values.all { it }) {
|
||||
onRequestPermissionFinish()
|
||||
} else {
|
||||
openSettingsActivity()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("请求权限出错\n$e", e, true)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
//跳转到设置界面
|
||||
Request.TYPE_REQUEST_SETTING -> showSettingDialog(permissions, rationale) {
|
||||
openSettingsActivity()
|
||||
}
|
||||
//所有文件的管理权限
|
||||
Request.TYPE_MANAGE_ALL_FILES_ACCESS -> showSettingDialog(permissions, rationale) {
|
||||
try {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
val settingIntent =
|
||||
Intent(
|
||||
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
||||
Uri.parse("package:$packageName")
|
||||
)
|
||||
settingActivityResult.launch(settingIntent)
|
||||
} else {
|
||||
throw NoStackTraceException("no MANAGE_ALL_FILES_ACCESS_PERMISSION")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("请求所有文件的管理权限出错\n$e", e, true)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
Request.TYPE_REQUEST_NOTIFICATIONS -> showSettingDialog(permissions, rationale) {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
||||
&& requestPermissionResult.launch(Permissions.POST_NOTIFICATIONS)
|
||||
) {
|
||||
onRequestPermissionFinish()
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
|
||||
intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)
|
||||
settingActivityResult.launch(intent)
|
||||
} else {
|
||||
openSettingsActivity()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("请求通知权限出错\n$e", e, true)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Request.TYPE_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS -> showSettingDialog(
|
||||
permissions, rationale
|
||||
) {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||
intent.setData(Uri.parse("package:$packageName"))
|
||||
val className =
|
||||
"com.android.settings.fuelgauge.RequestIgnoreBatteryOptimizations"
|
||||
val activities = packageManager.queryIntentActivities(
|
||||
intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY
|
||||
)
|
||||
if (activities.any { it.activityInfo.name == className }) {
|
||||
val component = intent.resolveActivity(packageManager)
|
||||
if (component.className != className) {
|
||||
intent.setClassName("com.android.settings", className)
|
||||
settingActivityResultAwait.launch(intent)
|
||||
}
|
||||
}
|
||||
intent.component = null
|
||||
settingActivityResult.launch(intent)
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("请求后台权限出错\n$e", e, true)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRequestPermissionFinish() {
|
||||
RequestPlugins.sRequestCallback?.onSettingActivityResult()
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun openSettingsActivity() {
|
||||
try {
|
||||
val settingIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
settingIntent.data = Uri.fromParts("package", packageName, null)
|
||||
settingActivityResult.launch(settingIntent)
|
||||
} catch (e: Exception) {
|
||||
toastOnUi(R.string.tip_cannot_jump_setting_page)
|
||||
RequestPlugins.sRequestCallback?.onError(e)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
RequestPlugins.sRequestCallback?.onRequestPermissionsResult(
|
||||
permissions,
|
||||
grantResults
|
||||
)
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
override fun startActivity(intent: Intent) {
|
||||
super.startActivity(intent)
|
||||
@Suppress("DEPRECATION")
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
super.finish()
|
||||
@Suppress("DEPRECATION")
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
|
||||
private fun showSettingDialog(
|
||||
permissions: Array<String>,
|
||||
rationale: CharSequence?,
|
||||
onOk: () -> Unit
|
||||
) {
|
||||
rationaleDialog?.dismiss()
|
||||
if (rationale.isNullOrEmpty()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
rationaleDialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title)
|
||||
.setMessage(rationale)
|
||||
.setPositiveButton(R.string.dialog_setting) { _, _ ->
|
||||
onOk.invoke()
|
||||
}
|
||||
.setNegativeButton(R.string.dialog_cancel) { _, _ ->
|
||||
RequestPlugins.sRequestCallback?.onRequestPermissionsResult(
|
||||
permissions,
|
||||
IntArray(0)
|
||||
)
|
||||
finish()
|
||||
}.setOnCancelListener {
|
||||
RequestPlugins.sRequestCallback?.onRequestPermissionsResult(
|
||||
permissions,
|
||||
IntArray(0)
|
||||
)
|
||||
finish()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val KEY_RATIONALE = "KEY_RATIONALE"
|
||||
const val KEY_INPUT_REQUEST_TYPE = "KEY_INPUT_REQUEST_TYPE"
|
||||
const val KEY_INPUT_PERMISSIONS_CODE = "KEY_INPUT_PERMISSIONS_CODE"
|
||||
const val KEY_INPUT_PERMISSIONS = "KEY_INPUT_PERMISSIONS"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
import android.os.Build
|
||||
|
||||
@Suppress("unused")
|
||||
object Permissions {
|
||||
|
||||
const val POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS"
|
||||
|
||||
const val READ_CALENDAR = "android.permission.READ_CALENDAR"
|
||||
const val WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"
|
||||
|
||||
const val CAMERA = "android.permission.CAMERA"
|
||||
|
||||
const val READ_CONTACTS = "android.permission.READ_CONTACTS"
|
||||
const val WRITE_CONTACTS = "android.permission.WRITE_CONTACTS"
|
||||
const val GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"
|
||||
|
||||
const val ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION"
|
||||
const val ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION"
|
||||
|
||||
const val RECORD_AUDIO = "android.permission.RECORD_AUDIO"
|
||||
|
||||
const val READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"
|
||||
const val CALL_PHONE = "android.permission.CALL_PHONE"
|
||||
const val READ_CALL_LOG = "android.permission.READ_CALL_LOG"
|
||||
const val WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG"
|
||||
const val ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"
|
||||
const val USE_SIP = "android.permission.USE_SIP"
|
||||
const val PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"
|
||||
|
||||
const val BODY_SENSORS = "android.permission.BODY_SENSORS"
|
||||
|
||||
const val SEND_SMS = "android.permission.SEND_SMS"
|
||||
const val RECEIVE_SMS = "android.permission.RECEIVE_SMS"
|
||||
const val READ_SMS = "android.permission.READ_SMS"
|
||||
const val RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"
|
||||
const val RECEIVE_MMS = "android.permission.RECEIVE_MMS"
|
||||
|
||||
const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"
|
||||
const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
const val MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||
|
||||
const val ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION"
|
||||
|
||||
const val REQUEST_IGNORE_BATTERY_OPTIMIZATIONS =
|
||||
"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
|
||||
|
||||
object Group {
|
||||
val STORAGE = if (isManageExternalStorage()) {
|
||||
arrayOf(MANAGE_EXTERNAL_STORAGE)
|
||||
} else {
|
||||
arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
val CAMERA = arrayOf(Permissions.CAMERA)
|
||||
|
||||
val CALENDAR = arrayOf(READ_CALENDAR, WRITE_CALENDAR)
|
||||
|
||||
val CONTACTS = arrayOf(READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS)
|
||||
|
||||
val LOCATION = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
|
||||
|
||||
val MICROPHONE = arrayOf(RECORD_AUDIO)
|
||||
|
||||
val PHONE = arrayOf(
|
||||
READ_PHONE_STATE,
|
||||
CALL_PHONE,
|
||||
READ_CALL_LOG,
|
||||
WRITE_CALL_LOG,
|
||||
ADD_VOICEMAIL,
|
||||
USE_SIP,
|
||||
PROCESS_OUTGOING_CALLS
|
||||
)
|
||||
|
||||
val SENSORS = arrayOf(BODY_SENSORS)
|
||||
|
||||
val SMS = arrayOf(
|
||||
SEND_SMS,
|
||||
RECEIVE_SMS,
|
||||
READ_SMS,
|
||||
RECEIVE_WAP_PUSH,
|
||||
RECEIVE_MMS
|
||||
)
|
||||
}
|
||||
|
||||
fun isManageExternalStorage(): Boolean {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
@Suppress("unused")
|
||||
class PermissionsCompat private constructor() {
|
||||
|
||||
private var request: Request? = null
|
||||
|
||||
fun request() {
|
||||
RequestManager.pushRequest(request)
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private val request: Request = Request()
|
||||
|
||||
fun addPermissions(vararg permissions: String): Builder {
|
||||
request.addPermissions(*permissions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun onGranted(callback: () -> Unit): Builder {
|
||||
request.setOnGrantedCallback(object : OnPermissionsGrantedCallback {
|
||||
override fun onPermissionsGranted() {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
fun onDenied(callback: (deniedPermissions: Array<String>) -> Unit): Builder {
|
||||
request.setOnDeniedCallback(object : OnPermissionsDeniedCallback {
|
||||
override fun onPermissionsDenied(deniedPermissions: Array<String>) {
|
||||
callback(deniedPermissions)
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
fun onError(callback: (e: Exception) -> Unit): Builder {
|
||||
request.setOnErrorCallBack(object : OnErrorCallback{
|
||||
override fun onError(e: Exception) {
|
||||
callback(e)
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
fun rationale(rationale: CharSequence): Builder {
|
||||
request.setRationale(rationale)
|
||||
return this
|
||||
}
|
||||
|
||||
fun rationale(@StringRes resId: Int): Builder {
|
||||
request.setRationale(resId)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): PermissionsCompat {
|
||||
val compat = PermissionsCompat()
|
||||
compat.request = request
|
||||
return compat
|
||||
}
|
||||
|
||||
fun request(): PermissionsCompat {
|
||||
val compat = build()
|
||||
compat.request()
|
||||
return compat
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import io.legato.kazusa.utils.startActivity
|
||||
import splitties.init.appCtx
|
||||
import splitties.systemservices.powerManager
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal class Request : OnRequestPermissionsResultCallback {
|
||||
|
||||
internal val requestTime: Long = System.currentTimeMillis()
|
||||
private var requestCode: Int = TYPE_REQUEST_PERMISSION
|
||||
private var permissions: ArrayList<String> = ArrayList()
|
||||
private var grantedCallback: OnPermissionsGrantedCallback? = null
|
||||
private var deniedCallback: OnPermissionsDeniedCallback? = null
|
||||
private var errorCallback: OnErrorCallback? = null
|
||||
private var rationale: CharSequence? = null
|
||||
|
||||
private val deniedPermissions: Array<String>?
|
||||
get() {
|
||||
return getDeniedPermissions(this.permissions.toTypedArray())
|
||||
}
|
||||
|
||||
fun addPermissions(vararg permissions: String) {
|
||||
this.permissions.addAll(listOf(*permissions))
|
||||
}
|
||||
|
||||
fun setOnGrantedCallback(callback: OnPermissionsGrantedCallback) {
|
||||
grantedCallback = callback
|
||||
}
|
||||
|
||||
fun setOnDeniedCallback(callback: OnPermissionsDeniedCallback) {
|
||||
deniedCallback = callback
|
||||
}
|
||||
|
||||
fun setOnErrorCallBack(callback: OnErrorCallback) {
|
||||
errorCallback = callback
|
||||
}
|
||||
|
||||
fun setRationale(@StringRes resId: Int) {
|
||||
rationale = appCtx.getString(resId)
|
||||
}
|
||||
|
||||
fun setRationale(rationale: CharSequence) {
|
||||
this.rationale = rationale
|
||||
}
|
||||
|
||||
@SuppressLint("ObsoleteSdkInt")
|
||||
fun start() {
|
||||
RequestPlugins.setOnRequestPermissionsCallback(this)
|
||||
|
||||
val deniedPermissions = deniedPermissions
|
||||
val rationale = this.rationale
|
||||
if (deniedPermissions == null) {
|
||||
onPermissionsGranted()
|
||||
return
|
||||
}
|
||||
if (rationale == null) {
|
||||
onPermissionsDenied(deniedPermissions)
|
||||
return
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
toSetting()
|
||||
} else {
|
||||
if (deniedPermissions.contains(Permissions.MANAGE_EXTERNAL_STORAGE)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
toManageFileSetting(deniedPermissions)
|
||||
}
|
||||
} else if (deniedPermissions.contains(Permissions.POST_NOTIFICATIONS)) {
|
||||
toNotificationSetting(deniedPermissions)
|
||||
} else if (deniedPermissions.contains(Permissions.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
toIgnoreBatterySetting(deniedPermissions)
|
||||
}
|
||||
} else if (deniedPermissions.isNotEmpty()) {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_PERMISSION)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
grantedCallback = null
|
||||
deniedCallback = null
|
||||
}
|
||||
|
||||
fun getDeniedPermissions(permissions: Array<String>): Array<String>? {
|
||||
val deniedPermissionList = ArrayList<String>()
|
||||
for (permission in permissions) {
|
||||
when (permission) {
|
||||
Permissions.POST_NOTIFICATIONS -> {
|
||||
if (!NotificationManagerCompat.from(appCtx).areNotificationsEnabled()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
|
||||
Permissions.MANAGE_EXTERNAL_STORAGE -> {
|
||||
if (Permissions.isManageExternalStorage()) {
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Permissions.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (!powerManager.isIgnoringBatteryOptimizations(appCtx.packageName)) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (
|
||||
ContextCompat.checkSelfPermission(appCtx, permission)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
deniedPermissionList.add(permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val size = deniedPermissionList.size
|
||||
if (size > 0) {
|
||||
return deniedPermissionList.toTypedArray()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun onPermissionsGranted() {
|
||||
try {
|
||||
grantedCallback?.onPermissionsGranted()
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
|
||||
RequestPlugins.sResultCallback?.onPermissionsGranted()
|
||||
}
|
||||
|
||||
private fun onPermissionsDenied(deniedPermissions: Array<String>) {
|
||||
try {
|
||||
deniedCallback?.onPermissionsDenied(deniedPermissions)
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
|
||||
RequestPlugins.sResultCallback?.onPermissionsDenied(deniedPermissions)
|
||||
}
|
||||
|
||||
private fun toSetting() {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_SETTING)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toManageFileSetting(deniedPermissions: Array<String>) {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_MANAGE_ALL_FILES_ACCESS)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toNotificationSetting(deniedPermissions: Array<String>) {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_NOTIFICATIONS)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toIgnoreBatterySetting(deniedPermissions: Array<String>) {
|
||||
appCtx.startActivity<PermissionActivity> {
|
||||
putExtra(PermissionActivity.KEY_RATIONALE, rationale)
|
||||
putExtra(
|
||||
PermissionActivity.KEY_INPUT_REQUEST_TYPE,
|
||||
TYPE_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||
)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode)
|
||||
putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
val deniedPermissions = getDeniedPermissions(permissions)
|
||||
if (deniedPermissions != null) {
|
||||
onPermissionsDenied(deniedPermissions)
|
||||
} else {
|
||||
onPermissionsGranted()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSettingActivityResult() {
|
||||
val deniedPermissions = deniedPermissions
|
||||
if (deniedPermissions == null) {
|
||||
onPermissionsGranted()
|
||||
} else {
|
||||
onPermissionsDenied(deniedPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Exception) {
|
||||
errorCallback?.onError(e)
|
||||
RequestPlugins.sResultCallback?.onError(e)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE_REQUEST_PERMISSION = 1
|
||||
const val TYPE_REQUEST_SETTING = 2
|
||||
const val TYPE_MANAGE_ALL_FILES_ACCESS = 3
|
||||
const val TYPE_REQUEST_NOTIFICATIONS = 4
|
||||
const val TYPE_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import java.util.*
|
||||
|
||||
internal object RequestManager : OnPermissionsResultCallback {
|
||||
|
||||
private var requests: Stack<Request>? = null
|
||||
private var request: Request? = null
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
private val requestRunnable = Runnable {
|
||||
request?.start()
|
||||
}
|
||||
|
||||
private val isCurrentRequestInvalid: Boolean
|
||||
get() = request?.let { System.currentTimeMillis() - it.requestTime > 5 * 1000L } ?: true
|
||||
|
||||
init {
|
||||
RequestPlugins.setOnPermissionsResultCallback(this)
|
||||
}
|
||||
|
||||
fun pushRequest(request: Request?) {
|
||||
if (request == null) return
|
||||
|
||||
if (requests == null) {
|
||||
requests = Stack()
|
||||
}
|
||||
|
||||
requests?.let {
|
||||
val index = it.indexOf(request)
|
||||
if (index >= 0) {
|
||||
val to = it.size - 1
|
||||
if (index != to) {
|
||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
Collections.swap(requests, index, to)
|
||||
}
|
||||
} else {
|
||||
it.push(request)
|
||||
}
|
||||
|
||||
if (!it.empty() && isCurrentRequestInvalid) {
|
||||
this.request = it.pop()
|
||||
handler.post(requestRunnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startNextRequest() {
|
||||
request?.clear()
|
||||
request = null
|
||||
|
||||
requests?.let {
|
||||
request = if (it.empty()) null else it.pop()
|
||||
request?.let { handler.post(requestRunnable) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPermissionsGranted() {
|
||||
startNextRequest()
|
||||
}
|
||||
|
||||
override fun onPermissionsDenied(deniedPermissions: Array<String>?) {
|
||||
startNextRequest()
|
||||
}
|
||||
|
||||
override fun onError(e: Exception) {
|
||||
startNextRequest()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.legato.kazusa.lib.permission
|
||||
|
||||
internal object RequestPlugins {
|
||||
|
||||
@Volatile
|
||||
var sRequestCallback: OnRequestPermissionsResultCallback? = null
|
||||
|
||||
@Volatile
|
||||
var sResultCallback: OnPermissionsResultCallback? = null
|
||||
|
||||
fun setOnRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) {
|
||||
sRequestCallback = callback
|
||||
}
|
||||
|
||||
fun setOnPermissionsResultCallback(callback: OnPermissionsResultCallback) {
|
||||
sResultCallback = callback
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user