Friday, February 24, 2012

Accessing Apache Axis2 Web service inside a Android Application - Part 2 - Apache Axis 2, Android API 8, phpmyadmin, Eclipse Indigo, VMware Player

Part 2

As I explained in my earlier post,  Accessing Apache Axis2 Web service inside a Android Application - Part 1 you can create a web service. In this post I will explain how to create a android application use this web service. In my example's web service, it can give you details about cities and places in Sri Lanka. So we will query that service to get those data,

Step 1 - Create a new android project in Eclipse.
Step 2 - Add internet permission to the Android Application by editing AndroidManifest.xml file like this.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.web.frontend.calculator"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidFrontendActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Step 3 - Edit the main.xml file like this.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/txtCityLongitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtCityLatitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMLon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMLat"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMCat"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMDes"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

</LinearLayout>


Step 3 - I use KSOAP as my connection between web service and Android App. So download it from here. 

kSOAP2 - An efficient, lean, Java SOAP library for constrained devices

Add it to your android project. Right click on your project go to Java Build Path > Add External Jar
and select kSOAP.

Step 4 - Edit the java activity file like this.

package org.web.frontend.calculator;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidFrontendActivity extends Activity {

    private String METHOD_NAME = "";
    // our webservice method name
    private String NAMESPACE = "http://ws.travel_ceylon.web.org";
    // Here package name in webservice with reverse order.
    private String SOAP_ACTION = NAMESPACE + METHOD_NAME;
    // NAMESPACE + method name
    private static final String URL = "http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl";

    // you must use ipaddress here, don’t use Hostname or localhost

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String city = "Matara";
        String im = "Galle Face";

        METHOD_NAME = "getLongitude_City";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("city", city);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtCityLongitude)).setText(city
                    + " Longitude is : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtCityLongitude)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }
        METHOD_NAME = "getLatitude_City";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("city", city);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtCityLatitude)).setText(city
                    + " Latitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtCityLatitude)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getLongitude_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMLon)).setText(im
                    + " Longitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMLon)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getLatitude_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMLat)).setText(im
                    + " Latitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMLat)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getCategory_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMCat)).setText(im
                    + " Category : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMCat)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getDescription_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMDes)).setText(im
                    + " Description : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMDes)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }
    }
}


I will explain this code like this, Here are the variable assignments,


    private String METHOD_NAME = "";
    // Here you have to put your method you are calling
    // I am calling float getLongitude_City(String city) so I assign this variable like this. METHOD_NAME = "getLongitude_City";
    private String NAMESPACE = "http://ws.travel_ceylon.web.org";
    // Here package name in webservice with reverse order.
    private String SOAP_ACTION = NAMESPACE + METHOD_NAME;
    // NAMESPACE + method name
    private static final String URL = "http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl";

    // you must use ipaddress here, don’t use Hostname or localhost
    // That is why I used a virtual machine to have a small network inside my machine.


Next I will explain the other part of the source,

  METHOD_NAME = "getLongitude_City";

  try {
   SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
   request.addProperty("city", city);
   // Here we bind parmeters to our SOAP packet.
   // in my getLongitude_City"it has a argument called city of Stirng
   // type. This is the way I assigen value to it.

   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
   SoapEnvelope.VER11);
   envelope.dotNet = true;
   envelope.setOutputSoapObject(request);
   HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
   androidHttpTransport.call(SOAP_ACTION, envelope);
   Object result = envelope.getResponse();
   // Here we get the reposnse from the SOAP object.
   ((TextView) findViewById(R.id.txtCityLongitude)).setText(city
   + " Longitude is : " + result.toString());
  } catch (Exception E) {
   E.printStackTrace();
   ((TextView) findViewById(R.id.txtCityLongitude)).setText("ERROR:"
   + E.getClass().getName() + ":" + E.getMessage());
  }


After doing all these editing. Go to the virtual machine and run the web service. Check the connectivity between virtual machine and your machine. Then run the Android app. then you can see these information come from the web service.


Hope this article helped you. Please put comments about my article. It will help me to improve my articles in the future.

Accessing Apache Axis2 Web service inside a Android Application - Part 1 - Apache Axis 2, Android API 8, phpmyadmin, Eclipse Indigo, VMware Player

Part 1

