91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現

發布時間:2023-03-21 15:19:06 來源:億速云 閱讀:167 作者:iii 欄目:開發技術

這篇文章主要講解了“Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現”吧!

在進行需求開發的時候,我們總是避不開和用戶的數據打交道,那提到獲取用戶的數據一定會想到的東西就是申請權限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在我剛學習安卓的時候,我是以為APP一定要聲明了讀寫用戶空間權限并且在用戶授權之后才能獲取到用戶的文件,即使是做個簡簡單單的更換頭像的功能,或者是升級APP時下載新的APK。對于后者,我們其實可以將升級的APK包放到我們應用的私有目錄下(無需權限),對于前者,有什么比較輕量,適合快速開發需求的方法來滿足呢。

這里插三段小說明,如果只想知道方法的可以直接跳過

  • 首先我們要明白,為什么谷歌要用讀寫權限來限制APP對用戶文件的操作權。答案其實很明顯,因為需要防止APP惡意侵犯用戶隱私,或者是在用戶的目錄里存放大量的垃圾文件,在用戶目錄里存放的文件是不會隨著APP的卸載而被刪除的,所以如果所有APP都在用戶的目錄里存放文件(像是相冊文件夾/下載文件夾),那用戶的體驗別提有多糟糕了。

  • 其次就是聲明權限其實是有挺多弊端的,如果不是非必須的權限,其實谷歌是希望我們能不要就不要的。做過谷歌應用市場開發的就知道,你聲明的每個權限都會在谷歌應用的詳情頁標注,這不僅僅是讓用戶一進來就覺得:"這個APP又要窺探我隱私",而且是讓你在填應用的數據安全表單時更加地麻煩,因為你聲明了讀寫權限,那你就要說明你的APP會獲取用戶的什么數據,如何保存,用戶是否可以刪除以及是否知情等等。還有就是你聲明的權限越多,你的應用審核時間就會越長,這個我相信沒有人覺得無所謂吧

  • 第三就是,Android11及以上的版本其實已經大削了WRITE_EXTERNAL_STORAGE這個權限,谷歌不再允許APP悄悄地在用戶的外置存儲目錄里偷偷拉屎了,你在用戶目錄里創建什么目錄存取什么數據都要在用戶知情并且同意的情況下才能進行,而本文要介紹的方式是能兼容到Android13的,所以趕緊學起來吧^-^

模擬獲取用戶的圖片的邏輯

我們需要拿到代表用戶臨時授權給APP的Uri

通過

val intent = Intent(Intent.ACTION_GET_CONTENT)
    .addCategory(Intent.CATEGORY_OPENABLE)
    //這里傳的參數是你要獲取的文件類型的mimeType
    .setType(mimeType)
startActivityForResult(intent,1024)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 1024 && resultCode == RESULT_OK) {
        val uri = data?.data
        //這里獲取到的uri就是用戶臨時授權的文件/文件夾的的標識
    }
}

或者

val launch = registerForActivityResult(ActivityResultContracts.GetContent()){uri-> 
//這里獲取到的uri就是用戶臨時授權的文件/文件夾的的標識
}
//這里傳的參數是你要獲取的文件類型的mimeType
launch.launch("*/*")

啟動系統的內容選擇器讓用戶選擇要分享給我們APP的文件,以獲得文件的Uri

通過contentResolver打開文件的文件描述符FileDescriptor

val pfd : ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(uri, "r")

第一個參數是我們剛剛得到的文件的uri,第二個文件是表示我們對文件的操作模式,我現在示范的是讀取用戶圖片所以用只讀模式("r")就可以了,關于mode的具體注釋,這里我直接粘貼原文了

mode &ndash; The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" or "rwt". SeeParcelFileDescriptor.parseMode for more details.

通過FileDescriptor可以打開一個文件IO流(FIS或者FOS),就可以讀寫文件啦

FileInputStream(pfd.fileDescriptor).use {
//這里可以先將用戶的圖片復制到私有目錄中,再讓用戶做進一步的編輯操作
}
FileOutputStream(pfd.fileDescriptor).use {
}

