android 五種數據存儲 :SharePreferences、SQLite、Contert Provider、File、網絡存儲
Android系統提供了四種存儲數據方式。分別為:SharePreference、SQLite、Content Provider和File。但由於Android系統中,數據基本是私有的,都是存放於”data/data”程序包名目錄下,所以要實現數據共享,正確方式是使用Content Provider
SQLite:SQLite是一個輕量級的數據庫,支持基本的SQL語法,是常被采用的一種數據存儲方式。Android為此數據庫提供了一個名為SQLiteDatabase的類,封裝了一些操作數據庫的api
SharedPreference: 除SQLite數據庫外,另一種常用的數據存儲方式,其本質就是一個xml文件,常用於存儲較簡單的參數設置。
File: 即常說的文件(I/O)存儲方法,常用語存儲大數量的數據,但是缺點是更新數據將是一件困難的事情。
ContentProvider: Android系統中能實現所有應用程序共享的一種數據存儲方式,由於數據通常在各應用間的是互相私密的,所以此存儲方式較少使用,但是其又是必不可少的一種存儲方式。例如音頻,視頻,圖片和通訊錄,一般都可以采用此種方式進行存儲。每個Content Provider都會對外提供一個公共的URI(包裝成Uri對象),如果應用程序有數據需要共享時,就需要使用Content Provider為這些數據定義一個URI,然后其他的應用程序就通過Content Provider傳入這個URI來對數據進行操作。
URI由3個部分組成:"content://"、數據的路徑、標識ID(可選)。
1)SQLite數據存儲
======================================================================
SQLite是一種轉為嵌入式設備設計的輕型數據庫,其只有五種數據類型,分別為:
NULL:空值
INTEGER:整數
REAL:浮點數
TEXT:字符串
BLOB:大數據
在SQLite中,並沒有專門設計BOOLEAN和DATE類型,因為BOOLEAN型可以用INTEGER的0和1代替true和false,而DATE類型則可以擁有特定格式的TEXT、REAL和INTEGER的值來代替顯示,為了能方便的操作DATE類型,SQLite提供了一組函數,
詳見:http://www.sqlite.org/lang_datefunc.html。這樣簡單的數據類型設計更加符合嵌入式設備的要求。關於SQLite的更多資料,請參看:http://www.sqlite.org/
在Android系統中提供了anroid.database.sqlite包,用於進行SQLite數據庫的增,刪,改,查工作,其主要方法如下:
beginTransaction(): 開始一個事務。
close(): 關閉連接,釋放資源。
delete(String table, String whereClause, String[] whereArgs): 根據給定條件,刪除符合條件的記錄。
endTransaction(): 結束一個事務。
execSQL(String sql): 執行給定SQL語句。
insert(String table, String nullColumnHack, ContentValues values): 根據給定條件,插入一條記錄。
openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory): 根據給定條件連接數據庫,如果此數據庫不存在,則創建。
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy): 執行查詢。
rawQuery(String sql, String[] selectionArgs): 根據給定SQL,執行查詢。
update(String table, ContentValues values, String whereClause, String[] whereArgs): 根據給定條件,修改符合條件的記錄。
除了上訴主要方法外,Android還提供了諸多實用的方法,總之一句話:其實Android訪問數據庫是一件很方便的事兒。
可以清晰的在查詢結果中,紅線上下的數據是完全一致的,也就是說query和rawQuery方法在的不同僅僅在於所需參數的不同。rawQuery方法需要開發者手動寫出查詢SQL,而query方法是由目標表名、where子句、order by子句、having子句等諸多子句由系統組成SQL語句。兩方法同返回Cursor對象,所以兩方在使用時孰優孰劣,就看具體情況了。本人更喜歡rawQuery的方式,因為此方式更接近傳統Java開發,也可以由專業DBA來書寫SQL語句,這樣更符合MVC的思想,而且這樣的代碼可讀性更高。(query方法里面參數實在太多,有點記不住誰是order by子句,誰是having子句了)
Cursor對象可以理解為游標對象,凡是對數據有所了解的人,相信對此對象都不會陌生,在這里機不再累述。只提醒一點,在第一次讀取Cursor對象中的數據時,一定要先移動游標,否則此游標的位置在第一條記錄之前,會引發異常。
2.案例:
http://blog.csdn.net/developer_jiangqq/article/details/7043487
======================================================================
(2)SharedPreference數據存儲
======================================================================
除了SQLite數據庫外,SharedPreferences也是一種輕型的數據存儲方式,它的本質是基於XML文件存儲key-value鍵值對數據,通常用來存儲一些簡單的配置信息。其存儲位置在/data/data/<包名>/shared_prefs目錄下。SharedPreferences對象本身只能獲取數據而不支持存儲和修改,存儲修改是通過Editor對象實現。實現SharedPreferences存儲的步驟如下:
一、根據Context獲取SharedPreferences對象
二、利用edit()方法獲取Editor對象。
三、通過Editor對象存儲key-value鍵值對數據。
四、通過commit()方法提交數據。
1.getSharedPreferences(String name, int mode)
得到名為‘name’的偏好文件。同時你可以更改和返回他的值。任何調用者在調用同樣名字的偏好文件時只有一個實例返回,這就意味着這些調用者都可以看到其他調用者做出的更改。
name為本組件的配置文件名( 自己定義,也就是一個文件名),當這個文件不存在時,直接創建,如果已經存在,則直接使用,
mode為操作模式,默認的模式為0或MODE_PRIVATE,還可以使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE
mode指定為MODE_PRIVATE,則該配置文件只能被自己的應用程序訪問。
mode指定為MODE_WORLD_READABLE,則該配置文件除了自己訪問外還可以被其它應該程序讀取。
mode指定為MODE_WORLD_WRITEABLE,則該配置文件除了自己訪問外還可以被其它應該程序讀取和寫入
2,PreferenceManager的方法getSharedPreferences()
這個方法是一個普通的方法,必須有PreferenceManager的實例調用才行
3.getDefaultSharedPreferences方法
這個方法是靜態的,因此可以直接調用,同時它與我們調用getSharedPreferences()方法得到的返回值是一樣的,只是調用的方式不同罷了。
因為SharedPreferences背后是使用xml文件保存數據,getSharedPreferences(name,mode)方法的第一個參數用於指定該文件的名稱,名稱不用帶后綴,后綴會由Android自動加上。方法的第二個參數指定文件的操作模式,共有四種操作模式,這四種模式前面介紹使用文件方式保存數據時已經講解過。如果希望SharedPreferences背后使用的xml文件能被其他應用讀和寫,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。
另外Activity還提供了另一個getPreferences(mode)方法操作SharedPreferences,這個方法默認使用當前類不帶包名的類名作為文件的名稱。
如果訪問其他應用中的Preference,前提條件是:該preference創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE權限。如:有個<package name>為cn.yang.action的應用使用下面語句創建了preference。
getSharedPreferences("TEST", Context.MODE_WORLD_READABLE);
其他應用要訪問上面應用的preference,首先需要創建上面應用的Context,然后通過Context 訪問preference ,訪問preference時會在應用所在包下的shared_prefs目錄找到preference :
Context otherAppsContext = createPackageContext("cn.wsl.action", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences("TEST", Context.MODE_WORLD_READABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("sex", "");
如果不通過創建Context訪問其他應用的preference,也可以以讀取xml文件方式直接訪問其他應用preference對應的xml文件,如:
File xmlFile = new File(“/data/data/<package name>/shared_prefs/itcast.xml”);//<package name>應替換成應用的包名。
具體實現代碼如下:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//獲取SharedPreferences對象
Context ctx = MainActivity.this;
SharedPreferences sp = ctx.getSharedPreferences("SI", MODE_PRIVATE);
//存入數據
Editor editor = sp.edit();//獲取編輯器
editor.putString("STRING_KEY", "string1");
editor.putInt("INT_KEY", 0);
editor.putBoolean("BOOLEAN_KEY", true);
editor.commit();
//返回STRING_KEY的值
Log.d("SP", sp.getString("STRING_KEY", "none"));
//如果NOT_EXIST不存在,則返回值為"none"
Log.d("SP", sp.getString("NOT_EXIST", "none"));
}
}
這段代碼執行過后,即在/data/data/com.test/shared_prefs目錄下生成了一個SI.xml文件,一個應用可以創建多個這樣的xml文件。如圖所示:
SP.xml文件的具體內容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="STRING_KEY">string</string>
<int name="INT_KEY" value="0" />
<boolean name="BOOLEAN_KEY" value="true" />
</map>
在程序代碼中,通過getXXX方法,可以方便的獲得對應Key的Value值,如果key值錯誤或者此key無對應value值,SharedPreferences提供了一個賦予默認值的機會,以此保證程序的健壯性。如下圖運行結果中因為並無值為"NOT_EXIST"的Key,所以Log打印出的是其默認值:“none”。在訪問一個不存在key值這個過程中,並無任何異常拋出。
SharedPreferences對象與SQLite數據庫相比,免去了創建數據庫,創建表,寫SQL語句等諸多操作,相對而言更加方便,簡潔。但是SharedPreferences也有其自身缺陷,比如其職能存儲boolean,int,float,long和String五種簡單的數據類型,比如其無法進行條件查詢等。所以不論SharedPreferences的數據存儲操作是如何簡單,它也只能是存儲方式的一種補充,而無法完全替代如SQLite數據庫這樣的其他數據存儲方式。
2.案例說明:
private void saveflag(int flag){
SharedPreferences sp=this.getSharedPreferences("scrolltag", Context.MODE_PRIVATE);
Editor editor=sp.edit();
editor.putInt("flagtag", flag);
editor.commit();
}
private int getflag(){
SharedPreferences sharedPreferences =getSharedPreferences("scrolltag", Context.MODE_PRIVATE);
int flag=sharedPreferences.getInt("flagtag", 0);
return flag;
}
//此方法可以在任何程序中添加該段代碼,來獲取cn.com.shine.hotel應用中的數據了,前提是在該應用生成xml文件的時候的權限應該是 Context.MODE_WORLD_READABLE,或者是:讀寫
private String getScrollTextOther(){
String str=null;
Context otherAppsContext = null;
try {
otherAppsContext = createPackageContext("cn.com.shine.hotel",Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sp =otherAppsContext.getSharedPreferences("scrolltext",Context.MODE_WORLD_READABLE);
str=sp.getString("scrolltext", "");
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
======================================================================
(3)ContentProvider數據存儲
======================================================================
ContentProvider是安卓平台中,在不同應用程序之間實現數據共享的一種機制。一個應用程序如果需要讓別的程序可以操作自己的數據,即可采用這種機制。並且此種方式忽略了底層的數據存儲實現,ContentProvider提供了一種統一的通過Uri實現數據操作的方式。其步驟為:
1. 在當前應用程序中定義一個ContentProvider。
2. 在當前應用程序的AndroidManifest.xml中注冊此ContentProvider
3. 其他應用程序通過ContentResolver和Uri來獲取此ContentProvider的數據。
ContentResolver提供了諸如insert(), delete(), query()和update()之類的方法。用於實現對ContentProvider中數據的存取操作。
Uri是一個通用資源標志符,將其分為A,B,C,D 4個部分:
A:無法改變的標准前綴,包括;"content://"、"tel://"等。當前綴是"content://"時,說明通過一個Content Provider控制這些數據
B:URI的標識,它通過authorities屬性聲明,用於定義了是哪個ContentProvider提供這些數據。對於第三方應用程序,為了保證URI標識的唯一性,它必須是一個完整的、小寫的 類名。例如;"content://com.test.data.myprovider"
C:路徑,可以近似的理解為需要操作的數據庫中表的名字,如:"content://hx.android.text.myprovider/name"中的name
D:如果URI中包含表示需要獲取的記錄的ID;則就返回該id對應的數據,如果沒有ID,就表示返回全部;
下面進行案展示:演示一下如何在應用程序之間相互獲取數據:
在應用程序A中,繼承ContentProvider類,並重寫其中方法:
public class MyProvider extends ContentProvider{
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
//在Create中初始化一個數據庫
@Override
public boolean onCreate() {
SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
ContentValues values = new ContentValues();
values.put("name", "test");
db.insert("tab", "_id", values);
db.close();
return true;
}
//實現query方法
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
Cursor c = db.query("tab", null, null, null, null, null,null);
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
在其AndroidManifest.xml中聲明此ContentProvider,其中authorities屬性定義了此ContentProvider的Uri標識
<provider android:name=".MyProvider" android:authorities="com.test.MyProvider"/>
在應用程序B中,通過ContentResolver獲取程序A的ContentProvider中的數據。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//獲取上下文
Context ctx = MainActivity.this;
//獲取ContentResolver對象
ContentResolver resolver = ctx.getContentResolver();
//獲取Uri對象
Uri uri = Uri.parse("content://com.test.MyProvider");
//獲取數據
Cursor c = resolver.query(uri, null, null, null, null);
c.moveToFirst();
for(int i=0; i<c.getCount(); i++){
int index = c.getColumnIndexOrThrow("name");
String src = c.getString(index);
Log.d("", src);
c.moveToNext();
}
}
}
應用程序B的運行結果如下,從此圖可以發現我們在程序B中成功的獲取到了程序A中的數據:
再觀察兩個應用程序的結構,如下圖,其中紅框是應用程序A的程序結構,可以清楚看到其有一個名為“test_db.db3”的數據庫,藍框是應用程序B的程序結構,其並沒有任何數據庫用於存儲數據。由此圖,可以確定應用程序B中查詢出來的數據結果是來自於應用程序A。
http://www.cnblogs.com/dyllove98/archive/2013/07/17/3196821.html
http://blog.csdn.net/biaozhiyuan/article/details/7298095
以上就是ContentProvider的使用方式,這種存儲方式相比SQLite和SharedPreferences,其復雜性是顯而易見的,但是在處處可見“雲”的今天,程序間的數據交互需求令ContentProvider存儲機制變成必不可少的一部分。
======================================================================
(4)File數據存儲
======================================================================
使用File進行存儲 我們有時候可以將數據直接以文件的形式保存在設備中,
例如:文本文件,圖片文件等等
使用File進行存儲操作主要使用到以下的
(1):public abstract FileInputStream openFileInput (String name)
這個主要是打開文件,返回FileInputStream
(2):public abstract FileOutputStream openFileOutput (String name, int mode)
這個主要是寫入文件,如果該文件不存在,直接進行創建,返回FileOutputStream
Mode(主要有以下的一種的模式)
MODE_PRIVATE //私有
(3):FileInputStream(獲取文件輸入流)與FileOutputStream (獲取文件輸出流)這兩類在JavaIO 操作中很常見
接下來進行操作 保存成功之后講文件保存在當前應該程序的包名下的files/(可以改變存儲的其他路徑)
package com.jiangqq.file;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class FileAcitivy extends Activity
{
private Button bt1, bt2;
private EditText et1, et2;
private static final String FILENAME = "temp_file.txt";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt1 = (Button) this.findViewById(R.id.bt1);
bt2 = (Button) this.findViewById(R.id.bt2);
et1 = (EditText) this.findViewById(R.id.et1);
et2 = (EditText) this.findViewById(R.id.et2);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
write(et1.getText().toString());
Toast.makeText(FileAcitivy.this, "文件寫入成功", Toast.LENGTH_LONG)
.show();
}
});
bt2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
et2.setText(read());
Toast.makeText(FileAcitivy.this, "文件讀出成功", Toast.LENGTH_LONG)
.show();
}
});
}
// 讀文件方法
private String read() {
try {
FileInputStream inputStream = openFileInput(FILENAME);
byte[] b = new byte[inputStream.available()];
inputStream.read(b);
return new String(b);
} catch (Exception e) {
}
return null;
}
// 寫文件
private void write(String content) {
try {
FileOutputStream fos = openFileOutput(FILENAME, MODE_APPEND);
fos.write(content.getBytes());
fos.close();
} catch (Exception e) {
}
}
}
2.文件存儲,Activity提供了openFileOutput()方法可以用於把數據輸出到文件中,具體的實現過程與在J2SE環境中保存數據到文件中是一樣的。
public void save()
{
try {
FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);
outStream.write(text.getText().toString().getBytes());
outStream.close();
Toast.makeText(MyActivity.this,"Saved",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
return;
}
catch (IOException e){
return ;
}
}
openFileOutput()方法的第一參數用於指定文件名稱,不能包含路徑分隔符“/” ,如果文件不存在,Android 會自動創建它。創建的文件保存在/data/data/<package name>/files目錄,如: /data/data/cn.itcast.action/files/itcast.txt ,通過點擊Eclipse菜單“Window”-“Show View”-“Other”,在對話窗口中展開android文件夾,選擇下面的File Explorer視圖,然后在File Explorer視圖中展開/data/data/<package name>/files目錄就可以看到該文件。
openFileOutput()方法的第二參數用於指定操作模式,有四種模式,分別為: Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容,如果想把新寫入的內容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應用是否有權限讀寫該文件。
MODE_WORLD_READABLE:表示當前文件可以被其他應用讀取;MODE_WORLD_WRITEABLE:表示當前文件可以被其他應用寫入。
如果希望文件被其他應用讀和寫,可以傳入:
openFileOutput("itcast.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
android有一套自己的安全模型,當應用程序(.apk)在安裝時系統就會分配給他一個userid,當該應用要去訪問其他資源比如文件的時候,就需要userid匹配。默認情況下,任何應用創建的文件,sharedpreferences,數據庫都應該是私有的(位於/data/data/<package name>/files),其他程序無法訪問。除非在創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有這樣其他程序才能正確訪問。
public void load()
{
try {
FileInputStream inStream=this.openFileInput("a.txt");
ByteArrayOutputStream stream=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int length=-1;
while((length=inStream.read(buffer))!=-1) {
stream.write(buffer,0,length);
}
stream.close();
inStream.close();
text.setText(stream.toString());
Toast.makeText(MyActivity.this,"Loaded",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e){
return ;
}
}
對於私有文件只能被創建該文件的應用訪問,如果希望文件能被其他應用讀和寫,可以在創建文件時,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。
Activity還提供了getCacheDir()和getFilesDir()方法:
getCacheDir()方法用於獲取/data/data/<package name>/cache目錄
getFilesDir()方法用於獲取/data/data/<package name>/files目錄
使用Activity的openFileOutput()方法保存文件,文件是存放在手機空間上,一般手機的存儲空間不是很大,存放些小文件還行,如果要存放像視頻這樣的大文件,是不可行的。對於像視頻這樣的大文件,我們可以把它存放在SDCard。 SDCard是干什么的?你可以把它看作是移動硬盤或U盤。
在模擬器中使用SDCard,你需要先創建一張SDCard卡(當然不是真的SDCard,只是鏡像文件)。創建SDCard可以在Eclipse創建模擬器時隨同創建,也可以使用DOS命令進行創建,如下:
在Dos窗口中進入android SDK安裝路徑的tools目錄,輸入以下命令創建一張容量為2G的SDCard,文件后綴可以隨便取,建議使用.img:
mksdcard 2048M D:\AndroidTool\sdcard.img
在程序中訪問SDCard,你需要申請訪問SDCard的權限。
在AndroidManifest.xml中加入訪問SDCard的權限如下:
<!-- 在SDCard中創建與刪除文件權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
要往SDCard存放文件,程序必須先判斷手機是否裝有SDCard,並且可以進行讀寫。
注意:訪問SDCard必須在AndroidManifest.xml中加入訪問SDCard的權限
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File sdCardDir = Environment.getExternalStorageDirectory();//獲取SDCard目錄
File saveFile = new File(sdCardDir, “a.txt”);
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("test".getBytes());
outStream.close();
}
Environment.getExternalStorageState()方法用於獲取SDCard的狀態,如果手機裝有SDCard,並且可以進行讀寫,那么方法返回的狀態等於Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()方法用於獲取SDCard的目錄,當然要獲取SDCard的目錄,你也可以這樣寫:
File sdCardDir = new File("/sdcard"); //獲取SDCard目錄
File saveFile = new File(sdCardDir, "itcast.txt");
//上面兩句代碼可以合成一句: File saveFile = new File("/sdcard/a.txt");
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("test".getBytes());
outStream.close();
5.網絡存儲:
Android提供了通過網絡來實現數據的存儲和獲取的方法。
我們可以調用WebService返回的數據或是解析HTTP協議實現網絡數據交互。
具體需要熟悉java.net.*,Android.net.*這兩個包的內容,詳細的類與方法的說明,請參考SDK。
下面是一個通過地區名稱查詢該地區的天氣預報,以POST發送的方式發送請求到webservicex.net站點,訪問WebService.webservicex.net站點上提供查詢天氣預報的服務。
代碼如下:
package com.android.weather;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
public class MyAndroidWeatherActivity extends Activity {
//定義需要獲取的內容來源地址
private static final String SERVER_URL =
"http://www.webservicex.net/WeatherForecast.asmx/GetWeatherByPlaceName";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HttpPost request = new HttpPost(SERVER_URL); //根據內容來源地址創建一個Http請求
// 添加一個變量
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 設置一個地區名稱
params.add(new BasicNameValuePair("PlaceName", "NewYork")); //添加必須的參數
try {
//設置參數的編碼
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
//發送請求並獲取反饋
HttpResponse httpResponse = new DefaultHttpClient().execute(request);
// 解析返回的內容
if(httpResponse.getStatusLine().getStatusCode() != 404){
String result = EntityUtils.toString(httpResponse.getEntity());
System.out.println(result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
別忘記了在配置文件中設置訪問網絡權限:
<uses-permission android:name="android.permission.INTERNET" />