Android儲存選擇

來源:互聯網
上載者:User

標籤:

最近翻譯了一篇Android Developer上的文章,文章的原路徑是Storage Options。這篇文章說的是Android中的儲存選擇。
Android為我們提供了幾種儲存穩固的應用資料的選擇。你選擇的方法取決於你的具體的需求,例如資料是否應該是對於當前應用是私人的或者對於其他的應用是可訪問的,還有你的資料需要多大的空間。
你的資料存放區方式如下:

  1. Shared Preferences:
    用key-value的方式儲存基本的私人資料。

  2. Internal Storage:(內部儲存)
    在裝置記憶體上儲存私人資料。

  3. External Storage:(外部儲存)
    在擴充儲存上儲存共有的資料。

  4. SQLite Databases:
    在私人資料庫上儲存有組織的資料。

  5. Network Connection:
    使用你自己的網路伺服器再往上儲存資料。

Android提供了一種方式去向其他的Android應用暴露你的資料甚至包括私人資料,也就是content provider。content provider是一個可選擇的控制項,它暴露了你的應用資料的讀或者寫的許可權,受限於任何你想要加的限制。如果你想瞭解更多關於 content provider的資訊,去看content provider的文檔。

Using Shared Preferences

SharedPreferences類提供了一個架構,它允許你去儲存和取回以key-value格式的資料。你可以使用SharedPreferences去儲存任何基礎資料型別 (Elementary Data Type):booleans, floats, ints, longs, 和strings。這個資料將會持續使用者周期(即使你的應用已經被殺死了)。
Shared Preferences並不是嚴格地用來儲存使用者偏好的,例如使用者選擇了什麼鈴聲。如果你對於為你的應用建立使用者偏好(user preferences)感興趣,看PreferenceActivity,它提供了一個Activity架構去建立user preferences,它將自動使用Shared Preferences。

你可以使用以下的方法去為你的應用擷取一個SharedPreferences對象:
getSharedPreferences():如果你需要多個由名字區分的preferences的檔案,你用第一個參數來區分這些檔案,你可以使用這個方法。
getPreferences():如果你只需要為你的Activity提供一個preferences檔案,你可以使用這個方法。因為這僅僅是一個針對你的Activity的 preferences 檔案,你不必提供一個名字來區分。

來寫值:
1. 調用edit()去擷取SharedPreferences.Editor。
2. 使用這些方法putBoolean()等來添加值。
3. 用commit()來提交這些新的值。

用getBoolean()等方法來讀取儲存的值。

這是一個在一個計算機裡為鍵盤按鍵儲存preference的例子:

public class Calc extends Activity {    public static final String PREFS_NAME = "MyPrefsFile";    @Override    protected void onCreate(Bundle state){       super.onCreate(state);       . . .       // Restore preferences       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);       boolean silent = settings.getBoolean("silentMode", false);       setSilent(silent);    }    @Override    protected void onStop(){       super.onStop();      // We need an Editor object to make preference changes.      // All objects are from android.context.Context      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);      SharedPreferences.Editor editor = settings.edit();      editor.putBoolean("silentMode", mSilentMode);      // Commit the edits!      editor.commit();    }}
使用內部儲存

你可以在裝置的內部儲存上直接存放檔案。預設情況下,儲存到內部儲存的檔案對於你的應用是私人的並且其他的應用不能擷取到它們。當使用者卸載了你的應用時,這些檔案也同時被移除了。
為了建立和寫入一個私人的檔案到內部儲存:
1. 調用openFileOutput()方法,它會返回一個FileOutputStream。
2. 用write()去寫到檔案裡。
3. 用close()去關閉我們的流(stream)。

例如:

String FILENAME = "hello_file";String string = "hello world!";FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);fos.write(string.getBytes());fos.close();

MODE_PRIVATE 將會建立檔案(或者替代重名的檔案)並且使他對於你的應用來說是私人的。
其他可以選擇的模式是:MODE_APPEND, MODE_WORLD_READABLE, 和MODE_WORLD_WRITEABLE。

從內部儲存中讀取一個檔案:
1. 調用openFileInput(),它返回了FileInputStream。
2. 用read()從檔案中讀取位元組。
3. 用close()關閉檔案流。

Tip:如果你想在編譯的時候去在你的應用裡儲存一個檔案,儲存你的檔案在這個項目目錄:res/raw/。你可以用openRawResource()開啟它,傳遞參數 R.raw.<檔案名稱> 。這種方式返回InputStream,你可以用這個流去讀這個檔案。(但是你不能對最初的檔案進行寫操作)

儲存快取檔案

如果你想緩衝一些資料,而不是一直儲存它們,你可以使用getCacheDir()去開啟一個檔案,這個檔案指的是你的應用儲存臨時快取檔案的內部目錄。
當裝置的內部儲存空間不足時,Android有可能刪除這些快取檔案來釋放空間。但是,你不應該依賴系統去清理這些快取檔案。你應該自己去控制快取檔案的添加和刪除並且保持它們佔據的空間在一個合理的範圍內(例如1MB)。當使用者卸載你的應用時,這些檔案將被移除。

其它有用的方法

getFilesDir():
擷取你的內部檔案被儲存的檔案系統的目錄的絕對路徑。
getDir():
建立(或者開啟一個已經存在的)一個內部儲存空間的目錄。
deleteFile():
刪除內部儲存裡的一個檔案。
fileList():
返回目前被你的應用儲存的檔案的一個列表。

使用擴充儲存

每部Android裝置都會支援用來隱藏檔的外部儲存。外部儲存可以是一個可以移除的媒介(例如SD卡)或者一個內部儲存(不可移除的)。儲存在外存的檔案是全域可讀的並且可以被允許USB mass 儲存的使用者所修改。
注意:如果使用者在電腦上增加了外部儲存或者移除了媒介,外部儲存將會變得不可用。並且你儲存到外存的檔案也會沒有安全保證。所有的應用都可以讀寫放置在外存的檔案並且他們也可以刪除它們。

擷取外部儲存的許可權

為了在外部儲存空間上讀寫檔案,你的應用必須擷取READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE系統許可權。例如:

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

如果你想同時讀寫檔案,你只需要添加WRITE_EXTERNAL_STORAGE許可權,因為它已經包括了讀許可權。

提示:從Android 4.4版本開始,如果你僅僅讀寫你應用的私人檔案,這些允許並不是必須的。更多的內容,見saving files that are app-private。

檢查媒介的可用性

在你操作外存之前,你應該調用getExternalStorageState()去檢查當前媒介(外部儲存目錄)是否可用。這個媒介將會被添加到電腦,丟失,唯讀,或者在其它的狀態。例如,下面的方法你可以用來檢測儲存介質的可用性:

/* Checks if external storage is available for read and write */public boolean isExternalStorageWritable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state)) {        return true;    }    return false;}/* Checks if external storage is available to at least read */public boolean isExternalStorageReadable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state) ||        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {        return true;    }    return false;}

