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

来源:互联网 发布:javascript库 知乎 编辑:程序博客网 时间:2024/05/01 19:40

转自:http://www.cnblogs.com/yiway/archive/2011/12/16/Consuming_WCF_Serveric_With_Android.html

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

 

在移动设备中,使用XML传输可能会消耗更多的资源,Android没有提供任何组件来直接调用WCF,但是我们可以通过第三方的包(例如:org.apache.http,org.json)来相对简单的调用REST形式的WCF服务。

本文将演示如何创建REST形式的WCF服务和在Android上如何调用服务。

第一步,创建一个包含两个GET操作和一个POST操作的Service Contract。由于是通过JSON对象传输数据,这里需要指定Request和Response的数据格式为JSON。为了支持多个参数,还需要设置BodyStyle为WrappedRequest。

 

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

下一步,定义一个用于数据传输的对象,这个对象很简单。

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

现在,我们修改web.config文件,发布WCF服务。

复制代码
<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>
复制代码

由于VS内置的开发服务器只能处理来自本机的请求,所以需要把服务部署到IIS。

另外,如果你在URL中使用主机名(比如:机器名)的话,你也许还需要在设备或模拟器中设置DNS,这样才可以解析主机名。方法是,进入“系统设置(Setting)”->无线网络设置(Wireless Control)->网络接入点,选择正在使用的那一个,填写代理和端口。

 image

现在,我需要创建Android客户端来调用WCF服务。

image[1]_3

在启动过程中,活动(Activity)调用IVehicleService.GetPlates方法填充Spinner。

当Load Vehicle按钮点击时,通过调用IVehicleService.GetVehicle方法得到Vehicle对象并填充到EditText中。

点击Save按钮时,将数据包装并提交到IVehicleService.SaveVehicle方法。

复制代码
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();    }}
复制代码



在数据保存或者Activity被恢复(resumed)的时候会调用refreshVehicles方法,它向WCF服务发送一个Get请求,得到一个由JSON字符串表达的数据对象。

复制代码
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();    }}
复制代码

onLoadVehicleClick 方法处理Load Vehicle 点击事件,和refreshVehicles 方法相似,它发送一个GET请求到WCF服务,通过plate number得到一个vehicle对象,但区别在于,它在结果处理中使用了JSONObject 转换,就像直接从WCF服务中拿到的vehicle对象一样。

复制代码
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();    }}
复制代码

当Save按钮点击时,调用onSaveVehicleClick 方法。这个方法中简单的将所有的文本字段的值放入一个JSONObject对象,然后提交(POST)给WCF服务。注意所有的数据包装进了一个叫vehicle的对象,WCF收到后,会将其作为名称为vehicle的参数。

复制代码
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();    }}
复制代码

最后,在AndroidManifest.xml中添加Internet的访问权限。

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

DEMO可以运行。

android application


原创粉丝点击