android與webservice通過json通訊

前言

前段時間來了個小項目,項目是通過手機掃貨架上面的二維碼,然后進行物料相關的操作,然后貨架上面對應的物料燈就會亮起,整個項目流程并不復雜,但是需要對接的服務器是webservice的,在我們android開發中,我們經常與后臺對接,但是大多都是http的請求,返回json格式,但是與webservice通訊中,常用到的一些庫并不推薦使用。一開始我們采用soap解析xml,還是可以使用的,但是隨著功能的增加,xml規范還是不太適合android,尤其是xml的解析看起來很亂,不像是json有很多的實用庫,用起來很方便,后來還是感覺json作為返回值會方便的很多。

WebService

由于我不是做服務端的,起初webservice并不了解,但是代碼都是很類似的,也是參與到了其中的部分開發,這里簡單的介紹一下,webservice服務我就理解為一個后臺接口,只不過通訊用的是soap,返回的xml。網上有很多介紹webservice的博文,介紹的都很詳細。

在使用json前我們需要添加幾個庫。
using System.Net.Http;
using Newtonsoft.Json;
using System.Text;
using System.Runtime.Serialization.Json;

這里需要添加一些資源庫進去,然后引用。
分別是System.Net.Http.dll Newtonsoft.Json.dll。
下載鏈接:
http://download.csdn.net/download/ljz0826/9959968
http://download.csdn.net/download/ljz0826/9959839
這樣我們就能使用json了。

下面舉一個接口的例子:

[WebMethod(Description = "核實登錄信息")]
public string WebLogin(string username, string pass)
{
        ResponseMessage rs = new ResponseMessage();
        try
        {
            string ConnStr = "server=lz-bjb;database='jzclk';uid='sa';pwd='sadhslzlz';";
            SqlConnection sqlConn = new SqlConnection(ConnStr);
            sqlConn.Open();
            string sqlSel = "select count(*) from tb_md where [工號]='" + username + "' and [密碼]='" + pass + "'";
            SqlCommand sqlcom = new SqlCommand(sqlSel, sqlConn);
            int i = Convert.ToInt32(sqlcom.ExecuteScalar());
            sqlConn.Close();
            if (i == 1)
            {
                string sqlSel1 = "select 姓名,部門,權限 from tb_md where [工號]='" + username + "' and [密碼]='" + pass + "'";
                SqlDataAdapter da = new SqlDataAdapter(sqlSel1, sqlConn);
                DataSet ds = new DataSet();
                da.Fill(ds, "tb_md");
                DataRowView drv = ds.Tables["tb_md"].DefaultView[0];
                string name = Convert.ToString(drv.Row["姓名"]);
                string bm = Convert.ToString(drv.Row["部門"]);
                string qx = Convert.ToString(drv.Row["權限"]);
                
                KCB cb = new KCB();
                cb.Gonghao = username;
                cb.Name = name;
                cb.Dept = bm;
                cb.Auth = qx;
                
                rs.Code = 1;
                rs.Msg = "success";
                rs.Result = cb;

                String sjon =JsonConvert.SerializeObject(rs);
                //GetQrCodeList(sjon);
                //Context.Response.Charset = "GB2312"; //設置字符集類型  
                //Context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
                //Context.Response.Write(sjon);
                return sjon;
            }
            else
            {
                rs.Code = 2;
                rs.Msg = "工號錯誤或密碼錯誤";
                //rs.Result = "工號錯誤或密碼錯誤";

                String sjon = JsonConvert.SerializeObject(rs);
                //GetQrCodeList(sjon);
                //Context.Response.Charset = "GB2312"; //設置字符集類型  
                //Context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
                //Context.Response.Write(sjon);
                return sjon;
            }
        }catch (Exception ex){          
            rs.Code =0;
            rs.Msg = "服務器處理異常錯誤";
            //rs.Result = "服務器處理異常錯誤";

            String sjon = JsonConvert.SerializeObject(rs);
            //GetQrCodeList(sjon);
            //Context.Response.Charset = "GB2312"; //設置字符集類型  
            //Context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
            //Context.Response.Write(sjon);
            return sjon;
        }
}

