In this post I’m going to explain how would you consume a WCF service published on IIS on your local machine from an Android app on a device connected to local WiFi.
Before we start 3 prerequisites are needed:
- Basic knowledge of Android development.
- Knowledge of WCF services and SOA architecture.
- Basic knowledge of JSON data interchange protocol and format.
HOWEVER, I always believe in upside knowledge gain in software development; just try to code something even of you don’t understand much about .. you’ll get the big picture later.
Let’s start!
- The service:
The service we’re building is a very simple one. It will provide some data about people ( just ID’s and Names).
- Create a WCF Service application on Visual Studio call it “PersonsService”.
- We’re using REST module for building our service so on the Web.config file, remove the <system.serviceModel> tag with all of it’s contents.
- Right click on PersonsService.svc –> View Markup and add the following line to the <servicehost> tag:
Factory ="System.ServiceModel.Activation.WebServiceHostFactory"
Congratulations we now have a REST service, let’s start to make it useful for anything!
On IPersonsService.cs, you’ll find the Interface which will expose our methods and a class which acts as a data contract:
Rename the class to Person, remove the existing fields and add ID and Name Fields. It should look like this:
[DataContract]
public class Person
{
int id;
string name;
[DataMember]
public int ID
{
get { return id; }
set { id = value; }
}
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
}
Next, clean everything at the interface “IPersonService” and add a GetPersonsDataJSON() method that returns a list of persons:
[ServiceContract]
public interface IPersonService
{
[WebGet(UriTemplate="/personsdataJSON",
ResponseFormat=WebMessageFormat.Json)]
[OperationContract]
List GetPersonsDataJSON();
}
Notice the “WebGet” annotation above the method, this actually says 2 things:
- ResponseFormat=WebMessageFormat.Json: which means that we would like to use the JSON protocol for exchanging the data between our service and our client.
- UriTemplate=”/personsdataJSON”: means that the data formatted in JSON will be under the /personsdataJSON.
If we needed to provide data in XML format for some reason instead, we would add a new method to the IPersonService interface called GetPersonsDataXML() with UriTemplate=”/personsdataXML” & ResponseFormat=WebMessageFormat.XML.
One step for the end, on PersonService.svc.cs inherit the IPersonsService and implement the GetPersonsDataJSON method. Should look like this:
public class PersonService : IPersonService
{
public List GetPersonsDataJSON()
{
Person p1 = new Person();
p1.ID = 1;
p1.Name = "Mina";
Person p2 = new Person();
p2.ID = 2;
p2.Name = "John";
Person p3 = new Person();
p3.ID = 3;
p3.Name = "Paula";
List persons = new List();
persons.Add(p1);
persons.Add(p2);
persons.Add(p3);
return persons;
}
}
And the service is ready!
- Publishing on IIS:
This should be the easiest part: Right click on your project –> Properties –> Web –> select Use Local IIS Web Server and make sure Use IIS Express is unmarked then press Create Virtual Directory:
Web tab on project properties
Note: You should be running Visual Studio as Administrator to be able to create the publish the service on IIS.
Now open IIS Manager, the service should be under Sites/Default Web Site .. Right click on it –> Manage Application –> Browse. You should see your project listing opened on your browser. Add /PersonService.svc/personsdataJSON to the path, so it should be:
http://localhost/PersonService/PersonService.svc/personsdataJSON
And the data should be returned on JSON format:
JSON formatted data
Note: Make sure to grant full control permission for IIS_IUSRS on the Web.config from properties & also on the PersonsService application on IIS through: Right click –> Edit Permissions –> Security tab.
- The Client:
UI: Well this is just a simple example to prove the concept, so let’s keep it simple. Here are the views:
- Place a list view that displays names.
- A button titled “Get Data”.
- A TextView as a title for the list.
It should look something like this:
Client UI
As for the client logic there are 3 main components:
- Initialization
- Getting the data
- Extending AsyncTask to work asynchronously
1- Initialization:
- We need to initialize an instance of HttpClient which will help us to execute HttpGet which holds the service URL which returned the data previously when we ran it on browser.
- An instance or JSONObject which will hold the returned data.
- A string for the URL of the service
HttpClient client;
final static String URL = "http://192.168.1.6/RPersonService/PersonService.svc/personsdata";
JSONObject json;
Inside the onCreate method place:
client = new DefaultHttpClient();
2- Getting the Data:
Now add another method and call it getPersonsData(). This method will do the following:
- Create an instance of HttpGet and give it the URL of the service.
- Use the HttpClient we created to execute HttpGet and return a response.
- Check the response status if it’s success, then starts filling the data in a JSONArray and returns it.
Code:
public JSONArray getPersonsData() throws ClientProtocolException, IOException, JSONException
{
HttpGet get = new HttpGet(URL);
HttpResponse response = client.execute(get);
int status = response.getStatusLine().getStatusCode();
if(status == 200) //sucess
{
HttpEntity e = response.getEntity();
String data = EntityUtils.toString(e);
JSONArray personsData = new JSONArray(data);
return personsData;
}
else
{
Toast.makeText(this, "error", Toast.LENGTH_SHORT);
return null;
}
}
3- Extending AsyncTask to work asynchronously:
Add a new class called ReadData and set it to extend AsyncTask class. AsyncTask class let’s us generically specify the data structure we’re going to convert the JSONarray to, here we’ll use an ArrayList<String>.
Code:
public class ReadData extends AsyncTask<String, Integer, ArrayList>
{
@Override
protected void onPostExecute(ArrayList data) {
ArrayAdapter arrayAdapter =
new ArrayAdapter(getApplicationContext(),android.R.layout.simple_list_item_1, data);
lstView.setAdapter(arrayAdapter);
super.onPostExecute(data);
}
@Override
protected ArrayList doInBackground(String... params) {
try {
JSONArray personsNames = getPersonsData();
ArrayList persons = new ArrayList();
for(int i=0; i< personsNames.length(); i++)
{
persons.add(personsNames.getJSONObject(i).getString("Name"));
}
return persons;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
ReadData class contains two overridden functions:
- doInBackground: Will call the getPersonsData and encapsulates the returned JSON data into an ArrayList<String>
- onPostExecute: Will take the ArrayList<String> formatted data and place it in the UI (ListView).
Notice that the returned data type from doInBackground must match with the data type of the parameter passed to the OnPostExecute method.
At the button click event of button Get Data we will use the ReadData class as follows:
new ReadData().execute();
One last thing, on AndroidManifest.xml add this line which will give permission to the app to use the internet/WiFi:
<uses-permission android:name="android.permission.INTERNET"/>
Now disable your Windows firewall, Run & press Get Data!:
Your android client is consuming your WCF service!
Happy Coding! 🙂