Wednesday, December 17, 2014

Android Webservices -KSOAP2 / Complex Object Types / Array

In this tutorial I'll tell you how to invoke a (SOAP) web service using android. First I may tell you that, when comparing with the REST with JSON, the SOAP is not the fastest way to exchange data with android.

- You can download all source codes using the links at the bottom of the post.

Basically android SDK does not provide any kind of SOAP library. Therefore either we have to manually create a soap request and handle it or we can use an external library. I'll choose the second approach. In this tutorial I'm going to use the KSOAP2 library. You can download it from here.

When we are talking about web services, for our purpose let's divide those services based on output.

1. Primitive type output - services which return a string , int , double ... etc
2. Complex type output - services which return a complex type object like Person{name,age,address}
3. Array of objects

Primitive type


In here what we are going to do is create a simple converter which convert Celsius to Fahrenheit.
Web service : http://www.w3schools.com/webservices/tempconvert.asmx
WSDL : http://www.w3schools.com/webservices/tempconvert.asmx?WSDL

First you have to create a new project , add buttons and text views, link those with the activity. I assumed that kind of basic things you can do easily. In my design nothing special, I just added a edit text to read the value, a button and a text view to show the result.



Now create a new activity, I named it as PrimitiveTypeActivity.  For call a soap method using ksoap we need these 4 things. You can find those information using the WSDL.
( Soap Action = Namespace + Method name )

private final String NAMESPACE="http://www.w3schools.com/webservices/";
private final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL";
private final String SOAP_ACTION="http://www.w3schools.com/webservices/CelsiusToFahrenheit";
private final String METHOD_NAME="CelsiusToFahrenheit";





After that what I'm going to do is call the web service when the button is pressed.

btnConvert.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    String inputString = editTextCValue.getText().toString();
    ConvertorAsyncTask task = new ConvertorAsyncTask();
    task.execute(inputString);
   }
  });


Here you can see I'm creating a new ConvertorAsyncTask variable and call the execute function of it. When calling the execute function I'm passing the value which is read from the text view. So what is happening in ConvertorAsyncTask ?

class ConvertorAsyncTask extends AsyncTask  {
//

You can see now I extended AsyncTask class and created a new inner class. When you're calling web services you have to run the process in background. Otherwise you're activity will not responding until the response is coming . If it is not responding then the android OS will identify it and try to terminate that. Therefore we have to run those in background asynchronously.

@Override
  protected String doInBackground(String... params) {
   // TODO Auto-generated method stub

   SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
   
                        //Sending the value to service
                        PropertyInfo celPI = new PropertyInfo();
   celPI.setName("Celsius");
   celPI.setValue(params[0]);
   celPI.setType(double.class);
   request.addProperty(celPI);

   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
     SoapEnvelope.VER11);

   envelope.dotNet = true;
   envelope.setOutputSoapObject(request);
   HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

   try {
    androidHttpTransport.call(SOAP_ACTION, envelope);
    SoapPrimitive response = (SoapPrimitive) envelope.getResponse();
    return response.toString();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (XmlPullParserException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   return null;
  }

  @Override
  protected void onPostExecute(String result) {
   // TODO Auto-generated method stub
   if (result != null)
    textViewAnswer.setText(result + " F");
   else
    textViewAnswer.setText("Result cannot get.Please try again");

  }

 }

Enter your code inside the doInBackground method. In onPostExecute I set the result to a text view.
Before run the code remember to add the permission tag to manifet file.



That's all. :D


Complex Type

Here I'm going to tell you how to retrieve a complex type object. I created the ComplexTypeActivity for this. For the UI I just added a button and a text view to display results. Let's create the complex type class.
Here I created a class which contain 3 string values. I named it as SimpleObject.

public class SimpleObject implements KvmSerializable {

 private String name;
 private String address;
 private String id;

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }

 @Override
 public Object getProperty(int pid) {
  // TODO Auto-generated method stub
  switch (pid) {
  case 0:
   return this.id;

  case 1:
   return this.name;

  case 2:
   return this.address;
   
  default:
   break;

  }

  return null;
 }

 @Override
 public int getPropertyCount() {
  // TODO Auto-generated method stub
  return 3;
 }

