Android中提供了不少進行Server-Client 連線的方法,其中透過HTTP連線的方式有了相當健全的API可供使用,但基於安全考量,在Android SDK 3.0之後強制要求在Android中使用HTTP時不可以在主UI執行序中執行,必須在子執行序中運作。相關AIP可看官網解說(Developers)
本篇將針對HTTP Get 及HTTP Post 來撰寫,兩種方法將會分別寫在Service中,其中HTTP Post將會透過Handler的將Message丟給MainActivity,讓主UI執行序可以進行一些相對應的動作(例如:訊息顯示等),由於開發環境是在Ubuntu中,所以若還不會在Ubuntu中建置及設定Apache2及php的可以參考這篇『Ubuntu 安裝及設定 Apache 2 & PHP 5』。
首先,在開發Android App前先建立我們Server端的連線頁面。
- HTTP Get
我們直接使用行政院(Open Data)提供的資料來進行Http Get存取所需的Url。
- HTTP Post
先寫一個簡易的php檔來當Server端的接收端,此php檔在接收到"data"訊息後會將傳上來的資料再回傳回去,要注意的是此檔案要放在『 /var/www/html/ 』中,此目錄在安裝Apache2之後會自動產生,或者是看自己設定網頁存取的資料夾為哪個來作位置修改。
簡易的php檔如下,而檔名則隨各自喜愛去命名(name.php)。
<?php //Setting Utf-8 encoding header("Content-Type:text/html; charest=utf-8"); $data=$_POST['data']; echo"data=".$data; ?>
在開始講解HTTP Get 和 Post 的程式碼前有一個很重要的部份,要記得在App中的『AndroidManifest.xml』加入網路存取的授權,否則無法網路功能則無法正常存取。
- Get 使用步驟
1. 建立HTTP Client物件:
HttpClient httpClient = new DefaultHttpClient();
2. 建立HTTP Get物件並給予要連線的Url:
HttpGet get = new HttpGet(Url);
3. 使用client進行get後,Server會回傳HttpResponse:
HttpResponse response = httpClient.execute(get);
4. 取得回傳的資料實體:
HttpEntity resEntity = response.getEntity();
5. 將資料轉為字串使用:
String result = EntityUtils.toString(resEntity);
- Post 使用步驟
1. 建立HTTP Client物件:
HttpClient httpClient = new DefaultHttpClient();
2. 建立HTTP Post物件並給予要連線的UrL:
HttpPost httpRequest = new HttpPost(postUrl);
3. 要透過Post傳到Server的參數(params):
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("data", strTxt));
4. 使用Post來傳送參數給Server(記得設定為UTF8格式):
httpPost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
5. 取得Server回傳的HttpResponse:
HttpResponse httpResponse = new DefaultHttpClient().execute(httpPost);
6. 取得回傳的資料實體(需自行轉UTF8格式):
String strResult = EntityUtils.toString(httpResponse.getEntity(),HTTP.UTF_8);
特別注意的是,若是在Server端回傳的資料不是UTF8格式的話,我們接收資料後要自行轉UTF8格式,否則該資料在顯示時會是亂碼。
(以上資料來自Tony Blog,Post後面部份有小修改,請依個人習慣參考使用)
接下來為Android App專案部份:
- AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="terence.http_post_get" > <!-- 加入網路使用權限 --> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".Http_Get" android:enabled="true" android:exported="true" > </service> <service android:name=".Http_Post" android:enabled="true" android:exported="true" > </service> </application> </manifest>
註:記得在App中的『AndroidManifest.xml』加入網路存取的授權,否則無法網路功能則無法正常存取。
- MainActivity.java
package terence.http_post_get; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity implements View.OnClickListener{ //設定HTTP Get & Post要連線的Url private String postUrl = "http://192.168.2.100/abc.php"; private String getUrl = "http://opendata.epa.gov.tw/ws/Data/AQX/?$format=xml"; private EditText txtMessage; private Button postBtn; private Button getBtn; private String msg = null; //存放要Post的訊息 private String result; //存放Post回傳值 Http_Post HP; Http_Get HG; static Handler handler; //宣告成static讓service可以直接使用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); HG = new Http_Get(); HP = new Http_Post(); txtMessage = (EditText) findViewById(R.id.txt_message); postBtn = (Button) findViewById(R.id.http_post_btn); getBtn = (Button) findViewById(R.id.http_get_btn); //讓多個Button共用一個Listener,在Listener中再去設定各按鈕要做的事 postBtn.setOnClickListener(this); getBtn.setOnClickListener(this); //接收service傳出Post的到的回傳訊息,並透過Toast顯示出來 handler = new Handler(){ public void handleMessage(Message msg){ switch (msg.what){ case 123: String ss = (String)msg.obj; Toast.makeText(MainActivity.this, ss,Toast.LENGTH_LONG).show(); break; } } }; } //依照按下的按鈕去做相對應的任務 public void onClick(View v){ switch (v.getId()){ case R.id.http_get_btn: HG.Get(getUrl); break; case R.id.http_post_btn: if (txtMessage != null) { //取得EditText的內容 msg = txtMessage.getEditableText().toString(); HP.Post(msg,postUrl); } break; } } }
- HttpGet.java
package terence.http_post_get; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import java.io.IOException; public class Http_Get extends Service { private String getUrl; public void Get(String url){ this.getUrl = url; new Thread(new Runnable() { @Override public void run() { //建立HttpClient物件 HttpClient httpClient = new DefaultHttpClient(); //建立Http Get,並給予要連線的Url HttpGet get = new HttpGet(getUrl); //透過Get跟Http Server連線並取回傳值,並將傳值透過Log顯示出來 try { HttpResponse response = httpClient.execute(get); HttpEntity resEntity = response.getEntity(); Log.d("Response of GET request", EntityUtils.toString(resEntity)); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } }
- HttpPost.java
package terence.http_post_get; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.Message; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; 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 java.io.IOException; import java.util.ArrayList; import java.util.List; public class Http_Post extends Service { String strTxt=null; String postUrl=null; String strResult=null; public void Post(String StrTxt, final String PostUrl){ this.strTxt = StrTxt; this.postUrl = PostUrl; new Thread(new Runnable() { @Override public void run() { //建立HttpClient物件 HttpClient httpClient = new DefaultHttpClient(); //建立一個Post物件,並給予要連線的Url HttpPost httpPost = new HttpPost(postUrl); //建立一個ArrayList且需是NameValuePair,此ArrayList是用來傳送給Http server端的訊息 List params = new ArrayList(); params.add(new BasicNameValuePair("data", strTxt)); try{ //發送Http Request,內容為params,且為UTF8格式 httpPost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); //接收Http Server的回應 HttpResponse httpResponse = new DefaultHttpClient().execute(httpPost); //判斷Http Server是否回傳OK(200) if(httpResponse.getStatusLine().getStatusCode() == 200){ //將Post回傳的值轉為String,將轉回來的值轉為UTF8,否則若是中文會亂碼 strResult = EntityUtils.toString(httpResponse.getEntity(),HTTP.UTF_8); Message msg = Message.obtain(); //設定Message的內容 msg.what = 123; msg.obj=strResult; //使用MainActivity的static handler來丟Message MainActivity.handler.sendMessage(msg); } }catch (IOException e) { // Log exception e.printStackTrace(); } }}).start(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } }
- main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/help_txt"/> <EditText android:id="@+id/txt_message" android:text="@string/txt_message_hint" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/http_get_btn" android:text="@string/http_get" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/http_post_btn" android:text="@string/http_post" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>
- strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">HTTP_POST_GET</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="help_txt">請輸入要Post的內容</string> <string name="txt_message_hint">請輸入文字</string> <string name="http_get">Http Get</string> <string name="http_post">Http Post</string> </resources>
程式執行結果
- Http Get
- Http Post
留言列表