2011-04-21 02 04 20.png  

**************************

2012.08.13版主回覆:

底下好多留言都詢問,奇怪?怎麼模擬器上都出現文字
然後網頁上沒出現?

不要再相信沒有事實根據的說法了 (大誤
不要再說沒有小弟不才,沒有爬文 

請移步至新版:

http://j796160836.pixnet.net/blog/post/30577968

個人還是建議從本篇看起,概念比較清楚

**************************

 

 最近常常被問到這些問題

Android要怎麼接MySQL資料庫呀? MySQL在網路上

Android怎麼接上雲端的資料庫?

Android怎麼傳送表單內容?

 

這些答案都在這裡

網路上的資料庫,不太容易,也不建議直接與資料庫做溝通

因為涉及到資訊安全的東西

 

 

可以用網頁來做中間的介面,讓二者產生關聯

做類似WebServices的東西
(雖然不是真正的WebServices,但其角色是類似的)

 

--------------------------------------------------------------------

伺服器端

你可以簡單寫個印字串的程式,如果收到POST的封包

就印出其內容

如果是PHP可能這樣寫

<?php

        //宣告utf-8的編碼

        header("Content-Type:text/html; charset=utf-8");

        $data=$_POST['data'];

        echo "data=".$data;

?>

把寫好程式,取名httpPostTest.php

把他擺到htdoc底下 (windows)

或是/var/www/ (ubuntu)

或是/var/www/html (Fedora, Cent OS)

用ASP可能這樣寫


<%@ LANGUAGE=VBScript CodePage=950%>
<%
data=request("data")
response.write "data="&data
%>

不管如何,請照你的伺服器語言撰寫

 

--------------------------------------------------------------------

Android手機端

 

可以用範例程式碼來解決問題

這些範例仿間找的到

因為過於複雜,所以我又重新整理了其範例給大家看

 

關鍵程式碼不到5行,但重點是在於你對Android的UI介面認識與否

和動態網頁的語言的熟練度

 

 

--------------------------------------------------------------------

照慣例,文字要放在string.xml裡

/res/values/string.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="app_name">httpPostTest</string>

    <string name="help_txt">請輸入文字以便使用POST傳送:</string>

    <string name="txt_message_hint">請輸入文字</string>

    <string name="send">送出</string>

</resources>

--------------------------------------------------------------------

看一下Layout檔

/res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<TextView 

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:text="@string/help_txt"

    />

    <EditText

    android:id="@+id/txt_message"

    android:hint="@string/txt_message_hint"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

   />

   <Button

   android:id="@+id/send_btn"

   android:text="@string/send"

   android:layout_width="fill_parent"

   android:layout_height="wrap_content"

   />

</LinearLayout>

 

這裡沒甚麼特別,就是一個EditText來讓使用者能打入資料

然候一個按鈕讓系統傳送封包到寫死的網址路徑

 

--------------------------------------------------------------------

程式碼要上了

main.java

 

package com.J_Test.httpPostTest;

 

/*

 * ====httpPostTest範例====

 * 1. 請先確認Apache有沒有正確執行

 * 2. 放入以下PHP代碼到htdoc資料夾中(或是/var/www/)等路徑

 *

 

 <?php

 //宣告utf-8的編碼

 header("Content-Type:text/html; charset=utf-8");

 $data=$_POST['data'];

 echo "data=".$data;

 ?>

 

 *

 * 3. 修改uriAPIIP和檔案名稱為正確 (請用電腦對外之IP)

 * (不可用127.0.0.1因為Android手機上也有本機位址)

 *

 */

 

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

 

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.client.ClientProtocolException;

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;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.Toast;

 

publicclass main extends Activity implements OnClickListener

{

    private EditText txtMessage;

    private Button sendBtn;

    private String uriAPI = "http://192.168.1.3/httpPostTest.php";

 

    @Override

    publicvoid onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

 

        txtMessage = (EditText) findViewById(R.id.txt_message);

        sendBtn = (Button) findViewById(R.id.send_btn);

 

        if (sendBtn != null)

        {

            sendBtn.setOnClickListener(this);

        }


    }

 

    @Override

    publicvoid onClick(View v)

    {

        if (v == sendBtn)

        {

            String msg = null;

            if (txtMessage != null)

            {

                msg = txtMessage.getEditableText().toString();

                String result = sendPostDataToInternet(msg);

 

                // 印出網路回傳的文字

                if (result != null)

                    Toast.makeText(this, result, Toast.LENGTH_LONG).show();

            }

        }

    }

 

    private String sendPostDataToInternet(String strTxt)

    {

        /* 建立HTTP Post連線 */

        HttpPost httpRequest = new HttpPost(uriAPI);

        /*

         * Post運作傳送變數必須用NameValuePair[]陣列儲存

         */

        List<NameValuePair> params = new ArrayList<NameValuePair>();

        params.add(new BasicNameValuePair("data", strTxt));

        try

        {

            /* 發出HTTP request */

            httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

            /* 取得HTTP response */

            HttpResponse httpResponse = new DefaultHttpClient()

                    .execute(httpRequest);

            /* 若狀態碼為200 ok */

            if (httpResponse.getStatusLine().getStatusCode() == 200)

            {

                /* 取出回應字串 */

                String strResult = EntityUtils.toString(httpResponse

                        .getEntity());

 

                // 回傳回應字串

                return strResult;

            }

 

        } catch (ClientProtocolException e)

        {

            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)

                    .show();

            e.printStackTrace();

        } catch (IOException e)

        {

            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)

                    .show();

            e.printStackTrace();

        } catch (Exception e)

        {

            Toast.makeText(this, e.getMessage().toString(), Toast.LENGTH_SHORT)

                    .show();

            e.printStackTrace();

        }

        returnnull;

    }

 

}

 

 