getExternalStorageState()方法會返回其它的狀態,例如這個介質是否在被共用(串連到了電腦),丟失了,被錯誤地移除等等。當你的應用需要外部儲存的許可權的時候,你可以使用這些傳回值去告訴使用者目前的外部儲存的狀態。

儲存可以與其它應用共用的檔案

通常地,使用者可以通過你的APP得到的新的檔案應該儲存在一個公用的地方,在這個公用的地方其它的APP可以訪問他們並且使用者可以從裝置中輕易的拷貝它們。當這麼做的時候,你應該使用共用的公有目錄之一,例如:Music/, Pictures/, and Ringtones/。
調用getExternalStoragePublicDirectory()方法,通過傳遞某種你需要的目錄的類型,例如DIRECTORY_MUSIC, DIRECTORY_PICTURES, DIRECTORY_RINGTONES(鈴聲目錄)等,去擷取相應公有目錄裡的檔案。通過儲存你的檔案到相應的目錄中,系統的掃描器將會對你的檔案進行分類。(例如,鈴聲將在系統中被設定為鈴聲的目錄,而不是音樂)
例如,這裡是一個在公有的照片目錄為新的相簿建立目錄的方法:

public File getAlbumStorageDir(String albumName) {    // Get the directory for the user‘s public pictures directory.    File file = new File(Environment.getExternalStoragePublicDirectory(            Environment.DIRECTORY_PICTURES), albumName);    if (!file.mkdirs()) {        Log.e(LOG_TAG, "Directory not created");    }    return file;}

把你的檔案藏起來放置檔案掃描器把它掃描出來(隱藏自己的檔案)
你可以在你的外存目錄下包含一個名叫 .nomedia 的空檔案(在檔案名稱裡注意點的首碼)。這將放置Android系統去擷取到你的檔案並且通過MediaStore content provider把它們提供給其它的應用。但是,如果你的檔案的確對於你的應用是私人的,你應該把它們儲存在app的私人目錄(save them in an app-private directory)。

儲存應用的私人檔案

如果你想處理並不想給其它應用使用的檔案(例如僅僅由你的應用使用的圖片或者音效),你應該通過調用getExternalFilesDir()在外部儲存中去使用私人的儲存目錄。這個方法同樣需要一個參數去區分子目錄的類型(例如DIRECTORY_MOVIES)。如果你不需要一個特殊的外接媒介目錄,傳遞null去過去你的私人應用目錄的根目錄。
從Android 4.4版本開始,在你的app 私人目錄讀寫檔案不再需要READ_EXTERNAL_STORAGE 或WRITE_EXTERNAL_STORAGE許可權。所以你只用在更低的Android版本通過添加maxSdkVersion屬性去聲明這個許可權,如下:

<manifest ...>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"                     android:maxSdkVersion="18" />    ...</manifest>

注意:當使用者卸載了你的應用時,這個目錄以及它的內容都將被刪除。同樣地,系統掃描將不會讀取這些目錄下的檔案,所以MediaStore content provider將不會擷取到它們的內容。同樣地,你不應該使用這些目錄來儲存最後屬於使用者的檔案,例如照片或者你購買的音樂,這些檔案應該存放在公有目錄裡。

有些時候,有一部分記憶體被分配用作外部儲存的Android裝置可能仍會提供一個SD卡插槽。當在Android 4.3或者更低的版本時,getExternalFilesDir()方法僅僅提供了內部分配(記憶體)的許可權並且你的app不能讀寫sd卡。但是,從Android 4.4版本開始,你可以通過調用返迴文件數組的方法getExternalFilesDirs()去獲得以上兩個目錄的許可權。數組中的第一個入口是主要的外部儲存,並且除非它滿了或者是不可用,你都應該使用這個地址目錄。如果你想在Android 4.3或以下的裝置去同時擷取以上這兩個目錄,你可以使用support library 裡的靜態方法ContextCompat.getExternalFilesDirs()。
這個方法同樣包含一個檔案數組,但是在Android 4.3或更低的版本上只有一個入口。

注意:儘管由getExternalFilesDir() 和getExternalFilesDirs()提供的目錄不能被MediaStore content provider所訪問,擁有READ_EXTERNAL_STORAGE許可權的其他應用可以訪問所有外部儲存包括上面目錄裡的檔案。如果你想完全限制你的檔案的存取權限,你應該把你的檔案寫到記憶體儲存中去。

儲存快取檔案

調用getExternalCacheDir()方法去開啟你認為在外存上應該去儲存的快取檔案。如果使用者卸載了你的應用,這些檔案將會被自動刪除。
與ContextCompat.getExternalFilesDirs()類似,我們在上面提過的,你同樣可以通過調用
ContextCompat.getExternalCacheDirs()方法在二級外存目錄(如果可訪問)上去訪問緩衝目錄。

小提示:為了儲存你的檔案空間和保證你應用的效能,細緻地操作你的快取檔案並且在你的應用的生命週期中去刪除無用的緩衝是非常重要的。

使用資料庫

Android 為SQLite資料庫提供了完整的支援。任何你建立的資料庫可以在你的應用裡通過名字去擷取,但是在應用外則不可以訪問。
Android推薦的建立新的資料庫的方法是建立一個SQLiteOpenHelper的子類並且重載onCreate()方法,在這個方法中你可以通過SQLite指令去建立資料庫中的表。
例如:

public class DictionaryOpenHelper extends SQLiteOpenHelper {    private static final int DATABASE_VERSION = 2;    private static final String DICTIONARY_TABLE_NAME = "dictionary";    private static final String DICTIONARY_TABLE_CREATE =                "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +                KEY_WORD + " TEXT, " +                KEY_DEFINITION + " TEXT);";    DictionaryOpenHelper(Context context) {        super(context, DATABASE_NAME, null, DATABASE_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(DICTIONARY_TABLE_CREATE);    }}

你可以擷取你的SQLiteOpenHelper的執行個體通過你定義的建構函式。分別調用getWritableDatabase() 和 getReadableDatabase() 去讀寫資料庫。它們都返回了SQLiteDatabase對象,並且為我們的資料庫操作提供了相應的方法。

你可以通過使用參數包括表名,選擇條件,列,排序等的SQLiteDatabase query()方法去使用SQLite查詢語句。對於像這些需要列別名的複雜的查詢,你應該使用提供了很多便捷方法去建立查詢語句的SQLiteQueryBuilder。

每個SQLite查詢都會返回一個指向通過這次查詢找到的所有行的Cursor。Cursor通常是一個協助你來導航資料庫查詢結果的機制。

例如,你可以看Note Pad和Searchable Dictionary應用去看如何在Android中使用SQLite資料庫。

資料庫調試

Android SDK包含了一個sqlite3工具,它協助我們去瀏覽表的內容,運行資料庫指令,並且使用其它有用的資料庫功能。看Examining sqlite3 databases from a remote shell如何去使用這個功能。

注意:Android沒有為SQLite施加任何限制。我們推薦在你的表裡應該包含一個自增長的範圍,我們可以通過它去迅速定位一條記錄。這對於私人資料並不是必須的,但是當你聲明了一個content provider,你必須使用BaseColumns._ID常量去包含一個獨一無二的ID。

使用網路連接

你可以使用網路(當它可用時)去儲存和取資料。為了做網路操作,使用下麵包裡的類:

java.net.*android.net.*

Android儲存選擇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.