你我都是Android專家

Screen Shot 2012-04-06 at 下午4.47.14     

 

這是由之前寫的這一篇

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

所延伸出來的

 

眼尖的網友已經發現,之前放上的程式碼範例已經不能Run了
把專案使用的Android版本放在2.3.3以下就可以正確執行
而把它升到4.0就會出錯

有人發現為什麼了嗎?

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

打開LogCat就可以清楚的看到

Screen Shot 2012-04-06 at 上午12.13.33  

Android 4.0 (ICS)在網路的部份多了一個新的Exception

叫做android.os.NetworkOnMainThreadException
意思很白話的就是:網路的活動跑在主要執行緒上了啦!

ICS很貼心的告訴你,這樣子你的APP可能會因為等待回應太久(超過5秒)
而會被系統強制關閉(收到ANR)

 

(備註:之前是為了示例方便,所以沒有照多執行緒的寫法撰寫,在這裡當然也就不能執行啦
Android光這點就還蠻嚴謹的)

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

OK,瞭解為何出錯的原因
也剛好在這裡,帶大家看看多執行緒要怎麼改吧

專案的Layout版面等定義上和之前這篇一模一樣
有特別修改的地方會特別標出

 

package com.J_Test.httpPostTest;

import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
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.os.Handler;
import android.os.Message;
import android.util.Log;
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/httptest/httpPostTest.php";

   /** 「要更新版面」的訊息代碼 */

   protected static final int REFRESH_DATA = 0x00000001;

 

   /** 建立UI Thread使用的Handler,來接收其他Thread來的訊息 */

   Handler mHandler = new Handler()

   {

      @Override

      public void handleMessage(Message msg)

      {

          switch (msg.what)

          {

          // 顯示網路上抓取的資料

          case REFRESH_DATA:

             String result = null;

             if (msg.obj instanceof String)

                result = (String) msg.obj;

             if (result != null)

                // 印出網路回傳的文字

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

             break;

          }

      }

   };

 

   @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)

      {

          if (txtMessage != null)

          {

             // 擷取文字框上的文字

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

             // 動一個Thread(執行緒),將要傳送的資料放進Runnable中,讓Thread執行

             Thread t = new Thread(new sendPostRunnable(msg));

             t.start();

          }

      }

   }

 

   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 (Exception e)

      {

          e.printStackTrace();

      }

      return null;

   }

 

   class sendPostRunnable implements Runnable

   {

      String strTxt = null;

 

      // 建構子,設定要傳的字串

      public sendPostRunnable(String strTxt)

      {

         this.strTxt = strTxt;

      }

 

      @Override

      public void run()

      {

          String result = sendPostDataToInternet(strTxt);

          mHandler.obtainMessage(REFRESH_DATA, result).sendToTarget();

      }

   }

}

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

特別注意這裡

  Handler mHandler = new Handler()

   {

      @Override

      public void handleMessage(Message msg)

      {

          switch (msg.what)

          {

          case REFRESH_DATA:

             // ............(相關程式碼)

             break;

          }

      }

   }; 

這是Android對於多執行緒的寫法

這裡做了一個Handler來接收訊息

因為當你建立執行緒,資料處理與主執行緒無關

當然,新建出來的執行緒,是碰不到UI介面的 (會跳Exception)

所以才會如此設計

 

訊息,說穿了就是一個int,可以自行定義訊息的內容

 

/** 「要更新版面」的訊息代碼 */

   protected static final intREFRESH_DATA = 0x00000001;

 

類別一開始就定義這個常數

然後在

public void handleMessage(Message msg){

}

的地方就可以使用 msg.what 存取到訊息的內容

這裡用Switch - case的方式撰寫

 

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

 

發訊息的函式如下

mHandler.obtainMessage(REFRESH_DATA, result).sendToTarget(); 

發訊息的相關方法呼叫可參考官方說明

http://developer.android.com/reference/android/os/Handler.html

 

文件上可看到,obtainMessage有這幾個多載方法

obtainMessage(int what);

obtainMessage(int what, int arg1, int arg2);

obtainMessage(int what, int arg1, int arg2, Object obj);

obtainMessage(int what, Object obj);

常用的有第一、第二、第四種

 

尤其是第四種,這訊息可以傳入Object

所以自由度很高

 

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

