2013年10月10日 星期四

Android HttpURLConnection post 傳遞資料到 server 回傳JSON資料

參考資料:
1.How to use HttpURLConnection POST data to web server?
2.How to connect Android with PHP, MySQL (如果你是用PHP+MySQL可參考,而我是參考此篇的寫法)
如果你還不懂AsyncTask,以下是必看文章
3.使用AsyncTask執行非同步任務
4.Android中AsyncTask的使用與源碼分析

以下假設是在順利執行的情況下

步驟:
Step 1.先在Eclipse建立Android專案(Android版本我是用4.3),建立完成後,先新增一個class名為JSONParser,程式碼如下:
P.S原則上我是參考資料2的做法,只是改成java的HttpURLConnection
JSONParser.java
package com.androidhive.jsonparsing;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;

public class JSONParser {
    static JSONObject jObj = null;
    static String json = "";
    // constructor
    public JSONParser() {}
// getJSONFromUrl方法為單存取資料用
    public JSONObject getJSONFromUrl(String temp_url) {
    HttpURLConnection conn = null;
        // Making HTTP request
        try {
        // 建立連線
            URL url =new URL(temp_url);
            conn = (HttpURLConnection)url.openConnection();
            //===============================
            //下面註解兩行可有可無
            //conn.setReadTimeout(10000);
            //conn.setConnectTimeout(15000);
            //===============================
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.connect();

            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            reader.close();
            json = sb.toString();
        }catch (Exception e) {
        System.out.println("getJSONFromUrl Exception Error :"+e);
        }finally {
            if (conn != null) {
                conn.disconnect();
            }
        }  
        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "getJSONFromUrl Error parsing data " + e.toString());
        }
        return jObj;
    }
 
    public JSONObject makeHttpRequest(String temp_url, String method, String urlParameters){
    HttpURLConnection conn = null;
    try{
            // 建立連線
            URL url =new URL(temp_url);
            conn = (HttpURLConnection)url.openConnection();
            //===============================
            //下面註解兩行可有可無
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            //===============================
            conn.setRequestMethod(method); //URL 請求的方法
            //發送表單類型資料,設定請求標頭
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            //設定要傳送的資料長度
            conn.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
            //設定內容語言
            conn.setRequestProperty("Content-Language", "zh-tw");

            conn.setUseCaches (false);
            conn.setDoInput(true);
            conn.setDoOutput(true);
         
            //Send request
            DataOutputStream wr = new DataOutputStream (conn.getOutputStream ());
            wr.writeBytes (urlParameters);
            wr.flush ();
            wr.close ();
         
            //Get Response
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            StringBuffer sb = new StringBuffer();
             
            while((line = reader.readLine()) != null) {
            sb.append(line + "\n");
            }
            reader.close();
            json = sb.toString();
    }catch (Exception e) {
    System.out.println("makeHttpRequest Error:"+e.toString());
        }finally {
            if (conn != null) {
                conn.disconnect();
            }
    }  
        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "getJSONFromUrl Error parsing data " + e.toString());
        }
        // return JSON String
        return jObj;
    }
}

Step 2.再來是直接使用剛剛建立好的JSONParser類別來傳資料取資料,程式碼如下:
P.S以下有些程式碼您必須自行修改,別照抄
Item2.java
package com.android.school;
import com.androidhive.jsonparsing.JSONParser;
import android.os.AsyncTask; //處理非同步
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.app.Activity;
import android.os.Bundle;
public class Item2 extends Activity {
//JSON節點名稱名稱,
    String T_temp1= "test";
    //JSON節點名稱,也就是要取資料的欄位名稱,必須要以網頁回傳的為主,如:"欄位1,欄位2,欄位3..."
    String get_str="test1,test2,test3";
 
    JSONParser jParser; //剛剛建立的JSONParser類別
    JSONObject json;
    JSONArray contacts = null;
    Item2_AT I_AT; //非同步AsyncTask類別
    EditText txt2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item2);

Button B1=(Button)findViewById(R.id.button1);
B1.setOnClickListener(B1_Click);
txt2=(EditText)findViewById(R.id.editText2);
//假如你是連結自己的IIS必須寫10.0.2.2:port,因為預設iis的port為80
new Item2_AT().execute("url","http://10.0.2.2:80/TEST/TEST.aspx");
}

private OnClickListener B1_Click=new OnClickListener(){
   public void onClick(View v){
    I_AT=new Item2_AT();
    System.out.println("return="+I_AT.execute("select","http://10.0.2.2:80/TEST/TEST.aspx"));
   }
};

