Child pages
  • Step by step tutorial

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

Step by step tutorial

Hi, this is Gábor Auth – lead developer of AndroidSOAP, let me present the project!

First: what do you need?

On the easy way:

  1. You only need an IDE with Maven support:
    1. NetBeans 6.x or above out-of-the-box
    2. Eclipse Indigio or above (with m2eclipse plugin)
    3. Other IDE with Maven integration
  2. Android SDK
  3. Some bottles of beer... (smile)

Second: create a project!

Create a new Maven based Android project as described on the android-maven-plugin's page: http://code.google.com/p/maven-android-plugin/wiki/GettingStarted

Code Block
$ mvn archetype:generate -DarchetypeArtifactId=android-quickstart -DarchetypeGroupId=de.akquinet.android.archetypes -DarchetypeVersion=1.0.8 -DgroupId=hu.javaforum.android.soapexample -DartifactId=soap-example
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO] 
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO] 
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository missing. Using the one from [de.akquinet.android.archetypes:android-quickstart:1.0.8] found in catalog remote
[INFO] Using property: groupId = hu.javaforum.android.soapexample
[INFO] Using property: artifactId = soap-example
Define value for property 'version':  1.0-SNAPSHOT: : 
[INFO] Using property: package = hu.javaforum.android.soapexample
[INFO] Using property: android-plugin-version = 3.1.1
[INFO] Using property: emulator = not-specified
[INFO] Using property: platform = 10
Confirm properties configuration:
groupId: hu.javaforum.android.soapexample
artifactId: soap-example
version: 1.0-SNAPSHOT
package: hu.javaforum.android.soapexample
android-plugin-version: 3.1.1
emulator: not-specified
platform: 10
 Y: : 
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: android-quickstart:1.0.8
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: hu.javaforum.android.soapexample
[INFO] Parameter: artifactId, Value: soap-example
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: hu.javaforum.android.soapexample
[INFO] Parameter: packageInPathFormat, Value: hu/javaforum/android/soapexample
[INFO] Parameter: platform, Value: 10
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: hu.javaforum.android.soapexample
[INFO] Parameter: emulator, Value: not-specified
[INFO] Parameter: groupId, Value: hu.javaforum.android.soapexample
[INFO] Parameter: android-plugin-version, Value: 3.1.1
[INFO] Parameter: artifactId, Value: soap-example
[WARNING] Don't override file /home/work/Android/Projects/soap-example/pom.xml
[INFO] project created from Archetype in dir: /home/work/Android/Projects/soap-example
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.843s
[INFO] Finished at: Mon Apr 23 20:20:18 CEST 2012
[INFO] Final Memory: 11M/118M
[INFO] ------------------------------------------------------------------------

Open it in your IDE, and create a build:

