Friday, February 24, 2012

Pin It


Get Gadget

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.

15 comments:

  1. Hi .,
    These is very nice tutorials.But am not getting output..am getting ERROR:org.ksoap2.soapfault:null on all the textview.y dis error is came here.please help me.

    ReplyDelete
  2. Please put the entire error log here. So then I can tell where the thing has went wrong.

    Thnks
    AndunSLG

    ReplyDelete
  3. Hi. First of all thank you very much for this article. I´ve been looking for one like this for two days. You explain everything really well. I have one problem when i try the application, may be you can help me. This is the error:

    06-22 17:31:44.515: W/System.err(685): java.net.SocketTimeoutException: failed to connect to /192.128.0.62 (port 8080) after 20000ms

    The android virtual machine can connect to the service, because I can access from the navigator. Please if you hace any idea to solve the problem, please tell me.

    Thank you

    Santiago

    ReplyDelete
    Replies
    1. Hi Andun. It´s me again. I solved the problem (using ip 10.0.2.2 instead of 192.168.0.62). But now I don´t receive the value returned by the web service method; what I received is saludarResponse{return=Hola; } (the method name is saludar and it only returns "Hola"). This is not really a problem, because I can format the result, but what happens when the method return a complex object, like a List for example. Do you know how to get the result in that case?

      Thank you very much Andun, you have helped me a lot with this post.

      Santiago

      Delete
    2. I think we cant return that kind of object in a web service. Because if we return that kind of objects ,that will create a Interoperability problem. As I know web services are platform independent. Those List kind of objects are platform dependent.

      Thnks

      Delete
    3. Thank you Andun. I solved the problem. You can return an array of Objects but the objects must implement the interface "KvmSerializable" and then there are methods to get the objects. The good thing of this is that the server can return an array of objects implemented in .Net (for example) and you can get the objects en the client with Java (for example).

      Thank you for answer me and for this blog.

      Delete
  4. Hi...in my emulator shows ERROR:org.ksoap2.SoapFault:com/mysql/jdbc/Connection...

    my logcat window shows:
    07-10 12:15:31.212: W/System.err(668): SoapFault - faultcode: 'soapenv:Server' faultstring: 'com/mysql/jdbc/Connection' faultactor: 'null' detail: org.kxml2.kdom.Node@44f5d060
    07-10 12:15:31.212: W/System.err(668): at org.ksoap2.serialization.SoapSerializationEnvelope.parseBody(SoapSerializationEnvelope.java:141)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:140)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.transport.Transport.parseResponse(Transport.java:100)


    07-10 12:15:31.533: W/System.err(668): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    07-10 12:15:31.533: W/System.err(668): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    07-10 12:15:31.533: W/System.err(668): at dalvik.system.NativeStart.main(Native Method)
    07-10 12:15:31.633: W/System.err(668): SoapFault - faultcode: 'soapenv:Server' faultstring: 'com/mysql/jdbc/Connection' faultactor: 'null' detail: org.kxml2.kdom.Node@44f92658
    07-10 12:15:31.633: W/System.err(668): at org.ksoap2.serialization.SoapSerializationEnvelope.parseBody(SoapSerializationEnvelope.java:141)
    07-10 12:15:31.642: W/System.err(668): at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:140)
    07-10 12:15:31.642: W/System.err(668): at org.ksoap2.transport.Transport.parseResponse(Transport.java:100)
    07-10 12:15:31.642: W/System.err(668): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:214)
    07-10 12:15:31.642: W/System.err(668): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:96)
    07-10 12:15:31.642: W/System.err(668): at com.example.soap.AndroidFrontendActivity.onCreate(AndroidFrontendActivity.java:102)
    07-10 12:15:31.642: W/System.err(668): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    07-10 12:15:31.642: W/System.err(668): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    07-10 12:15:31.642: W/System.err(668): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    07-10 12:15:31.652: W/System.err(668): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    07-10 12:15:31.652: W/System.err(668): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    07-10 12:15:31.652: W/System.err(668): at android.os.Handler.dispatchMessage(Handler.java:99)
    07-10 12:15:31.652: W/System.err(668): at android.os.Looper.loop(Looper.java:123)
    07-10 12:15:31.652: W/System.err(668): at android.app.ActivityThread.main(ActivityThread.java:4627)
    07-10 12:15:31.652: W/System.err(668): at java.lang.reflect.Method.invokeNative(Native Method)
    07-10 12:15:31.652: W/System.err(668): at java.lang.reflect.Method.invoke(Method.java:521)
    07-10 12:15:31.652: W/System.err(668): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    07-10 12:15:31.652: W/System.err(668): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    07-10 12:15:31.662: W/System.err(668): at dalvik.system.NativeStart.main(Native Method)

    07-10 12:15:32.042: W/System.err(668): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    07-10 12:15:32.042: W/System.err(668): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    07-10 12:15:32.042: W/System.err(668): at dalvik.system.NativeStart.main(Native Method)

    How can i resolve above error...please guide me.

    ReplyDelete
  5. Hi.,

    my emulator is shows following error:
    ERROR://org.ksoap2.SoapFault:/com/mysql/jdbc/connection.

    My Logcat window have to displayed:
    07-10 12:15:31.212: W/System.err(668): SoapFault - faultcode: 'soapenv:Server' faultstring: 'com/mysql/jdbc/Connection' faultactor: 'null' detail: org.kxml2.kdom.Node@44f5d060
    07-10 12:15:31.212: W/System.err(668): at org.ksoap2.serialization.SoapSerializationEnvelope.parseBody(SoapSerializationEnvelope.java:141)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:140)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.transport.Transport.parseResponse(Transport.java:100)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:214)
    07-10 12:15:31.222: W/System.err(668): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:96)
    07-10 12:15:31.222: W/System.err(668): at com.example.soap.AndroidFrontendActivity.onCreate(AndroidFrontendActivity.java:43)
    07-10 12:15:31.222: W/System.err(668): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    07-10 12:15:31.222: W/System.err(668): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    07-10 12:15:31.232: W/System.err(668): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    07-10 12:15:31.232: W/System.err(668): at android.app.ActivityThread.access$2300(ActivityThread.java:125)

    07-10 12:15:32.042: W/System.err(668): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    07-10 12:15:32.042: W/System.err(668): at dalvik.system.NativeStart.main(Native Method)

    ReplyDelete
    Replies
    1. Please Check The EPR you are using for the Web Service Call is correct. Most probably this is due to OLD version of KSOAP. Please get one form http://code.google.com/p/ksoap2-android/

      Also please look at this http://stackoverflow.com/questions/6382241/how-to-send-a-soap-request-in-android

      Delete
    2. me also download ksoap2 jar from above link only.the above link also did not helpful for me.how can resolve dis..any other solutions.

      Delete
  6. Hi.,
    me also download ksoap2 jar from above link only.the above link also did not helpful for me.how can resolve dis..any other solutions.

    ReplyDelete
  7. Hi very nice tutorial..
    Can u please me about this...
    I have created one signup page in android and it contains some text boxes for names and also it contains one upload button throgh this ihave to upload image from android gallery and have to store it in mysql.
    How can I store image into mysql using web services?
    I appreciate your help..
    Thanks in advance

    ReplyDelete
  8. AnonymousJuly The problem is not in Android, is in the Web Service: make sure you have this points:
    * Your webservice is using an ip addres, not localhost nor 127.0.0.1, therefore you must to create a new database user with all the power % to read the database from any host.
    * You need to add the mysql-connector.jar to your WEB-INF/lib folder

    ReplyDelete
  9. Hi, i also use in my android application ksoap2 to send data to axis2 webservices. Although in my case i have a thread that sends the data inside a handler, this handler is called if the user selects a select box.

    What happens is that when the activity stays in background eventually it gets stopped. When the user gets it to foreground again and starts the handler again the axis2 webservice already closed the connection to that specific client. So when the user clients in the select box again i receive a broken pipe error in the android application and have to restart the server.

    Any hints on how to solve this issue? Thx in advance.

    ReplyDelete
  10. Follwing my code for creating webservice:
    package net.sample;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;

    /**
    * @author www.javaworkspace.com
    *
    */
    public class ConnectMSSQL {


    public String get_role(String user1,String password)
    {
    // Create a variable for the connection string.
    String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
    "databaseName=Runali_Login;user=sa;password=ftl@123";

    String user2="";
    String password1="";


    try {

    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    Connection connection = DriverManager.getConnection(connectionUrl);


    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM login_db where
    username='xyz'");
    while ( resultSet.next())
    {

    user2=resultSet.getString("username");
    password1=resultSet.getString("password1");
    }

    } catch (Exception e) {
    e.printStackTrace();

    }
    if(user2.equals("xyz"))
    {
    return "Sucess";
    }
    else
    {
    return "Unsucess";
    }


    }
    }

    Can you plz help me??
    I am not getting any values from db.so its always returning o\p as Unsucess.
    Eventhough values are present in db.
    Can you plz let me no where am wrong???

    ReplyDelete