In this series of articles I am going to show you the complete set of steps to access a web service inside Android application. I am expecting you to have knowledge about following,
  • Create a web service using Apache Axis 2 and Eclipse. (If you don't know here are some useful links : Link1 , Link 2)
  • Create a simple web service client using Axis2 plug in and Eclipse. (If you don't know here are some useful links : Link1)
  • Create a simple android project with text fields to show some texts. (If you don't know here are some useful links : Link1)
  • More importantly you have to have a working virtual machine inside  your machine using something like VMware player. Also you have to have a host only private network with this virtual machine and you machine. Also you have to install Eclipse,Apache axis 2 and tomcat server in this virtual machine.
So having those prerequisites I will continue like this.I am going to create a simple web service which is capable to give data to it users by querying a local database it has.

Step 1- In my example I use a database called travel_ceylon. So In side your virtual machine create a database using phpmyadmin. and import following sql file to that database,

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `category` (
  `Category` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `category` (`Category`) VALUES
('History'),
('Religon - Buddhisum'),
('Religon - Catholic'),
('Religon - Islam'),
('Religon - Hindu'),
('Technology'),
('Nature');

CREATE TABLE IF NOT EXISTS `city` (
  `City_Name` varchar(100) NOT NULL,
  `Latitude` float NOT NULL,
  `Longitude` float NOT NULL,
  PRIMARY KEY (`City_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


INSERT INTO `city` (`City_Name`, `Latitude`, `Longitude`) VALUES
('Aluthgama', 6.59991, 79.9568),
('Ambalangoda', 6.2367, 80.0544),
('Matara', 5.94413, 80.5494),
('Monaragala', 6.87268, 81.3506),
('Moratuwa', 6.77453, 79.8826),
('Wellawaya', 6.73203, 81.1019);

CREATE TABLE IF NOT EXISTS `close_to` (
  `City_Name` varchar(100) NOT NULL,
  `Place_Name` varchar(100) NOT NULL,
  `Distance` float NOT NULL,
  KEY `City_Name` (`City_Name`,`Place_Name`),
  KEY `Place_Name` (`Place_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

CREATE TABLE IF NOT EXISTS `important_places` (
  `Place_Name` varchar(100) NOT NULL,
  `Category` varchar(200) NOT NULL,
  `Description` varchar(500) NOT NULL,
  `Latitude` float NOT NULL,
  `Longitude` float NOT NULL,
  PRIMARY KEY (`Place_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

INSERT INTO `important_places` (`Place_Name`, `Category`, `Description`, `Latitude`, `Longitude`) VALUES
('Galle Face', 'Lesuire,History', 'Park', 6.92496, 79.8446),
('Gangaramya Temple', 'Buddhisum,History,Religon', 'A Big Temple in Colombo', 6.91625, 79.8563),
('Viharamahadevia Park', 'Lesuire', 'Park', 6.91379, 79.8626),
('Weherahena Temple', 'Buddhisum,History,Religon', 'Weherahena Temple with a hugh Buddha Satchive', 5.95313, 80.5759);

CREATE TABLE IF NOT EXISTS `important_places_for_approval` (
  `Place_Name` varchar(100) NOT NULL,
  `Category` varchar(150) NOT NULL,
  `Description` varchar(500) NOT NULL,
  `Longitude` float NOT NULL,
  `Latitude` float NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

ALTER TABLE `close_to`
  ADD CONSTRAINT `close_to_ibfk_1` FOREIGN KEY (`City_Name`) REFERENCES `city` (`City_Name`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `close_to_ibfk_2` FOREIGN KEY (`Place_Name`) REFERENCES `important_places` (`Place_Name`) ON DELETE CASCADE ON UPDATE CASCADE;

Step 2 - Create a Dynamic Web Project using Eclipse inside your virtual machine. Put this as your web service definition,

package org.web.travel_ceylon.ws;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class Travel_Ceylon_Web_Service {
 private String url;
 private Connection con;
 private Statement stmt;

 public void connectToDB() {
  url = "jdbc:mysql://localhost:3306/travel_ceylon";
  try {
   Class.forName("com.mysql.jdbc.Driver");
   con = (Connection) DriverManager.getConnection(url, "root", "");
  } catch (Exception e) {
   System.out.println("Error - Unable to Connect to the Database" + e);

  }
 }

 public float getLongitude_City(String city) {
  connectToDB();
  float lngt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Longitude FROM city WHERE City_Name='"
       + city + "'");
   rs.next();
   lngt = rs.getFloat("Longitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get longitude of " + city
     + " :" + e);
  }
  return lngt;
 }

 public float getLatitude_City(String city) {
  connectToDB();
  float latt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Latitude FROM city WHERE City_Name='"
       + city + "'");
   rs.next();
   latt = rs.getFloat("Latitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get latitude of " + city
     + " :" + e);
  }
  return latt;
 }

 public float getLongitude_Im_Place(String place) {
  connectToDB();
  float lngt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Longitude FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   lngt = rs.getFloat("Longitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get longitude of " + place
     + " :" + e);
  }
  return lngt;
 }

 public float getLatitude_Im_Place(String place) {
  connectToDB();
  float latt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Latitude FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   latt = rs.getFloat("Latitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get latitude of " + place
     + " :" + e);
  }
  return latt;
 }

 public String getCategory_Im_Place(String place) {
  connectToDB();
  String cat = "";
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Category FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   cat = rs.getString("Category");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get  Category of " + place
     + " :" + e);
  }
  return cat;
 }

 public String getDescription_Im_Place(String place) {
  connectToDB();
  String des = "";
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Description FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   des = rs.getString("Description");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get Description of " + place
     + " :" + e);
  }
  return des;
 }
} 

Step 3 - Run your web service project in the tomcat server on eclipse. Yo will get your WSDL file like this


You know that this web service running inside the virtual machine you have. Also As I explained earlier you have host only network between virtual machine and your machine. So this web service can be access via your original machine. To verify that please enter this in your web browserhttp://Virtual Machines IP address:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl. In my example it was this. http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl  Then you can see this in your web browser.



So know you have a web service which can be accessible through a network. So lets proceed to the part of creating 
Android Client which use this web service. I will explain it in my next post.

Monday, February 13, 2012

How to create Multiple Screens in Android Applications : Android API 15, Eclipse


In this post I will show you the way I found to have multiple screens in your Android Application. To do this I used Eclipse as my IDE. And I used Android API 15 as my development environment.
When you create a new Android project in Eclipse, you can find that it will auto generate a main.xml file and the particular .java file for handling that. Lets see a screen shot of that.


When you insert some code and run it, it will show a single screen like this,


So this way you can develop your single screen android applications. Until you need single screen to develop a application it will be not a problem. But when you want to have several screens in your app and you need to navigate though them. You are in trouble. So I found out a way to do this. So I thought to share it with you guys.
To have multiple screen, first of all you have to create XML files for those screens. So in your projects res/layout folder create a new android XML file. then it will generate a new screen. Here is the way I created, Lets see a screen shot :





 Here In my project I have created three screens. In the main.xml file It will show the well come screen. In there I have put a button. When the user push that button then user will brought to the second screen which is named as selection_screen.xml. To do that we have to have a .java file for the selection_screen.xml. So I have created a java file for that. Here it is :


So how we use this xml files java files to achieve our task of switch between screens? As you know each and every screen in Android is a activity. So first of all we have to introduce our new screen as a activity to the Android app. To do that you have to edit the AndroidManifest.xml.

To add a new activity, you have to add this element as child element of application,


<?xml version="1.0" encoding="utf-8"?>
 <activity
            android:name=".You Java Files Name"
            android:label="Any name you want show as the title of the activity window." &gt;
</activity>

Here is my Example,


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="travelceylon.client"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk android:minSdkVersion="15" />


    <application
android:icon="@drawable/ic_launcher"
        android:label="Travel Ceylon" >
        <activity
            android:name=".Travel_CeylonActivity"
            android:label="Travel Ceylon" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SelectionActivity"
            android:label="Travel Ceylon Selection" >
        </activity>
        <activity
            android:name=".Important_place_addActivity"
            android:label="Add Importatn place to Travel Ceylon" >
        </activity>
    </application>


</manifest>




So after adding this you can see the R.java file in you application is generated. With your new elements in your new screens. So next thing is to add some code to those java files to navigate through screens. Here is the code you should add to your onCreate() method. It will show the new screen when  you press a button.


Button b = (Button) findViewById(R.id.button1); // Here the R.id.button1 is the button form you design
           b.setOnClickListener(new View.OnClickListener() {
           public void onClick(View arg0) {
           Intent i = new Intent(Current Java Files Name.this, The name of the next java files which will be executed on the button click.class);
           startActivity(i);
           }
});

Here is my example. It will guide user from Travel_CeylonActivity to SelectionActivity when user push the button Enter Travel Ceylon.



package travelceylon.client;




import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


public class Travel_CeylonActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b = (Button) findViewById(R.id.button1);
        b.setOnClickListener(new View.OnClickListener() {
           public void onClick(View arg0) {
           Intent i = new Intent(Travel_CeylonActivity.this, SelectionActivity.class);
           startActivity(i);
           }
        });
    }
}

After doing this I have edited the SelectionActivity.java like this, It also have two buttons and I have code it for go to another screen when I push a button.


package travelceylon.client;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;




public class SelectionActivity extends Activity {
public void onCreate(Bundle icicle)
  {
     super.onCreate(icicle);
     setContentView(R.layout.selection_screen);
     Button b = (Button) findViewById(R.id.button3);
       b.setOnClickListener(new View.OnClickListener() {
          public void onClick(View arg0) {
          Intent i = new Intent(SelectionActivity.this, Important_place_addActivity.class);
          startActivity(i);
          }
       });
  }
}

So after that you can run your application. You can see that when you press the button it will take you from screen 1 to screen 2. So like wise customize this approach to your app. I thought this will help you. Please leave your comments.