1. 程式人生 > >Android儲存許可權之深入淺出

Android儲存許可權之深入淺出

Android檔案儲存及許可權解析

Android中常見的儲存方式有SharedPreferences、Sqlite、檔案IO儲存、雲端儲存、ContentProvider等。

其中IO儲存最為靈活,適用場景也多。這裡就不同檔案路徑和其對應的許可權進行分析。

Android系統分割槽

首先我們需要知道Android的系統分割槽結構,熟悉Android系統和刷機愛好者應該知道,Android中主要分為以下幾個區:

  • /sdcard

    請注意只有sdcard是所有Android裝置都有的,我們平時使用者在檔案管理裡面看到的內容就是該分割槽下的,不要被名字誤導了,不是特指我們常說的Sd卡,而是代表普通使用者可操作

    分割槽,這是你個人儲存大檔案的地方。

  • /boot

    這個分割槽上有Android的載入程式,包括核心和記憶體操作程式。沒有這個分割槽裝置就不能被引導。恢復系統的時候會擦除這個分割槽,並且必須重新安裝載入程式和ROM才能重啟系統。

  • /system

    這個分割槽上是除了核心和記憶體操作之外的整個作業系統。裡面包含了Android使用者介面和預先安裝的系統應用。擦除了這個分割槽就會刪除掉Andorid系統,所以你需要進入recovery模式或者bootloader模式去安裝一個新的ROM。

  • /recovery

    recovery分割槽被認為是另一個啟動分割槽,你可以啟動裝置進入recovery控制檯去執行高階的系統恢復和管理操作。

  • /data

    這個分割槽儲存著使用者資料。通訊錄、簡訊、設定和你所有安裝的App都在這個分割槽上。擦除這個分割槽相當於恢復出廠設定,當你第一次啟動裝置的時候或者在安裝了官方或者客戶的ROM之後系統會自動重建這個分割槽。當你執行恢復出廠設定時,就是在擦除這個分割槽。

  • /cache

    這個分割槽是Android系統儲存頻繁訪問的資料和app的地方。擦除這個分割槽不影響你的個人資料,當你繼續使用裝置時,被擦除的資料就會自動被建立。

  • /misc

    這個分割槽包含各種複雜的類似於on/off的系統設定。這些設定可能是USB配置和某些硬體配置資訊。這是一個重要的分割槽,如果該分割槽損壞或者丟失,裝置的功能可能就工作不正常。

內部包路徑

我們知道每個應用都是根據其包名唯一性進行安裝的,在軟體安裝時,Android系統會在data分割槽上為每個App建立其對應包名的目錄,該目錄可以由我們自由控制的。

  • 安全性

    該目錄位於data分割槽,許可權為包私有,也就是僅有該包目錄對應程式具有讀寫許可權,對普通使用者和應用不可見。安全性相對較高,但是私密資料還是需要進行加密儲存,因為系統Root後依然可以被別有用心之人檢視和修改。

  • 許可權

    在私有包目錄下進行讀寫操作均不需要額外申請許可權。

  • 持久化

    伴隨應用解除安裝一起刪除。

  • 獲取途徑

    val file = context.getFilesDir()
    val cacheDir = context.getCacheDir()
    ...
    

外部包路徑

外部包路徑內部包路徑類似,同樣是以應用包名來進行命名,但是不同點在於它位於sdcard分割槽上。通常路徑為0/Android/data/包名

  • 安全性

    該目錄位於sdcard分割槽,許可權為公有,對普通使用者和應用可見。安全性相對較低,不建議存放私密資料。

  • 許可權

    在包目錄下進行讀寫操作均不需要額外申請許可權。

  • 持久化

    伴隨應用解除安裝一起刪除。

  • 獲取途徑

    val file = context.getExternalFilesDir(type:String)
    val cacheDir = context.getExternalCacheDir()
    

外部路徑

和外部包路徑一樣位於sdcard分割槽上,是最靈活的一種儲存方式,平時用的也很多。

  • 安全性

    該目錄位於sdcard分割槽,許可權為公有,對普通使用者和應用可見。安全性相對較低,不建議存放私密資料。

  • 許可權

    需要額外申請讀寫許可權。

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
  • 持久化

    不會伴隨應用解除安裝刪除,如果沒有人為干涉會一直儲存,會造成系統垃圾殘留,控制不好會很流氓,需要謹慎使用。

  • 獲取途徑

    val rootDirectory = Environment.getExternalStorageDirectory()
    val publicDirectory = Environment.getExternalStoragePublicDirectory(type:String)
    

注意事項

  • 使用外部路徑時需要注意許可權獲取,在target23以前僅需要在Manifest.xml中申請即可,之後需要在程式碼中動態判斷。

  • 使用存在sdcard分割槽上目錄時,需要先判斷sdcard分割槽狀態是否可用。

    /* Checks if external storage is available for read and write */
    fun isExternalStorageWritable(): Boolean {
        return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
    }
    
    /* Checks if external storage is available to at least read */
    fun isExternalStorageReadable(): Boolean {
         return Environment.getExternalStorageState() in
            setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
    }
    
  • 在建立新目錄時,一定先判斷其父目錄是否存在,如果不存在需要先建立。

    fun createFile(parentFile: File, name: String) {
        if (!parentFile.exists()) {
            parentFile.mkdirs()
        }
        File(parentFile, name)
    }