Code Block
$ mvn clean install -Dandroid.sdk.path=/home/work/android-sdk-linux/ android:deploy
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building soap-example 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ soap-example ---
[INFO] Deleting /home/work/Android/Projects/soap-example/target
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:generate-sources (default-generate-sources) @ soap-example ---
[INFO] ANDROID-904-002: Found aidl files: Count = 0
[INFO] ANDROID-904-002: Found aidl files: Count = 0
[INFO] /home/work/android-sdk-linux/platform-tools/aapt [package, -m, -J, /home/work/Android/Projects/soap-example/target/generated-sources/r, -M, /home/work/Android/Projects/soap-example/AndroidManifest.xml, -S, /home/work/Android/Projects/soap-example/res, --auto-add-overlay, -A, /home/work/Android/Projects/soap-example/assets, -I, /home/work/android-sdk-linux/platforms/android-13/android.jar]
[INFO] 
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ soap-example ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/work/Android/Projects/soap-example/src/main/resources
[INFO] skip non existing resourceDirectory /home/work/Android/Projects/soap-example/target/generated-sources/extracted-dependencies/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ soap-example ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 2 source files to /home/work/Android/Projects/soap-example/target/classes
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:proguard (default-proguard) @ soap-example ---
[INFO] 
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ soap-example ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/work/Android/Projects/soap-example/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ soap-example ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12:test (default-test) @ soap-example ---
[INFO] No tests to run.
[INFO] Surefire report directory: /home/work/Android/Projects/soap-example/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- android-maven-plugin:3.1.1:dex (default-dex) @ soap-example ---
[INFO] /usr/lib64/jvm/java-1.6.0-openjdk-1.6.0/jre/bin/java [-Xmx1024M, -jar, /home/work/android-sdk-linux/platform-tools/lib/dx.jar, --dex, --output=/home/work/Android/Projects/soap-example/target/classes.dex, /home/work/Android/Projects/soap-example/target/classes]
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ soap-example ---
[INFO] Building jar: /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:apk (default-apk) @ soap-example ---
[INFO] Copying local assets files to combined assets directory.
[INFO] /home/work/android-sdk-linux/platform-tools/aapt [package, -f, -M, /home/work/Android/Projects/soap-example/AndroidManifest.xml, -S, /home/work/Android/Projects/soap-example/res, --auto-add-overlay, -A, /home/work/Android/Projects/soap-example/target/generated-sources/combined-assets/assets, -I, /home/work/android-sdk-linux/platforms/android-13/android.jar, -F, /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.ap_]
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:internal-pre-integration-test (default-internal-pre-integration-test) @ soap-example ---
[INFO] No InstrumentationRunner found - skipping tests
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:internal-integration-test (default-internal-integration-test) @ soap-example ---
[INFO] No InstrumentationRunner found - skipping tests
[INFO] 
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ soap-example ---
[INFO] Installing /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.apk to /home/auth.gabor/.m2/repository/hu/javaforum/android/soapexample/soap-example/1.0-SNAPSHOT/soap-example-1.0-SNAPSHOT.apk
[INFO] Installing /home/work/Android/Projects/soap-example/pom.xml to /home/auth.gabor/.m2/repository/hu/javaforum/android/soapexample/soap-example/1.0-SNAPSHOT/soap-example-1.0-SNAPSHOT.pom
[INFO] Installing /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.jar to /home/auth.gabor/.m2/repository/hu/javaforum/android/soapexample/soap-example/1.0-SNAPSHOT/soap-example-1.0-SNAPSHOT.jar
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building soap-example 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- android-maven-plugin:3.1.1:deploy (default-cli) @ soap-example ---
[INFO] /home/work/android-sdk-linux/platform-tools/aapt [dump, xmltree, /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.apk, AndroidManifest.xml]
N: android=http://schemas.android.com/apk/res/android
  E: manifest (line=2)
    A: android:versionCode(0x0101021b)=(type 0x10)0x1
    A: android:versionName(0x0101021c)="1.0-SNAPSHOT" (Raw: "1.0-SNAPSHOT")
    A: package="hu.javaforum.android.soapexample" (Raw: "hu.javaforum.android.soapexample")
    E: application (line=5)
      A: android:label(0x01010001)=@0x7f040001
      A: android:icon(0x01010002)=@0x7f020000
      E: activity (line=6)
        A: android:name(0x01010003)=".HelloAndroidActivity" (Raw: ".HelloAndroidActivity")
        E: intent-filter (line=7)
          E: action (line=8)
            A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN")
          E: category (line=9)
            A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw: "android.intent.category.LAUNCHER")
[INFO] Waiting for initial device list from the Android Debug Bridge
[INFO] Found 1 devices connected with the Android Debug Bridge
[INFO] android.device parameter not set, using all attached devices
[INFO] Successfully uninstalled hu.javaforum.android.soapexample from HT0C5RX01088_HTC_HTCDesireHDA9191
[INFO] Found 1 devices connected with the Android Debug Bridge
[INFO] android.device parameter not set, using all attached devices
[INFO] Successfully installed /home/work/Android/Projects/soap-example/target/soap-example-1.0-SNAPSHOT.apk to HT0C5RX01088_HTC_HTCDesireHDA9191
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.111s
[INFO] Finished at: Mon Apr 23 20:45:38 CEST 2012
[INFO] Final Memory: 14M/210M
[INFO] ------------------------------------------------------------------------

It works! Great! Open the first bottle of beer... (smile)

Third: find a real WebService

I think, if you've found this project, you have an URL address of WebService and you want to access it from your Android device. In the world of desktops or servers, you tipically generate Java classes from the WSDL with wsimport (part of JDK6 or above), and call the SOAP operation with these generated classes, like this: http://www.javadb.com/create-a-web-service-client-with-jax-ws

