【學習階段】
-
WebService網絡請求?
其實我也是第一次遇到,之所以有這個需要是因為一些與 ERP 相關的業務,需要用到這樣的一個請求方式。
-
開始學習WebService
①當然是百度搜索,這里找了一個學習的博客 https://blog.csdn.net/swjtugiser/article/details/76840353
使用 ksoap2 框架請求 ,jar 包下載地址 http://simpligility.github.io/ksoap2-android/getting-started.html ,放在Project 模式的 libs 目錄下。
根據以上地址進行學習。
②在開發的過程中我們頻繁的用到 網絡請求,所以我們最好能封裝成像okhttp一樣的類。
1 package com.example.aust_app; 2
3
4 /*Created by wqy on 2019/11/8.*/
5
6 import android.content.Context; 7 import android.os.AsyncTask; 8
9 import org.ksoap2.SoapEnvelope; 10 import org.ksoap2.serialization.SoapObject; 11 import org.ksoap2.serialization.SoapSerializationEnvelope; 12 import org.ksoap2.transport.HttpTransportSE; 13
14 public class WebRequest { 15
16 private String SOAP_ACTION="http://WebXml.com.cn/getRegionProvince"; //可以設置一些默認值 17 private String NAMESPACE="http://WebXml.com.cn/"; 18 private String METHOD_NAME="getRegionProvince"; 19 private String URL="http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?WSDL"; 20
21 WebRequest request = null; 22 Context context = null; 23
24
25 public WebRequest(Context context) { 26 this.context = context; 27 } 28
29 public static WebRequest init(Context context){ 30 return new WebRequest(context); 31 } 32
33 public String getSOAP_ACTION() { 34 return SOAP_ACTION; 35 } 36
37 public WebRequest setSOAP_ACTION(String SOAP_ACTION) { 38 this.SOAP_ACTION = SOAP_ACTION; 39 return this; 40 } 41
42 public String getNAMESPACE() { 43 return NAMESPACE; 44 } 45
46 public WebRequest setNAMESPACE(String NAMESPACE) { 47 this.NAMESPACE = NAMESPACE; 48 return this; 49 } 50
51 public String getMETHOD_NAME() { 52 return METHOD_NAME; 53 } 54
55 public WebRequest setMETHOD_NAME(String METHOD_NAME) { 56 this.METHOD_NAME = METHOD_NAME; 57 return this; 58 } 59
60 public String getURL() { 61 return URL; 62 } 63
64 public WebRequest setURL(String URL) { 65 this.URL = URL; 66 return this; 67 } 68
69 private SoapObject getInformation(){ 70 SoapObject request=new SoapObject(NAMESPACE,METHOD_NAME); 71
72 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 73 envelope.setOutputSoapObject(request); 74 try{ 75 HttpTransportSE transportSE=new HttpTransportSE(URL); 76 transportSE.call(SOAP_ACTION,envelope); 77 SoapObject result=(SoapObject)envelope.bodyIn; //獲取到返回的結果,並強制轉換成SoapObject對象
78 SoapObject test = (SoapObject)result.getProperty(0); //該對象中還嵌套了一個SoapObject對象,需要使用getProperty(0)把這個對象提取出來
79 return test; 80 }catch (Exception e){ 81 e.printStackTrace(); 82 } 83 return null; 84 } 85
86 SoapObject result; //在子線程中請求webservice
87 class DownloadTask extends AsyncTask<Void,Integer,Boolean> { 88
89 @Override 90 protected Boolean doInBackground(Void... voids) { 91 result = getInformation(); 92 return null; 93 } 94
95 @Override 96 protected void onPostExecute(Boolean aBoolean) { 97 StringBuilder builder = new StringBuilder(); 98 //解析返回的數據
99 for(int i=0;i<result.getPropertyCount();i++){ 100 builder.append(result.getProperty(i)); 101 } 102 if (postExecute!=null){ 103 postExecute.getResult(builder.toString()); 104 } 105 } 106 } 107
108 public void execute(){ 109 new DownloadTask().execute(); 110 } 111
112 PostExecuteListener postExecute; 113 interface PostExecuteListener{ 114 void getResult(String result); 115 } 116
117 public PostExecuteListener getPostExecute() { 118 return postExecute; 119 } 120
121 public WebRequest setPostExecuteListener(PostExecuteListener postExecute) { 122 this.postExecute = postExecute; 123 return this; 124 } 125 }
③在Activity中使用這樣的類
WebRequest.init(this).setURL("url").setNAMESPACE("namespace").setMETHOD_NAME("methodName") .setSOAP_ACTION("soapAction").setPostExecuteListener(new WebRequest.PostExecuteListener() { @Override public void getResult(String result) { Toast.makeText(Main2Activity.this, ""+result, Toast.LENGTH_SHORT).show(); } }).execute();
【開發階段】
以上是學習階段,利用別人給的測試接口進行測試,並且進行一定的封裝使用,一系列沒有任何問題。然后再去進入自己開發階段。【解決問題⬇🔽⬇】
- 以上遇到的四個參數 URL(請求地址),METHOD_NAME(請求方法名),NAMESPACE(命名空間),SOAP_ACTION(這個我就不知道是什么)
但我發現 SOAP_ACTION 好像是 NAMESPACE + METHOD_NAME 。不知道我請求的地址剛好是這樣還是如何,但是也有看到是 空值的,但是我空值不通過,我采用的是這樣方式。
-
這次學習中並沒有講到 請求頭 和 請求參數,那這些怎么傳呢?
百度搜索 Android ksoap2 可以參考一下這個鏈接
【1】https://blog.csdn.net/fjnu_se/article/details/90647663 可以得到參數傳遞的方式
【2】https://www.cnblogs.com/bdsdkrb/p/9258099.html
-
修改請求類
1 package com.example.aust_app; 2
3
4 /*Created by wqy on 2019/11/8.*/
5
6 import android.content.Context; 7 import android.os.AsyncTask; 8
9 import com.example.aust_app.utils.LogUtil; 10 import com.example.aust_app.utils.ShareUtils; 11 import com.example.aust_app.utils.ToastTool; 12
13 import org.ksoap2.HeaderProperty; 14 import org.ksoap2.SoapEnvelope; 15 import org.ksoap2.serialization.SoapObject; 16 import org.ksoap2.serialization.SoapSerializationEnvelope; 17 import org.ksoap2.transport.HttpTransportSE; 18
19 import java.util.ArrayList; 20 import java.util.Map; 21 import java.util.Set; 22
23 public class WebRequest { 24
25 private String SOAP_ACTION = ""; 26 private String NAMESPACE = ""; 27 private String METHOD_NAME = ""; 28 private String URL = "http://ip/name.asmx"; 29
30 WebRequest request = null; 31 Context context = null; 32
33 public WebRequest(Context context) { 34 this.context = context; 35 URL = ShareUtils.getURL(context); 36 if (URL.equals("")) 37 ToastTool.showShortToast("請配置正確請求地址"); 38
39 } 40
41 public static WebRequest init(Context context) { 42 return new WebRequest(context); 43 } 44
45 public String getSOAP_ACTION() { 46 return SOAP_ACTION; 47 } 48
49 public WebRequest setSOAP_ACTION(String SOAP_ACTION) { 50 this.SOAP_ACTION = SOAP_ACTION; 51 return this; 52 } 53
54 public String getNAMESPACE() { 55 return NAMESPACE; 56 } 57
58 public WebRequest setNAMESPACE(String NAMESPACE) { 59 this.NAMESPACE = NAMESPACE; 60 return this; 61 } 62
63 public String getMETHOD_NAME() { 64 return METHOD_NAME; 65 } 66
67 public WebRequest setMETHOD_NAME(String METHOD_NAME) { 68 this.METHOD_NAME = METHOD_NAME; 69 SOAP_ACTION += METHOD_NAME; 70 return this; 71 } 72
73 public String getURL() { 74 return URL; 75 } 76
77 public WebRequest setURL(String URL) { 78 this.URL = URL; 79 return this; 80 } 81
82
83 private SoapObject getInformation() { 84 SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 85
86 if (queryParamsMap != null && queryParamsMap.size() > 0) { 87 Set<String> keys = queryParamsMap.keySet(); 88 for (String queryKey : keys) { 89 request.addProperty(queryKey, queryParamsMap.get(queryKey)); 90 } 91 LogUtil.logi("param", "" + queryParamsMap); 92 } 93
94 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 95 envelope.setOutputSoapObject(request); 96 envelope.dotNet = true;//很重要 97 try { 98 HttpTransportSE transportSE = new HttpTransportSE(URL); 99 if (headParamsMap != null) 100 transportSE.call(SOAP_ACTION, envelope, addHeadProperty(headParamsMap)); 101 else
102 transportSE.call(SOAP_ACTION, envelope); 103 SoapObject result = (SoapObject) envelope.bodyIn; //獲取到返回的結果,並強制轉換成SoapObject對象
104 return result; 105 } catch (Exception e) { 106 e.printStackTrace(); 107 if (postExecute != null) { 108 postExecute.onError(e.toString()); 109 } 110
111 } 112 return null; 113 } 114
115 SoapObject result; //在子線程中請求webservice
116
117 class DownloadTask extends AsyncTask<Void, Integer, Boolean> { 118
119 @Override 120 protected Boolean doInBackground(Void... voids) { 121 result = getInformation(); 122 return null; 123 } 124
125 @Override 126 protected void onPostExecute(Boolean aBoolean) { 127 StringBuilder builder = new StringBuilder(); 128 //解析返回的數據
129 if (result != null) 130 for (int i = 0; i < result.getPropertyCount(); i++) { 131 builder.append(result.getProperty(i)); 132 } 133 LogUtil.logi("result", "" + builder.toString()); 134 if (postExecute != null) { 135 postExecute.getResult(builder.toString()); 136 } 137 } 138 } 139
140 public void execute() { 141 new DownloadTask().execute(); 142 } 143
144 PostExecuteListener postExecute; 145
146 interface PostExecuteListener { 147 void getResult(String result); 148
149 void onError(String result); 150 } 151
152 public PostExecuteListener getPostExecute() { 153 return postExecute; 154 } 155
156 public WebRequest setPostExecuteListener(PostExecuteListener postExecute) { 157 this.postExecute = postExecute; 158 return this; 159 } 160
161 Map<String, Object> queryParamsMap; 162 Map<String, Object> headParamsMap; 163
164 public Map<String, Object> getQueryParamsMap() { 165 return queryParamsMap; 166 } 167
168 public WebRequest setQueryParamsMap(Map<String, Object> queryParamsMap) { 169 this.queryParamsMap = queryParamsMap; 170 return this; 171 } 172
173 public Map<String, Object> getHeadParamsMap() { 174 return headParamsMap; 175 } 176
177 public WebRequest setHeadParamsMap(Map<String, Object> headParamsMap) { 178 this.headParamsMap = headParamsMap; 179 return this; 180 } 181
182 public ArrayList<HeaderProperty> addHeadProperty(Map<String, Object> headerParamsMap) { 183 ArrayList<HeaderProperty> headerProperty = new ArrayList<>(); 184 //添加head參數
185 if (headerParamsMap != null && headerParamsMap.size() > 0) { 186 Set<String> keys = headerParamsMap.keySet(); 187 for (String headerKey : keys) { 188 headerProperty.add(new HeaderProperty(headerKey, (String) headerParamsMap.get(headerKey))); 189 } 190 } 191 return headerProperty; 192 } 193
194 }
-
在Activity中使用
Map<String, Object> param = new HashMap<>(); param.put("param", {{參數}}); WebRequest.init(this) .setMETHOD_NAME("QueryItem") .setQueryParamsMap(param) .setPostExecuteListener(new WebRequest.PostExecuteListener() { @Override public void getResult(String result) { LogUtil.logi("TAG", result);//拿到返回結果
} @Override public void onError(String result) { //請求錯誤的接口
ToastTool.showShortToast("請求發生錯誤!"); } }) .execute();
【最后問題】
在傳參方式,四個參數都准備完畢的時候,遇到了一個問題就是:可以請求無參數的方法是成功的,但是有參數的后台方法請求得到的參數都是為空的。
這里一個很重要的就是(我是通過如下方式解決的,Java和PHP都要設置這樣的一個屬性)
envelope.dotNet = true;
但在百度的時候解決方法也有很多,比如,命名空間后面要加 “/” ,如果以上方式並未成功,建議參考如下方式:
【最后最后】
溫馨提示:webservice 也是網絡請求,Android 清單文件不要忘記加 網絡訪問 的權限 。