Android学习笔记-Android10文件访问适配

需求:需要能浏览应用外存储空间的文件
问题点:传统方案不能兼容Android10以上的系统
 
解决思路:利用系统文件浏览器找到指定的文件,在
onActivityResult
回调中拿到Uri,在从Uri中拿到流,将文件转存到应用内存储
/*如果是Android10以上设备,则调用系统文件浏览器*/ if (Build.VERSION.SDK_INT >= 29){ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) .apply { // Provide read access to files and sub-directories in the user-selected // directory. addCategory(Intent.CATEGORY_OPENABLE) type = "*/*" } startActivityForResult(intent, Constants.CODE.REQUEST_SERIES) }
 
在回调中处理(主要代码):
1 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK && requestCode == Constants.CODE.REQUEST_SERIES){ data?.data?.let { Log.e(TAG,it.toString()) dumpImageMetaData(it) } } else if (requestCode == Constants.CODE.REQUEST_SERIES){ dismiss() } } /** * 处理选中的文件,只支持单文件。如果是多选则只处理第一个 * 该方法涉及IO操作 */ private fun dumpImageMetaData(uri: Uri) { // The query, because it only applies to a single document, returns only // one row. There's no need to filter, sort, or select fields, // because we want all fields for one document. val cursor: Cursor? = context?.contentResolver?.query( uri, null, null, null, null, null) cursor?.use { // moveToFirst() returns false if the cursor has 0 rows. Very handy for // "if there's anything to look at, look at it" conditionals. if (it.moveToFirst()) { // Note it's called "Display Name". This is // provider-specific, and might not necessarily be the file name. val displayName: String = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)) Log.i(TAG, "Display Name: $displayName") var file = File(FileUtils.SDPATH + displayName) if (file.exists()){ Log.i(TAG,"File exists") } var inputStream = context?.contentResolver?.openInputStream(uri) var outPutStream = FileOutputStream(file) var bufferIn = BufferedInputStream(inputStream) var bufferOut = BufferedOutputStream(outPutStream) val b = ByteArray(1024) while (bufferIn.read(b) != -1){ bufferOut.write(b) } bufferIn.close() bufferOut.close() val sizeIndex: Int = it.getColumnIndex(OpenableColumns.SIZE) // If the size is unknown, the value stored is null. But because an // int can't be null, the behavior is implementation-specific, // and unpredictable. So as // a rule, check if it's null before assigning to an int. This will // happen often: The storage API allows for remote files, whose // size might not be locally known. val size: String = if (!it.isNull(sizeIndex)) { // Technically the column stores an int, but cursor.getString() // will do the conversion automatically. it.getString(sizeIndex) } else { "Unknown" } } } }

 

posted @   Mr,Han  阅读(263)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示