目录
在 Android 开发中获取设备中的所有文件信息,需要注意权限管理和隐私安全。在 Android 11 及更高版本,访问设备文件的权限得到了进一步限制,应用只能访问自身的私有存储区域和经过用户授权的共享存储区域。
方法概述
要获取文件信息,可以使用以下方法:
- 访问应用的私有存储:使用
Context.getFilesDir()
等方法获取应用的私有目录中的文件信息。 - 访问共享存储的文件:在 Android 10 及更高版本,使用
MediaStore
访问公开文件(例如图片、视频、音频等)。 - 访问特定的文件路径:通过
File
类指定路径访问文件夹内容,适用于 Android 10 以下版本,或获得特殊权限的情况。
重要提示
- 从 Android 6.0 开始,访问外部存储需要申请 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 权限。
- 从 Android 11(API 30)开始,应用只能访问其私有目录和部分经过权限批准的共享文件,使用
MediaStore
访问多媒体文件。 - 为了更灵活地管理存储访问权限,可以使用 Storage Access Framework (SAF) 或 Scoped Storage。
示例代码
以下代码演示如何在 Android 10 及以下版本中获取所有文件的信息,并在 Android 11 及更高版本中使用 MediaStore
获取公开文件的信息。
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import java.io.File;
public class FileUtils {
private static final String TAG = "FileUtils";
/**
* 获取应用私有目录中的所有文件
*
* @param context 应用上下文
*/
public static void getAllPrivateFiles(Context context) {
File privateDir = context.getFilesDir(); // 获取应用私有文件目录
listFilesRecursively(privateDir);
}
/**
* 列出文件夹及其子文件夹中的所有文件
*
* @param dir 目标文件夹
*/
private static void listFilesRecursively(File dir) {
if (dir != null && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
listFilesRecursively(file); // 递归遍历子目录
} else {
Log.d(TAG, "File: " + file.getAbsolutePath());
}
}
}
}
}
/**
* 获取外部存储中的所有文件信息(适用于 Android 10 及以下版本)
*
* @param context 应用上下文
*/
public static void getAllExternalFiles(Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "需要 READ_EXTERNAL_STORAGE 权限");
return;
}
File externalDir = Environment.getExternalStorageDirectory(); // 获取外部存储根目录
listFilesRecursively(externalDir);
}
/**
* 使用 MediaStore 获取多媒体文件信息(适用于 Android 11 及更高版本)
*
* @param context 应用上下文
*/
@RequiresApi(api = Build.VERSION_CODES.R)
public static void getAllMediaFiles(Context context) {
String[] projection = new String[]{
MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.DATA
};
Cursor cursor = context.getContentResolver().query(
MediaStore.Files.getContentUri("external"),
projection,
null,
null,
null
);
if (cursor != null) {
while (cursor.moveToNext()) {
String fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME));
String filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
Log.d(TAG, "Media File: " + fileName + " Path: " + filePath);
}
cursor.close();
}
}
}
使用说明
- 应用私有目录:
getAllPrivateFiles()
方法会递归遍历应用的私有存储目录,无需特殊权限。 - 外部存储目录:
getAllExternalFiles()
方法在 Android 10 及以下版本中运行。调用该方法前,需要检查并请求READ_EXTERNAL_STORAGE
权限。 - 多媒体文件访问:
getAllMediaFiles()
使用MediaStore
访问多媒体文件(图片、视频、音频等),适用于 Android 11 及更高版本。
权限申请
在 AndroidManifest.xml
文件中添加以下权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
在 Android 6.0 及更高版本中,运行时请求权限:
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
}
注意事项
- 使用
MediaStore
是 Android 11 及以上版本访问公共存储的推荐方法。 - 对于非公共目录或特定类型的文件,需使用 Storage Access Framework (SAF) 或其他系统 API。
- 在 Android 10 及以上,建议使用
Scoped Storage
访问共享存储数据。