 @Override
 public void getPropertyInfo(int index, Hashtable htable, PropertyInfo info) {
  // TODO Auto-generated method stub

  switch (index) {
  case 0:
   info.type = PropertyInfo.STRING_CLASS;
   info.name = "id";
   break;
  case 1:
   info.type = PropertyInfo.STRING_CLASS;
   info.name = "name";
   break;
  case 2:
   info.type = PropertyInfo.STRING_CLASS;
   info.name = "address";
   break;

  }

 }

 @Override
 public void setProperty(int index, Object value) {
  // TODO Auto-generated method stub
  switch (index) {
  case 0:
   this.id = value.toString();
   break;
  case 1:
   this.name = value.toString();
   break;
  case 2:
   this.address = value.toString();
   break;

  }

 }

}

Note that I implemented the KvmSerializable interface here. Using that interface KSOAP map those class properties with soap message.

Same as earlier I'm going to call the web service when pressed the button.
btnShowDetails.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    LoadDetailsTask task = new LoadDetailsTask();
    task.execute("ID01");
   }
  });

class LoadDetailsTask extends AsyncTask {

  private final String NAMESPACE = "http://service.blog.anjula.com/";
  private final String URL = "http://112.135.137.22:8080/BlogWebService/BlogWebService?WSDL";
  private final String SOAP_ACTION = "http://service.blog.anjula.com/getDetails";
  private final String METHOD_NAME = "getDetails";

  SimpleObject result = new SimpleObject();

  @Override
  protected SimpleObject doInBackground(String... addId) {

   SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

   PropertyInfo idListPropety = new PropertyInfo();

   idListPropety.setName("id");
   idListPropety.setValue(addId[0]);
   idListPropety.setType(addId[0].getClass());
   request.addProperty(idListPropety);

   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
     SoapEnvelope.VER11);

   // envelope.dotNet = true;
   envelope.setOutputSoapObject(request);

   envelope.addMapping(NAMESPACE, "SimpleObject",
     new SimpleObject().getClass());

   HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

   try {
    androidHttpTransport.debug = true;
    androidHttpTransport.call(SOAP_ACTION, envelope);
    SoapObject response = (SoapObject) envelope.getResponse();

    result.setId(response.getProperty("id").toString());
    result.setName(response.getProperty("name").toString());
    result.setAddress(response.getProperty("address").toString());

    return result;

   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (XmlPullParserException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

   return null;

  }

  @Override
  protected void onPostExecute(SimpleObject result) {
   // TODO Auto-generated method stub
   if (result != null)
    textViewResult.setText("Id: " + result.getId() + "\nName: "
      + result.getName() + "\nAddress: "
      + result.getAddress());
  }

 }
//

Here you can see I'm mapping the out put using field names.

result.setId(response.getProperty("id").toString());
    result.setName(response.getProperty("name").toString());
    result.setAddress(response.getProperty("address").toString());

In URL I entered my IP address there, because I ran the service in my computer. Therefore you have to change that IP address to your IP address if you're running the server application in your computer.
After you pressed the button the program will invoke this method.

public SimpleObject getDetails(String id){
        SimpleObject result = new SimpleObject();        
        result.setId(id);
        result.setName("Anjula");
        result.setAddress("Kaduwela");        
        return result;        
    }

That's all :D

Array of Objects

Here I'm using the same complex type class which I mentioned above. My activity name is ArrayTypeActivity. 



class LoadDetailsTask extends AsyncTask {

  private final String NAMESPACE = "http://service.blog.anjula.com/";
  private final String URL = "http://112.135.137.22:8080/BlogWebService/BlogWebService?WSDL";
  private final String SOAP_ACTION = "http://service.blog.anjula.com/getArrayDetails";
  private final String METHOD_NAME = "getArrayDetails";
  SimpleObject result[] = new SimpleObject[3];

  @Override
  protected SimpleObject[] doInBackground(String... idList) {

   SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
   PropertyInfo idListPropety = new PropertyInfo();  
   idListPropety.setName("id");
   idListPropety.setValue(idList[0]);
   idListPropety.setType(idList[0].getClass());
   request.addProperty(idListPropety);
   
   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
     SoapEnvelope.VER11);

