Google越來(lái)越重視Android用戶的隱私保護(hù),所以在Android Q版本引進(jìn)了作用域存儲(chǔ)的概念,這一操作直接限制了開(kāi)發(fā)者慣用外部存儲(chǔ)做一些配置信息的永久儲(chǔ)存的方式(實(shí)際上開(kāi)發(fā)者因?yàn)椴蛔袷亻_(kāi)發(fā)規(guī)范,導(dǎo)致用戶的手機(jī)目錄變得雜亂不堪)。
話不多說(shuō),直接上總結(jié):
應(yīng)用內(nèi)目錄:
getCacheDir() = /data/user/0/packname/cache 某個(gè)應(yīng)用在內(nèi)部存儲(chǔ)中的cache路徑
getFilesDir() = /data/user/0/packname/cache /data/user/0/packname/files某個(gè)應(yīng)用在內(nèi)部存儲(chǔ)中的files路徑
getExternalCacheDir() = /storage/emulated/0/Android/data/packname/cache 某個(gè)應(yīng)用在外部存儲(chǔ)中的cache路徑
getExternalFilesDir(“”) = /storage/emulated/0/Android/data/packname/files某個(gè)應(yīng)用在外部存儲(chǔ)中的files路徑
getDir(“xxxxx”, MODE_PRIVATE).getAbsolutePath() = /data/user/0/packname/app_xxxxx 某個(gè)應(yīng)用在內(nèi)部存儲(chǔ)中的自定義路徑
以上方法路徑都含有包名,代表屬于某個(gè)應(yīng)用,可直接通過(guò)File()訪問(wèn),并且不需要申請(qǐng)讀寫權(quán)限
外部目錄(Android Q廢棄)
- Environment.getDataDirectory() = /data 內(nèi)部存儲(chǔ)的根路徑
- Environment.getDownloadCacheDirectory() = /data/cache
- Environment.getRootDirectory() = /system
- Environment.getExternalStorageDirectory().getAbsolutePath() = /storage/emulated/0 外部存儲(chǔ)的根路徑
- Environment.getExternalStoragePublicDirectory(“”).getAbsolutePath() = /storage/emulated/0 外部存儲(chǔ)的根路徑
Android Q版本以下,在有讀寫權(quán)限的情況下,可直接使用File()訪問(wèn),Android Q版本以上,會(huì)報(bào)權(quán)限不足的異常。
公有共享目錄
- Image: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
- Video: MediaStore.Video.Media.EXTERNAL_CONTENT_URI
- Audio: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
- Downloads: MediaStore.Downloads.EXTERNAL_CONTENT_URI
Android系統(tǒng)針對(duì)文件類型進(jìn)行了分類,圖片、音頻、視頻這三類文件將可以通過(guò)MediaStore API來(lái)進(jìn)行訪問(wèn),而其他類型的文件則需要使用系統(tǒng)的文件選擇器來(lái)進(jìn)行訪問(wèn)。
應(yīng)用程序向媒體庫(kù)貢獻(xiàn)的圖片、音頻或視頻,將會(huì)自動(dòng)擁有其讀寫權(quán)限,不需要額外申請(qǐng)READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE權(quán)限。而如果你要讀取其他應(yīng)用程序向媒體庫(kù)貢獻(xiàn)的圖片、音頻或視頻,則必須要申請(qǐng)READ_EXTERNAL_STORAGE權(quán)限才行。WRITE_EXTERNAL_STORAGE權(quán)限將會(huì)在未來(lái)的Android版本中廢棄。
如何向公有共享目錄添加數(shù)據(jù)
- insert:image、video、audio、downloads可使用contentResolver.insert(uri,contentValues)方法得到新增文件的uri,然后通過(guò)contentResolver.openOutputStream(uri)字節(jié)流插入數(shù)據(jù)
try {
val contentValues = ContentValues()
contentValues.put(MediaStore.Downloads.DISPLAY_NAME, filename)
contentValues.put(MediaStore.Downloads.DATE_TAKEN, System.currentTimeMillis())
val uri = this.contentResolver.insert(
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
contentValues
)
val os = this.contentResolver.openOutputStream(uri!!)
os?.use {
os.write("這是測(cè)試數(shù)據(jù)".toByteArray())
os.flush()
}
} catch (e: Exception) {
e.printStackTrace()
}
如何獲取共有共享目錄的媒體文件
- getUri:image、video、audio可通過(guò)contentResolver.query(uri,projection,selection,selectionArgs,sortOrder)方法查找到uri,而downloads下的文件只能通過(guò)Intent(Intent.Intent.ACTION_OPEN_DOCUMENT)文件選擇器,在onActivityResult()方法中通過(guò)data.data獲取文件的uri
//獲取相冊(cè)中的圖片
val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, "${MediaStore.MediaColumns.DATE_ADDED} desc")
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
val uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
println("image uri is $uri")
}
cursor.close()
}
//獲取Downloads文件夾下的文件
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(
DocumentsContract.EXTRA_INITIAL_URI,
MediaStore.Downloads.EXTERNAL_CONTENT_URI
)
}
startActivityForResult(intent, SELECT_REQ)
如何更新公有共享目錄現(xiàn)有的媒體文件
- update: 拿到文件的uri后,通過(guò)contentResolver.openOutputStream(uri)方法,通過(guò)字節(jié)流改變文件內(nèi)容
val os = this.contentResolver.openOutputStream(uri!!)
os?.use {
os.write("這是測(cè)試數(shù)據(jù)".toByteArray())
os.flush()
}