數據存儲的位置有兩個:手機自帶的存儲空間(電腦的自帶硬盤)和外存儲設備(sdcard,移動硬盤,也有可能是固定在手機內部,用usb鏈接電腦後可以看到的存儲設備)
當使用context的openFileOutput()來保存文件時,文件會被保存在手機自帶的存儲空間中,而且根據保存時操作模式的不同而權限不同。手機自帶的存儲空間通常較小,適合存放一些小的文件。大的文件通常存放在SDCard中,保存在SDCard中的文件是其他應用都能訪問的。
SDCard使用方法:
第一步:添加SDCard使用權限
第二步:判斷SDCard是否可用Environment.getExternalStorageState();
需要判斷兩個狀態 是否安裝了SDCard(MEDIA_MOUNTED);是否有寫保護(MEDIA_MOUNTED_READONLY)
第三步:保存文件
File file = new File(“/mnt/sdcard”,filename);
FileOutputStream outStream = newFileOutputStream(file);
outStream.write(content.getBytes());
outStream.close();
在SDCard中創建文件時,文件目錄通過Environment.getExternalStorageDirectory()獲得可以屏蔽掉一些版本的差異。
數據存儲的方式有五種:
1. 文件
實際上是用javaSE中的IO技術
1) 通過上下文對象context快速得到文件輸出流對象
FileOutputStreamoutStream=context.openFileOutput(filename,mode);
outStream.write(str.getBytes());
Filename:輸出流所寫文件的文件名
Mode:權限控制及寫入方式(追加,覆蓋…)
eg:context.MODE_PRIVATE,私有操作模式:創建出來的文件只能被本應用使用,其他應用無法訪問該文件,並且以覆蓋方式寫入
因爲是字節輸出流,所以要將寫入內容轉換成字節
通過這種方式,文件會被保存在data/data/packagename/files文件夾下面
2) 通過上下文對象context快速得到文件輸出流對象
FileInputStream inStream=context.openFileInput(filename);
ByteArrayOutputStream outStream=new ByteArrayOutputStream();//字節數組輸出流對象,用來緩存字節數組在內存中
Byte []buffer=new byte[1024];
While((len=inStream.read(buffer))!=-1)//讀到文件結尾時read方法返回-1
{
outStream.write(buffer,0, len);
}
Byte [] data = outStream.toByteArray();
3) 創建文件時所使用的操作模式
Context.MODE_PRIVATE:默認操作模式,如上述。
Context.MODE_APPEND:追加操作模式,檢查文件是否存在,存在就往文件末尾追加內容;若不存在,就創建文件,創建的文件只能被本應用訪問。
Context.MODE_WORLD_READABLE:表示當前文件可以被其他應用寫入
Context.MODE_WORLD_WRITABLE:表示當前文件可以被其他應用寫入
Android有一套自己的安全模型,當應用程序在安裝時系統會分配給它一個userid,當該應用要去訪問其他資源比如文件時,就需要userid匹配。默認情況下,任何應用創建的文件,SharedPreferences,數據庫都應該是私有的(位於/data/data/<packagename>/files/)其他應用無法訪問。除非在創建時就指定了context.MODE_WORLD_WRITABLE或者context.MODE_WORLD_READABLE
2. SharedPreferences(偏好參數保存)
很多時候我們開發的軟件需要向用戶提供軟件參數設置的功能。對於軟件配置參數的保存,如果是window軟件通常我們會採用ini文件進行保存,如果是j2se應用,我們會採用properties屬性文件或者xml進行保存。如果是android應用,我們用什麼方式保存軟件配置參數呢?Android平臺給我們提供了一個SharedPreferences類,它是一個輕量級的存儲類,特別適合用於保存軟件配置參數。使用sharedpreferences保存數據,其背後是用xml文件存放數據,相當於是該類封裝了對xml文件進行操作的一些方法,保存的xml文件存放在/data/data/<packagename>/shared_prefs目錄下。
使用步驟:
1) 保存:
第一步:獲得sharedPreferences類的對象。
SharedPreferencessharedPreferences=context.getSharedPreferences(filename,mode);
Filename是SharedPreferences內部所使用的xml文件的名稱,不要自己加上後綴名.xml,mode是操作模式
第二步:獲取編輯器,並利用編輯器保存內容
Editoreditor=sharedPreferences.edit();
Editor.putString(key,value);
Editor.putInt(key,value);
第三步:提交修改,第二步實際並未寫入xml文件
Editor.commit();
2) 讀取
Map<string ,string> params = new HashMap<String, String>();
第一步:獲得sharedPreferences對象
SharedPreferences preferences = context.getSharedPreferences(“itcast”,Context.MODE_PRIVATE);
第二步:從對象中讀取參數
Params.put(“name”, preferences.getString(key , defualtvalue));
Params.put(“age”,String.valueOf(preferences.getInt(“age”,0)));
key是鍵值,通過key來查找得到值,defualtvalue是當該鍵值不存在時,返回一個默認的值。
3. SQLite數據庫
Android對SQLite數據庫提供了全面的支持。在一個應用中創建的數據庫,可以被該應用中的任何類按照數據庫的名字來訪問,但是不允許別的應用訪問。
1) 創建數據庫:推薦的方法是繼承SQLiteOpenHelper類,然後重載它的onCreate方法,在這個方法中可以通過執行SQLite的命令來創建表。
SQLiteOpenHelper的方法:
構造函數: name爲數據庫的名稱,若該數據庫不存在則創建該數據庫,version是數據庫的版本號,注:通過構造方法獲得該類的實例時,並不會創建或者打開數據庫,而是在通過該對象調用getWritableDatabase()和getReadableDatabase()時纔會創建或者打開數據庫。
onCreate()方法:數據庫創建時調用,一般在此方法中建表。若是數據庫存在,則不會再調用該方法。
onUpgrade()方法:當數據庫存在,且新建該類實例對象時所傳入的版本號比之前的版本號大時,會調用此方法。一般在此方法中更新表的結構。如果想要在獲得數據庫時,調用此方法,則應該將版本號增加。
1) 數據庫的業務處理,增刪改查。有兩種方法:
傳統的sql語句:
添加、刪除、修改所用到的函數是一樣的
先通過helper獲得可寫入的數據庫,準備好sql語句和相應參數,通過調用execSQL(String sql,Object[] params)來執行。其中sql語句中可能含有?佔位符,會用字符串數組params來賦值。
查詢操作:
分爲單條查詢和多條查詢:
首先獲得可讀取的數據庫,準備好sql語句和參數,調用rawQuery()來執行,返回一個Cursor對象,指向第一條返回記錄之前。通過cursor可以獲得返回記錄的列數,然後循環記錄每列的列名和值,注:列數是從0開始。可以用map<string,string>對象來存儲行記錄。在多條查詢時,用list<map<String,String>>來保存返回結果。
Android封裝好的方法:
一般來說,上述方法無法返回SQL執行所影響的行數,使用Android封裝的方法更爲簡便。
在數據庫中插入記錄:
注意其中的第二個參數StringnullColumnHack.這個參數是可選的,或爲空,或者指定某一列的列名。如果爲空,則不允許插入空記錄,即values裏沒有存放任何東西。如果指定某一列,那麼如果遇到空記錄,系統會將該列的值賦值爲null,然後插入。ContentValues類型相當於一個Map,存放了所需要更新的列名,和更新值。
在數據庫中刪除記錄:
在數據庫中更改記錄:
在數據庫中查詢數據:
4. 內容提供者(Content Provider)
內容提供者管理了對一組結構化數據訪問,即提供了一組接口(方法)來響應數據訪問端的請求。內容提供者封裝了數據,提供了一種應用間共享數據的機制。如果需要將本應用的數據對外進行共享,你需要創建一個ContentProvider,而其他的應用訪問這些共享的數據時,通過ContentResolver來進行訪問。
URI:android系統中一般有很多個ContentProvider,如何訪問指定的ContentProvider呢?需要uri來唯一標識一個ContentProvider。在Provider端(相當於服務器),有一個待匹配的uri(通常會在這裏使用通配符,#代表任意長度的數字,*代表任意長度的字符串),在Resolver端,如果要訪問某個Provider,要給出訪問的uri。
URI格式:content://authority/path
Content://authority/path/id
第一條表示操作的數據是多條數據(通常是一個表),第二條表示操作的是某一條記錄。
Authority是在配置文件中申明ContentProvider時所指定的唯一的標識符。
而在Provider端,uri所表示的意義:
Com.example.sqlitetest/* :表示的是該Provider裏的所有表
Com.example.sqlitetest/student:表示該Provider只允許操作student表裏的內容
Com.example.sqlitetest/student/#::表示該provider只允許操作student表裏的某一條記錄
ContentProvider使用方法:
1. 因爲ContentProvider是android四大組件之一,所以需要在配置文件中進行聲明。
2. 編寫Provider類實現ContentProvider父類,並覆蓋其中的抽象方法。
需要定義的常量,其中的URIMatcher是用來進行uri匹配的輔助類,在靜態代碼塊中爲其初始化,添加了兩條待匹配的uri。第三個參數是匹配成功時返回的編碼,STUDENT表示對單條記錄進行操作,STUDENTS表示對多條記錄進行操作。
得到數據庫->匹配uri->根據匹配得到的編碼,執行相應的處理(單條記錄需要用到ContentUris取出id部分)
在客戶端訪問ContentProvider時的代碼:
先獲得Resolver然後準備參數,最後執行
5. 網絡