Android calls .Net WCF service.

Originally I thought on the java platform with axis2 generated client proxy class and then ported to the Android platform just fine. I did not expect a lot of problems during the migration process. Description DVM gap between JVM and android is still very large.

JVM class file is executed, and the execution of DVM is dex file.

Android application development in eclipse which when compiled will jar packets inside one class DVM compiled into an executable file dex. Of course, there is a premise that jar package is placed inside the source folder. This eclipse will be in time compiler to compile the jar package apk file. Although local eclipse or else not being given, but in the simulator will complain NoClassDefFound.

And some jar package can not be converted correctly into dexdump.exe dex files. This results in the jar package can not be used, the consequences are the entire program can not be run correctly.

I will axis2 ported to the Android platform up when there are not converted jar package. Then the Internet to find a lot of information, no one solution to this problem. If you want someone to solve a share about the next.

Later it is to die, to see the Internet, said the Android platform to invoke the Web Service with ksoap2. Axis2 feel not solve the problem. So can only change direction. Learn about ksoap2. When ksoap2 call a WCF service, there have been a lot of problems. Fortunately, I gradually began to have been resolved. Now the problems I encountered and solutions solutions are written down, other people have encountered these problems for reference.

 

Here are what I encountered problems and solutions

1. Call a description of the parameters

 

  1. static String NameSpace="http://tempuri.org/";  
  2. static String URL="https://10.0.2.2:9001/test";  
  3. static String SOAP_ACTION="http://tempuri.org/ITestService/GetUser";  
  4. static String MethodName="GetUser";  

 

 

Namespace is the namespace you set up the service, the general is not set http://tempuri.org/

URL is your service exposed addresses can access the wsdl via this address. Inside represented in the android emulator address is 127.0.0.1, which is represented by the computer 10.0.0.2 127.0.0.1. So if it is their native WCF server to do so, such a program should be set up inside.

SOAP_ACTION is the address of your wsdl inside corresponding method.

MethodName is the name of the method specified in the ACTION SOAP_ACTION final surface.

 

2. The parameter transfer complex objects

The service which will inevitably pass parameters, but may not be possible to resolve the parameters you pass in the end wcf service. After intercepting tcptrace soap found by reason namespace does not correspond to the parameters. Below is an example

Server code:

 

  1. User ITestService.GetUser(User u)  
  2.         {  
  3.             User user = new User();  
  4.             user.UId = "Server:" + u.UId;  
  5.             user.UName = "Server:" + u.UName;  
  6.             return user;  
  7.         }  

 

 

User class:

 

  1. [DataContract]  
  2.     public class User  
  3.     {  
  4.         [DataMember]  
  5.         public string UId;  
  6.         [DataMember]  
  7.         public string UName;  
  8.     }  

 

 

 

android client code as follows:

 

  1. SoapObject requet=new SoapObject(NameSpace,MethodName);  
  2.           
  3.         PropertyInfo perPropertyInfo=new PropertyInfo();  
  4.         User user=new User();  
  5.         user.setUId("123");  
  6.         user.setUName("cch");  
  7.         perPropertyInfo.setName("u");  
  8.         perPropertyInfo.setValue(user);  
  9.         perPropertyInfo.setType(User.class);  
  10.         requet.addProperty(perPropertyInfo);  
  11.           
  12.         Soap Serialization Envelope envelope = new Soap Serialization Envelope (SoapEnvelope.VER11);  
  13.         envelope.addMapping (User.NAMESPACE, "the User", the User. class); // this is very important to the Register   
  14.         envelope.setOutputSoapObject(requet);  
  15.         envelope.dotNet=true;  
  16.         AndroidHttpTransport transport=new AndroidHttpTransport (URL);  
  17.           
  18.         ClientUtil.SetCertification ();   // Set credentials   
  19.         try {  
  20.               
  21.             transport.call(SOAP_ACTION,envelope);  
  22. //             
  23.             SoapObject response=(SoapObject)envelope.getResponse();  
  24. //             
  25.             //PraseXML_SF(response);   
  26.             ((TextView)findViewById(R.id.txt01)).setText(String.valueOf(response.toString()));  
  27.         } catch (IOException e) {  
  28.             // TODO Auto-generated catch block   
  29.             e.printStackTrace ();  
  30.         } catch (XmlPullParserException e) {  
  31.             // TODO Auto-generated catch block   
  32.             e.printStackTrace ();  
  33.         }  

 

 