最後,是建立執行緒

 

// 動一個Thread(執行緒),將要傳送的資料放進Runnable中,讓Thread執行

Thread t = new Thread(new sendPostRunnable(msg));

t.start();

 

這裡是用一個臨時的執行緒的方式

在建構子之中傳入一個Runnable來達成

執行緒的部分也可以用匿名class的方式撰寫

 

// 擷取文字框上的文字

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

new Thread()

{

       public void run()

       {

            String result = sendPostDataToInternet(msg);

            mHandler.obtainMessage(REFRESH_DATA, result).sendToTarget();

       }

}.start();

 

但這樣的方式要注意,內部類別(Inner class)當中

只能存取外部的常數(這是Java的規定)

final String msg;

所以為何String前面要加上final了

 

詳細多執行緒可參考

[Android] 多執行緒-Handler和Thread的關係

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

[Android] 關於Thread執行緒

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

 

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

很多網友都問到,

為何我在Android傳送出來的資料
在瀏覽器中怎麼都看不見

因為資料到伺服器上沒有將它存下來
在這裡可以做一些修改

我們把傳到伺服器上的資料
用MySQL存下來,然後再顯示最後輸入的資料

 

以PHP為例,我們在phpmyadmin上
建立一個資料庫,名稱叫 httpPostTest

實際設定如圖:

Screen Shot 2012-04-06 at 下午2.45.22  

這是其對應的SQL

