長久以來,Google的SdCard研發團隊,朝令夕改,讓開發者幾近抓狂。如今Android 10更是讓人吐血,你他媽的,怎麼Google專養你們這群垃圾
Andorid 10(API 29)開始,又再對SDCard動了手腳。到了Android 11(API 30) 更是改到讓人抓狂。
最慘的就是導航王(Naviking)的圖資儲存問題。到了2021年的4月,這款app還是沒出新版,在Android 11的系統中狂閃退。沒了它,本人就自動切換到路痴模式,真是大災情啊。
分區儲存(Scoped Stroage)
Android 10 開始 (API29),導入分區儲存概念,將sdcard分成二個區域
app私有
位於 Android/data/Package name/files,可用getExternalFilesDir(null)取得此路徑。在此路徑內的文件,app可以自行存取,不需要取得sdcard權限。不過若是API28及以前,是需要先取得sdcard權限的。
共享區域
比如Download, Movies, DCIM這些路徑,即為共享區域。API29開始,不能使用File物件直接存取這些地方的文件,而需改用MediaStore(媒體庫) 進行存取
權限
底下代碼,為簡易取得權限的方式
class MainActivity : AppCompatActivity() {
companion object {
private const val REQUEST_CODE = 10
private val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(allPermissionsGranted())initial()
else ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults:IntArray) {
if (requestCode==REQUEST_CODE) {
if(allPermissionsGranted())initial()
else {
Toast.makeText(this, "無法取得權限", Toast.LENGTH_SHORT).show()
finish()
}
}
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
Android 10 寫入共享區
Android 10開始,要將資料寫入共享區域的目錄中,需先使用MediaStore取得Uri, 再由Uri創建outputStream,然後由outputStream寫入資料。
