[转]实例:在Android调用WCF服务

本文转自:http://hi.baidu.com/iytwcrfaukbbcuq/item/366263e2ebc1612e4ddcaffe

 

原文:http://fszlin.dymetis.com/post/2010/05/10/Comsuming-WCF-Services-With-Android.aspx

 

It seems processing XML is too heavy for mobile devices. Android did not provide any tool to help consuming SOAP web service. But as Android bundled with org.apache.http and org.json packages, it is relative simple to consume RESTful WCF services.

The following sections describe the steps to create RESTfule WCF services and the Android client to consume the services.

First, I created a service contract with two GET and one POST operations. Since the Android client will transfer data in JSON objects, I specify JSON as request and response format. In order to support more than one parameter, I set BodyStyle to WrappedRequest.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace HttpWcfWeb
{
     [ServiceContract(Namespace = "http://services.example.com/" )]
     public interface IVehicleService
     {
         [OperationContract]
         [WebGet(
             UriTemplate = "GetPlates" ,
             BodyStyle = WebMessageBodyStyle.WrappedRequest,
             ResponseFormat = WebMessageFormat.Json,
             RequestFormat = WebMessageFormat.Json)]
         IList< string > GetPlates();
  
         [OperationContract]
         [WebGet(UriTemplate = "GetVehicle/{plate}" ,
             BodyStyle = WebMessageBodyStyle.WrappedRequest,
             ResponseFormat = WebMessageFormat.Json,
             RequestFormat = WebMessageFormat.Json)]
         Vehicle GetVehicle( string plate);
  
         [OperationContract]
         [WebInvoke(
             Method = "POST" ,
             UriTemplate = "SaveVehicle" ,
             BodyStyle = WebMessageBodyStyle.WrappedRequest,
             ResponseFormat = WebMessageFormat.Json,
             RequestFormat = WebMessageFormat.Json)]
         void SaveVehicle(Vehicle vehicle);
     }
}

Next, I defined the composite object will be transferred between server and Android client. It is simple but enough to prove we will be able to transfer complex objects.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
namespace HttpWcfWeb
{
     [DataContract]
     public class Vehicle
     {
         [DataMember(Name = "year" )]
         public int Year
         {
             get ;
             set ;
         }
  
         [DataMember(Name = "plate" )]
         public string Plate
         {
             get ;
             set ;
         }
  
         [DataMember(Name = "make" )]
         public string Make
         {
             get ;
             set ;
         }
  
         [DataMember(Name = "model" )]
         public string Model
         {
             get ;
             set ;
         }
     }
}

Now, expose the WCF service via webHttp behavior in web.config.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
< system.serviceModel >
   < behaviors >
     < endpointBehaviors >
       < behavior name = "httpBehavior" >
         < webHttp />
       </ behavior >
     </ endpointBehaviors >
     < serviceBehaviors >
       < behavior name = "" >
         < serviceMetadata httpGetEnabled = "true" />
         < serviceDebug includeExceptionDetailInFaults = "false" />
       </ behavior >
     </ serviceBehaviors >
   </ behaviors >
   < serviceHostingEnvironment multipleSiteBindingsEnabled = "true" />
     < services >
       < service name = "HttpWcfWeb.VehicleService" >
         < endpoint address = ""
                      behaviorConfiguration = "httpBehavior"
                      binding = "webHttpBinding"
                      contract = "HttpWcfWeb.IVehicleService" />
     </ service >
   </ services >
</ system.serviceModel >

It you are using Visual Studio's Development Server to test the WCF service, you may need to deploy the service to IIS. This is due to the Development Server only serve request from local machine, and the Android client won't be able to access the service hosted on it.

Further, if you are using host name (e.g. computer name) in the URL of the service, you may have to setup the DNS in you device or emulator, so that it can resolve the host name. Simply go to Settings -> Wireless Control -> Mobile Networks -> Access Point Names, click on the one that is in use, fill in Proxy and Port with your DNS server.
Setup Proxy and Port

Now, I have my WCF service ready, and I am going to build the Android client to consume the WCF service.
Android UI

During initialization, the Activity will invoke IVehicleService.GetPlates method to populate the Spinner. When the Load Vehicle button is clicked, the vehicle will be loaded from the IVehicleService.GetVehicle method and the EditText views will be populated. On the other hand, Save button will wrap the data entered and post to IVehicleService.SaveVehicle method.

The code the initialize the UI I created.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MainActivity extends Activity {
  
     private final static String SERVICE_URI = "http://lt0.studio.entail.ca:8080/VehicleService.svc" ;
  
     private Spinner plateSpinner;
     private EditText makeEdit;
     private EditText plateEdit;
     private EditText yearEdit;
     private EditText modelEdit;
  
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
  
         plateSpinner = (Spinner)findViewById(R.id.plate_spinner);
         makeEdit = (EditText)findViewById(R.id.make_edit);
         plateEdit = (EditText)findViewById(R.id.plate_edit);
         yearEdit = (EditText)findViewById(R.id.year_edit);
         modelEdit = (EditText)findViewById(R.id.model_edit);
     }
      
     @Override
     public void onResume() {
         super .onResume();
  
         // Invoke IVehicleService.GetPlates and populate plateSpinner
         refreshVehicles();
     }
}

