close

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

HttpGet  

  • Http Post

HttpPost 

 

參考資料:Tony Blog清新下午茶hil2000專欄,,

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 fiend1120 的頭像
    fiend1120

    嵌入式的復健筆記

    fiend1120 發表在 痞客邦 留言(3) 人氣()