1. 程式人生 > 其它 >Android學習筆記-Android10檔案訪問適配

Android學習筆記-Android10檔案訪問適配

參考文章:https://blog.csdn.net/guolin_blog/article/details/105419420/ 需求:需要能瀏覽應用外儲存空間的檔案 問題點:傳統方案不能相容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" } } } }