You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android权限请求弹窗未显示问题排查求助

问题描述

我开发了一个仅包含单个按钮的简单Android应用,点击按钮时权限请求并未向用户弹出。已在Manifest文件中添加权限列表,且在Android 13和14设备上测试过,问题仍未解决。

MainActivity.kt 代码

package ir.alirezapersonal.startup2

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import ir.alirezapersonal.startup2.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        binding.btnRequestPermissions.setOnClickListener {
            requestPermissions()
        }
    }

    private fun hasWriteExternalStoragePermission() =
        ActivityCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED

    private fun hasLocationForegroundPermission() =
        ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED

    private fun hasLocationBackgroundPermission() =
        ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED

    private fun requestPermissions() {
        var permissionsToRequest = mutableListOf<String>()
        if(!hasWriteExternalStoragePermission()){
            permissionsToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
        if(!hasLocationForegroundPermission()){
            permissionsToRequest.add(Manifest.permission.ACCESS_COARSE_LOCATION)
        }
        if (!hasLocationBackgroundPermission()){
            permissionsToRequest.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
        }

        if(permissionsToRequest.isNotEmpty()){
            ActivityCompat.requestPermissions(this, permissionsToRequest.toTypedArray(),0)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if(requestCode == 0 && grantResults.isNotEmpty()){
            for(i in grantResults.indices){
                if(grantResults[i] == PackageManager.PERMISSION_GRANTED){
                    Log.d("PermissionRequest", "${permissions[i]} granted.")
                } else {
                    Log.d("PermissionRequest", "${permissions[i]} NOT granted.")
                }
            }
        }
    }
}

AndroidManifest.xml 代码

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Startup2"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
可能的原因及解决方案

1. Android 13+ 存储权限适配问题

从Android 13(API 33)开始,WRITE_EXTERNAL_STORAGE权限已被废弃,系统会自动授予等效的存储访问权限,无需动态申请。代码中仍在检查并请求该权限,但Android13+设备上不会弹出对应的权限对话框,甚至可能干扰其他权限的请求流程。

2. 后台位置权限申请逻辑不符合规范

Android 10(API 29)及以上版本,申请ACCESS_BACKGROUND_LOCATION必须满足两个条件:

  • 已先获得前台位置权限(如ACCESS_COARSE_LOCATION)
  • 不能与前台权限同时请求,需单独发起申请

代码中同时将前台和后台位置权限加入请求列表,违反了系统规则,导致后台权限请求被忽略,甚至整个权限请求流程失效。

3. 权限被用户永久拒绝

如果用户之前勾选了"不再询问"并拒绝过权限,后续的动态请求不会弹出对话框,直接返回拒绝结果。可通过ActivityCompat.shouldShowRequestPermissionRationale()判断:若返回false,说明用户已永久拒绝,需引导用户到应用设置页手动开启权限。

4. 视图绑定或按钮ID不匹配

检查布局文件中按钮的ID是否确实为btnRequestPermissions,确保视图绑定初始化正确,点击事件已成功注册。若ID不匹配,点击按钮不会触发requestPermissions()方法。

修复建议

  • 移除对WRITE_EXTERNAL_STORAGE的动态请求,适配Android13+存储权限机制;
  • 修改权限请求逻辑:先请求前台位置权限,用户授予后再单独请求后台位置权限;
  • 添加权限拒绝处理:当shouldShowRequestPermissionRationale()返回false时,引导用户进入应用设置页;
  • 验证布局文件按钮ID与代码绑定ID一致。

内容的提问来源于stack exchange,提问作者Alireza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:26:00