Android 11 获取Download路径

在Android 11中,由于用户隐私的保护,应用程序无法直接访问外部存储的Download目录。而在之前的Android版本中,我们可以通过Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)来获取Download目录的路径。但是在Android 11中,这个方法被废弃了。本文将介绍如何在Android 11中获取Download目录的路径。

使用MediaStore API

在Android 11中,我们可以使用MediaStore类提供的API来获取Download目录的路径。MediaStore类是一个用于访问媒体文件(如音频、视频、图片等)的内容提供者。

首先,我们需要声明以下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

然后,在代码中,我们可以使用以下方法来获取Download目录的路径:

public static Uri getDownloadUri() {
    return MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL);
}

public static String getDownloadPath(Context context) {
    String[] projection = {MediaStore.Downloads._ID, MediaStore.Downloads.DISPLAY_NAME};
    String selection = MediaStore.Downloads.IS_DOWNLOAD;
    String sortOrder = MediaStore.Downloads.DISPLAY_NAME + " ASC";

    Cursor cursor = context.getContentResolver().query(
        getDownloadUri(),
        projection,
        selection,
        null,
        sortOrder
    );

    if (cursor != null && cursor.moveToFirst()) {
        int idColumnIndex = cursor.getColumnIndex(MediaStore.Downloads._ID);
        int nameColumnIndex = cursor.getColumnIndex(MediaStore.Downloads.DISPLAY_NAME);
        String id = cursor.getString(idColumnIndex);
        String name = cursor.getString(nameColumnIndex);

        String path = Environment.getExternalStorageDirectory().getPath() + "/Download/" + name;
        cursor.close();
        return path;
    }

    if (cursor != null) {
        cursor.close();
    }
    return null;
}

在上述代码中,getDownloadUri()方法返回Download目录的UrigetDownloadPath(Context context)方法使用ContentResolver查询Download目录下的文件,并获取文件的路径。

需要注意的是,由于Android 11中的存储权限变更,我们需要在运行时请求READ_EXTERNAL_STORAGE权限:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    if (Environment.isExternalStorageManager()) {
        // 已经获取了存储权限
        // 进行相关操作
    } else {
        Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
        startActivity(intent);
    }
} else {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) {
        // 已经获取了存储权限
        // 进行相关操作
    } else {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
    }
}

如果应用程序运行在Android 11及以上版本,我们需要检查是否已经获取了存储权限。如果没有获取权限,我们需要使用ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION打开系统设置,让用户手动授权。

代码示例

下面是一个完整的代码示例,演示了如何在Android 11中获取Download目录的路径:

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_CODE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                // 已经获取了存储权限
                // 进行相关操作
                String downloadPath = getDownloadPath(MainActivity.this);
                Log.d("MainActivity", "Download path: " + downloadPath);
            } else {
                Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                startActivity(intent);
            }
        } else {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                // 已经获取了存储权限
                // 进行相关操作
                String downloadPath = getDownloadPath(MainActivity.this);
                Log.d("MainActivity", "Download path: " + downloadPath);
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
            }
        }
    }

    public static Uri getDownloadUri() {
        return MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL);
    }

    public static String getDownloadPath(Context context) {
        String[] projection = {MediaStore.Downloads._ID, MediaStore.Downloads.DISPLAY_NAME};
        String selection = MediaStore.Downloads.IS_DOWNLOAD;
        String sortOrder = MediaStore.Downloads.DISPLAY_NAME + " ASC";

        Cursor cursor = context.getContentResolver().query(