[英]File exists and IS directory, but listFiles() returns null
File.listFiles()
的文檔表明只有在調用它的文件不是目錄的情況下才會返回null
。
我有以下幾點:
String dir = "/storage/emulated/0";
File f = new File(dir);
Log.v("Files",f.exists()+"");
Log.v("Files",f.isDirectory()+"");
Log.v("Files",f.listFiles()+"");
日志寫道:
true
true
null
出於某種原因,即使File
被識別為有效目錄, listFiles(
) 也會返回null
。 我對 Android 文件層次結構的行為不是很熟悉,所以我猜問題出在那里。
作為參考,我正在 Moto X 上進行調試,無論手機是否插入我的計算機,結果都是一樣的 - 所以我認為這與插入時的安裝無關。
對於有此問題的人,請將其添加到 AndroidManifest.xml 中:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
問題解決了:D
編輯:如果這不起作用,請確保路徑是否正確
除了其他答案和評論,我建議您檢查是否需要
<application android:requestLegacyExternalStorage="true"
在您的清單中。 似乎最近的一些api需要它。
無論如何, zapl 的評論相當短,但很有見地。 您可以“ls -ld”設備上的目錄(通過“adb shell”或其他一些shell)。 如果您對該目錄具有“r”權限,則可以調用 listFiles()。 否則,它返回 null。 請注意,如果您知道文件名並且對該目錄具有“x”權限,則您可以訪問不可讀目錄下的文件。 你可以通過“whoami”和“groups”命令知道你是誰。
對於 android 23 或更高版本,您需要在 onresume 方法中以編程方式授予運行時權限,如下所示,
public final String[] EXTERNAL_PERMS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE
};
public final int EXTERNAL_REQUEST = 138;
requestForPermission();
public boolean requestForPermission() {
boolean isPermissionOn = true;
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {
if (!canAccessExternalSd()) {
isPermissionOn = false;
requestPermissions(EXTERNAL_PERMS, EXTERNAL_REQUEST);
}
}
return isPermissionOn;
}
public boolean canAccessExternalSd() {
return (hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
}
private boolean hasPermission(String perm) {
return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, perm));
}
對於有此問題的人,您要授予讀取權限,請將其添加到 AndroidManifest.xml 中:
android:name="android.permission.READ_EXTERNAL_STORAGE"
你還應該授予許可
設置 > 應用程序 > “您的應用程序名稱” > 權限 > 存儲
來自 File 'listFiles' 方法文檔:如果此抽象路徑名不表示目錄,或者發生 I/O 錯誤,則返回 null。
所以可能發生了 I/O 錯誤。 檢查該目錄的權限,運行java程序的用戶是否有讀取該目錄的權限? 如果沒有,那就有你的答案。 如果他們這樣做,那么目錄可能是空的。
順便說一句,您不應該使用 +"" 將某些內容轉換為字符串,這是一種不好的做法,因為它比 String.valueOf 慢。 我會使用 apache 的 StringUtils 將該數組加入一個字符串中,但這需要將該 jar 添加到您的類路徑中。
只需在 manifest uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
添加權限,您的問題就會得到解決。
@tamo 的回答解決了我的問題,我在 ANQ 上編譯 exoplayer,然后設置:
構建.gradle:
android {
compileSdkVersion 29
buildToolsVersion '29.0.0'
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
}
清單.xml :
<application
android:name="com.google.android.exoplayer.demo.ExoPlayerDemoApplication"
android:label="@string/application_name"
android:icon="@drawable/ic_launcher"
android:largeHeap="true"
android:allowBackup="false"
android:requestLegacyExternalStorage="true">
我檢查了android開發站點,它已經解釋了這一點: https : //developer.android.com/training/data-storage/compatibility
如果您的目標是 API 29 或更高版本,只需遵循 google 的設置。
將此添加到您的 AndroidManifest.xml <application android:requestLegacyExternalStorage="true" .../> 它對我有用。
我的問題是由於某種原因 android:sharedUserId="android.uid.system" 屬性不允許應用程序在特定設備上讀取 /sdcard/ 。
因為我只需要做一個快速測試,我刪除了 sharedUserId 屬性,測試並添加回來。
首先確保您正在請求讀取外部存儲的權限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
如果您願意,可以使用 Dexter 庫請求許可,使用 dexter 庫請求許可非常容易
這是鏈接
然后在清單的<application標簽中添加以下標簽
android:requestLegacyExternalStorage="true"
那么 listFiles() 函數將不會返回空數組
我在 java 中遇到了同樣的問題,但在 android 中沒有,我正在讀取帶引號的路徑的配置文件。 我通過刪除引號解決了我的問題
所以你可以通過字符串替換函數來完成,也可以不加引號
String someString="C:\\path"; someString=someString.replace("\\"","");
在<uses-permission .... >
部分的清單文件中,添加這一行android:name="android.permission.READ_EXTERNAL_STORAGE"
。 我認為這可能會解決您的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.