- Пользователь нажимает кнопку выбора файла, чтобы выбрать файл с помощью системного средства выбора файлов.
- Используя файловые потоки, приложение сохраняет местоположение URI в своем внутреннем хранилище.
- Приложение читает файл и что-то делает с его содержимым.
- Когда пользователь в следующий раз откроет приложение, местоположение URI считывается из его внутреннего хранилища, а содержимое файла считывается без каких-либо действий со стороны пользователя.
Однако у меня возникли проблемы с сохранением это разрешение. Я думаю, это как-то связано со способом хранения URI (он должен быть преобразован в строку, прежде чем его можно будет записать в виде массива байтов), поэтому, возможно, информация о разрешениях потеряна?
Сейчас пользователь может выбрать файл, но когда приложение перезапускается и он пытается загрузить файл снова, приложение вылетает из-за java.lang.SecurityException: отказ в разрешении: открытие поставщика com.android .externalstorage.ExternalStorageProvider из ProcessRecord{...} требует, чтобы вы получили доступ с помощью ACTION_OPEN_DOCUMENT или связанных API
Мой код сейчас выглядит так:
Код: Выделить всё
[package and imports...]
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
AppTheme {
FileSelect() // dialog for selecting a file
}
}
}
}
@Composable
fun FileSelect() {
// State variables
val context = LocalContext.current
var selectedFileUri by remember { mutableStateOf(null) }
var fileContent by remember { mutableStateOf(null) }
// Open file from URI, set fileContent, and write URI to internal storage
val openFile = { uri: Uri? ->
selectedFileUri = uri
uri?.let {
fileContent = readTextFromUri(context, it)
try {
takePersistableUriPermission(context, it)
} catch (e: SecurityException) {
e.printStackTrace()
}
}
// Try writing to internal storage for future use
try {
val fos: FileOutputStream = context.openFileOutput("URILocation.txt", Context.MODE_PRIVATE)
fos.write(selectedFileUri.toString().toByteArray()); fos.flush(); fos.close()
Log.d("MainActivity", "Write URILocation.txt - success")
} catch (e: IOException) {
// Error writing to URILocation.txt
Log.d("MainActivity", "Write URILocation.txt - failure")
e.printStackTrace()
}
}
// Launch file selector
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent(),
onResult = { uri: Uri? -> openFile(uri) }
)
// Handle select file
fun buttonOnClick(){
try {
// Try reading URILocation.txt
val fin: FileInputStream = context.openFileInput("URILocation.txt")
Log.d("MainActivity", "Read URILocation.txt - success")
var a: Int; val temp = StringBuilder(); while (fin.read().also { a = it } != -1) { temp.append(a.toChar()) }
val uriS = temp.toString() // URI String
fin.close()
// URI URI Object
val uri: Uri = Uri.parse(uriS)
// Read file at URI
openFile(uri)
} catch (e: IOException) {
// If no URILocation.txt, launch file picker
launcher.launch("*/*")
}
}
Surface {
Column {
// Select file button
Spacer(modifier = Modifier.height(100.dp))
Button(onClick = {
buttonOnClick()
}) {
Text(text = "Select or Load File")
}
// Display file contents
selectedFileUri?.let { uri ->
Text(text = "Selected file: $uri")
fileContent?.let { content ->
Text(text = content)
[Do something with the content...]
}
}
}
}
}
// Takes file URI -> returns nullable string of content
fun readTextFromUri(context: Context, uri: Uri): String? {
return context.contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
reader.readText()
}
}
}
// Grant persistable permissions to URI
fun takePersistableUriPermission(context: Context, uri: Uri) {
val contentResolver: ContentResolver = context.contentResolver
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
// Check if the URI can be granted persistable permissions
val takeFlagsSupported = DocumentsContract.isDocumentUri(context, uri)
if (takeFlagsSupported) {
try {
contentResolver.takePersistableUriPermission(uri, takeFlags)
} catch (e: SecurityException) {
e.printStackTrace()
}
} else {
// Handle the case where the URI does not support persistable permissions
Log.d("MainActivity","Persistable permissions not supported for this URI: $uri")
}
}
Подробнее здесь: https://stackoverflow.com/questions/786 ... ntly-acces