CREATE TABLE IF NOT EXISTS `weblog` (
`log_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
`data` varchar(255) NOT NULL COMMENT '傳入的資料',
`post_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '發佈時間',
PRIMARY KEY (`log_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='訊息記錄' AUTO_INCREMENT=1 ;

 

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

 

之前使用的 httpPostTest.php 我們做一些修改

<?php

// 資料庫相關資料
$database_dblink = "httpPostTest";
$username_dblink = "root";
$password_dblink = "YOUR_ROOT_PASSWORD";


// 建立資料庫連線
$dblink = mysql_pconnect("localhost", $username_dblink, $password_dblink) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_query("SET NAMES utf8",$dblink);
mysql_query("SET CHARACTER_SET_CLIENT=utf8",$dblink);
mysql_query("SET CHARACTER_SET_RESULTS=utf8",$dblink);
mysql_select_db($database_dblink, $dblink);


// 宣告utf-8的編碼
header("Content-Type:text/html; charset=utf-8");
// 接收POST/GET的資料
$data=@$_REQUEST['data'];


// 如果有資料
if (strcmp(trim($data), "")!=0)
{
      // 將資料輸入進資料庫
      $insertSQL = sprintf("INSERT INTO `weblog` (`data`) VALUES ('%s');", $data);
      mysql_query($insertSQL, $dblink) or die(mysql_error());
}

// 從資料庫撈出來最後一筆資料
$query_rs = "SELECT * FROM `weblog` order by log_id desc limit 0,1";
$rs = mysql_query($query_rs, $dblink) or die(mysql_error());

$row = mysql_fetch_assoc($rs);
echo "data=".$row['data']."\n"."time=".$row['post_time'];

?>

這樣在瀏覽器就會暫存最後一筆的資料了

如果有學過PHP相關的語法

以上的程式碼應該不難才是

 

 

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

最後還是提醒一下,Android還沒有跑出來的朋友
若是在Logcat看到類似Permission denied的字眼

代表你忘記了AndroidManifest.xml的這句摟,詳細看之前寫的這篇

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

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

 

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

關於source code的部份,我已經放上gitHub了

https://github.com/j796160836/httpPostTest

創作者介紹

清新下午茶

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


留言列表 (55)

發表留言
  • Syuan
  • 您好:

    想請問一下,我的

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

    這一行 Main都會一直出現錯誤
    我有把它改成只有this 還是會出現錯誤
    請問這有可能是什麼原因造成的?
  • 改成你「目前」的Activity的名字應該就可以了
    因為我的Activity叫做Main所以是Main.this
    那是Context的觀念

    Johnny 鋼鍊 於 2012/05/30 22:51 回覆

  • 儀
  • 受教了,想說為什麼都會一直當掉,原來是占到主要的執行緒= =...

    順便回樓上的....我想應該是你把toast寫在 click裡面了吧....用下面的函式吧,只要呼叫就可以了,

    public void Toast(String TxtView){ //自定Toast函式
    ImageView icon = new ImageView(你的ACTIVITY名稱.this);
    TextView ToastTextView =new TextView(你的ACTIVITY名稱.this);
    ToastTextView.setText(TxtView);
    LinearLayout lay =new LinearLayout(你的ACTIVITY名稱.this);
    Linkify.addLinks(ToastTextView, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS);
    Toast toast =Toast.makeText(this, ToastTextView.getText(), Toast.LENGTH_LONG);
    View textView=toast.getView();
    lay.setOrientation(LinearLayout.HORIZONTAL);
    icon.setImageResource(R.drawable.icon);//設定圖片
    lay.addView(icon);
    lay.addView(textView);
    toast.setView(lay);
    toast.show();
    }
  • 給你一個讚!
    ------------
    自己用程式碼建LinearLayout的那段
    可以用LayoutInflater讀取現有的XML唷

    程式碼看起來更清爽

    Johnny 鋼鍊 於 2012/05/30 22:54 回覆

  • ryan
  • 想請問如果以這個方法去作, 出現server錯誤的話該怎麼讓程式可以直接進行下一步, 現在在模擬伺服器錯誤的情況, 往往會發生程式直接exception...
  • 錯誤看是哪種的錯誤
    Android本身網路連不上的Exception
    還是說連線正常,例如輸入錯誤的資料,你自己寫的回傳錯誤...等等
    前者要用try-catch把他抓起來然後再處理
    看是要跳訊息框...還是做其他的動作
    後者自己寫的錯誤,就自行把資料處理起來,跳訊息框...等
    如果連線沒回應,Loading框一直轉轉轉,會讓使用者等太久的話
    可以把timeout時間調短些

    Johnny 鋼鍊 於 2012/09/25 15:50 回覆

  • ppaa
  • 請問如果有兩個EditText要如何處理
  • 若是Android要上傳二個以上的POST欄位可以找到
    /*
    * Post運作傳送變數必須用NameValuePair[]陣列儲存
    */
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("data", strTxt));
    的這裡自行增加
    params.add(new BasicNameValuePair("data2", "hello"));
    params.add(new BasicNameValuePair("data3", "world"));
    以此類推

    伺服器的部分就一樣跟著增加(PHP為例)
    echo "data2="$_POST['data2']; //結果: data2=hello
    echo "data3="$_POST['data3']; //結果: data3=world
    接下來就是湊SQL的問題了,看是要select還是insert...等等
    這段就跟一般寫PHP&MySQL...等動態網頁差不多了
    可以寫一個簡單HTML表單做測試接口

    Johnny 鋼鍊 於 2012/09/25 15:44 回覆

  • 訪客
  • if(result.equals("y"))
    {
    Toast.makeText(httpPostTest.this, "成功", Toast.LENGTH_SHORT).show();
    }
    else
    {
    Toast.makeText(httpPostTest.this, "失敗", Toast.LENGTH_SHORT).show();
    }

    為什麼這樣判斷總是失敗?
  • 網路連線錯誤就沒話說了
    你看到的y,很有可能你看到的是瀏覽器的y
    而不是檢視原始碼裡的
    所以還有一些無謂的HTML標籤干擾你

    可以去除它或是用result.contains("y")
    字串中「含有」y

    Johnny 鋼鍊 於 2012/09/25 15:53 回覆

  • 訪客
  • 補充一下是使用php
  • 訪客
  • 問題已解決,看了前一篇的回覆 原來是PHP編碼問題 謝謝站長
  • 相關參數建議使用英文會比較穩定唷 :D

    Johnny 鋼鍊 於 2012/08/13 14:32 回覆

  • sg6481elmf
  • 感謝分享,
    請問一下當用模擬器執行時php檔要放哪裡呢?
    還有模擬器需要額外設置嗎?
  • 放在apache類似htdocs裡喔,可以用appserv、xampp...等整合性環境

    Johnny 鋼鍊 於 2012/09/25 15:10 回覆

  • 訪客
  • 可以情你把原始檔貼給我嗎~一值有問題
  • 剛好路過的人
  • 請問站長~
    如果說 android 要抓取遠端資料庫裡面的資料
    可以建議一下有什麼樣比較容易實行的做法嘛?!
  • JSP疑問者
  • 你好!
    請問一下要如何將你所寫的PHP改為JSP的模式呢?!

    是否有提供JSP模式的範例?!
  • JSP的範例近期會推出

    Johnny 鋼鍊 於 2012/09/25 15:23 回覆

  • 想學習的人
  • 你好~
    我練習了一下都沒錯誤
    但是模擬器執行時卻不給執行
    可以解答一下嗎?
    謝謝
  • 自行debug一下吧

    Johnny 鋼鍊 於 2012/09/25 15:53 回覆

  • 張國源
  • 請問遺下~我現在做的話有兩個填寫空格~
    要將他POST的MYSQL裡面放在同一個列表
    要怎麼做?
    自己在測試時~都會亂跳

  • 若是Android要上傳二個以上的POST欄位可以找到
    /*
    * Post運作傳送變數必須用NameValuePair[]陣列儲存
    */
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("data", strTxt));
    的這裡自行增加
    params.add(new BasicNameValuePair("data2", "hello"));
    params.add(new BasicNameValuePair("data3", "world"));
    以此類推

    伺服器的部分就一樣跟著增加(PHP為例)
    echo "data2="$_POST['data2']; //結果: data2=hello
    echo "data3="$_POST['data3']; //結果: data3=world
    接下來就是湊SQL的問題了,看是要select還是insert...等等
    這段就跟一般寫PHP&MySQL...等動態網頁差不多了
    可以寫一個簡單HTML表單做測試接口

    Johnny 鋼鍊 於 2012/09/25 15:35 回覆

  • Roger
  • 您好:
    我有問題跟五樓相同,請問要如何有效判斷回傳值好根據回傳值做後續動作...
    感謝回答
  • Android針對回傳值的處理,方法很多
    比較有系統的做法可以用JSON、XML...等等
    用分隔字元組成的字串也可以
    就基礎原理來說就是這些而已

    另外,Android還會有類似#3樓所說的伺服器掛掉連不上等等的情況
    先把錯誤給try-catch起來,再來
    可以用剛剛學到的Thread做迴圈等待若干時間再重試
    或是很直接跳出網路錯誤訊息,請使用者手動點擊重試按鈕
    寫法很多種

    Johnny 鋼鍊 於 2012/09/25 15:44 回覆

  • Roger
  • 非常感謝,結果我的作法跟你回答五樓的類似,
    就是尋找回傳字串中有無我想要的字傳集合。
  • result.contains("y")不很建議用,因為太模糊了
    放在適當的地方就很好用

    Johnny 鋼鍊 於 2012/09/28 16:17 回覆

  • 阿提
  • 感謝教學,小弟想請問兩個問題~
    1.您舊文所使用的上傳方式,在Android 4.X手機一律沒辦法使用嗎? 還是只要API Level在2.3.3的APP,在任何手機(當然要高於2.3.3)都能夠跑得動?

    2.現在我知道要怎麼上傳到server端了,請問要怎麼從server端拿資料呢??(小弟我在server端是用PHP+MySQL)
  • API Level在2.3.3的APP,在任何手機(當然要高於2.3.3)都能夠跑得動?
    我個人是用2.2開專案的,當然complie檢查是用2.2的方式檢查
    有些人想使用新功能所以會用4.0開專案,4.0檢查比2.2等更嚴謹
    理論上,你的想法沒有錯

    2. 請問要怎麼從server端拿資料呢??
    方法一樣,想想剛剛的運作方式,很快就有答案了 ^_^

    Johnny 鋼鍊 於 2012/09/30 23:41 回覆

  • 阿提
  • 不好意思,小弟我資質稍微駑鈍,有些地方有點想不通:

    1.您說從MySQL抓資料庫的方式是相同的,是指同樣開一個ArrayList,然後傳SQL給中介php,接著再把變數透過同一個ArrayList轉回來嗎?

    2.指定到網路資料庫的時候,因為php是有url 的,所以可以直接指定,但是php這端如果要傳輸資料到手機,要如何取得定址並傳輸?

    新手上路...有諸多菜味,請多海涵><
  • 不建議直接從Android上直接做SQL然後傳給中介php
    把手機想成瀏覽器的表單,個別從EditText拿到值,傳給php然後做事

    例: 會員資料要修改姓名&年齡
    如果你用post方式傳一個變數sql
    值為update member set name='Amy', age='18' where id=2;
    只要我抓到你怎麼傳的,同樣的方式我就可以直接下
    drop table member

    你應該傳三個變數
    變數name 值 Amy
    變數age 值 18
    變數action 值 update (如果你還有其他動作的話,就可以用這個變數區別之)
    然後在php那邊收到這三個變數
    $_POST['name'] $_POST['age'] $_POST['update']

    然後判斷是否為數字...不合法字元等等
    確定輸入的值都是正常的值
    再拼湊成sql給mysql

    2. http是雙向一來一往,傳輸資料完畢就會斷線
    當你在輸入網址的時候,伺服器也沒有問你的地址就把網頁傳給你了
    然後你就看到網頁了

    你說傳輸方式大概分成二種
    Polling (間隔詢問伺服器有沒有資料)
    Push (伺服器直接傳資料給手機)
    新版文章是採Polling方式,也是大多數人會使用的方式

    Push文獻說會對伺服器上負擔較重
    大概是這樣

    Johnny 鋼鍊 於 2012/10/05 09:04 回覆

  • 陳英中
  • 您好,想請問您一下
    根據您的範例下去改,
    不過我的按鈕都要按很多次,網頁才會回應我字串,
    我連遠端的IP和localhost都是一樣情形
  • 鄭耿宇
  • 您好,請問一下喔,現在eclipse版本更新後,建立Activity他會強制固定為MainActivity,每次用到AndroidManifest那邊後就會出項錯誤,但是又沒有說錯誤在哪,是否要改正其他地方??(原本大大預設是main)
    感覺新版的很不順暢,一直有莫名問題跑出來....
    還有,之前在做的時後常常卡在"模擬器意外終止"的問題,到現在我還不知道為何會這樣當時我是自己創一個Activity名稱,最後是改回大大預設的main才解決....
  • 大概是Activity沒有正確註冊

    Johnny 鋼鍊 於 2012/10/26 11:33 回覆

  • water
  • 請問要如何從Andoid手機端新增資料透過PHP至MySQL儲存?
    之後Android手機端再從MySQL抓取資料顯示在手機上
  • 嘎嘎
  • 請問我資料庫的編碼改utf8_unicode_ci
    eclipse的編碼也改成UTF8了
    為什麼讀出來的中文字還是亂碼呢
  • 你是不是之前還沒做設定的之前,就已經存了亂碼
    這時候你調回正確設定值時
    那些亂碼就還是會亂碼,他不會幫你轉碼

    Johnny 鋼鍊 於 2013/08/14 22:44 回覆

  • 顏振翔
  • 會出現吐司,錯誤
    <br/>
    <b>Fatal error</b>:Call to undefined function mysql_pconnect()
    <b>路徑</b>on line<b>10</b><br/>
  • 打錯字或是php_mysql沒有正確設定

    Johnny 鋼鍊 於 2012/12/23 18:38 回覆

  • 訪客
  • 可以給我只有post 到http 上面的程式碼(可運行)嗎??
  • 亞當斯
  • 請問參考您的範例執行時會出現下面的runtime error訊息..不知版大是否有遇過類似情形或有什麼地方出錯了..煩請指點~多謝.
    -------------------------------------------------------------------------------------
    FATAL EXCEPTION: Thread-10
    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:121)
    at android.widget.Toast.<init>(Toast.java:68)
    at android.widget.Toast.makeText(Toast.java:231)
    at com.ntic.niceshot.register.sendPostDataToInternet(register.java:94)
    at com.ntic.niceshot.register.access$1(register.java:61)
    at com.ntic.niceshot.register$sendPostRunnable.run(register.java:145)
    at java.lang.Thread.run(Thread.java:1019)
  • 你在抓取網路的Thread裡 呼叫UI相關的東西(因為他在Main thread,故資料不能互通)
    在這個例子,我想你可能是在
    if (httpResponse.getStatusLine().getStatusCode() != 200)
    {
    }

    抓到回應字串之後直接就放Toast

    Johnny 鋼鍊 於 2012/12/23 18:42 回覆

  • 阿期
  • 您好:
    請問一下
    我的
    setContentView(R.layout.main);
    這行一直出錯 用程式上面兩個解決方法也無法排除
    游標指上去寫
    main cannot be resolved or is not a field
    請問這個可能是什麼原因?
  • 只要是R出問題,就去查layout檔或是string檔
    或是把專案clean掉重新build

    Johnny 鋼鍊 於 2012/12/23 18:37 回覆

  • 訪客
  • 請問~如果我連線卻找不到網頁(404)然後想TOAST出訊息該怎麼寫?
    我將程式碼改成以下
    if (httpResponse.getStatusLine().getStatusCode() != 200)
    {
    //程式內容
    }
    卻不能用直接錯誤耶?
  • 寫在try-catch的catch裡面吧!有時候抓不到網頁也有可能是網路錯誤(EX: 網路不通)

    Johnny 鋼鍊 於 2012/12/23 18:36 回覆

  • 訪客
  • 您好,我是#26的訪客
    關於網路不通這部分我另外寫了一個code來確認已連上網路後
    才做資料的傳送
    你說的catch是指ClientProtocolException嗎?
  • 網路連不上的話,例如
    java.net.ConnectException: <你的IP> - Network is unreachable
    dns找不到紀錄的話
    java.net.UnknownHostException: <網路位置>

    如果是我的話,直接用比較大的IOException包起來就可以了

    Johnny 鋼鍊 於 2012/12/29 11:15 回覆

  • 悄悄話
  • 嘟嘴
  • 大大你好 我看了你的範例做了一個練習 但是我不太懂資料庫那個部分
    可以請問一下資料庫那個部分如何使用嗎??資量庫那部分是使用哪種軟體??
  • MySQL,如果你會其它套資料庫也可以試著修改程式碼

    Johnny 鋼鍊 於 2013/08/14 20:57 回覆

  • 訪客
  • 大大您好 我多新增一個EditTextView欄位 也多新增了params.add(new BasicNameValuePair 但PHP的部分我不知道從何下手

    我把PHP改成$insertSQL = sprintf("INSERT INTO `weblog` (`name` , `data` ) VALUES ('%s','%s');", $name, $data); 也只是兩個不同的值 同時傳到name data
    欄位 就像 123 123 456 456 這樣 怎麼樣才能變成 123 456 而不是傳兩次呢
  • 訪客
  • 感謝大大 看過大大上面的回答後 我成功了!!
  • :)

    Johnny 鋼鍊 於 2013/08/14 20:58 回覆

  • 兔兒
  • 大大您好,想請問您為何我資料寫入SQL後,有時後寫入的資料會在最後一筆(資料表欄位最上方)可以正常讀回資料,但有時候寫入的資料不一定會在最後一筆,導致我data傳回值可能會是之前寫入的?謝謝:)
  • 恭喜你,發現了一個Bug,可見你有認真在看:)
    是我寫錯了,應該要用mysql_insert_id()抓取當下新增的那筆id
    然後用SQL把內容抓出來

    Johnny 鋼鍊 於 2013/08/14 22:46 回覆

  • 兔兒
  • 大大您好,想再請問您一個問題,httpResponse.getStatusLine().getStatusCode() == 200 這句我改成httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK之後也可以跑(我是看別人的code有這樣寫過),原以為上一個問題的原因是這個,但後來試發現不是,但還是可以跑,想請問大大知道這兩個的差別嗎?謝謝:)
  • HttpStatus.SC_OK是一個常數,他的內容就是200
    來源:
    http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpStatus.html

    Johnny 鋼鍊 於 2013/08/14 22:39 回覆

  • 康德斯丁
  • 大大你好 測試你的程式我遇到一個問題
    那就是有關
    /* 發出HTTP request */
    httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
    /* 取得HTTP response */
    HttpResponse httpResponse = new DefaultHttpClient().execute(httpRequest);
    這兩段 我發現我錯誤的原因是因為new DefaultHttpClient().execute(httpRequest);是NULL值
    請問這是怎樣的原因才會發生
  • ButterC
  • 您好,在模擬器執行時 一按下按鈕就直接錯誤跳出Unfortunately,xxx has stopped.
    錯誤訊息為
    FATAL EXCEPTION: Thread-139
    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:197)
    at android.os.Handler.<init>(Handler.java:111)
    at android.widget.Toast$TN.<init>(Toast.java:324)
    at android.widget.Toast.<init>(Toast.java:91)
    at android.widget.Toast.makeText(Toast.java:238)
    at com.example.mysqltest.Sqltest.sendPostDataToInternet(Sqltest.java:113)
    at com.example.mysqltest.Sqltest.access$0(Sqltest.java:89)
    at com.example.mysqltest.Sqltest$sendPostRunnable.run(Sqltest.java:133)
    at java.lang.Thread.run(Thread.java:856)

    跟#24問題蠻像的
    不太懂是甚麼意思
    麻煩大大再度指點 謝謝!!
  • 因為你可能是在收到資料之後直接更新畫面的資料
    就會有這個錯誤
    你可以用Activity.runOnUiThread的方式
    或者寫一個Handler


    Johnny 鋼鍊 於 2013/08/14 21:03 回覆

  • yy
  • 請問這個方法適合拿來用在類似line的聊天室實作嗎??
  • 如果要做到像line那樣規模...這個範例可能撐不住這些連線
    可以改用Socket再縮減傳輸的資料
    Server端也要做一些調較...

    Johnny 鋼鍊 於 2013/08/14 21:05 回覆

  • Brady
  • 你好 怎麼將中文字做post傳送的動作,因為傳送過去會產生亂碼
    麻煩了,急需解答,謝謝
  • 幾個重點... Android Client端、Sever端(假設是PHP)、資料庫連線(假設MySQL)、資料表
    (SQL Create指令)
    全部設定成UTF-8

    Johnny 鋼鍊 於 2013/08/14 21:14 回覆

  • KunYu Tsai
  • 不好意思,請問按下送出後出現
    <br/ >
    <b>Parse error</b>: syntax error, unexpected '$' in <b>C:\Documents and Settings\kun\My Documents\Downloads\TWAMPd_v1.3.6.1_zh-tw\TWAMPd\htdocs\httpPostTest.php</b> on line <b>3</b><br />

    是路徑上出現問題嗎?
    httpPostTest.php 第3行有錯?
    我是用TWAMP來暫時架PHP的部分會有影響?
  • KunYu Tsai
  • 找到問題了,把架設的TWAMP資料夾改放置在C:\下,手機端部分OK data=1234
    但網頁在 localhost/httpPostTest.php 則只有顯示data=
    就沒有顯示我剛剛鍵入的1234
  • KunYu Tsai
  • 想請問一下,上面有人提到 POST在同一個weblogl的"data"中
    測試後成功可以將兩個EditText的數字寫入到"data"中

    如果在資料庫新增一個"data2"
    使用兩個EditText,要分別寫入在"data"和"data2"中,該如何做修正
    weblog中新增了"data2" 會出現
    field "data 2" doesn't have a default value
  • Chu-Ling Li
  • 大大~
    將您給的code
    Thread t = new Thread(new sendPostRunnable(msg));
    的msg 會錯耶...請問這要如何修正
  • Chu-Ling Li
  • 沒事了唷ˊˇˋ
    大大給的CODE 跟PO文有些許遺漏
    仔細的讀過後補上就OK了
    謝謝大大的教學唷~
  • :)

    Johnny 鋼鍊 於 2013/08/14 21:08 回覆

  • Rita
  • 我用版主的php與mysql連線時
    網也一直出現 Unknow column 'no' in 'order clause '
    請問版主這該怎麼解決 謝謝你
  • 英文訊息已經寫得很清楚,找不到no欄位
    可能你開表格的問題

    Johnny 鋼鍊 於 2013/08/14 21:03 回覆

  • Rita
  • 前幾天的那個問題解決了
    謝謝版主大大
    但現在的問題是
    我的android模擬器上是有出現httpposttest的app
    但是按下傳送資料的時候卻無法正確的傳送到網頁上
    在console跟Logcat上也沒有出現問題
    唯一就是在import android.util.Log; 這個部分顯示從未使用;

    而由於我的目前宿舍是有用分享器連線
    所以我有跟中華電信申請非固定制固定ip了
    uri API:的部分也是打上http:114.33.38.10/httpposttest.php
    但是模擬器傳送資料後還是無法傳到網頁上
    而在phpmyadmin上傳MySQL資料的話,是可以在網頁上看到的
    請問版主大大,這個模擬器上傳資料到網頁是哪裡出了問題呢?
    感謝你~
  • 你可以試寫一個method='post' 的html表單試試看
    要不然把$_POST的地方改成$_GET,然後在瀏覽器後面直接掛參數 試試看

    Johnny 鋼鍊 於 2013/08/26 20:45 回覆

  • 0口0
  • 我想問說 如果要傳多值的話

    handler那邊怎麼修改呢
  • 塞在object裡

    Johnny 鋼鍊 於 2013/09/03 13:14 回覆

  • 小彤 賴
  • 我要作一個會員登入的功能
    我做了一些改變 把要傳進去的東西

    params.add(new BasicNameValuePair("member",member));
    params.add(new BasicNameValuePair("password", password));
    這樣子對嗎?
    還有回傳回來的東西 我不知道如何顯示,
    我按下了送出,可是就是沒有其它反應。
  • 不好意思把隱藏解除了,這樣我回您才看得到

    對的,傳二個參數這樣寫沒錯
    至於顯示...我範例是印Toast
    你要用TextView等控件把值秀出來也可以
    重點要用runOnUiThread()把修正畫面相關的程式用這包起來

    Johnny 鋼鍊 於 2013/10/08 21:33 回覆

  • 小彤 賴
  • runOnUiThread() .....
    這個我就不太懂了
    請問可以去哪邊找到參考資料呢?
  • LCYU
  • 你好
    Toast顯示回傳值
    開頭都有一個  的符號
    然後才是傳送的資料
    請問一下有甚麼方法解決嗎?
  • 5555
  • 想請問在建立連線後
    把讀取php資料寫在下面是可行的嗎?
  • Ps Lin
  • 謝謝大大~
  • zetarv
  • 想請問一下
    我是使用GET的方法接收PHP ecoh的查詢結果
    但是Android端收到的時候會包含html的標籤
    雖然切割一下就可以用,但我怕可能會被抓出漏洞
    想請問有沒有方法可以讓他只回傳json的格是不要包含html呢?
  • 初心者
  • 想請問一下
    如果我要新增一個EditText用來輸入要連接的url
    並且寫入到檔案中
    在開啟程式時讀取該檔案中的內容做為url連接路徑
    目前寫入檔案跟讀取檔案是沒問題
    也有成功更改url連線路徑(用setText顯示在畫面上測試的)
    但是就是沒辦法連線
    請問一下要怎麼修改?
  • 悄悄話
  • jjj
  • 您好,請問若我想用迴圈跑執行緒但不想讓他跑太快因為我資料來不及更新,我爬了很多文說會用到sleep或delaypost之類的,但我就是不太知道怎麼做,懇請大大幫助我!

    for (int n = 1; n < 10; n++) {
    t.setText("CLat:" + latlocation + " CLng: "
    + lonlocation + "C精準度" + accuracy);
    //noinspection MissingPermission
    locationManager.requestLocationUpdates("gps", 5000, 0, listener);
    if (txtMessage != null)

    {
    // 擷取文字框上的文字
    msg_gps = txtMessage.getEditableText().toString();
    // 啟動一個Thread(執行緒),將要傳送的資料放進Runnable中,讓Thread執行
    // Thread t = new Thread(new sendPostRunnable(msg));
    // t.start();
    } else {
    msg_gps = "0";
    // Thread t = new Thread(new sendPostRunnable(msgg));
    // t.start();
    }


    if (txtMessage2 != null)

    {
    // 擷取文字框上的文字
    msg_beacon = txtMessage2.getEditableText().toString();
    // 啟動一個Thread(執行緒),將要傳送的資料放進Runnable中,讓Thread執行
    // Thread t2 = new Thread(new sendPostRunnable(msg));
    // t2.start();
    } else {
    msg_beacon = "0";
    // Thread t = new Thread(new sendPostRunnable(msg));
    // t.start();
    }

    String sending_msg = null;
    sending_msg = msg_gps + " :: " + msg_beacon + ";";

    Thread t = new Thread(new sendPostRunnable(sending_msg));
    t.start();
    }
  • QAQQQ
  • 想請問一下
    如果要同時上傳圖片檔跟文字到SQL的話,要如何將圖片存到params裡面呢?
    然後PHP的部分要怎麼修改呢?
找更多相關文章與討論