admin管理员组文章数量:1401651
I am writing an Android app in Kotlin and I am using Jetpack Compose.
In my app, I ask the user to select a directory where I can create a file and write to it. This is the relevant code extracted from my app:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TestApplicationTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
DirectorySelectionScreen(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun DirectorySelectionScreen(modifier: Modifier = Modifier) {
val context = LocalContext.current
// Launcher for directory selection
val openDirectoryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
uri?.let {
// Handle the selected directory URI
createFileInDirectory(context, it)
}
}
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Select a Directory to Create File",
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(bottom = 16.dp),
fontWeight = FontWeight.Bold
)
Button(onClick = { openDirectoryLauncher.launch(null) }) {
Text(text = "Select Directory")
}
}
}
fun createFileInDirectory(context: Context, parentUri: Uri) {
val contentResolver = context.contentResolver
val mimeType = "text/plain"
val displayName = "example.txt"
try {
// Create a new document (file) in the selected directory
val newDocumentUri = DocumentsContract.createDocument(
contentResolver,
parentUri, // URI of the selected directory
mimeType,
displayName
)
newDocumentUri?.let {
// Now write to the file
writeToFile(context, it)
}
} catch (e: Exception) {
Toast.makeText(context, "Error creating file: ${e.message}", Toast.LENGTH_LONG).show()
}
}
fun writeToFile(context: Context, fileUri: Uri) {
try {
// Open an OutputStream to the created file and write content
context.contentResolver.openOutputStream(fileUri)?.use { outputStream ->
val content = "Hello, world!"
outputStream.write(content.toByteArray())
}
} catch (e: Exception) {
Toast.makeText(context, "Error writing to file: ${e.message}", Toast.LENGTH_LONG).show()
}
}
I am getting following exception after I select a directory:
Failed to create document
java.lang.IllegalArgumentException: Invalid URI: content://com.android.externalstorage.documents/tree/primary%3ADownload%2FTest
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
at android.content.ContentProviderProxy.call(ContentProviderNative.java:764)
at android.content.ContentResolver.call(ContentResolver.java:2466)
at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1380)
I am not able to understand what am I missing here.
I am writing an Android app in Kotlin and I am using Jetpack Compose.
In my app, I ask the user to select a directory where I can create a file and write to it. This is the relevant code extracted from my app:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TestApplicationTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
DirectorySelectionScreen(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun DirectorySelectionScreen(modifier: Modifier = Modifier) {
val context = LocalContext.current
// Launcher for directory selection
val openDirectoryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
uri?.let {
// Handle the selected directory URI
createFileInDirectory(context, it)
}
}
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Select a Directory to Create File",
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(bottom = 16.dp),
fontWeight = FontWeight.Bold
)
Button(onClick = { openDirectoryLauncher.launch(null) }) {
Text(text = "Select Directory")
}
}
}
fun createFileInDirectory(context: Context, parentUri: Uri) {
val contentResolver = context.contentResolver
val mimeType = "text/plain"
val displayName = "example.txt"
try {
// Create a new document (file) in the selected directory
val newDocumentUri = DocumentsContract.createDocument(
contentResolver,
parentUri, // URI of the selected directory
mimeType,
displayName
)
newDocumentUri?.let {
// Now write to the file
writeToFile(context, it)
}
} catch (e: Exception) {
Toast.makeText(context, "Error creating file: ${e.message}", Toast.LENGTH_LONG).show()
}
}
fun writeToFile(context: Context, fileUri: Uri) {
try {
// Open an OutputStream to the created file and write content
context.contentResolver.openOutputStream(fileUri)?.use { outputStream ->
val content = "Hello, world!"
outputStream.write(content.toByteArray())
}
} catch (e: Exception) {
Toast.makeText(context, "Error writing to file: ${e.message}", Toast.LENGTH_LONG).show()
}
}
I am getting following exception after I select a directory:
Failed to create document
java.lang.IllegalArgumentException: Invalid URI: content://com.android.externalstorage.documents/tree/primary%3ADownload%2FTest
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
at android.content.ContentProviderProxy.call(ContentProviderNative.java:764)
at android.content.ContentResolver.call(ContentResolver.java:2466)
at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1380)
I am not able to understand what am I missing here.
Share Improve this question asked Mar 23 at 0:54 jyoteshjyotesh 4507 silver badges19 bronze badges1 Answer
Reset to default 1I figured it out. You have to first convert the URI that is obtained from ACTION_OPEN_DOCUMENT_TREE
by calling DocumentsContract.buildDocumentUriUsingTree
and then use the obtained URI in the call to DocumentsContract.createDocument
like this
val parentDocumentUri = DocumentsContract.buildDocumentUriUsingTree(
parentUri,
DocumentsContract.getTreeDocumentId(parentUri)
)
val newDocumentUri = DocumentsContract.createDocument(
contentResolver,
parentDocumentUri, // Tree URI of the selected directory
mimeType,
displayName
)
The call to DocumentsContract.buildDocumentUriUsingTree
converts the URI from
content://com.android.externalstorage.documents/tree/primary%3ADownload%2FTest
to
content://com.android.externalstorage.documents/tree/primary%3ADownload%2FTest/document/primary%3ADownload%2FTest
本文标签: androidInvalid URI in DocumentsContractcreateDocumentStack Overflow
版权声明:本文标题:android - Invalid URI in DocumentsContract.createDocument - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744299729a2599519.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论