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. 修改 uriAPI 的 IP 和檔案名稱為正確 ( 請用電腦對外之 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;
public class main extends Activity implements OnClickListener
{
private EditText txtMessage ;
private Button sendBtn ;
private String uriAPI = "http://192.168.1.3/httpPostTest.php " ;
@Override
public void 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
public void 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();
}
return null ;
}
}
最後是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 可以指定編碼格式,不過要跟伺服器端相同(照我範例走的話是不用動)
其實這個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>
不過還是再三的提醒
範例程式碼很簡陋,指是要讓大家看懂其中的語法
真正寫程式使用的時候
要記得在伺服器判斷輸入的型別
更不要直接讓表單直接下SQL指令
怕被資料隱碼攻擊(SQL Injection)
這是很危險低~~~~
參考資料 Google Android SDK開發範例大全 佘志龍等人著 悅知文化