--------------------------------------------------------------------

最後是AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="com.J_Test.httpPostTest"

      android:versionCode="1"

      android:versionName="1.0">

    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".main"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

    <!-- 這裡加入可以存取網路的權限 -->

    <uses-permission android:name="android.permission.INTERNET" />

</manifest>

 

這裡很重要也很容易疏忽

除了Activity要在這裡註冊外

能對外上網的權限也在這裡註冊

如果遇到

WARN/System.err(503): java.net.SocketException: Permission denied

就該發現權限少了這一項

<uses-permission android:name="android.permission.INTERNET" />

另一個權限也常用,但仿間書常常會遺漏

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

就是能夠存取手機記憶卡的權限

 

 

--------------------------------------------------------------------

這樣有看懂嗎?

 

主要重點在這裡

  /* 建立HTTP Post連線 */

  HttpPost httpRequest = new HttpPost(uriAPI);

這個HttpPost是主要的Class名,這裡要填入存取的網址

 

然後

 /*

  * Post運作傳送變數必須用NameValuePair[]陣列儲存

  */

  List<NameValuePair> params = new ArrayList<NameValuePair>();

  params.add(new BasicNameValuePair("data", strTxt));

 

使用系統指定的資料格式BasicNameValuePair

BasicNameValuePair在new的時候裡面為二個字串,一個是名稱,一個是值

這裡用"data"當名字,值就是剛剛讓使用者打的資料

 

  /* 發出HTTP request */

  httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

的  HTTP.UTF_8 可以指定編碼格式,不過要跟伺服器端相同(照我範例走的話是不用動)


--------------------------------------------------------------------

2011-04-21 02 18 45.png  

其實這個Android其實是跟以下網頁的功能是相同的

有些值你可以對照看看,相關對照的字詞都用顏色標明了

可以將它另存到httpPostTest.htm

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">


<head>
<meta http-equiv="Content-Language" content="zh-tw" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF_8" />
<title>httpPostTest</title>
<head></head>
<body>
請輸入文字以便使用POST傳送:<br />
<form method="POST" action="http://192.168.1.3/httpPostTest.php">
<input type="text" name="data" size="20" value="請輸入文字" /><br />
<input name="Submit1" type="submit" value="送出" /><br />
</form>
</body>
</html>

 

--------------------------------------------------------------------

延伸

其實網頁大多喜歡把很多功能做在一個檔裡,就是用一個隱藏值來判斷現在進行到那個階段

本例用op當階段的旗標

 

PHP版:

請輸入文字以便使用POST傳送:<br />
<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="text" name="data" size="20" value="請輸入文字" /><br />
<input type="hidden" name="op" value="showValue" />
<input name="Submit1" type="submit" value="送出" /><br />
</form>

 

ASP版:

 

請輸入文字以便使用POST傳送:<br />
<form method="POST" action="<%=Request.ServerVariables("PATH_INFO")%>">
<input type="text" name="data" size="20" value="請輸入文字" /><br />
<input type="hidden" name="op" value="showValue" />
<input name="Submit1" type="submit" value="送出" /><br />
</form>

--------------------------------------------------------------------

2011-04-21 02 05 40.png

   2011-04-21 02 17 35.png  

 

2011-04-21 02 25 29.png  

 

不過還是再三的提醒

範例程式碼很簡陋,指是要讓大家看懂其中的語法

真正寫程式使用的時候

 

要記得在伺服器判斷輸入的型別

更不要直接讓表單直接下SQL指令

 

怕被資料隱碼攻擊(SQL Injection)

 

這是很危險低~~~~

 

 

參考資料
Google Android SDK開發範例大全 佘志龍等人著
悅知文化

arrow
arrow
    全站熱搜

    Johnny 鋼鍊 發表在 痞客邦 留言(109) 人氣()