Android

Android 圖片讀取&影片讀取&音檔讀取&其他檔案讀取SAF

Android 圖片讀取&影片讀取&音檔讀取&其他檔案讀取SAF

  1. 讀取前要先取得權限
  2. 圖片讀取(Images)
  3. 影片讀取(Video)
  4. 音檔讀取(Video)
  5. 其他檔案讀取(利用SAF)
  6. 檔案儲存到機身外部儲存

1.讀取前要先取得權限

Manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Activity
const val REQUEST_READ_EXTERNAL_STORAGE = 3

requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_READ_EXTERNAL_STORAGE)

2.圖片讀取(Images)

Uri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null)

cursor?.apply {
    while (moveToNext()) {
        val id = getLong(getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
        val uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
        uriToFileApiQ(uri, false)
    }
    cursor.close()
}

3.影片讀取(Video)

Uri(MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
val cursor = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, null)

cursor?.apply {
    while (moveToNext()) {
        val id = getLong(getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
        val uri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)
        uriToFileApiQ(uri, false)
    }
    cursor.close()
}

4.音檔讀取(Video)

Uri(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
val cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null)

cursor?.apply {
    while (moveToNext()) {
        val id = getLong(getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
        val uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id)
        uriToFileApiQ(uri, false)
    }
    cursor.close()
}

5.其他檔案讀取(利用SAF)

const val SAF_REQUEST = 0

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.type = "application/pdf"
//開啟多選
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
startActivityForResult(intent, SAF_REQUEST)
回傳單筆與多筆
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == SAF_REQUEST && resultCode == Activity.RESULT_OK) {
        //單筆
        data?.data?.let {
            val uri = Uri.parse(it.toString())
            uriToFileApiQ(uri, true)
        }

        //多筆
        data?.clipData?.let {
            for (i in 0 until it.itemCount) {
                val uri = Uri.parse(it.getItemAt(i).uri.toString())
                uriToFileApiQ(uri, true)
            }
        }
    }
}

6.檔案儲存到機身外部儲存

@SuppressLint("SimpleDateFormat")
private fun uriToFileApiQ(uri: Uri, pdf: Boolean): File? {
    var file: File? = null
    if (uri.scheme == ContentResolver.SCHEME_FILE) {
        file = File(uri.toString())
    } else if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
        var date: String
        val info = contentResolver.query(uri, null, null, null, null)
        info?.run {
            moveToFirst()
            //檔案大小
            val size = getString(getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))
            date = if (!pdf) {
                //檔案建立日期(時間戳轉換)
                val dateAdded =
                    getString(getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED))
                val sdf = SimpleDateFormat("yyyy年MM月dd日 HH點mm分ss秒")
                sdf.format(Date(dateAdded.toLong() * 1000))
            } else {
                ""
            }

            //檔案名稱
            val fileName =
                getString(getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))

            if (size.isNullOrEmpty()) return@run

            //輸入流
            val inputStream = contentResolver.openInputStream(uri)

            //輸出流
            val filePath = File(getExternalFilesDir("myPhoto")?.absolutePath, "datefileName")
            val fos = FileOutputStream(filePath)

            FileUtils.copy(inputStream!!, fos)
            file = filePath

            fos.close()
            inputStream.close()
            info.close()
        }
    }
    return file
}
MediaStore.Images.Media.RELATIVE_PATH //取得圖片上層路徑
MediaStore.Images.Media.DISPLAY_NAME  //圖片名稱

發表迴響