android side also have a User class that is inherited BaseObject, BaseObject interfaces implemented KvmSerializable

先BaseObject:

 

  1. package CCH.Model;  
  2. import org.ksoap2.serialization.KvmSerializable;  
  3. import org.ksoap2.serialization.SoapObject;  
  4. public abstract class BaseObject implements KvmSerializable  
  5. {  
  6.     public static final String NAMESPACE = "http://schemas.datacontract.org/2004/07/TestService";  
  7.     //public static final String NAMESPACE = "http://schemas.datacontract.org/2004/07/HL7.Base.Struct";   
  8.         public BaseObject() {  
  9.             super();  
  10.         }  
  11.       
  12. }  

 

 

Then the User class

 

  1. package CCH.Model;  
  2. import java.util.Hashtable;  
  3. import org.ksoap2.serialization.PropertyInfo;  
  4. public class User extends BaseObject  
  5. {  
  6.     private String UId;  
  7.     private String UName;  
  8.       
  9.     public Object getProperty(int index) {  
  10.         // TODO Auto-generated method stub   
  11.         switch (index) {  
  12.         case 0:  
  13.             return UId;  
  14.         case 1:  
  15.             return UName;  
  16.         default:  
  17.             return null;  
  18.         }  
  19.     }  
  20.     public int getPropertyCount() {  
  21.         // TODO Auto-generated method stub   
  22.         return 2;  
  23.     }  
  24.     public void getPropertyInfo(int index, Hashtable ht, PropertyInfo info) {  
  25.         // TODO Auto-generated method stub   
  26.         = info.namespace super.NAMESPACE; // this is very important   
  27.         switch (index) {  
  28.         case 0:  
  29.             info.type=PropertyInfo.STRING_CLASS;  
  30.             info.name="UId";  
  31.             break;  
  32.         case 1:  
  33.             info.type=PropertyInfo.STRING_CLASS;  
  34.             info.name="UName";  
  35.             break;  
  36.         default:  
  37.             break;  
  38.         }  
  39.     }  
  40.     public void setProperty(int index, Object value) {  
  41.         // TODO Auto-generated method stub   
  42.         switch (index) {  
  43.         case 0:  
  44.             UId=value.toString();  
  45.             break;  
  46.         case 1:  
  47.             UName=value.toString();  
  48.             break;  
  49.         default:  
  50.             break;  
  51.         }  
  52.     }  
  53.     public String getUId() {  
  54.         return UId;  
  55.     }  
  56.     public void setUId(String uId) {  
  57.         UID = UID;  
  58.     }  
  59.     public String getUName() {  
  60.         return UName;  
  61.     }  
  62.     public void setUName(String uName) {  
  63.         UName = uName;  
  64.     }  
  65.       
  66. }  

 

 

Because what you want to serialize ah, the more trouble to explain. Here it is not explained. We are interested can go look it up. Only explain by info.namespace + info.name to deserialize.

 

3. If the certificate encryption, will always say timeout.

The solution is in the android client calls the following method. To call this method in httptransport.call before ()

 

 

  1. ClientUtil.SetCertification ();   // Set credentials  

 

Class is so written:

 

  1. public class ClientUtil {  
  2.     // Set the certificate to be trusted   
  3.     public static void SetCertification() {  
  4.         try {  
  5.             HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){  
  6.                     @Override  
  7.                     public boolean verify(String hostname,  
  8.                             SSLSession session) {  
  9.                         // TODO Auto-generated method stub   
  10.                         return true;  
  11.                     }});  
  12.             SSLContext context = SSLContext.getInstance("TLS");  
  13.             context.init(null, new X509TrustManager[]{new X509TrustManager(){  
  14.                     public void checkClientTrusted(X509Certificate[] chain,  
  15.                                     String authType) throws CertificateException {}  
  16.                     public void checkServerTrusted(X509Certificate[] chain,  
  17.                                     String authType) throws CertificateException {}  
  18.                     public X509Certificate[] getAcceptedIssuers() {  
  19.                             return new X509Certificate[0];  
  20.                     }}}, new SecureRandom());  
  21.             HttpsURLConnection.setDefaultSSLSocketFactory(  
  22.                             context.getSocketFactory());  
  23.     } catch (Exception e) {   
  24.             e.printStackTrace ();  
  25.     }  
  26. }  
  27. }  

 

 

The trust all certificates. Homemade certificate should not be trusted, so shakehand time has been timeout.

Custom account password authentication 4.wcf set (userNameAuthentication)

After the addition is added to the user information in the head inside the soap before transmission.

The method is added:

 

  1. /* 
  2.          * Authenticator adding password account verification 
  3.          * */  
  4.         ServiceConnection connection=super.getServiceConnection();  
  5.         String Login=Base64.encode("cch:cch1".getBytes());  
  6.         connection.setRequestProperty("Authorization","Basic "+Login);  

 

 

This needs to be rewritten httptransport of getServiceConnection () method.

Because Connection was only initialized when calling httptransport.call (), so outside the program getServiceConnection (). SetRequestProperty () will get an error saying nullpoint.

 

I hope to be helpful.

 

Posted about parsing code:

 

  1. int resultCount=response.getPropertyCount();  
  2.         ArrayList<Dy_sdzbh> list=new ArrayList<Dy_sdzbh>();  
  3.         for (int i = 0; i < resultCount; i++) {  
  4.             SoapObject item = (SoapObject)response.getProperty(i);  
  5.             String sdzbh = item.getProperty("Sdzbh").toString();  
  6.             String sfm = item.getProperty("Sfm").toString();  
  7.             Dy_sdzbh modelDySdzbh = new Dy_sdzbh ();  
  8.             modeldysdzbh.setsfdzbm (sdzbh);  
  9.             modelDySdzbh.setSfm(sfm);  
  10.             list.add(modelDySdzbh);  
  11.         }  
  12.         for (int i = 0; i < resultCount; i++) {  
  13.             java.lang.System.out.println(list.get(i).getSfm());  
  14.         }  

 

 

3 SoapObject 解析
          SoapObject  soapChild=(SoapObject)result.getProperty(int);

          For(int i=0; i<soapChild.getPropertyCount();i++){

                    SoapObject  soapChilds=(SoapObject)result.getProperty(i);

                    String data=soapChilds.getProperty(“Key_Name”).toString();

}

SoapObject class is a major class of service for calling WCF, which can be used as the object request, the server transmits to the WCF; may also be used to store the response information.

The object itself is stored in a set of HTML text of the statement. The SoapObject itself provides a set of HTML parsing of the statement.


We resolve to SoapObject, in fact, it can be understood as parsing of HTML statement.

String type of paper to obtain the target (i.e., service server WCF method returns a String data)

First, we returned to a String divided into three cases: a single String, a String array, a two-dimensional array of String

 

① For a single String, at the time of writing we call a WCF service method, envelope.bodyIn can not be coerced to SoapObject, otherwise it will prompt type conversion errors at run time. At this point envelope.bodyIn Object object can be used as a direct return, you can call its toString () method, you can get the data you want.

 

② String for a one-dimensional array, we want envelope.bodyIn cast into SoapObject, get a SoapObject object of type soap.

In this case, as long as the call SoapObject getProperty () method to obtain the desired data, the parameters corresponding to a dimension array.

For example: return from a one-dimensional array to obtain the first element, just call soap.setProperty (0) can be.

 

③ For a two-dimensional array of String.

at this time. By debugging found, getProgerty () method returns the object SoapObject another, so we can imagine the object SoapObject envelope.bodyIn of a two-dimensional array, wherein getProperty () method returns a row of one-dimensional array, the corresponding parameter is row index, and then by calling it a SoapObject of getProperty () method, you can get an element.

 

For example: For String [0] [1] element, as long as the two calls getProperty () method from envelope.bodyIn the SoapObject: soap.getProperty (0) .getProperty (1)

It is seen, as long as the SoapObject abstracted into an array, it is not difficult to understand and parse the data therein.

 

The SoapObject imagine an array, the array elements can be among his own, soapObject.setProperty (int index, Object value), value here may also be a target soapObject

Guess you like

Origin www.cnblogs.com/Alex80/p/11111896.html