为什么 File.listFiles() 方法只能列出目录。

huangapple go评论66阅读模式
英文:

Why File.listFiles() method can only list directories

问题

我在Android R上遇到了一个非常奇怪的问题。以下是我所做的:

  1. 在Manifest.xml中声明我会使用WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限。
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  1. 在我的代码中检查并请求权限。
    private void checkPermission() {
        int pid = android.os.Process.myPid();
        int read = checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, pid, 1);
        int write = checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, 1);
        ArrayList<String> permissions = new ArrayList<>();
        if (read != PackageManager.PERMISSION_GRANTED)
            permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        if (write != PackageManager.PERMISSION_GRANTED)
            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permissions.size() > 0) {
            String[] permissionArray = new String[permissions.size()];
            permissions.toArray(permissionArray);
            requestPermissions(permissionArray,1);
        }
    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        //我在这里忽略了结果检查,因为我确定当我被要求允许权限时,我点击了“允许”按钮
        File directory = new File("/storage/emulated/0/ebook");
        File[] files = directory.listFiles();
        for(File file : files)
        {
            try {

                Log.i("tagd", "file name: " +file.getCanonicalPath());

            } catch (IOException e) {
                e.printStackTrace();

            }
        }
    }

好的,下面是奇怪的事情。从日志中,我只得到了一行:

file name: /storage/emulated/0/ebook/temp

但在文件夹“ebook”中实际上有40个项目。有39个PDF文档和1个名为“temp”的文件夹。所有的PDF文档都不见了。同样的情况也发生在其他包含任何类型文件的目录中。

问题只能在Android Q上复现。这段代码非常简单,在其他Android版本上工作正常。有人有任何关于发生了什么的想法吗?任何帮助将不胜感激,谢谢。

英文:

I'm stucking with a really wired problem on Android R. Here is what I did.

  1. Claim that I would use WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions in Manifest.xml.
   &lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; /&gt;
   &lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; /&gt;
  1. Check and request permissions in my code
   private void checkPermission() {
       int pid = android.os.Process.myPid();
       int read = checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, pid, 1);
       int write = checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, 1);
       ArrayList&lt;String&gt; permissions = new ArrayList&lt;&gt;();
       if (read != PackageManager.PERMISSION_GRANTED)
           permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
       if (write != PackageManager.PERMISSION_GRANTED)
           permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
       if (permissions.size() &gt; 0) {
           String[] permissionArray = new String[permissions.size()];
           permissions.toArray(permissionArray);
           requestPermissions(permissionArray,1);
       }
   }

   public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                          @NonNull int[] grantResults) {
       //I ignored the result check here since I definitely know that I clicked on the &quot;Allow&quot; button when
       //I was asked to allow the permissions
       File directory = new File(&quot;/storage/emulated/0/ebook&quot;);
       File[] files = directory.listFiles();
       for(File file : files)
       {
           try {

               Log.i(&quot;tagd&quot;, &quot;file name: &quot; +file.getCanonicalPath());

           } catch (IOException e) {
               e.printStackTrace();

           }
       }
   }

OK, here comes the wired thing. From the log, I got only one line:

file name: /storage/emulated/0/ebook/temp

But in the folder "ebook" there are actually 40 items. 39 PDF documents and 1 folder "temp". All PDF documents are missing. Same thing happened in other directories with any type of file.

generic_x86_64_arm64:/sdcard/ebook $ ls
1.pdf                                                       dovado\ 4GR\ Reference_manua62X.pdf.pdf
111(1).pdf                                                  fit_diff_pages.pdf
2013\ Mar.pdf                                               help.pdf
2017-08-03_SZ_NK.pdf                                        interactiveform_enabled.pdf
223622-100518.pdf                                           invoice\ 2013-1-28.pdf
59df269384986.pdf                                           pass-111111.pdf
732101500002013-07-21_03-55-53-3352579.pdf                  pdf_commenting_new.pdf
Aeroplane\ -\ bjo.pdf                                       pdfa_pagina_a4_gear_movie.pdf
BoardMeetingMinutes.1024.pdf                                signature.pdf
CreditCardReckoning201211.pdf                               temp
DEMO_SV_lowsize.pdf                                         test.pdf
Geografie_\ Gr\ 10\ Portefeuljeboek\ -\ vnull.pdf           test.pfx
Geografie_\ Gr\ 10\ Portefeuljeboek\ -\ vnull_unlocked.pdf  test1.pdf
Layali_Ashar[1].pdf                                         test28k.pdf
PDF\ markup\ design-Model.pdf                               test_att.pdf
Praise\ And\ Thanksgiving\ (Morning\ Has\ Broken).pdf       visa-china.pdf
Professional_Android_2_Application_Development.pdf          为人父母.pdf
Welcome_to_Radaee_PDF_Master.pdf                            张霁\ 简历\ 3\ -\ 副本.pdf
Xaml_Introduction.pdf                                       比亚迪.pdf
__ViewPoint\ 8000________________\ (2).pdf                  美时每客CakeTime移动平台项目开发分析报告.pdf

The issue can only be reproduced on Android Q. The code is really simple and works fine on other Android releases. Any one got any idea for what happened here? Any help would be appreciated, thank you.

答案1

得分: 1

似乎这与安卓11存储更新有关。这是一个非常让人烦恼的改变。他们在没有提供太多有用错误信息的情况下,悄悄地打破了API契约。无论是抛出异常还是在日志中添加一些警告,都会为开发人员节省更多时间。

链接:https://developer.android.com/about/versions/11/privacy/storage

英文:

Seems this is related to android 11 storage update. That's a very annoying change. They silently breaks the API contract without much useful error information provided. Either throw exception or add some warning in the log will provide much better clue to save developers times.

https://developer.android.com/about/versions/11/privacy/storage

答案2

得分: 0

可能与权限有关 - 对于这个方法存在一个异常

> 如果存在安全管理器,并且它的SecurityManager#checkRead(String)方法拒绝了对目录的读取访问

https://developer.android.com/reference/java/io/File#listFiles()

英文:

it might be related to permissions - there is an exception for this method

> If a security manager exists and its SecurityManager#checkRead(String) method denies read access to the directory

https://developer.android.com/reference/java/io/File#listFiles()

答案3

得分: 0

我遇到了类似的问题。重新启动设备解决了它。太奇怪了,可能是安卓的一个 bug。

英文:

I had a similar issue. restarting the device solved it.. So weird.. maybe its an android bug

答案4

得分: -1

Java File.listFiles()方法返回一个数组,其中包含表示由此抽象路径名表示的目录中的文件的抽象路径名。

如果目录为空,则该数组将为空。如果此抽象路径名不表示目录,或者发生I/O错误,则返回null。

但你可以尝试类似这样的代码:

for (File file: files) {
    try {
        Log.i("文件名:" + file.getCanonicalPath() + "/n");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
英文:

Java File.listFiles() method Returns an array of abstract path names denoting the files in the directory denoted by this abstract path name.

The array will be empty if the directory is empty. Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.

but you can try something like this

for (File file: files) {
        try {

            Log.i(&quot;file name&quot; +file.getCanonicalPath()+&quot;/n&quot;);

        } catch (IOException e) {
            e.printStackTrace();

        }

huangapple
  • 本文由 发表于 2020年9月15日 17:13:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63898697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定