美文网首页Android知识
android与webservice通过json通讯

android与webservice通过json通讯

作者: 蜡笔小州 | 来源:发表于2017-09-01 11:13 被阅读458次

前言

前段时间来了个小项目,项目是通过手机扫货架上面的二维码,然后进行物料相关的操作,然后货架上面对应的物料灯就会亮起,整个项目流程并不复杂,但是需要对接的服务器是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.jianshu.com/p/a7960e5214dd

相关文章

网友评论

    本文标题:android与webservice通过json通讯

    本文链接:https://www.haomeiwen.com/subject/spuhjxtx.html