但是注意,打開的fileDescriptor是Closeable對象,所以用完之后需要手動close(),這里我用的是ktolin的擴展函數,會在use代碼塊里的代碼運行完之后自動關閉流

另一種讀取文件的方法,還是使用contentResolver直接打開io流

context.contentResolver.openInputStream(uri)?.use {
}
context.contentResolver.openOutputStream(uri)?.use {
}

模擬將文件寫入用戶目錄的操作

其實思路是一模一樣的,只是你啟動文件系統的意圖(intent)不一樣,以及對文件的操作不一樣

我們需要拿到代表用戶臨時授權給APP的Uri

//這里傳入你要創建的文件類型的mimeType,如果是"*/*"那就代表文件夾
val launcher = registerForActivityResult(ActivityResultContracts.CreateDocument("*/*")){uri->
    //這里獲取到的uri是已經創建好的文件的uri
}
//這里傳入要創建的文件名
launcher.launch("cache.png")

啟動之后是這個界面

Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現

通過contentResolver打開文件的文件描述符FileDescriptor

val pfd : ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(uri, "rw")

第一個參數是我們剛剛得到的文件的uri,第二個文件是表示我們對文件的操作模式,我現在示范的是保存一張圖片所以要用讀寫模式("rw")

通過FileDescriptor可以打開一個文件IO流(FIS或者FOS),就可以寫文件啦

FileOutputStream(pfd.fileDescriptor).use {
//這里將處理好的圖片利用fos寫到用戶剛才用uri指定的地方
}

另一種讀取文件的方法,還是使用contentResolver直接打開io流

context.contentResolver.openOutputStream(uri)?.use {
}

模擬獲取用戶文件夾控制權的操作

最后再模擬一下獲取用戶文件夾控制權的操作,通過這個方法你可以拿到其他應用在外置存儲里的目錄(例如一些聊天軟件的聊天記錄其實就是存放在這個目錄的)

Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現

通過Uri獲取文件信息

最后再介紹一 通過Uri獲取文件信息(文件名/文件大小/文件Mime類型)的方法

//第二個參數相當于是sql里的select,列表里是要過濾的列名,如果傳null那說明取所有的列,這樣性能會比較差
val cursor: Cursor? = context.contentResolver.query(
    this,
    arrayOf(MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.SIZE),
    null,
    null,
    null
)?.use { cursor ->
    if (cursor.moveToFirst()) {
        val columnIndex1 = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
        if (columnIndex1 > -1) {
            name = cursor.getString(columnIndex1)
        }
        val columnIndex2 = cursor.getColumnIndex(MediaStore.MediaColumns.SIZE)
        if (columnIndex2 > -1) {
            size = cursor.getLong(columnIndex2)
        }
    }

文件的話,用正常途徑也只能拿到文件名(MediaStore.MediaColumns.DISPLAY_NAME),文件大小(MediaStore.MediaColumns.SIZE),文件Mime類型(MediaStore.MediaColumns.MIME_TYPE)這三個有用的信息 注意,獲取到的cursor是Closeable對象,所以用完之后需要手動close()

感謝各位的閱讀,以上就是“Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現”的內容了,經過本文的學習后,相信大家對Android無需讀寫權限通過臨時授權讀寫用戶文件怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

霍邱县| 内黄县| 博爱县| 新丰县| 刚察县| 旺苍县| 靖西县| 沛县| 碌曲县| 金溪县| 涿州市| 贵港市| 新绛县| 博兴县| 江津市| 军事| 南昌县| 万州区| 富顺县| 林芝县| 河西区| 邳州市| 仪征市| 公安县| 苍南县| 山东| 潼南县| 凌海市| 太原市| 舟曲县| 永顺县| 安平县| 潮州市| 离岛区| 鹤壁市| 靖边县| 江阴市| 万宁市| 祁连县| 汉沽区| 奉化市|