安卓10写入和读取sdcard文件

3,266 阅读1分钟

从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")
        ...
    }
}

参考文档: