Android kotlin:即使在授予权限后也获得 EACCES(权限被拒绝)

Posted

技术标签:

【中文标题】Android kotlin:即使在授予权限后也获得 EACCES(权限被拒绝)【英文标题】:Android kotlin: Getting EACCES (Permission denied) even after giving permissions 【发布时间】:2022-01-01 08:54:28 【问题描述】:

我正在开发一个 android 应用,但在权限处理方面遇到了问题(API lvl 30,Android 版本 11)

我尝试按照此处的步骤操作:https://developer.android.com/training/permissions/requesting.html

当使用“checkSelfPermission()”函数时,看起来我有必要的权限,但是当我尝试写入文件时,我得到了显示在这篇文章底部的日志中的错误。

这是我的代码:

class FilesActivity : AppCompatActivity() 



val requestPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission())  isGranted: Boolean ->
        if (isGranted) 
            Log.d("access granted", isGranted.toString())

         else 
            Log.d("access granted", isGranted.toString())
        
    


private lateinit var binding: ActivityFilesBinding

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)




    requestPermissions()

检查权限的方法如下:

    private fun requestPermissions() 
    when 
        ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_GRANTED -> 
            Log.d("Permission","Already granted")
        
        else -> 
            requestPermissionLauncher.launch(
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            )
        
    

我得到权限提示,在授予权限后我尝试下载文件。下载文件的代码位于回收站视图的适配器类中。

                    try
                    if(ContextCompat.checkSelfPermission(
                        mContext,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                    ) == PackageManager.PERMISSION_GRANTED) 
                        val myFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),file.getFilename()!!)
                        val fileRef = Firebase.storage.getReferenceFromUrl(file.getUrl()!!)

                        fileRef.getFile(myFile).addOnSuccessListener 
                            // Local temp file has been created
                            Toast.makeText(mContext,"File downloaded to Downloads Dir.",Toast.LENGTH_LONG).show()
                        .addOnFailureListener 
                            Toast.makeText(mContext,it.toString(),Toast.LENGTH_LONG).show()
                        
                    

                 catch(e :Error)
                    Toast.makeText(mContext,e.toString(),Toast.LENGTH_LONG).show()
                

我不确定,我做错了什么。 也许这里有人可以帮助我。 提前致谢

编辑:我的 AndroidManifest.xml 看起来像这样:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/round_logo_app"
    android:label="@string/app_name"
    android:roundIcon="@drawable/app_logo_round"
    android:supportsRtl="true"
    android:requestLegacyExternalStorage="true"
    android:theme="@style/Theme.app">
    <activity android:name=".UserRatingsActivity"></activity>


    <activity
        android:name=".ui.myFiles.FilesActivity"
        android:label="@string/title_activity_files"
        android:theme="@style/Theme.StuddyV0_1.NoActionBar" />
    <activity android:name=".Register" />
    <activity android:name=".EnterCourses" />
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main" />
    <activity android:name=".LoginActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <service
        android:name=".PushNotifications.FirebaseService"
        android:permission="com.google.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>
    <service
        android:name=".NotificationsPckg.MyFirebaseMessaging"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
</application>

在我手机的设置中,我可以看到该应用有权访问存储。

编辑:它可以在模拟器中运行,但不能在真实手机上运行。 (银河s20)

日志如下所示:

E/FileDownloadTask: Exception occurred during file write.  Aborting.
java.io.FileNotFoundException: /storage/emulated/0/Download/SKE_Labor.pdf: open failed: EACCES (Permission denied)
    at libcore.io.IoBridge.open(IoBridge.java:492)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
    at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147)
    at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228)
    at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072)
    at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:923)
 Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
    at libcore.io.Linux.open(Native Method)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8494)
    at libcore.io.IoBridge.open(IoBridge.java:478)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:236) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:186) 
    at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147) 
    at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228) 
    at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072) 
    at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
    at java.lang.Thread.run(Thread.java:923) 
