Android无需读写权限通过临时授权读写用户文件怎么实现

发布时间:2023-03-21 15:19:06 作者:iii
来源:亿速云 阅读:224

Android无需读写权限通过临时授权读写用户文件怎么实现

在Android开发中,文件读写是一个常见的需求。传统的做法是通过申请READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限来访问用户的文件。然而,随着Android系统的不断更新,权限管理变得越来越严格,用户对隐私保护的意识也在不断增强。为了减少对用户隐私的侵犯,Android提供了一种无需申请读写权限即可通过临时授权读写用户文件的机制。本文将详细介绍如何实现这一机制。

1. 背景介绍

在Android 10(API级别29)及更高版本中,Google引入了Scoped Storage(作用域存储)的概念,旨在更好地保护用户隐私。Scoped Storage限制了应用对共享存储空间的访问,要求应用只能访问自己的私有目录和通过特定API访问的媒体文件。

然而,在某些情况下,应用仍然需要访问用户的文件,例如用户选择文件进行上传或下载。为了在不申请读写权限的情况下实现这一需求,Android提供了Storage Access Framework(SAF)和ContentResolver等机制。

2. 使用Storage Access Framework(SAF)

Storage Access Framework(SAF)是Android提供的一种允许用户选择文件和目录的框架。通过SAF,应用可以在不申请读写权限的情况下访问用户选择的文件。

2.1 启动文件选择器

要使用SAF,首先需要启动一个文件选择器。可以通过Intent.ACTION_OPEN_DOCUMENTIntent.ACTION_CREATE_DOCUMENT来启动文件选择器。

// 启动文件选择器以选择文件
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT);

// 启动文件选择器以创建文件
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, "newfile.txt");
startActivityForResult(intent, REQUEST_CODE_CREATE_DOCUMENT);

2.2 处理文件选择结果

onActivityResult方法中处理文件选择结果。通过返回的Uri,应用可以读取或写入文件。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK && data != null) {
        Uri uri = data.getData();
        if (requestCode == REQUEST_CODE_OPEN_DOCUMENT) {
            // 读取文件
            readFile(uri);
        } else if (requestCode == REQUEST_CODE_CREATE_DOCUMENT) {
            // 写入文件
            writeFile(uri, "Hello, World!");
        }
    }
}

2.3 读取文件

通过ContentResolver读取文件内容。

private void readFile(Uri uri) {
    try {
        InputStream inputStream = getContentResolver().openInputStream(uri);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
        }
        inputStream.close();
        String fileContent = stringBuilder.toString();
        Log.d("FileContent", fileContent);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.4 写入文件

通过ContentResolver写入文件内容。

private void writeFile(Uri uri, String content) {
    try {
        OutputStream outputStream = getContentResolver().openOutputStream(uri);
        outputStream.write(content.getBytes());
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3. 使用ContentResolver访问媒体文件

除了使用SAF,Android还提供了ContentResolver来访问媒体文件(如图片、视频、音频等)。通过ContentResolver,应用可以在不申请读写权限的情况下访问媒体文件。

3.1 查询媒体文件

通过ContentResolver查询媒体文件。

Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

if (cursor != null) {
    while (cursor.moveToNext()) {
        long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
        String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
        Log.d("MediaFile", "ID: " + id + ", Name: " + name);
    }
    cursor.close();
}

3.2 读取媒体文件

通过ContentResolver读取媒体文件。

Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
try {
    InputStream inputStream = getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
    inputStream.close();
    // 使用bitmap
} catch (IOException e) {
    e.printStackTrace();
}

3.3 写入媒体文件

通过ContentResolver写入媒体文件。

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "new_image.jpg");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

try {
    OutputStream outputStream = getContentResolver().openOutputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_image);
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
    outputStream.close();
} catch (IOException e) {
    e.printStackTrace();
}

4. 临时授权

通过SAF或ContentResolver访问文件时,Android会为应用授予临时访问权限。临时授权在应用重启后失效,因此如果需要持久化访问权限,可以通过takePersistableUriPermission方法获取持久化权限。

final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(uri, takeFlags);

5. 总结

通过使用Storage Access FrameworkContentResolver,Android应用可以在不申请读写权限的情况下访问用户文件。这种方式不仅减少了权限申请对用户的干扰,还提高了用户隐私保护的水平。开发者应根据具体需求选择合适的机制,并在必要时获取持久化权限,以确保应用的正常运行。

在实际开发中,开发者应始终遵循最小权限原则,尽量减少对用户隐私的侵犯,同时提供良好的用户体验。通过合理使用Android提供的文件访问机制,开发者可以在保护用户隐私的同时,实现应用的功能需求。

推荐阅读:
  1. 如何用Android实现加载效果
  2. Android制作水平圆点加载进度条

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

android

上一篇:php中怎么使用重定向跳转页面

下一篇:SpringBoot如何实现RAS+AES自动接口解密

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》