• [转]实例:在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

  • 相关阅读:
    Delphi代码获取网卡物理地址三种方法 本文来自Delphi之窗,原文地址:http://www.52delphi.com...
    SQL SERVER 中实现公历到农历的转换
    cxgrid相同列合并显示
    rzCheckList.ItemChecked[Index]就可以判断指定节点地状态.
    为什么PING域名得到IP与实际公网IP不符
    如何让sql server2005和sql server2000共存安装在同一机器上
    如何编译通过 Raize 5.3 中的 RzBorder.pas
    u6升级到u890的过程
    技术部门到底该如何管理才能“和谐”
    在CXGRID中如何让字段能以0.00的格式显示
  • 原文地址:https://www.cnblogs.com/freeliver54/p/2705274.html
Copyright © 2020-2023  润新知