方法就是一個簡單的登錄的功能,參數是客戶端傳入的用戶名和密碼,然后webservice和sqlserivce數據庫去比對,正確了就登錄。
我們注意到其中屏蔽的代碼。

//GetQrCodeList(sjon);
//Context.Response.Charset = "GB2312"; //設置字符集類型  
//Context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
//Context.Response.Write(sjon);

在使用這段代碼中,我們并沒有return,這樣瀏覽器測試接口的時候,我們發現接口雖然通,返回的的結果也是json,但是我們知道webservice取值的時候還是需要命名空間的,沒有xml我無法拿到其中的內容(····這里是我不知道怎么去取),所以我將返回的內容封裝到json然后再通過xml的內容返回給客戶端。
用瀏覽器打開webserservice瀏覽



這里我們做了一些其他功能,我們先選擇登錄。

登錄瀏覽.png

這個是webserivce的測試接口的方法,在對話框中填入測試的值,然后調用就可以測試了。


login返回值.png

我們看到瀏覽器的返回值中,在xml內部便出現了json內容,這樣我們在客戶端可以進行soap進行解析出json,然后就可以用gson之類的常用庫進行json的解析啦。

android

在客戶端用使用soap也是需要庫的,我們添加了soap的庫之后便可以進行soap的解析了。
soap下載鏈接:
http://download.csdn.net/download/ljz0826/9959925
首先我們封裝一下soap的請求代碼。

public class RemoteDataHandler {

    private static Map<String,SoapObject> sso = new HashMap<String, SoapObject>();

    private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6,
            30, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

    public interface CallBackXml {
        public void dataLoaded(SoapObject soapObject);
    }

    /**
     *
     * @param activity  BaseActivity
     * @param methodname  方法名
     * @param rpc  參數
     * @param callback  回調
     * @param showProgress  是否顯示對話框
     */
    public static void asyncSoap(final BaseActivity activity, final String methodname, final SoapObject rpc, final CallBackXml callback, final boolean showProgress){
        if (showProgress)
            activity.showProgress();
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case 0:
                        activity.closeProgress();
                        SoapObject soapObject = sso.get(msg.obj);
                        sso.clear();
                        callback.dataLoaded(soapObject);
                }
            }
        };

        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                String nameSpace = Constants.NAME_SPACE; //命名空間
                String endPoint = Constants.END_POINT;
                String soapAction = nameSpace+methodname; //Action
                // 生成調用WebService方法的SOAP請求信息,并指定SOAP的版本
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
                envelope.bodyOut = rpc;
                // 設置是否調用的是dotNet開發的WebService
                envelope.dotNet = true;
                // 等價于envelope.bodyOut = rpc;
                envelope.setOutputSoapObject(rpc);
                HttpTransportSE transport = new HttpTransportSE(endPoint);
                try {
                    // 調用WebService
                    transport.call(soapAction, envelope);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                SoapObject object = (SoapObject) envelope.bodyIn;
                Log.i("soap","object : "+object+"");
                ////////////////////////////////////////////////////////
                sso.put(methodname, object);
                Message msg = handler.obtainMessage(0,methodname);
                handler.sendMessage(msg);
            }
        });

    }

    /**
     *
     * @param fragment  BaseFragment
     * @param methodname  方法名
     * @param rpc  參數
     * @param callback  回調
     * @param showProgress  是否顯示對話框
     */
    public static void asyncSoapfromfragment(final BaseFragment fragment, final String methodname, final SoapObject rpc, final CallBackXml callback, final boolean showProgress){
        if (showProgress)
            TrainApplication.getCoreApplication().showProgressDialog(fragment.getContext());
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case 0:
                        TrainApplication.getCoreApplication().dismissProgressDialog();
                        SoapObject soapObject = sso.get(msg.obj);
                        callback.dataLoaded(soapObject);
                        sso.clear();
                }
            }
        };

        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                String nameSpace = Constants.NAME_SPACE; //命名空間
                String endPoint = Constants.END_POINT;
                String soapAction = nameSpace+methodname; 
                // 生成調用WebService方法的SOAP請求信息,并指定SOAP的版本
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
                envelope.bodyOut = rpc;
                // 設置是否調用的是dotNet開發的WebService
                envelope.dotNet = true;
                // 等價于envelope.bodyOut = rpc;
                envelope.setOutputSoapObject(rpc);
                HttpTransportSE transport = new HttpTransportSE(endPoint);
                try {
                    // 調用WebService
                    transport.call(soapAction, envelope);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                SoapObject object = (SoapObject) envelope.bodyIn;
                ////////////////////////////////////////////////////////
                sso.put(methodname, object);
                Message msg = handler.obtainMessage(0,methodname);
                handler.sendMessage(msg);
            }
        });
    }
}

