从target=29开始,要想读取sdcard中的文件,通过Environment.getExternalStoreage读取sdcard文件的方式已经行不通了。
当然,官方提供了一种缓解策略,在application的manifest中定义:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
创建并且写入文件
写入文件需要用户点击确定,并且如果文件重名,会默认在后面加上(1)这种括号123等等
发送intent:
val initialUri = Uri.parse("file:///sdcard/Downloads/")
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/text"
putExtra(Intent.EXTRA_TITLE, "hot_exchange_${DateTimeUtils.formatNow()}.json")
// Optionally, specify a URI for the directory that should be opened in
// the system file picker before your app creates the document.
putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri)
}
startActivityForResult(intent, REQ_CREATE_FILE)
intent在onActivityResult中回来之后,写入数据
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQ_CREATE_FILE -> {
if (resultCode == RESULT_OK) {
data?.data?.also { uri ->
handleWriteData(uri)
}
}
}
}
}
获取outPutStream数据写入
contentResolver.openOutputStream(uri, "w").use { out ->
BufferedWriter(OutputStreamWriter(out)).use { writer ->
writer.write(gson.toJson(result))
}
}
读取数据
通过intent打开文件选择
val pickerInitialUri = Uri.parse("file:///sdcard/Download/")
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/text"
putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
}
startActivityForResult(intent, REQ_CODE_IMPORT_TX)
读取文件内容
contentResolver.openInputStream(uri).use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
val text = reader.readText()
Log.d("hot", "text:$text")
...
}
}
参考文档: