編輯:關於Android編程
Android提供了5種方式來讓用戶保存持久化應用程序數據。根據自己的需求來做選擇,比如數據是否是應用程序私有的,是否能被其他程序訪問,需要多少數據存儲空間等,分別是:
① 使用SharedPreferences存儲數據
② 文件存儲數據
③ SQLite數據庫存儲數據
④ 使用ContentProvider存儲數據
⑤ 網絡存儲數據
Android提供了一種方式來暴露你的數據(甚至是私有數據)給其他應用程序 - ContentProvider。它是一個可選組件,可公開讀寫你應用程序數據。
2、SharedPreferences存儲SharedPreference類提供了一個總體框架,使您可以保存和檢索的任何基本數據類型( boolean, float, int, long, string)的持久鍵-值對(基於XML文件存儲的“key-value”鍵值對數據)。
通常用來存儲程序的一些配置信息。其存儲在“data/data/程序包名/shared_prefs目錄下。
xml 處理時Dalvik會通過自帶底層的本地XML Parser解析,比如XMLpull方式,這樣對於內存資源占用比較好。
2.1 我們可以通過以下兩種方法獲取SharedPreferences對象(通過Context):
① getSharedPreferences (String name, int mode)
當我們有多個SharedPreferences的時候,根據第一個參數name獲得相應的SharedPreferences對象。
② getPreferences (int mode)
如果你的Activity中只需要一個SharedPreferences的時候使用。
這裡的mode有四個選項:
Context.MODE_PRIVATE
該SharedPreferences數據只能被本應用程序讀、寫。
Context.MODE_WORLD_READABLE
該SharedPreferences數據能被其他應用程序讀,但不能寫。
Context.MODE_WORLD_WRITEABLE
該SharedPreferences數據能被其他應用程序讀和寫。
Context.MODE_MULTI_PROCESS
sdk2.3後添加的選項,當多個進程同時讀寫同一個SharedPreferences時它會檢查文件是否修改。
2.2 向Shared Preferences中寫入值
首先要通過 SharedPreferences.Editor獲取到Editor對象;
然後通過Editor的putBoolean() 或 putString()等方法存入值;
最後調用Editor的commit()方法提交;
//Use 0 or MODE_PRIVATE for the default operation
SharedPreferences settings = getSharedPreferences("fanrunqi", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("isAmazing", true);
// 提交本次編輯
editor.commit();
同時Edit還有兩個常用的方法:
editor.remove(String key) :下一次commit的時候會移除key對應的鍵值對
editor.clear():移除所有鍵值對
2.3 從Shared Preferences中讀取值
讀取值使用 SharedPreference對象的getBoolean()或getString()等方法就行了(沒Editor 啥子事)。
SharedPreferences settings = getSharedPreferences("fanrunqi", 0);
boolean isAmazing= settings.getBoolean("isAmazing",true);
2.4 Shared Preferences的優缺點
可以看出來Preferences是很輕量級的應用,使用起來也很方便,簡潔。但存儲數據類型比較單一(只有基本數據類型),無法進行條件查詢,只能在不復雜的存儲需求下使用,比如保存配置信息等。
3、文件數據存儲當文件被保存在內部存儲中時,默認情況下,文件是應用程序私有的,其他應用不能訪問。當用戶卸載應用程序時這些文件也跟著被刪除。
文件默認存儲位置:/data/data/包名/files/文件名。
① 調用Context的openFileOutput()函數,填入文件名和操作模式,它會返回一個FileOutputStream對象。
② 通過FileOutputStream對象的write()函數寫入數據。
③ FileOutputStream對象的close ()函數關閉流。
例如:
String FILENAME = "a.txt";
String string = "fanrunqi";
try {
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
在 openFileOutput(String name, int mode)方法中
name參數: 用於指定文件名稱,不能包含路徑分隔符“/” ,如果文件不存在,Android 會自動創建它。
mode參數:用於指定操作模式,分為四種:
Context.MODE_PRIVATE = 0
為默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容。
Context.MODE_APPEND = 32768
該模式會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件。
Context.MODE_WORLD_READABLE = 1
表示當前文件可以被其他應用讀取。
MODE_WORLD_WRITEABLE
表示當前文件可以被其他應用寫入。
① 調用openFileInput( ),參數中填入文件名,會返回一個FileInputStream對象。
② 使用流對象的 read()方法讀取字節
③ 調用流的close()方法關閉流
例如:
String FILENAME = "a.txt";
try {
FileInputStream inStream = openFileInput(FILENAME);
int len = 0;
byte[] buf = new byte[1024];
StringBuilder sb = new StringBuilder();
while ((len = inStream.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
inStream.close();
} catch (Exception e) {
e.printStackTrace();
}
其他一些經常用到的方法:
getFilesDir(): 得到內存儲文件的絕對路徑
getDir(): 在內存儲空間中創建或打開一個已經存在的目錄
deleteFile(): 刪除保存在內部存儲的文件。
fileList(): 返回當前由應用程序保存的文件的數組(內存儲目錄下的全部文件)。
如果你想在應用編譯時保存靜態文件,應該把文件保存在項目的 res/raw/ 目錄下,你可以通過 openRawResource()方法去打開它(傳入參數R.raw.filename),這個方法返回一個 InputStream流對象你可以讀取文件但是不能修改原始文件。
InputStream is = this.getResources().openRawResource(R.raw.filename);
有時候我們只想緩存一些數據而不是持久化保存,可以使用getCacheDir()去打開一個文件,文件的存儲目錄( /data/data/包名/cache )是一個應用專門來保存臨時緩存文件的內存目錄。
當設備的內部存儲空間比較低的時候,Android可能會刪除這些緩存文件來恢復空間,但是你不應該依賴系統來回收,要自己維護這些緩存文件把它們的大小限制在一個合理的范圍內,比如1MB.當你卸載應用的時候這些緩存文件也會被移除。
因為內部存儲容量限制,有時候需要存儲數據比較大的時候需要用到外部存儲,使用外部存儲分為以下幾個步驟:
首先,要在AndroidManifest.xml中加入訪問SDCard的權限,如下:
在使用外部存儲時我們需要檢測其狀態,它可能被連接到計算機、丟失或者只讀等。下面代碼將說明如何檢查狀態:
//獲取外存儲的狀態
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// 可讀可寫
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// 可讀
} else {
// 可能有很多其他的狀態,但是我們只需要知道,不能讀也不能寫
}
1、如果 API 版本大於或等於8,使用
getExternalFilesDir (String type)
該方法打開一個外存儲目錄,此方法需要一個類型,指定你想要的子目錄,如類型參數DIRECTORY_MUSIC和 DIRECTORY_RINGTONES(傳null就是你應用程序的文件目錄的根目錄)。通過指定目錄的類型,確保Android的媒體掃描儀將掃描分類系統中的文件(例如,鈴聲被確定為鈴聲)。如果用戶卸載應用程序,這個目錄及其所有內容將被刪除。
例如:
File file = new File(getExternalFilesDir(null), "fanrunqi.jpg");
2、如果API 版本小於 8 (7或者更低)
getExternalStorageDirectory ()
通過該方法打開外存儲的根目錄,你應該在以下目錄下寫入你的應用數據,這樣當卸載應用程序時該目錄及其所有內容也將被刪除。
/Android/data//files/
讀寫數據:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File sdCardDir = Environment.getExternalStorageDirectory();//獲取SDCard目錄 "/sdcard"
File saveFile = new File(sdCardDir,"a.txt");
//寫數據
try {
FileOutputStream fos= new FileOutputStream(saveFile);
fos.write("fanrunqi".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
//讀數據
try {
FileInputStream fis= new FileInputStream(saveFile);
int len =0;
byte[] buf = new byte[1024];
StringBuffer sb = new StringBuffer();
while((len=fis.read(buf))!=-1){
sb.append(new String(buf, 0, len));
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
我們也可以在 /Android/data/package_name/cache/目錄下做外部緩存。
部分翻譯於:android-data-storage
4、 網絡存儲數據 HttpUrlConnection是Java.net包中提供的API,我們知道Android SDK是基於Java的,所以當然優先考慮HttpUrlConnection這種最原始最基本的API,其實大多數開源的聯網框架基本上也是基於JDK的HttpUrlConnection進行的封裝罷了,掌握HttpUrlConnection需要以下幾個步驟:
1、將訪問的路徑轉換成URL。
URL url = new URL(path);
2、通過URL獲取連接。
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
3、設置請求方式。
conn.setRequestMethod(GET);
4、設置連接超時時間。
conn.setConnectTimeout(5000);
5、設置請求頭的信息。
conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));
7、針對不同的響應碼,做不同的操作(請求碼200,表明請求成功,獲取返回內容的輸入流)
工具類:
public class StreamTools {
/**
* 將輸入流轉換成字符串
*
* @param is
* 從網絡獲取的輸入流
* @return
*/
public static String streamToString(InputStream is) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
baos.close();
is.close();
byte[] byteArray = baos.toByteArray();
return new String(byteArray);
} catch (Exception e) {
Log.e(tag, e.toString());
return null;
}
}
}
public static String loginByGet(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod(GET);
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream(); // 字節流轉換成字符串
return StreamTools.streamToString(is);
} else {
return 網絡訪問失敗;
}
} catch (Exception e) {
e.printStackTrace();
return 網絡訪問失敗;
}
}
public static String loginByPost(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod(POST);
conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
String data = username= + username + &password= + password;
conn.setRequestProperty(Content-Length, data.length() + );
// POST方式,其實就是浏覽器把數據寫給服務器
conn.setDoOutput(true); // 設置可輸出流
OutputStream os = conn.getOutputStream(); // 獲取輸出流
os.write(data.getBytes()); // 將數據寫給服務器
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream();
return StreamTools.streamToString(is);
} else {
return 網絡訪問失敗;
}
} catch (Exception e) {
e.printStackTrace();
return 網絡訪問失敗;
}
}
HttpClient是開源組織Apache提供的Java請求網絡框架,其最早是為了方便Java服務器開發而誕生的,是對JDK中的HttpUrlConnection各API進行了封裝和簡化,提高了性能並且降低了調用API的繁瑣,Android因此也引進了這個聯網框架,我們再不需要導入任何jar或者類庫就可以直接使用,值得注意的是Android官方已經宣布不建議使用HttpClient了。
1、 創建HttpClient對象
2、創建HttpGet對象,指定請求地址(帶參數)
3、使用HttpClient的execute(),方法執行HttpGet請求,得到HttpResponse對象
4、調用HttpResponse的getStatusLine().getStatusCode()方法得到響應碼
5、調用的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的數據
public static String loginByHttpClientGet(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
+ username + &password= + password;
HttpClient client = new DefaultHttpClient(); // 開啟網絡訪問客戶端
HttpGet httpGet = new HttpGet(path); // 包裝一個GET請求
try {
HttpResponse response = client.execute(httpGet); // 客戶端執行請求
int code = response.getStatusLine().getStatusCode(); // 獲取響應碼
if (code == 200) {
InputStream is = response.getEntity().getContent(); // 獲取實體內容
String result = StreamTools.streamToString(is); // 字節流轉字符串
return result;
} else {
return 網絡訪問失敗;
}
} catch (Exception e) {
e.printStackTrace();
return 網絡訪問失敗;
}
}
1,創建HttpClient對象
2,創建HttpPost對象,指定請求地址
3,創建List,用來裝載參數
4,調用HttpPost對象的setEntity()方法,裝入一個UrlEncodedFormEntity對象,攜帶之前封裝好的參數
5,使用HttpClient的execute()方法執行HttpPost請求,得到HttpResponse對象
6, 調用HttpResponse的getStatusLine().getStatusCode()方法得到響應碼
7, 調用的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的數據
public static String loginByHttpClientPOST(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
try {
HttpClient client = new DefaultHttpClient(); // 建立一個客戶端
HttpPost httpPost = new HttpPost(path); // 包裝POST請求
// 設置發送的實體參數
List parameters = new ArrayList();
parameters.add(new BasicNameValuePair(username, username));
parameters.add(new BasicNameValuePair(password, password));
httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
HttpResponse response = client.execute(httpPost); // 執行POST請求
int code = response.getStatusLine().getStatusCode();
if (code == 200) {
InputStream is = response.getEntity().getContent();
String result = StreamTools.streamToString(is);
return result;
} else {
return 網絡訪問失敗;
}
} catch (Exception e) {
e.printStackTrace();
return 訪問網絡失敗;
}
}
HttpClient和HttpUrlConnection的兩種網絡訪問方式編寫網絡代碼,需要自己考慮很多,獲取數據或許可以,但是如果要將手機本地數據上傳至網絡,根據不同的web端接口,需要組織不同的數據內容上傳,給手機端造成了很大的工作量。
目前有幾種快捷的網絡開發開源框架,給我們提供了非常大的便利。下面是這些項目Github地址,有文檔和Api說明。
android-async-http
http-request
okhttp
5、 SQLite數據庫存儲數據前面的文章 SQLite的使用入門已經做了詳細說明,這裡就不在多說了。
6、 使用ContentProvider存儲數據同樣可以查看 ContentProvider實例詳解
本文實例講述了Android實現捕獲TextView超鏈接的方法。分享給大家供大家參考,具體如下:這裡分享一篇捕獲TextView超鏈接的文章,希望對大家有所幫助,我終於
dispatchTouchEvent話不多說直接上源碼 /** * Pass the touch screen motion event down to t
Android 軟鍵盤自動彈出與關閉在我們寫修改信息或者搜索,修改密碼等界面的時候,用戶進入這個界面的主要目的就是輸入修改/查找 某些信息,為了用戶體驗應該自動彈出軟鍵盤
安卓手機QQ自帶截圖功能,iPad、iPhone則需要使用iOS系統自帶的截圖方法或者第三方APP。下面就隨小編分別來看看,安卓手機QQ和iOS系統的ipa