E/StorageException: StorageException has occurred.
    An unknown error occurred, please check the HTTP result code and inner exception for server response.
     Code: -13000 HttpResult: 200
    /storage/emulated/0/Download/SKE_Labor.pdf: open failed: EACCES (Permission denied)
    java.io.FileNotFoundException: /storage/emulated/0/Download/SKE_Labor.pdf: open failed: EACCES (Permission denied)
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
        at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147)
        at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228)
        at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072)
        at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
     Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8494)
        at libcore.io.IoBridge.open(IoBridge.java:478)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236) 
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186) 
        at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147) 
        at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228) 
        at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072) 
        at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:923) 
E/StorageException: StorageException has occurred.
    An unknown error occurred, please check the HTTP result code and inner exception for server response.
     Code: -13000 HttpResult: 200
    /storage/emulated/0/Download/SKE_Labor.pdf: open failed: EACCES (Permission denied)
    java.io.FileNotFoundException: /storage/emulated/0/Download/SKE_Labor.pdf: open failed: EACCES (Permission denied)
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
        at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147)
        at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228)
        at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072)
        at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
     Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8494)
        at libcore.io.IoBridge.open(IoBridge.java:478)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236) 
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186) 
        at com.google.firebase.storage.FileDownloadTask.processResponse(FileDownloadTask.java:147) 
        at com.google.firebase.storage.FileDownloadTask.run(FileDownloadTask.java:228) 
        at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072) 
        at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:923) 

编辑:回到这个问题后,我注意到,它只发生在 .pdf 文件中。其他所有内容均已正确下载并保存。

【问题讨论】:

如果您进入应用程序的设置,您可以查看您是否确实具有写入权限。 ` Android kotlin: Getting EACCES (Permission denied) .. 不清楚该文件是哪个文件。用于在您的设备上创建文件或用于 Firebase 中的文件。 这是我在下载之前创建的文件,用于将下载写入文件。 “验证我的文件” val myFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),file.getFilename()!! 你创建了一个 File 实例。那不会创建文件。所以不会导致访问失败。请调查。 我以为会是这一行:“fileRef.getFile(myFile).addOnSuccessListener”导致错误。顺便说一句:它在模拟器中工作,但在我的真实手机上却没有 【参考方案1】:

Extends ActivityCompat.OnRequestPermissionsResultCallback 在 FilesActivity 类中不可用。

class FilesActivity : AppCompatActivity() , ActivityCompat.OnRequestPermissionsResultCallback 

您需要为 requestPermissionLauncher 定义调用 ActivityCompat.OnRequestPermissionsResultCallback 接口。

示例代码:

class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsResultCallback 


private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    )  isGranted: Boolean ->
        if (isGranted) 
            // Permission has been granted. Start camera preview Activity.

                startCamera()

         else 
            // Permission request was denied.
            requestPermissions()
        
    



override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    requestPermissions()




private fun requestPermissions() 
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
        == PackageManager.PERMISSION_GRANTED) 
        // Permission has been granted. Start camera preview Activity.
        startCamera()

     else  requestPermissionLauncher.launch(Manifest.permission.CAMERA)



private fun startCamera() 
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    startActivity(intent)

https://github.com/harunkor/requestPermissionLauncherSample

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。 感谢您的回答。当我在 FilesActivity 中下载文件时,它确实有效。但是我想用 FilesAdapter 类中的一个函数来下载文件,用于上述的回收器视图。我仍然在那里检查权限,但没有运气。 这毫无意义。您在哪里询问并获得许可并不重要。它将在整个应用程序的整个生命周期内有效。只有在获得许可后才能下载和编写。你可以在第二天这样做,以确保安全 ;-)。 感谢您的所有帮助,但在我已经发布的适配器类的代码中,我在下载前检查了权限。我在那里做错了吗?我知道这没有意义。

以上是关于Android kotlin:即使在授予权限后也获得 EACCES(权限被拒绝)的主要内容,如果未能解决你的问题,请参考以下文章

存储访问框架 - 权限被拒绝问题,即使授予权限

即使在 Flutter 中授予权限后,通知访问屏幕也会不断弹出

为啥 fork 炸弹没有使 android 崩溃?

如何在android中以编程方式授予系统级权限?

清单中存在时未授予运行时权限(Android)[重复]

即使在寻求存储权限后也没有创建目录