Android存儲訪問框架SAF:給應(yīng)用裝上"智能導(dǎo)航儀"
當(dāng)文件管理遇上"智能管家"
你的手機(jī)是個大倉庫,各種文件就是里面的貨物。傳統(tǒng)方式就像給倉庫管理員萬能鑰匙?? - 雖然方便但風(fēng)險巨大!而SAF就像給管理員配了個智能導(dǎo)航儀??,讓他只能走你指定的路線,既安全又高效。
SAF的三大超能力
1. 安全盾牌 ??? - 告別"全盤通吃",只接觸你允許的文件
2. 版本通吃王 ?? - 從Android 5.0到最新系統(tǒng)全兼容
3. 用戶遙控器 ?? - 文件訪問權(quán)完全由你掌控
三大實戰(zhàn)場景解密
場景1:打開文件就像點外賣
fun orderFile() {
// 啟動"文件外賣"界面
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
// 只選可操作文件
addCategory(Intent.CATEGORY_OPENABLE)
// 只要圖片文件
type = "image/*"
}
startActivityForResult(intent, FILE_PICK_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
data?.data?.let { fileUri ->
// 獲取"永久通行證"
contentResolver.takePersistableUriPermission(
fileUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
// 現(xiàn)在可以盡情使用文件啦!
displayImage(fileUri)
}
}
}
1. 用戶點擊"選文件"按鈕
2. 彈出系統(tǒng)文件選擇器(像外賣平臺)
3. 選中文件后自動獲得訪問權(quán)限
4. 應(yīng)用立即展示文件內(nèi)容
場景2:創(chuàng)建新文件就像發(fā)微博
fun createPost() {
// 啟動"文件創(chuàng)作"界面
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/plain"http:// 文本類型
putExtra(Intent.EXTRA_TITLE, "我的日記.txt") // 默認(rèn)文件名
}.also { startActivityForResult(it, CREATE_FILE_CODE) }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
data?.data?.let { newFileUri ->
// 把內(nèi)容"發(fā)布"到新文件
contentResolver.openOutputStream(newFileUri)?.use { stream ->
stream.write("今天是個好日子!".toByteArray())
}
// 提示用戶發(fā)布成功
showToast("日記保存成功!??")
}
}
}
1. 用戶自選保存位置
2. 系統(tǒng)自動處理命名沖突
3. 支持添加文件描述信息
場景3:管理文件夾就像整理書架
fun organizeBookshelf() {
// 請求訪問整個"書架"
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
// 設(shè)置初始位置(可選)
if (android.os.Build.VERSION.SDK_INT >= 26) {
putExtra(DocumentsContract.EXTRA_INITIAL_URI,
Uri.parse("content://com.android.externalstorage.documents/root/primary"))
}
}.also { startActivityForResult(it, FOLDER_ACCESS_CODE) }
}
fun scanBookshelf(folderUri: Uri) {
// 掃描"書架"所有文件
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
folderUri,
DocumentsContract.getTreeDocumentId(folderUri)
)
contentResolver.query(childrenUri, null, null, null, null)?.use { cursor ->
while (cursor.moveToNext()) {
// 獲取文件信息
val fileName = cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME))
val fileType = cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_MIME_TYPE))
// 根據(jù)類型分類處理
when {
fileType.startsWith("image/") -> processImage(fileName)
fileType == "application/pdf" -> processPDF(fileName)
}
}
}
}
? 支持遞歸遍歷子文件夾
? 自動獲取文件修改時間
? 精確顯示文件大小
高手進(jìn)階技巧
SAF vs 傳統(tǒng)方式 終極PK
能力項 | 傳統(tǒng)方式 | SAF智能導(dǎo)航 |
安全指數(shù) | ?? 裸奔風(fēng)險 | ?? 金庫級防護(hù) |
用戶控制 | ??♂? 用戶不知情 | ?? 用戶全權(quán)掌控 |
Android適配 | ?? 版本兼容噩夢 | ?? 全版本通吃 |
長期訪問 | ?? 可能突然失效 | ?? 永久訪問授權(quán) |
大文件傳輸秘籍
fun transferBigFile(uri: Uri) {
// 使用文件描述符提高性能
contentResolver.openFileDescriptor(uri, "r")?.use { pfd ->
// 創(chuàng)建內(nèi)存映射緩沖區(qū)
val length = pfd.statSize
val buffer = ByteBuffer.allocateDirect(length.toInt())
// 高效讀取大文件
FileInputStream(pfd.fileDescriptor).use { stream ->
stream.channel.read(buffer)
}
// 處理文件內(nèi)容...
processBigFile(buffer)
}
}
異常防護(hù)盾
try {
// SAF操作包一層異常處理
} catch (e: FileNotFoundException) {
showError("文件神秘消失了!??")
} catch (e: SecurityException) {
showError("訪問權(quán)限被收回了!??")
} catch (e: IOException) {
showError("文件傳輸遇到障礙!??")
}
智能文件過濾
// 只要音樂和文檔
intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf(
"audio/*",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
))
SAF不僅僅是技術(shù)升級,更是用戶體驗的革命!
? 精準(zhǔn)定位文件位置
? 自動避開風(fēng)險區(qū)域
? 把控制權(quán)真正交還用戶
現(xiàn)在就開始給你的應(yīng)用裝上這顆"智能芯",讓文件管理變得既安全又輕松!