Saturday, February 11, 2012

Link Android application with eBay web service



Introduction

 

In this tutorial I'll demonstrate a way of linking your hybrid Android applications (Android native + HTML) with eBay web services.

You can download file project source from here.
(Notice that you will need to insert AppID in url string at RestClient.java. Procedure is described in Sign up - ebay Developer Network section and Web service client section.)

We'll create simple Android app with service client for searching eBay items by a keyword. After search is completed, application will list a correct number of items with their hyperlinks to details and images.
For developing applications with eBay integration, Ebay Developer Network gives a good insight in some of the products for developers. From current featured products there are 4 categories:
1. Search - offers eBay finding API that enables application to search for eBay items.
2. Trading - offers API for authenticated access to private eBay data
3. Buying - offers eBay shopping API access to public read-only data
4. Go Local - offers Milo Open API that allows developers to access local availability information from 50,000+ stores all across the country

These APIs give you a powerfull tools for developing e-commerce apps using integration with eBay web services.

The same as in previous tutorial we'll develope hybrid Android application that is using native Java code for backend logic and HTML with jQuery for UI.

 

Screen flow


In this sample, our application will contain two HTML pages. The first page will be search interface that has search keyword input and number input that represents a number of searched result items that will be displayed in second screen. The second screen will display search results with item titles with hyperlinks and their images.
First page - (index.html) Search page
Second page - (searchitems.html) Search results
 

Sign up - ebay Developer Network

 

In case with developing application that will use eBay services, you'll need to have some application parameters that we'll be provided to you after you sing up on developer.ebay.com web site. In order to do that:
1. go on previous URL and click Join now section.
2. Fill in required data and register.
3. After you confirm your account, go back to web site and sign in.
4. Go to My Account
5. At application keys pane click Generate Keys


6. After you generate your keys you should get list of ids that will be used in your app configuration.

Setting up Android project

 

Android Manifest

Create new Android project in Eclipse environment - File -> New -> Android project, and choose target platform (in my case I used Android 2.1-update1).
1. After you created project enter AndroidManifest.xml and go to Permissions section.
2. Click Add... and choose Uses Permission
3. From Name option set choose android.permission.INTERNET
4. Save your changes

Layout XML

In project solution go to res folder and in layouts open main.xml. Go to main.xml section and replace your xml layout with next:

<!--?xml version="1.0" encoding="utf-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<webview android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/webview">
</webview>
</linearlayout>



In this step we added webView component which will be used to display HTML pages and execute JavaScript.

Assets folder

The same as in previous tutorial we'll use jQMobi library for jQuery development. Follow next steps to set up necessary resources for UI development:
1. Create directories in assets folder with following paths - assets/www/css-js and assets/www/img
2. Download jQMobi and extract js libraries in assets/www/css-js/
3. Store some PNG in img folder that we'll be used in search screen
4. Create two empty HTML files in www directory and name them as index.html and searchitems.html
Now your assets folder should look like this





Web service client


 

To establish link to eBay web service we'll need to write a client side class that is going to access eBay Finding service. In this case, we'll use REST-full eBay service and since these services are based on HTTP methods, we'll implement HTTP client to send HTTP requests to eBay service. In response, web service will send JSON object with items data as a search result.
Remark: You're not limited on using REST-full services, their is also a way of using SOAP based eBay web services. In that case you'll need to use kSOAP2 project. SOAP services won't be covered in this tutorial.


First step is to create new class in your package called RestClient. Then enter this code in your class:


 import java.io.IOException;  
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

public class RestClient {

public static String getEbayItems(String term, String number){

String json = null;

String url = "http://svcs.ebay.com/services/search/FindingService/v1?OPERATION-"+
"NAME=findItemsByKeywords"+
"&SERVICE-VERSION=1.0.0"+
"&SECURITY-APPNAME=000000000-0000-0000-0000-00000000000"+
"&RESPONSE-DATA-FORMAT=JSON"+
"&REST-PAYLOAD"+
"&keywords="+term+
"&paginationInput.entriesPerPage="+Integer.parseInt(number);

HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response;
try {
response = httpClient.execute(httpGet,responseHandler);
json = response.toString();
}catch (ClientProtocolException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return json;
}
}

 

As we can see, this class contains single method getEbayItems that will retrieve search results. Notice in url string HTTP POST arguments. These arguments represents our web service call parameters.
- In SECURITY-APPNAME you will enter your generated AppID key from Production keys section under your account at developer.ebay.com.
- RESPONSE-DATA-FORMAT represents data type that web service will return in response (JSON or XML).
- keywords is a search term.
- and paginationInput.entriesPerPage represents item number in search result.
If you set your parameters correctly, you will be able to see your JSON result when you enter this url in your web browser. In continue, we'll create simple HTTP client that will send HTTP GET request to eBay web service. In response it returns JSON result.

 

Main Activity class


In source of project, we'll edit Activity class that was generate when project was created. Modify your code:

import java.util.ArrayList; 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.webkit.WebView;

public class MainActivity extends Activity {
WebView webView;
String json;
String callback;

//Searched item data
ArrayList<String> titles = new ArrayList<String>();
ArrayList<String> imageUrl = new ArrayList<String>();
ArrayList<String> viewItemUrl = new ArrayList<String>();

private Handler handler;
private static final String HTML_ROOT = "file:///android_asset/www/";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(this, "jsInterface");
handler = new Handler();
loadPage("index.html");
}

public void loadPage(String page){
final String url = HTML_ROOT + page;
loadURL(url);
}

private void loadURL(final String url){
handler.post(new Runnable(){
public void run(){
webView.loadUrl(url);
}
});
}

public void callSearchService(String term, String number, String callback){
try {
json = RestClient.getEbayItems(term,number);
this.callback = callback;
//Parsing JSON result
JSONObject jObjectMain = new JSONObject(json);
JSONArray jArrayMain = jObjectMain.getJSONArray("findItemsByKeywordsResponse");
JSONObject jObjectResult = jArrayMain.getJSONObject(0);
JSONArray jArrayResult = jObjectResult.getJSONArray("searchResult");
JSONObject jObjectSearch = jArrayResult.getJSONObject(0);
JSONArray jArraySearch = jObjectSearch.getJSONArray("item");

JSONObject jObjectItems = new JSONObject();
titles = new ArrayList<String>();
imageUrl = new ArrayList<String>();
viewItemUrl = new ArrayList<String>();
for(int i=0; i<jarraysearch.length(); i++){
jObjectItems = jArraySearch.getJSONObject(i);
titles.add(jObjectItems.getString("title").replaceAll("[\"]|[\\[]|[\\]]", ""));
imageUrl.add(jObjectItems.getString("galleryURL").replaceAll("[\"]|[\\[]|[\\]]", ""));
viewItemUrl.add(jObjectItems.getString("viewItemURL").replaceAll("[\"]|[\\[]|[\\]]", ""));
}
loadPage("searchitems.html");
} catch (JSONException e) {
e.printStackTrace();
}
}

public void getSearchedItems(){
String innerHtml = "";
for(int i=0; i<titles.size(); i++){
innerHtml += "<div class="resultItem">" +
"<a href=""+viewItemUrl.get(i)+"">"+titles.get(i)+"</a>" +
"<img src=""+imageUrl.get(i)+"">" +
"</div>";
}
final String callbackMethod = "javascript:"+callback+"(\""+innerHtml+"\")";
loadURL(callbackMethod);
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()){
webView.goBack();
return true;
}

return super.onKeyDown(keyCode, event);
}
}
 

