【发布时间】:2011-12-21 08:08:16
【问题描述】:
我有一个网络服务,它根据图像 id 给我一个 byte[] 数组。我想将这些字节 [] 转换为文件并将文件存储在 android 上,用户希望在其中保存文件对话框,文件格式与其完全相同。
【问题讨论】:
标签: android android-layout android-widget
我有一个网络服务,它根据图像 id 给我一个 byte[] 数组。我想将这些字节 [] 转换为文件并将文件存储在 android 上,用户希望在其中保存文件对话框,文件格式与其完全相同。
【问题讨论】:
标签: android android-layout android-widget
由于这是您搜索该主题时在 google 中的最高结果,并且在我研究它时让我很困惑,我想我为这个问题添加了一个更新。 从 Android 19 开始,有一个内置的保存对话框。您不需要任何权限来执行此操作(甚至不需要 WRITE_EXTERNAL_STORAGE)。 它的工作方式非常简单:
//send an ACTION_CREATE_DOCUMENT intent to the system. It will open a dialog where the user can choose a location and a filename
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("YOUR FILETYPE"); //not needed, but maybe usefull
intent.putExtra(Intent.EXTRA_TITLE, "YOUR FILENAME"); //not needed, but maybe usefull
startActivityForResult(intent, SOME_INTEGER);
...
//after the user has selected a location you get an uri where you can write your data to:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == SOME_INTEGER && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
//just as an example, I am writing a String to the Uri I received from the user:
try {
OutputStream output = getContext().getContentResolver().openOutputStream(uri);
output.write(SOME_CONTENT.getBytes());
output.flush();
output.close();
}
catch(IOException e) {
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
}
}
}
更多: https://developer.android.com/guide/topics/providers/document-provider
【讨论】:
Android SDK 不提供自己的文件对话框,因此您必须自己构建。
【讨论】:
您无法创建保存文件对话框,但您可以借助以下链接将文件从您的应用程序保存到 android sd 卡
http://android-er.blogspot.com/2010/07/save-file-to-sd-card.html
http://www.blackmoonit.com/android/filebrowser/intents#intent.pick_file.new
【讨论】:
首先,您应该创建一个用于保存文件的对话框意图,用户选择后,您可以在该目录上写入并指定文件,而无需任何读/写权限。 (自 Android 19 起)
来源:https://developer.android.com/training/data-storage/shared/documents-files#create-file
// Request code for creating a PDF document.
private final int SAVE_DOCUMENT_REQUEST_CODE = 0x445;
private File targetFile;
private void createFile() {
Uri reportFileUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", targetFile);
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
intent.putExtra(Intent.EXTRA_TITLE, targetFile.getName());
// Optionally, specify a URI for the directory that should be opened in
// the system file picker when your app creates the document.
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
startActivityForResult(intent, SAVE_DOCUMENT_REQUEST_CODE );
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SAVE_DOCUMENT_REQUEST_CODE && resultCode == RESULT_OK){
Uri uri = data.getData();
saveFile(uri);
}
}
private void saveFile(Uri uri) {
try {
OutputStream output = getContentResolver().openOutputStream(uri);
FileInputStream fileInputStream = new FileInputStream(targetFile);
byte[] bytes = new byte[(int) targetFile.length()];
fileInputStream.read(bytes, 0, bytes.length);
output.write(bytes);
output.flush();
output.close();
Log.i(TAG, "done");
} catch (IOException e) {
Log.e(TAG, "onActivityResult: ", e);
}
}
【讨论】:
@JodliDev 已经提供了接受的答案,但是 startActivityForResult 现在已被弃用,所以我想在这里使用 registerForActivityResult(ActivityResultContracts.CreateDocument()) 提供我的解决方案
首先注册一个 ActivityResultLauncher,您可以在其中定义结果应该发生的情况。我们将取回可用于 OutpuStream 的 uri。但一定要一开始就初始化,否则会得到:
片段必须在创建之前调用 registerForActivityResult()(即初始化、onAttach() 或 onCreate())。
private var ics: String? = null
private val getFileUriForSavingICS = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
if(ics.isNullOrEmpty())
return@registerForActivityResult
try {
val output: OutputStream? =
context?.contentResolver?.openOutputStream(uri)
output?.write(ics?.toByteArray())
output?.flush()
output?.close()
} catch (e: IOException) {
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show()
}
}
然后只需在需要的地方使用 .launch(...) 调用您的 ActivityResultLauncher。
getFileUriForSavingICS.launch("filename.txt")
就是这样 ;-) 您还可以仔细查看 ActivityResultContracts.CreateDocument()。此方法提供文档保存对话框,但内部还有其他有用的功能(例如用于启动相机意图)。退房: https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts 对于可能的 ActivityResultContracts
或https://developer.android.com/training/basics/intents/result 获取更多培训材料以及如何创建自定义合同的一些信息!
【讨论】: