英文:
Saving file on Android 11+
问题
我想将来自我的应用程序专用目录的缓存PDF文件保存到Android 11+设备的共享存储中。我该怎么做?
我尝试理解作用域存储的概念,但无法实现。我正在使用Java开发应用程序。
英文:
I want to save cache pdf file from my app-specific directory to Android shared storage for Android 11+ devices. How can I do this
I tried to understand concept of scoped storage but unable to implement. I'm developing application in java
答案1
得分: -1
在Android 11及以上版本中,引入了作用域存储(scoped storage)的概念,这提供了更安全和受控的访问方式,用于访问应用程序特定的文件和目录。要将PDF文件从您的应用程序特定目录保存到Android共享存储中,请按照以下步骤操作:
-
请求必要的权限:在您的AndroidManifest.xml文件中添加以下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
检查运行时权限:在运行时向用户请求WRITE_EXTERNAL_STORAGE权限。您可以使用**checkSelfPermission()方法检查权限是否已授予,如果没有,则使用requestPermissions()**方法请求权限。
-
使用MediaStore API复制文件:Android 11引入了MediaStore API,允许您与共享媒体文件互动。您可以使用此API将PDF文件从您的应用程序特定目录复制到共享存储中的位置。
以下是一个示例代码片段,演示了如何将PDF文件从您的应用程序特定目录保存到共享存储中:
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
// 从应用程序特定目录获取PDF文件
File pdfFile = new File(getFilesDir(), "example.pdf");
// 为新文件准备内容值
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "example.pdf");
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf");
// 根据设备的API级别确定适当的内容URI
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 对于Android 10及以上版本,使用MediaStore API和MediaStore.Downloads
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
} else {
// 对于Android 9及以下版本,使用废弃的MediaStore API和MediaStore.Files
uri = MediaStore.Files.getContentUri("external");
}
// 将文件插入媒体存储
ContentResolver resolver = getContentResolver();
Uri newUri = resolver.insert(uri, values);
// 从应用程序特定目录复制文件内容到共享存储
try {
OutputStream outputStream = resolver.openOutputStream(newUri);
FileInputStream inputStream = new FileInputStream(pdfFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
在此代码片段中,使用getFilesDir()从应用程序特定目录检索example.pdf文件。然后,创建ContentValues以存储新文件的元数据,包括显示名称和MIME类型。根据设备的API级别确定适当的内容URI,并使用**insert()**将文件插入媒体存储。
最后,通过打开指向newUri的输出流并从应用程序特定文件获取的输入流中读取内容,将文件内容从应用程序特定目录复制到共享存储中。
英文:
In Android 11 and above, the concept of scoped storage was introduced, which provides more secure and controlled access to app-specific files and directories. To save a PDF file from your app-specific directory to Android shared storage, you need to follow these steps:
-
Request the necessary permissions: Add the following permission to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
Check for the runtime permission: Request the WRITE_EXTERNAL_STORAGE permission from the user at runtime. You can use the checkSelfPermission() method to check if the permission is already granted, and if not, request it using the requestPermissions() method.
-
Use the MediaStore API to copy the file: Android 11 introduced the MediaStore API, which allows you to interact with shared media files. You can use this API to copy the PDF file from your app-specific directory to a location in shared storage.
Here's an example code snippet that demonstrates how to save a PDF file from your app-specific directory to shared storage:
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
// Get the PDF file from your app-specific directory
File pdfFile = new File(getFilesDir(), "example.pdf");
// Prepare the content values for the new file
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "example.pdf");
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf");
// Determine the appropriate content URI based on the device's API level
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// For Android 10 and above, use MediaStore API with MediaStore.Downloads
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
} else {
// For Android 9 and below, use the deprecated MediaStore API with MediaStore.Files
uri = MediaStore.Files.getContentUri("external");
}
// Insert the file into the media store
ContentResolver resolver = getContentResolver();
Uri newUri = resolver.insert(uri, values);
// Copy the file content from the app-specific directory to the shared storage
try {
OutputStream outputStream = resolver.openOutputStream(newUri);
FileInputStream inputStream = new FileInputStream(pdfFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
In this code snippet, the example.pdf file is retrieved from the app-specific directory using getFilesDir(). Then, ContentValues are created to store the metadata of the new file, including its display name and MIME type. The appropriate content URI is determined based on the device's API level, and the file is inserted into the media store using insert().
Finally, the file content is copied from the app-specific directory to the shared storage by opening an output stream to the newUri and reading the content from the input stream obtained from the app-specific file.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论