原理:WCF属于webservice,我们使用soapUI获取WCF所有请求类型,及请求参数的XML格式,封装成安卓端请求。
依赖
app.build.gradle
android {
...
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/MANIFEST.MF'
exclude 'mozilla/public_suffix-list.txt'
exclude 'META-INF/maven/org.apache.httpcomponents/httpcore/pom.properties'
exclude 'META-INF/maven/org.apache.httpcomponents/httpcore/pom.xml'
}
...
}
implementation group: 'org.apache.httpcomponents.client5' , name: 'httpclient5' , version: '5.0-beta4'
发送请求
new Thread(()->{
String retStr;
String soapXML;
CloseableHttpClient closeableHttpClient = null;
try {
closeableHttpClient = HttpClientBuilder.create().build();
try {
HttpPost httpPost = new HttpPost("填写服务器域名及端口号");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(ConnectTimeout))
.setResponseTimeout(Timeout.ofSeconds(ResponseTimeout)).build();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
httpPost.setHeader("SOAPAction", "这里填你的WCF服务及类型");
httpPost.setEntity(new StringEntity(new String(soapXML.getBytes(), Charset.forName("UTF-8"))));
CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
String strData = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8"));
retStr = "Response:\n"+response.toString() + "\n" + response.getEntity().toString() + "\n" + strData;
} catch (Exception e) {
retStr = null;
e.printStackTrace();
}
}
finally {
try {closeableHttpClient.close();}catch(Exception e){}
}
}).start();
XML互转工具
public static String CursorToXML(final Cursor cursor ,Handler handler,String...DataAppend){
String Tables = "";
String RowsFormat ="<Table diffgr:id=\"Table%d\" msdata:rowOrder=\"%d\">";
cursor.moveToFirst();
for(int i =0,ni = cursor.getColumnCount();i<ni;++i){
String TableColumnType = null;
switch (cursor.getType(i)){
case Cursor.FIELD_TYPE_INTEGER:
TableColumnType = "int";
break;
case Cursor.FIELD_TYPE_STRING:
TableColumnType = "string";
break;
case Cursor.FIELD_TYPE_BLOB:
TableColumnType = "blob";
break;
case Cursor.FIELD_TYPE_FLOAT:
TableColumnType = "decimal";
}
if(TableColumnType!=null){
RowsFormat = RowsFormat + String.format("<%s>%%s</%s>",cursor.getColumnName(i),cursor.getColumnName(i));
Tables = String.format("%s <xs:element name=\"%s\" type=\"xs:%s\" minOccurs=\"0\"/>",Tables,cursor.getColumnName(i),TableColumnType);
}
}
cursor.moveToPrevious();
if(DataAppend!=null&&DataAppend.length>0) Tables=Tables+DataAppend[0];
RowsFormat=RowsFormat+"</Table>";
String Rows = "";
for (int i=0;cursor.moveToNext();++i){
try {if(i%100==0)Message.obtain(handler,WCFState_SoapProgress,100).sendToTarget();} catch (Exception e) {}
Object [] oParams = new Object[cursor.getColumnCount()+2];
oParams[0] = i+1;
oParams[1] = i;
for(int j=0,nj=cursor.getColumnCount();j<nj;++j) oParams[j+2] = cursor.getString(j);
Rows = Rows + String.format(RowsFormat,oParams);
}
String DataTable = String.format("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
"<xs:schema id=\"NewDataSet\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">" ,
"<xs:element name=\"NewDataSet\" msdata:IsDataSet=\"true\" msdata:MainDataTable=\"Table\" msdata:UseCurrentLocale=\"true\">" ,
"<xs:complexType>" ,
"<xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">" ,
"<xs:element name=\"Table\">" ,
"<xs:complexType>" ,
"<xs:sequence>" ,
Tables,
"</xs:sequence>" ,
"</xs:complexType>" ,
"</xs:element>" ,
"</xs:choice>" ,
"</xs:complexType>" ,
"</xs:element>" ,
"</xs:schema>" ,
"<diffgr:diffgram xmlns:diffgr=\"urn:schemas-microsoft-com:xml-diffgram-v1\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">" ,
"<NewDataSet xmlns=\"\">" ,
Rows,
"</NewDataSet>" ,
"</diffgr:diffgram>"
);
return DataTable;
}
public static Cursor XmlToCursor(final String DataTable){
List<List<String>> tDatas = new LinkedList<>();
Map<String, Integer> tNames = new HashMap<>();
Map<Integer, String> tIndexs= new HashMap<>();
List<Integer> tTypes = new LinkedList<>();
try {
String TableInfo = DataTable.substring(DataTable.indexOf("<xs:sequence>")+"<xs:sequence>".length(),DataTable.indexOf("</xs:sequence>"));
for (int i=0,idxName,idxType,idxEnd,lenName="<xs:element name=\"".length(),lenType="\" type=\"".length();(idxName=TableInfo.indexOf("<xs:element name=\""))>-1&&(idxType=TableInfo.indexOf("\" type=\""))>-1;++i){
String Name = TableInfo.substring(idxName+lenName,idxType);
idxEnd = TableInfo.indexOf("\"",idxType+lenType);
String Type = TableInfo.substring(idxType+lenType,idxEnd);
tIndexs.put(i,Name);
tNames.put(Name,i);
switch (Type){
case "xs:string":
tTypes.add(Cursor.FIELD_TYPE_STRING);
break;
case "xs:int":
tTypes.add(Cursor.FIELD_TYPE_INTEGER);
break;
case "xs:blob":
tTypes.add(Cursor.FIELD_TYPE_BLOB);
break;
case "xs:decimal":
tTypes.add(Cursor.FIELD_TYPE_FLOAT);
break;
}
TableInfo=TableInfo.substring(idxEnd);
}
} catch (Exception e) {}
try{
String RecordInfo = DataTable.substring(DataTable.indexOf("<NewDataSet xmlns=\"\">")+"<NewDataSet xmlns=\"\">".length(),DataTable.indexOf("</NewDataSet>"));
for(int i=0,idxBegin,idxEnd;;++i){
String rowBegin = String.format("<Table diffgr:id=\"Table%d\" msdata:rowOrder=\"%d\">",i+1,i);
idxBegin = RecordInfo.indexOf(rowBegin)+rowBegin.length();
idxEnd = RecordInfo.indexOf("</Table>",idxBegin);
String RowsInfo=RecordInfo.substring(idxBegin,idxEnd);
RecordInfo=RecordInfo.substring(idxEnd);
List<String> RowData = new LinkedList<>();
try {
while(true){
idxEnd = RowsInfo.indexOf('<',idxBegin = RowsInfo.indexOf('>')+1);
RowData.add(RowsInfo.substring(idxBegin,idxEnd));
RowsInfo=RowsInfo.substring((RowsInfo.substring(0,idxEnd).contains("/>")?idxEnd:RowsInfo.indexOf('>',idxEnd))+1);
}
} catch (Exception e) {e.printStackTrace();}
tDatas.add(RowData);
}
}catch (Exception e){e.printStackTrace();}
final List<List<String>> cDatas = tDatas;
final List<Integer> cTypes = tTypes;
final Map<String, Integer> cNames = tNames;
final Map<Integer, String> cIndexs = tIndexs;
return new Cursor() {
private int pIndex = -1;
private List<Integer> cColumnTypes = cTypes;
private List<List<String>> cRecords = cDatas;
private Map<String, Integer> cColumnNames = cNames;
private Map<Integer, String> cColumnIndexs = cIndexs;
@Override
public int getCount() { return cRecords==null?0:cRecords.size(); }
@Override
public int getPosition() { return pIndex; }
@Override
public boolean move(int i) { return (i<-1&&i>=cRecords.size())?false:((pIndex=i)==i); }
@Override
public boolean moveToPosition(int i) { return move(i); }
@Override
public boolean moveToFirst() { return getCount()>0&&(pIndex=0)==0; }
@Override
public boolean moveToLast() { return getCount()>0&&(pIndex=getCount())>0; }
@Override
public boolean moveToNext() { return getCount()>(pIndex+1)&&((pIndex=pIndex+1)>-1); }
@Override
public boolean moveToPrevious() { return getCount()>0&&pIndex-1>0&&((pIndex=pIndex-1)>-1); }
@Override
public boolean isFirst() { return pIndex==0; }
@Override
public boolean isLast() { return pIndex==getCount(); }
@Override
public boolean isBeforeFirst() { return pIndex==-1; }
@Override
public boolean isAfterLast() { return pIndex==getCount(); }
@Override
public int getColumnIndex(String s) { return cColumnNames.get(s); }
@Override
public int getColumnIndexOrThrow(String s) throws IllegalArgumentException { return cColumnNames.get(s); }
@Override
public String getColumnName(int i) { return cColumnIndexs.get(i); }
@Override
public String[] getColumnNames() {
String str[] = new String[cColumnIndexs.size()];
for(int i=0;i<str.length;++i)str[i]=cColumnIndexs.get(i);
return str;
}
@Override
public int getColumnCount() { return cColumnNames.size(); }
@Override
public byte[] getBlob(int i) { return cRecords.get(pIndex).get(i).getBytes(); }
@Override
public String getString(int i) { return cRecords.get(pIndex).get(i); }
@Override
public void copyStringToBuffer(int i, CharArrayBuffer charArrayBuffer) { }
@Override
public short getShort(int i) { return Short.parseShort(getString(i)); }
@Override
public int getInt(int i) { return Integer.parseInt(getString(i)); }
@Override
public long getLong(int i) { return Long.parseLong(getString(i)); }
@Override
public float getFloat(int i) { return Float.parseFloat(getString(i)); }
@Override
public double getDouble(int i) { return Double.parseDouble(getString(i)); }
@Override
public int getType(int i) { return cColumnTypes.get(i);}
@Override
public boolean isNull(int i) { return getString(i)==null; }
@Override
public void deactivate() {}
@Override
public boolean requery() { return false; }
@Override
public void close() {}
@Override
public boolean isClosed() { return false; }
@Override
public void registerContentObserver(ContentObserver contentObserver) {}
@Override
public void unregisterContentObserver(ContentObserver contentObserver) {}
@Override
public void registerDataSetObserver(DataSetObserver dataSetObserver) {}
@Override
public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {}
@Override
public void setNotificationUri(ContentResolver contentResolver, Uri uri) {}
@Override
public Uri getNotificationUri() { return null;}
@Override
public boolean getWantsAllOnMoveCalls() { return false; }
@Override
public void setExtras(Bundle bundle) {}
@Override
public Bundle getExtras() { return null; }
@Override
public Bundle respond(Bundle bundle) { return null; }
};
}