Но когда я проверяю canDrawOverlays с внутренним кодом Android, я всегда получаю false.
val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
appOpsManager.unsafeCheckOpNoThrow(
AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
uid,
packageName
)
} else {
@Suppress("DEPRECATION")
appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
uid,
packageName
)
}
Log.d(TAG, "AppOpsManager mode: $mode")
Поэтому, когда я запускаю приведенный выше код, значение режима получается как MODE_ERRORED (2).
Однако, если React-Native вызывает ту же функцию в Native Module, это обычно так.
То же самое верно, даже если вы удаляете и повторно разрешаете разрешения.
Я использовал тот же apk, но это происходило только на определенных устройствах.
Некоторые устройства являются версиями Android 16, но это также происходило и на других устройствах, поэтому я не думаю, что это проблема только Android 16.
Что мне делать?
CheckPermission.kt
object CheckPermission {
private const val TAG = "customNative - CheckPermission"
fun hasAllRequiredPermissions(context: Context): Boolean {
val requiredPermissions = mutableListOf(
Manifest.permission.READ_CALL_LOG,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_PHONE_NUMBERS
)
if (Build.VERSION.SDK_INT
ContextCompat.checkSelfPermission(context, perm) == PackageManager.PERMISSION_GRANTED
}
val canDrawOverlays = checkOverlayPermissionViaAppOps(context);
val hasFilePermission = MMKVHelper.hasRecordingPermission(context)
return allPermissionsGranted && canDrawOverlays && hasFilePermission
}
fun checkOverlayPermissionViaAppOps(context: Context): Boolean {
return try {
val appContext = context.applicationContext ?: return false
val appOpsManager = appContext.getSystemService(Context.APP_OPS_SERVICE) as? AppOpsManager
if (appOpsManager == null) {
Log.e(TAG, "
return false
}
val packageName = appContext.packageName
val uid = appContext.applicationInfo.uid
Log.d(TAG, "Package: $packageName, UID: $uid")
val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
appOpsManager.unsafeCheckOpNoThrow(
AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
uid,
packageName
)
} else {
@Suppress("DEPRECATION")
appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
uid,
packageName
)
}
Log.d(TAG, "AppOpsManager mode: $mode (0=ALLOW, 1=MODE_IGNORED, 2=ERRORED, 3=DEFAULT, 4=FOREGROUND)")
val result = mode == AppOpsManager.MODE_ALLOWED
result
} catch (e: Exception) {
Log.e(TAG, "
e.printStackTrace()
false
}
}
}
NativeModule.kt
@ReactMethod
fun canDrawOverlays(promise: Promise) {
try {
val canDraw = CheckPermission.checkOverlayPermissionViaAppOps(reactApplicationContext)
promise.resolve(canDraw)
} catch (e: Exception) {
promise.reject("OVERLAY_CHECK_ERROR", e.message)
}
}
PhoneStateReceiver.kt
class PhoneStateReceiver : BroadcastReceiver() {
companion object {
private const val TAG = "customNative - PhoneStateReceiver"
var isIncomingCall = false
private var callState = ""
private var lastCallNumber = ""
}
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("ScheduleExactAlarm", "UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context, intent: Intent) {
val appContext = MainApplication.getAppContext() ?: context.applicationContext
if (!CheckPermission.hasAllRequiredPermissions(appContext)) {
return //always false!
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... ways-false
Мобильная версия