**************************
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
<?xmlversion="1.0"_encoding="utf-8"_?>
<resources>
<stringname="app_name">httpPostTest</string>
<stringname="help_txt">請輸入文字以便使用POST傳送:</string>
<stringname="txt_message_hint">請輸入文字</string>
<stringname="send">送出</string>
</resources>
看一下Layout檔
/res/layout/main.xml
<?xmlversion="1.0"_encoding="utf-8"_?>
<LinearLayoutxmlns: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
packagecom.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手機上也有本機位址)
*
*/
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.List;
importorg.apache.http.HttpResponse;
importorg.apache.http.NameValuePair;
importorg.apache.http.client.ClientProtocolException;
importorg.apache.http.client.entity.UrlEncodedFormEntity;
importorg.apache.http.client.methods.HttpPost;
importorg.apache.http.impl.client.DefaultHttpClient;
importorg.apache.http.message.BasicNameValuePair;
importorg.apache.http.protocol.HTTP;
importorg.apache.http.util.EntityUtils;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Toast;
publicclassmainextendsActivityimplementsOnClickListener
{
privateEditTexttxtMessage;
privateButtonsendBtn;
privateStringuriAPI="http://192.168.1.3/httpPostTest.php";
@Override
publicvoidonCreate(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
publicvoidonClick(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\(\);
}
}
}
privateString 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\);
/*若狀態碼為200ok*/
if(httpResponse.getStatusLine().getStatusCode() == 200)
{
/*取出回應字串*/
String strResult = EntityUtils._toString_\(httpResponse
.getEntity\(\)\);
//回傳回應字串
returnstrResult;
}
}**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
<?xmlversion="1.0"_encoding="utf-8"_?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.J_Test.httpPostTest"
android:versionCode="1"
android:versionName="1.0">
<uses-sdkandroid:minSdkVersion="8"/>
<applicationandroid:icon="@drawable/icon"_android:label="@string/app_name"_>
<activityandroid:name=".main"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<!--這裡加入可以存取網路的權限-->
<uses-permissionandroid:name="android.permission.INTERNET"/>
</manifest>
這裡很重要也很容易疏忽
除了Activity要在這裡註冊外
能對外上網的權限也在這裡註冊
如果遇到
WARN/System.err(503): java.net.SocketException: Permission denied
就該發現權限少了這一項
<uses-permissionandroid:name="android.permission.INTERNET"/>
另一個權限也常用,但仿間書常常會遺漏
<uses-permissionandroid: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)
這是很危險低~~~~