The refreshVehicles method will be invoked when the activity is resumed or a new vehicle is saved. It send a GET request to the WCF service and retrieves a list of plates in JSON string, and the response string is parsed by JSONArray.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void refreshVehicles() {
     try {
 
         // Send GET request to <service>/GetPlates
         HttpGet request = new HttpGet(SERVICE_URI + "/GetPlates" );
         request.setHeader( "Accept" , "application/json" );
         request.setHeader( "Content-type" , "application/json" );
 
         DefaultHttpClient httpClient = new DefaultHttpClient();
         HttpResponse response = httpClient.execute(request);
 
         HttpEntity responseEntity = response.getEntity();
          
         // Read response data into buffer
         char [] buffer = new char [( int )responseEntity.getContentLength()];
         InputStream stream = responseEntity.getContent();
         InputStreamReader reader = new InputStreamReader(stream);
         reader.read(buffer);
         stream.close();
 
         JSONArray plates = new JSONArray( new String(buffer));
 
         // Reset plate spinner
         ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         for ( int i = 0 ; i < plates.length(); ++i) {
             adapter.add(plates.getString(i));
         }
         plateSpinner.setAdapter(adapter);
          
     } catch (Exception e) {
         e.printStackTrace();
     }
}

The onLoadVehicleClick method is the event handler for Load Vehicle button. Just like refreshVehicles method, It send a GET request to the WCF service and retrieve the vehicle information by plate number. But instead of JSONArray, it used JSONObject to parse the response data, since the WCF service is returning an vehicle object.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void onLoadVehicleClick(View button) {
     try {
         // Send GET request to <service>/GetVehicle/<plate>
         DefaultHttpClient httpClient = new DefaultHttpClient();
         HttpGet request = new HttpGet(SERVICE_URI + "/GetVehicle/" + plateSpinner.getSelectedItem());
 
         request.setHeader( "Accept" , "application/json" );
         request.setHeader( "Content-type" , "application/json" );
 
         HttpResponse response = httpClient.execute(request);
 
         HttpEntity responseEntity = response.getEntity();
 
         // Read response data into buffer
         char [] buffer = new char [( int )responseEntity.getContentLength()];
         InputStream stream = responseEntity.getContent();
         InputStreamReader reader = new InputStreamReader(stream);
         reader.read(buffer);
         stream.close();
 
         JSONObject vehicle = new JSONObject( new String(buffer));
 
         // Populate text fields
         makeEdit.setText(vehicle.getString( "make" ));
         plateEdit.setText(vehicle.getString( "plate" ));
         modelEdit.setText(vehicle.getString( "model" ));
         yearEdit.setText(vehicle.getString( "year" ));
 
     } catch (Exception e) {
         e.printStackTrace();
     }
}

When Save button is clicked, onSaveVehicleClick method will be invoked. It simply gather all text fields into a JSONObject and post it to the WCF service. Noticed that the all the data was wrapped into an object named vehicle, WCF will pass this object as parameter vehicle.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public void onSaveVehicleClick(View button) {
 
     try {
 
         Editable make = makeEdit.getText();
         Editable plate = plateEdit.getText();
         Editable model = modelEdit.getText();
         Editable year = yearEdit.getText();
 
         boolean isValid = true ;
 
         // Data validation goes here
 
         if (isValid) {
 
             // POST request to <service>/SaveVehicle
             HttpPost request = new HttpPost(SERVICE_URI + "/SaveVehicle" );
             request.setHeader( "Accept" , "application/json" );
             request.setHeader( "Content-type" , "application/json" );
 
             // Build JSON string
             JSONStringer vehicle = new JSONStringer()
                 .object()
                     .key( "vehicle" )
                         .object()
                             .key( "plate" ).value(plate)
                             .key( "make" ).value(make)
                             .key( "model" ).value(model)
                             .key( "year" ).value(Integer.parseInt(year.toString()))
                         .endObject()
                     .endObject();
             StringEntity entity = new StringEntity(vehicle.toString());
 
             request.setEntity(entity);
 
             // Send request to WCF service
             DefaultHttpClient httpClient = new DefaultHttpClient();
             HttpResponse response = httpClient.execute(request);
 
             Log.d( "WebInvoke" , "Saving : " + response.getStatusLine().getStatusCode());
              
             // Reload plate numbers
             refreshVehicles();
         }
 
     } catch (Exception e) {
         e.printStackTrace();
     }
}

Finally, add the internet permission into AndroidManifest.xml, to allow the sample application access WCF service.

?
1
< uses-permission android:name = "android.permission.INTERNET" />

And the demo is ready to go.
Android Application

转载于:https://www.cnblogs.com/freeliver54/archive/2012/09/27/2705274.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值