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
留言列表