The Maven3 method is slightly simpler, just add two plugins into the pom.xml: the first one for the source generation, and a second one for the build of generates source:

Code Block
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxws-maven-plugin</artifactId>
        <version>1.12</version>
        <executions>
          <execution>
            <id>listSkinPacksWsdl</id>
            <goals>
              <goal>wsimport</goal>
            </goals>
            <configuration>
              <wsdlUrls>
                <wsdlUrl>http://services.power.of.planets.hu/PoP-SkinPack-remote/listSkinPacks?wsdl</wsdlUrl>
              </wsdlUrls>
              <packageName>hu.javaforum.pop.skinpack.list</packageName>
              <sourceDestDir>${basedir}/target/generated-sources/wsimport</sourceDestDir>
              <staleFile>${project.build.directory}/jaxws/stale/listSkinPacksWsdl.done</staleFile>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>1.7</version>
        <executions>
          <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${basedir}/target/generated-sources/wsimport</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>

Rebuild the project and the only difference you will see is a wsimport code generation:

Code Block
[INFO] --- jaxws-maven-plugin:1.12:wsimport (listSkinPacksWsdl) @ soap-example ---
[WARNING] Could not transfer metadata org.jvnet.staxex:stax-ex/maven-metadata.xml from/to java.net (http://download.java.net/maven/1/): No connector available to access repository java.net (http://download.java.net/maven/1/) of type legacy using the available factories WagonRepositoryConnectorFactory
[INFO] Processing: http://services.power.of.planets.hu/PoP-SkinPack-remote/listSkinPacks?wsdl
[INFO] jaxws:wsimport args: [-s, /home/work/Android/Projects/soap-example/target/generated-sources/wsimport, -d, /home/work/Android/Projects/soap-example/target/classes, -p, hu.javaforum.pop.skinpack.list, -Xnocompile, http://services.power.of.planets.hu/PoP-SkinPack-remote/listSkinPacks?wsdl]
parsing WSDL...


generating code...

Great! Where is the second beer? Got it? (smile)

Fourth: Add the AndroidSOAP to the project

At this point, you can add the JavaForum Maven Repository before the dependencies section:

Code Block
  <repositories>
    <repository>
      <id>javaforum.hu</id>
      <name>JavaForum Maven Repository</name>
      <url>http://nexus.javaforum.hu/nexus/content/groups/public/</url>
    </repository>
  </repositories>

And you can add the AndroidSOAP (and the slf4j-api) into the dependencies section:

Code Block
    <dependency>
      <groupId>hu.javaforum.android.androidsoap</groupId>
      <artifactId>AndroidSOAP-lib</artifactId>
      <version>0.0.4</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.4</version>
      <scope>provided</scope>
    </dependency>

Then, rebuild the project, you will see some errors when the Android plugin creates a dex:

Code Block
[INFO] --- android-maven-plugin:3.1.1:dex (default-dex) @ soap-example ---
[INFO] /usr/lib64/jvm/java-1.6.0-openjdk-1.6.0/jre/bin/java [-Xmx1024M, -jar, /home/work/android-sdk-linux/platform-tools/lib/dx.jar, --dex, --output=/home/work/Android/Projects/soap-example/target/classes.dex, /home/auth.gabor/.m2/repository/hu/javaforum/android/androidsoap/AndroidSOAP-lib/0.0.4/AndroidSOAP-lib-0.0.4.jar, /home/auth.gabor/.m2/repository/org/slf4j/slf4j-android/1.6.1-RC1/slf4j-android-1.6.1-RC1.jar, /home/auth.gabor/.m2/repository/xmlunit/xmlunit/1.3/xmlunit-1.3.jar, /home/auth.gabor/.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3.jar, /home/auth.gabor/.m2/repository/hu/javaforum/javaforum20-commons/1.0.0/javaforum20-commons-1.0.0.jar, /home/work/Android/Projects/soap-example/target/classes, /home/auth.gabor/.m2/repository/javax/validation/validation-api/1.1.0.Alpha1/validation-api-1.1.0.Alpha1.jar]
[INFO] warning: Ignoring InnerClasses attribute for an anonymous inner class
[INFO] (org.custommonkey.xmlunit.DoctypeInputStream$1) that doesn't come with an
[INFO] associated EnclosingMethod attribute. This class was probably produced by a
[INFO] compiler that did not target the modern .class file format. The recommended
[INFO] solution is to recompile the class from source, using an up-to-date compiler
[INFO] and without specifying any "-target" type options. The consequence of ignoring
[INFO] this warning is that reflective operations on this class will incorrectly
[INFO] indicate that it is *not* an inner class.
[INFO] warning: Ignoring InnerClasses attribute for an anonymous inner class
[INFO] (org.custommonkey.xmlunit.DoctypeReader$1) that doesn't come with an
[INFO] associated EnclosingMethod attribute. This class was probably produced by a
[INFO] compiler that did not target the modern .class file format. The recommended
[INFO] solution is to recompile the class from source, using an up-to-date compiler
[INFO] and without specifying any "-target" type options. The consequence of ignoring
[INFO] this warning is that reflective operations on this class will incorrectly
[INFO] indicate that it is *not* an inner class.
[INFO] warning: Ignoring InnerClasses attribute for an anonymous inner class
[INFO] (org.custommonkey.xmlunit.SimpleXpathEngine$1) that doesn't come with an
[INFO] associated EnclosingMethod attribute. This class was probably produced by a
[INFO] compiler that did not target the modern .class file format. The recommended
[INFO] solution is to recompile the class from source, using an up-to-date compiler
[INFO] and without specifying any "-target" type options. The consequence of ignoring
[INFO] this warning is that reflective operations on this class will incorrectly
[INFO] indicate that it is *not* an inner class.

You can safety ignore them, it's ugly, but works, aren't you thirsty? Yet another beer... (smile)

Fifth: Before calling the WebService operation

You will need some additional information about your webservice:

  • the namespace of the operation, in this case http://skinpack.pop.javaforum.hu/
  • the URL of the operation, in this case http://services.power.of.planets.hu/PoP-SkinPack-remote/listSkinPacks
  • name of the operation, in this case listSkinPacks
  • name of the parameter(s), in this case request

All of them are described in the WSDL, but the WSDL is not human friendly. You may know the soapUI: the soapUI builds a sample request from the WSDL, and you can easily examine the necessary parameters:

Code Block
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:skin="http://skinpack.pop.javaforum.hu/">
   <soapenv:Header/>
   <soapenv:Body>
      <skin:listSkinPacks>
         <!--Optional:-->
         <request/>
      </skin:listSkinPacks>
   </soapenv:Body>
</soapenv:Envelope>

Sixth: Call!

Before you write any code, you need to edit the main.xml in the layout directory, because the TextView element has no id property:

Code Block
<TextView  
    android:id="@+main/text"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>

And add an INTERNET permission into the AndroidManifest.xml:

Code Block
  <uses-permission android:name="android.permission.INTERNET"/>

Then, you can write some code into the HelloAndroidActivity.java:

Code Block
    String urlOfTheWsdl = "http://services.power.of.planets.hu/PoP-SkinPack-remote/listSkinPacks";
    String namespaceOfTheRequest = "http://skinpack.pop.javaforum.hu/";
    String nameOfTheOperation = "listSkinPacks";
    String nameOfTheRequest = "request";
    String username = "androidsoap.demo@javaforum.hu";
    String password = "demopassword";

    StringBuilder sb = new StringBuilder();
    try
    {
      ListSkinPacksRequest request = new ListSkinPacksRequest();
      Map<String, Object> parameters = new HashMap<String, Object>();
      parameters.put(nameOfTheRequest, request);
      Envelope envelope = new SimpleEnvelope(namespaceOfTheRequest);
      envelope.setHeader(new SimpleHeader());
      envelope.setBody(new SimpleBody(nameOfTheOperation, parameters));
      Transport transport = new HttpTransport(urlOfTheWsdl, username, password);
      ListSkinPacksResponse response = transport.call(envelope, ListSkinPacksResponse.class);
      
      for (SkinPackMetadata metadata : response.getReturn().getSkinPacksList())
      {
        sb.append(metadata.getFileName()).append("-").append(metadata.getName()).append("\n");
      }
    } catch (IOException exception)
    {
      sb.append(exception.toString());
    }
    
    TextView textView = (TextView) findViewById(R.main.text);
    textView.setText(sb.toString());

Last one: Check the result...

...and reward your hard work with a cool beer:


Viewtracker