1. onCreate method - This method is called at creating activity state. In this part, we'll set our layout that was previously edited (main.xml) and in WebView component will enable JavaScript execution and register JavaScript interface. Using this interface we'll be able to call JavaScript from our Java code and vice versa (see previous tutorial). In the end of this method we'll load our first page (index.html).
2. loadPage method is used to load page in WebView component using page URL and loadURL is used for running HTML page and jQUery in WebView.
3. callSearchService method - this method gets three arguments: term (search keyword), number (item number in search result) and callback (name of JavaScript method to be called back). All of these arguments represent input data that will be forwarded from HTML page to Java by JavaScript method that will make callSearchService method call using jsInterface. In the first part, method gets search results by calling getEbaysItems from RestClient class. After that we parse our JSON result.
Basically, it re-encapsulates JSON arrays in result to get to item data. After we get our specific JSON Array with items data, we'll read their titles, image urls and url to details page. Don't get confused by replaceAll("[\"]|[\\[]|[\\]]", "") method. It is using Regex to remove redundant JSON characters - [" and "].
After we store JSON parsed results in class attributes, we load second page (searchitems.html) that is going to display search results.
4. getSearchedItems method - will send inner HTML with JSON prased results as an argument in callback JavaScript method in searchitems.html page.
5. onKeyDown method - overrides button "Back" functionality to go to previous HTML page.
 

HTML pages


Replace your index.html with following HTML:

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<script src="css-js/ui/jq.ui.js"></script>
<script src="css-js/jq.mobi.js"></script>
<script>
function sendSearchTerm(){
var inputString = $("#term").val();
var dropdown = document.getElementById("itemNum");
var index = dropdown.selectedIndex;
var inputNumber = dropdown.options[index].value;

if(inputString == "")
{
alert("Please enter search term.");
}
else
{
jsInterface.callSearchService(inputString, inputNumber, "getResult");
}
}
</script>
<style>
.info{
display: block;
line-height: 22px;
padding: 0 5px 5px 0;
color: #36558e;
}
#finding{
height: 152px;
padding: 80px 0 0 30px;
background: url('img/search.png') transparent no-repeat 0 0;
margin: 30px auto;
}
</style>
</head>
<body>
<div id="search">
<div id="finding">
<label for="input" class="info">Search
<strong style="color:red">e</strong>
<strong style="color:blue">b</strong>
<strong style="color:#ffcc00">a</strong>
<strong style="color:green">y</strong>
</label>
<input type="text" id="term" name="term">
number of items:
<select id="itemNum">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
<button onclick="sendSearchTerm()">Search</button>
</div>
</div>
</body>
</html>

This HTML contains two input elements for input search term and select list for number of search items. JScript function sendSearchTerm reads values from input fields and sends that to Java callSearchService method.

Second page will display search results:


<!DOCTYPE html>  
<html>
<head>
<meta charset="ISO-8859-1">
<script src="css-js/ui/jq.ui.js"></script>
<script src="css-js/jq.mobi.js"></script>
<script>
$(document).ready(function () {
jsInterface.getSearchedItems();
});
function getResult(innerHtml){
$("#result").html(innerHtml);
}
</script>
<style type="text/css">
.resultItem{
border: 1px solid #60672B;
}
</style>
</head>
<body>
<div>
<label>Searched items:</label>
<div id="result">
</div>
</div>
</body>
</html>

At a page load, $(document).ready function is called and Java getSearchedItems method gets executed. From this execution getResult function is called in callback and it will load results as innerHtml to "result" div element.

 


Conclusion



Voila! You just created Android hybrid application with connection to eBay service.
Through this tutorial I showed how to work with Android hybrid application using HTML and jQuery and how to expand Android functionality using web service clients. The purpose of this tutorial was to give some insights of working with web service clients and make your mobile apps a little more advanced.