前言
前段時間來了個小項目,項目是通過手機掃貨架上面的二維碼,然后進行物料相關的操作,然后貨架上面對應的物料燈就會亮起,整個項目流程并不復雜,但是需要對接的服務器是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.lxweimin.com/p/a7960e5214dd