在由Intent.ACTION_OPEN_DOCUMENT_TREE返回的目录中创建新文件。

huangapple go评论78阅读模式
英文:

Create new file in the directory returned by Intent.ACTION_OPEN_DOCUMENT_TREE

问题

在我的应用中,用户可以通过隐式意图ACTION_OPEN_DOCUMENT_TREE选择要在其中创建Excel文件的目录。然而,在onActivityResult()中返回的Uri不能被FileOutputStream()使用。它会抛出FileNotFoundException

java.io.FileNotFoundException: content:/com.android.externalstorage.documents/tree/home%3A:test.xlsx (没有这个文件或目录)

onActivityResult()中,我通过File.exists()检查路径是否存在,如果不存在,我想要创建一个新的Excel文件。

onActivityResult():

	@Override
	protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
		Log.d(TAG, "onActivityResult: called");
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == Activity.RESULT_OK && requestCode == 2) {
			Log.d(TAG, "onActivityResult: path = " + data.getData().getPath());
			Uri treePath = data.getData();
			File path = new File(treePath + File.pathSeparator + "test.xlsx");
			if (path.exists()) {
				updateExistingExcelFile(path);
			} else {
				createNewExcelFile(path);
			}
		}
	}

createNewExcelFile():

	private void createNewExcelFile(File path) {
		Log.d(TAG, "createNewExcelFile: called");
		Workbook workbook = new HSSFWorkbook();
		Cell cell;
		Sheet sheet;
		sheet = workbook.createSheet("表格名称");
		Row row = sheet.createRow(0);
		cell = row.createCell(0);
		cell.setCellValue("名称");
		cell = row.createCell(1);
		cell.setCellValue("编号");
		sheet.setColumnWidth(0, (10 * 200));
		sheet.setColumnWidth(1, (10 * 200));
		FileOutputStream fileOutputStream;
		try {
			fileOutputStream = new FileOutputStream(path);
			workbook.write(fileOutputStream);
			Toast.makeText(this, "已创建", Toast.LENGTH_LONG).show();
			fileOutputStream.close();
		} catch (IOException e) {
			Log.e(TAG, "createNewExcelFile: ", e);
		}
	}

如果我在隐式意图路径中使用Activity.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)或类似的内容,代码完全可以正常工作。

英文:

In my App the user can choose a directory where to create an Excel file using the implicit intent ACTION_OPEN_DOCUMENT_TREE.
However, the Uri returned in onActivityResult() cannot be used by FileOutputStream(). It throws a FileNotFoundException:

java.io.FileNotFoundException: content:/com.android.externalstorage.documents/tree/home%3A:test.xlsx (No such file or directory)

In onActivityResult() I check if the path exists via File.exists() and if not, I want to create a new Excel file.

onActivityResult():

	@Override
	protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
		Log.d(TAG, "onActivityResult: called");
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == Activity.RESULT_OK && requestCode == 2) {
			Log.d(TAG, "onActivityResult: path = " + data.getData()
			                                             .getPath());
			Uri treePath = data.getData();
			File path = new File(treePath + File.pathSeparator + "test.xlsx");
			if (path.exists()) {
				updateExistingExcelFile(path);
			} else {
				createNewExcelFile(path);
			}
		}
	}

createNewExcelFile():

	private void createNewExcelFile(File path) {
		Log.d(TAG, "createNewExcelFile: called");
		Workbook workbook = new HSSFWorkbook();
		Cell cell;
		Sheet sheet;
		sheet = workbook.createSheet("Name of sheet");
		Row row = sheet.createRow(0);
		cell = row.createCell(0);
		cell.setCellValue("Name");
		cell = row.createCell(1);
		cell.setCellValue("Number");
		sheet.setColumnWidth(0, (10 * 200));
		sheet.setColumnWidth(1, (10 * 200));
		FileOutputStream fileOutputStream;
		try {
			fileOutputStream = new FileOutputStream(path);
			workbook.write(fileOutputStream);
			Toast.makeText(this, "Created", Toast.LENGTH_LONG)
			     .show();
			fileOutputStream.close();
		} catch (IOException e) {
			Log.e(TAG, "createNewExcelFile: ", e);
		}
	}

The code works perfectly fine if I use Activity.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) or something similar instead of the implicit intents path.

答案1

得分: 22

Step #1: 使用从ACTION_OPEN_DOCUMENT_TREE获取的Uri,并传递给DocumentFile.fromTreeUri()

Step #2: 调用DocumentFile上的createFile()方法,以获取表示子文档的DocumentFile

Step #3: 调用在Step #2中创建的DocumentFile上的getUri()方法。

Step #4: 调用ContentResolver上的openOutputStream()方法,传入Step #3中的Uri,以获取可用于写入内容的OutputStream。您可以通过在某些Context上调用getContentResolver()(例如Activity)来获取ContentResolver

有关使用ACTION_OPEN_DOCUMENT_TREE的更多信息,请参阅此博客文章

英文:

Step #1: Take the Uri that you get from ACTION_OPEN_DOCUMENT_TREE and pass it to DocumentFile.fromTreeUri().

Step #2: Call createFile() on that DocumentFile to get a DocumentFile representing the child document.

Step #3: Call getUri() on the DocumentFile that you created in Step #2.

Step #4: Call openOutputStream() on a ContentResolver, passing in the Uri from Step #3, to get an OutputStream that you can use to write content. You get a ContentResolver by calling getContentResolver() on some Context, such as an Activity.

See this blog post for more on using ACTION_OPEN_DOCUMENT_TREE.

huangapple
  • 本文由 发表于 2020年4月9日 18:18:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/61118918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定