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

这里我们做了一些其他功能,我们先选择登录。

这个是webserivce的测试接口的方法,在对话框中填入测试的值,然后调用就可以测试了。

我们看到浏览器的返回值中,在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
网友评论