這里就是soap請求webservice的方法。
我們在使用的時候:

    private void login(){
        if(TextUtils.isEmpty(username.getText().toString().trim())){
            TrainToast.makeText(LoginActivity.this, getResources().getString(R.string.error_empty_username), Toast.LENGTH_SHORT).show();
            return;
        }
        if(TextUtils.isEmpty(password.getText().toString().trim())){
            TrainToast.makeText(this, getResources().getString(R.string.error_empty_password), Toast.LENGTH_SHORT).show();
            return;
        }
        SoapObject rpc = new SoapObject(Constants.NAME_SPACE, Constants.METHOD_LOGIN);
        rpc.addProperty("username", username.getText().toString().trim());
        rpc.addProperty("pass", password.getText().toString().trim());
        RemoteDataHandler.asyncSoap(LoginActivity.this, Constants.METHOD_LOGIN, rpc, new RemoteDataHandler.CallBackXml() {
            @Override
            public void dataLoaded(SoapObject soapObject) {
                if (soapObject != null && soapObject.getPropertyCount() > 0) {
                    String result = soapObject.getPropertyAsString(0);
                    if(result!=null){
                        StuffEntity stuffEntity = GsonUtil.json2bean(result, StuffEntity.class);
                        if(stuffEntity!=null){
                            int code = stuffEntity.getCode();
                            if(code==1){
                                //進行登錄操作
                            }else{
                                TrainToast.makeText(LoginActivity.this,stuffEntity.getMsg(), Toast.LENGTH_SHORT).show();
                            }
                        }else{
                            TrainToast.makeText(LoginActivity.this,getResources().getString(R.string.error_service), Toast.LENGTH_SHORT).show();
                        }
                    }else{
                        TrainToast.makeText(LoginActivity.this,getResources().getString(R.string.error_service), Toast.LENGTH_SHORT).show();
                    }
                } else {
                    TrainToast.makeText(LoginActivity.this, getResources().getString(R.string.error_net), Toast.LENGTH_SHORT).show();
                }
            }
        }, true);
    }

這樣我們就很熟悉了,拿到了結果不需要再進行復雜的xml解析,直接取到soapobject其中的第一條string,便是我們需要的json,然后直接用gson解析到bean類里面。這樣我們便成功的用android與webservice進行通訊并拿到了json的結果。

總結

其實其中的思路很簡單,就是soap解析webservice的結果,其中返回結果只使用了一條string作為返回值,而這條string在webservice中已經封裝成了json,所以我們客戶端拿到的string便是json的格式,然后解析json就可以了。
暫時先總結這么多,如果大家有更好的辦法還要請多多指教,謝謝!
轉載請注明出處:http://www.lxweimin.com/p/a7960e5214dd

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容