   // envelope.dotNet = true;
   envelope.setOutputSoapObject(request);

   envelope.addMapping(NAMESPACE, "SimpleObject",
     new SimpleObject().getClass());

   HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

   try {
    androidHttpTransport.debug = true;
    androidHttpTransport.call(SOAP_ACTION, envelope);

    Vector response = (Vector) envelope
      .getResponse();

    for (int i = 0; i < response.size(); i++) {
     SoapObject tempObject = response.get(i);
     if (tempObject != null) {
      SimpleObject temp = new SimpleObject();
      temp.setId(tempObject.getProperty("id").toString());
      temp.setName(tempObject.getProperty("name").toString());
      temp.setAddress(tempObject.getProperty("address")
        .toString());
      result[i] = temp;
     }
    }

    // SoapPrimitive response = (SoapPrimitive)
    // envelope.getResponse();

    return result;

   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (XmlPullParserException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

   return null;

  }

  @Override
  protected void onPostExecute(SimpleObject[] result) {
   // TODO Auto-generated method stub
   // super.onPostExecute(result);
   String text = "";
   if (result == null) {
    Log.d("NULL", "This is null");
   } else {
    for (int i = 0; i < result.length; i++) {
     if (result[i] != null) {
      
      text=text+"Id: " + result[i].getId() + "\nName: "
        + result[i].getName() + "\nAddress: "
        + result[i].getAddress()+"\n";

     }
    }
    textViewResult.setText(text);
   }

  }

 }

//

Here note that instead of retrieving a single object we are retrieving an array of objects. So we have to handle that using Vectors.
Vector response = (Vector) envelope
      .getResponse();

    for (int i = 0; i < response.size(); i++) {
     SoapObject tempObject = response.get(i);
     if (tempObject != null) {
      SimpleObject temp = new SimpleObject();
      temp.setId(tempObject.getProperty("id").toString());
      temp.setName(tempObject.getProperty("name").toString());
      temp.setAddress(tempObject.getProperty("address")
        .toString());
      result[i] = temp;
     }
    }
//



You can download web service from (Netbeans) here and to download the android source code (eclipse) click here. 

Friday, November 29, 2013

Having Fun with XNA - Game Development - Fly Me Home

XNA is a framework which provide facilities you to create your own game very easily. To work with XNA you don't need any extra knowledge about programming. Simply you just need to understand the life cycle of xna engine. after that creating your game is nothing and xna enable you to create game for xbox, PC,  as well as the windows phones.

In 2nd semester of 4th year we had a subject call GD (Game development). Under that subject there was an assignment to create a 2D game using xna. Me and my friend proffa developed a game call "Fly Me Home".
In that game user is playing as a bird. what you have to do is collect the foods withing a given time period and flying safe to home.

This is a short video of that game. :D





Saturday, November 16, 2013

The Seeker - Mobile Security App

When we were in 3rd year in SLIIT there was a subject called MAD - Mobile Application Development. Under that subject we learned iPhone app and android app development. Under MAD we had to develop a n app using android & ios. For that we developed two different applications. Using ios Proffa(Krishantha) developed a puzzle game and for android I developed a mobile security application called "The Seeker" .

The seeker is working based on commands received using SMS messages. Of course, you can customize those commands. In this version (1.1) I created only several basic security functions. In later versions I'm going to  implement this with more features.

SIM
In this function rather than the codes you have to mention a trusted mobile number. If the SIM is changed the app will automatically send you the new SIM number and other details. If you want you can get IMEI or the SIM number using the codes at any time.

GPS
After you activated this function, the app will send you the coordinates of the current location where the phone is.This will send a message in every 3 minutes until you send the code again and disable that feature.

ALARM
Using this function you can ring an alarm. This alarm can be stopped only by sending the code again.

LOCK
This will lock your device, even the user unlock it by using your pattern or pin automatically again it will locked. To unlock you have to send the code again.

WIPE
Simple to wipe all your data this function can be used. To wipe all data several minutes will taken. This time is depending on the device.

The Seeker is now available in Google Play.


You can see a demonstration video below.

Tuesday, November 5, 2013

Location Based Advertisements And Indoor Navigation System For Shopping Malls (Research)

Project Name : Location Based Advertisements And Indoor Navigation System For Shopping Malls
Duration : 8 Months
My Contribution : 1. Android App
                                      2. Web Service 
                                      3. Staircases Patterns 



This was our final year research project. There were four members in our group. In this project we were focusing on indoor navigation and make it use in practical way. Based on that idea we were able to developed the Location based advertisements system for indoor environment.

My team. ( From Left - Thilina , Krishantha, My self and Chathura  )


Advertising is one of the most innovative concept present in our society today. It helps to keep the consumers informed about whatever new products or services that are available in the market at their disposal and to spread awareness about products or services that are of some use to consumer and potential buyers. The main aim of advertising, many believe is to sell. These are the kind of people who vehemently oppose anything that make advertising seem unethical. Advertising on the whole helps business as well as the economy to prosper and makes the consumer aware of the various choices that are available to him. Although the concept is pictured over different aspects, currently in places like shopping malls they use the same conventional ways of displaying advertisements. In this project we introduce a novel concept of delivering location based advertisements to hand held devices reside in large shopping malls while navigating the user to particular shops they chose to visit.

Modern researches over indoor navigation systems has gained a fresh impetus over last couple of years, making indoor spaces and indispensable part of current geospatial research. Navigational applications are one of the booming industries, focusing more and more on the indoor world. Even though there are number of researches took place using various technologies, none of these has been developed and distributed to consumers.

Therefore through this project we hope to build up a “Location Based Advertisements and Navigation System for Shopping Malls”, a self –contained , map-based, indoor navigation and advertisement system Making use of hand held devices with motion (accelerometers) and rotation(gyroscopes) sensors to continuously calculate their motion and position. All the sensing and computing technologies we accurately localize user’s route, and provide turn by turn instructions to their destination.

Location based Advertisements

System Diagram

There are several QR codes placed in each entry at every floor of the shopping mall.When user is entering to the shopping mall he can read those QR using his mobile. In the QR we stored the position of the user. Therefore after read the QR code we know the current place of the user meanwhile the app will star to track the user movements using the sensors.

In the map we have defined several regions. Each region contain 2-3 shops. So the user will get the advertisements corresponding to the region he is in. So where are advertisements coming from ? Those advertisements coming from the application server. The shop owners of the shop can feed their advertisements into our system using the web interface we provided to them.

Simply the location based ads process is this.
1. Shop owner feed advertisements to the system
2. Those advertisements stored in application server
3. When user in the shopping mall the advertisements will send to his mobile based on location


Home Page 

Register Shop Owner

Upload Advertisements

Random Advertisements, Search Advertisements & More... 
Not only in the shopping mall our app can be used even you're at home. When you're at home the app will show you advertisements which are selected randomly. If you like particular advertisement you can add them to your favorite list. If you want to find a advertisement , there is a search function which allow you to find your advertisement fast. If you want to view advertisements that are belong to particular category, for that you can view the advertisements by category. 

Demonstration 
To be more realistic we used this app for a shopping mall in Sri Lanka which is called as Majestic City.



For the demonstration we selected simple area of MC and draw our map. In below video you can see how the app is working.



Monday, November 4, 2013

SKOLAYA - The School Management & Intelligent Results Prediction System (Research)

Project Name : SKOLAYA - A School Management & Intelligent Results Prediction System
Duration : 1 Month
What I Implemented : Complete System



“Talent wins games, but teamwork and intelligence wins championships.”
Michael Jordan

After we collect the all the requirements, we started to develop the system. Basically it is a school management system. In schools there are several streams that can be chosen when you're at grade 12. So managing those were little bit tricky. Using this system, the administrator level users should be able to create time tables for all classes. Implementing that was a one of hardest part of that project. We have implemented the system that the user can view the particular class time table as well as the time tables of all the classes in a particular grade. It will make user easier to handle overlaps when he is creating the time table.

Apart of that, as the research module the system will analyze the results of previous years, previous terms and predict the result of a student for each subject. And that was the second hardest part of this system.

This is a short video of that system.



Here you can see a video which describe most of the important functions of the system.