class Item2_AT extends AsyncTask<String, Integer, Integer>{
 //================================================================
 //必須建立
//execute("http://10.0.2.2:80/TEST/TEST.aspx")會傳給doInBackground
//doInBackground(String... param)代表傳入的值可以帶入很多個參數 如:new Item2_AT().execute("1","2");
   @Override
protected Integer doInBackground(String... param) {
int Judge;
    //get Data 單存取資料
    if (param[0].equals("url")==true){
// Creating JSON Parser instance
jParser = new JSONParser();
// getting JSON string from URL
json = jParser.getJSONFromUrl(param[1]);
    }else if (param[0].equals("select")==true){
    String urlParameters="0";
    try{
    urlParameters ="sid="+URLEncoder.encode(txt2.getText().toString(), "UTF-8");
    Judge=1;
    }catch(UnsupportedEncodingException e){
    System.out.println("UnsupportedEncodingException error:"+e.toString());
    Judge=0;
    }
    if (Judge==1){
    // Creating JSON Parser instance
jParser = new JSONParser();
         //param[1] 儲存的是url網址
json = jParser.makeHttpRequest(param[1],"POST",urlParameters);
    }
    }
    return null;
}

@Override
protected void onPostExecute(Integer result) {
//此method是在doInBackground完成以後,才會呼叫的
super.onPostExecute(result);
EditText txt=(EditText)findViewById(R.id.editText1);

//show Data
String str_temp;
try {
String[] T_temp1f=get_str.split(","); //分割字串

   // Getting Array of Contacts
   contacts = json.getJSONArray(T_temp1);
   // looping through All Contacts
   for(int i = 0; i < contacts.length(); i++){
    str_temp="";
       JSONObject c = contacts.getJSONObject(i);
     
       for (int x=0;x<T_temp1f.length;x++){
        if (x==T_temp1f.length-1){
        str_temp=str_temp + c.getString(T_temp1f[x])+";\n";
        }else{
        str_temp=str_temp + c.getString(T_temp1f[x])+",";
        }
       }
       txt.setText(txt.getText()+ str_temp);
   }
 
} catch (JSONException e) {
txt.setText("JSON error:"+e.toString());
   System.out.println("JSON error:"+e.toString());
}catch (Exception e) {
txt.setText("Error:"+e.toString());
System.out.println("Error:"+e.toString());
}
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}

@Override
protected void onPreExecute() {
super.onPreExecute();
}
//=============================================================
}
}

Step 3.建立要連結的網頁,因為我是連結ASP.NET的網頁,所以已ASP.NET為主,如果你沒有測試的網頁,可以試著連結這個網頁取資料 http://api.androidhive.info/contacts/ ,如果你是用測試的網頁 Android 部分就改用這個方法去取得資料getJSONFromUrl,但Android程式碼的寫法就要改成這篇的寫法 How to connect Android with PHP, MySQL  ,因為我的程式碼是用他的來改過的,所以有些部分就不一樣
P.S以下程式碼,可以先看看此篇會比較清楚 ASP.NET 產生 JSON 資料
TEST.aspx.vb
Imports System
Imports System.Data
Imports System.Data.SqlClient
'Json.NET相關的命名空間
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

Partial Class FSA_Student
    Inherits System.Web.UI.Page

    Dim strsqlCon As String = "Data Source=.\SQLEXPRESS;Initial Catalog=資料庫名稱;Trusted_Connection=True;"
    Dim str_sql As String
    Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            Dim p_value As String = Nothing
            'sql指令
            str_sql = "Select test1,test2,test3 from test where test1=@test1"
            If Not Request.Form("sid") Is Nothing Then
                p_value = Request.Form("sid")
            ELSE
                p_value = "0" '沒有接收到值,預設先指定一個參數值
            End If

            'function queryDataTable(sql指令, 參數名稱, 參數值) 方法執行完會回傳DataTable
            Dim dt As DataTable = queryDataTable(str_sql, "@test1", p_value)

            Dim str_json As String = JsonConvert.SerializeObject(dt)

            str_json = str_json.Replace(" ", "") '將空白取代掉
            Response.Write("{" & Chr(34) & "test" & Chr(34) & ":" & str_json & "}")

        End If
    End Sub

    Function queryDataTable(ByVal sql_str As String, ByVal pv As String, ByVal pv_value As String) As DataTable
        Dim sql_p() As String = Nothing
        sql_p = pv.Split(",") 'sql字串中的參數
        Dim sqlvalue_p() As String = Nothing
        sqlvalue_p = pv_value.Split(",") 'sql字串中的參數值

        Dim ds As New DataSet()
        Using conn As New SqlConnection(strsqlCon)
            Dim command As SqlCommand = New SqlCommand(str_sql, conn)

            Dim x_end As Integer = sql_p.Length - 1
            For x As Integer = 0 To x_end
             command.Parameters.AddWithValue(sql_p(x), sqlvalue_p(x)) '讓ADO.NET自行判斷型別轉換
            Next

            Dim da As New SqlDataAdapter()
            da.SelectCommand = command

            da.Fill(ds)
        End Using
        If ds.Tables.Count > 0 Then
            Return ds.Tables(0)
        Else
            Return New DataTable()
        End If
    End Function

End Class

1 則留言:

  1. 謝謝你~對新手很有幫助!希望你繼續寫...加油!

    回覆刪除