on Articles Expert Tutorials

Android JSON-RPC client and PHP Zend Framework server

1 comments
json_loiane
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon

XML-RPC rules, but the amount of data it generates is its big disadvantage. This is where JSON-RPC steps in. Data it generates is significally smaller, but this isn’t suprising as JSON is known as fat free XML.This articles is based on my earlier Android XML-RPC article. Its PHP code and Zend Framework setup will be used so you should go through it if you haven’t earlier (at least as far as XMLRPC Android client chapter).

JSON-RPC PHP Server

We’ll start with adding additional actions to our server controller (with zf tool) – zf create action json Server. Lets open our Server controller (application/controllers/Server.php) and start building JSON-RPC server in our newly created json action.

public function jsonAction()
{
	$this->_helper->viewRenderer->setNoRender();
	 
	$server = new Zend_Json_Server();
	$server->setClass('Application_Model_Data', 'cf');

	if ('GET' == $_SERVER['REQUEST_METHOD']) {
		$server
		->setTarget('http://localhost/xmlrpc-test/public/server/json')
		->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
		$smd = $server->getServiceMap();

		header('Content-Type: application/json');
		echo $smd;
		return;
	}

	echo $server->handle();
}

First, we disable view rendering, instantiate Zend_Json_Server and attach a class which will responde to client calls Application_Model_Data.

Zend_Json_Server listens only for POST requests (but fortunately most JSON-RPC client implementations will only POST requests) so we have to check if our request is POST or GET. In GET request we can serve SMD (http://groups.google.com/group/json-schema/web/service-mapping-description-proposal) specification which provides service metadata to service consumers.

Take note of $server->setTarget method, it adds our server URL to specification. Modify it to suit your setup.

JSON-RPC PHP Client

Now its time to create PHP client for the purpose of testing our server. Unfortunately, Zend Framework currently (version 1.11) doesn’t have JSON-RPC client. Version 2.0 should have one, but until then we have to use some 3rd party client. Simplest to implement is jQuery JSON-RPC client specifically made for Zend Framework, you can download it here – http://www.tanabi.com/projects/jsonrpc.

From downloaded archive we extract contents of js directory and place it into public/js directory (we have to create js directory).

Lets again use zf tool and create json client action – zf create action json Client.

Our newly created action should look like this:

public function jsonAction()
{
	$this->view->serverUrl = 'http://localhost/xmlrpc-test/public/server/json';
}

Its pretty straitforward, we only forward server URL to view script. Now, lets modify view script created (application/views/scripts/client).

<html>
<head>
<?php 
    echo $this->headScript()
    	->appendFile($this->baseUrl('/js/jquery-1.3.min.js'))
    	->appendFile($this->baseUrl('/js/json2.js'))
    	->appendFile($this->baseUrl('/js/jquery.zend.jsonrpc.js'));
?>
<script type="text/javascript">
	$(document).ready(function() {
		var testClient = jQuery.Zend.jsonrpc({
			url : '<?php echo $this->serverUrl; ?>'
		});
		var data1 = testClient.cf.test();
		if ('' != data1) {
			$('#result1').html(data1);
		}
	});
</script>
</head>
<body>
	<div id="result1"></div>
</body>
</html>

First, we add JS scripts (jquery-1.3.min.js, json2.js and jquery.zend.jsonrpc.js) then invoke jQuery and in line 11 we instantiate jQuery JSON-RPC client. In line 12 we call our RPC test method.

We are ready to test our JSON-RPC server. When we visit http://localhost/xmlrpc-test/public/client/json (at least in my setup) we should get results like this:

Yeah, it says XMLRPC but just because we haven’t change our Application_Model_Data class method. If we have similar looking results then we’re done with PHP part. Now, onto the Android part.

JSON-RPC Android Client 

Create new Android project and download Android JSON-RPC lib from http://code.google.com/p/android-json-rpc/. In eclipse, right click your project in package explorer and select properties. In properties select Java Build Path -> Add external JARs and navigate to downloaded .jar file.

Don’t forget to add internet permission to Android manifest file – open AndroidManifest.xml and in raw XML view add next line just before closing manifest tag:

<uses-permission android:name=”android.permission.INTERNET”></uses-permission>

In our example we’ll be using default layout file res/layout/main.xml but we’ll add an ID to its TextView element so that we can fill it out with received data. So open res/layout/main.xml file and locate TextView element. Add an android.id attribute with @+id/text_view value to it:

&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;LinearLayout xmlns:android=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;
	android:orientation=&amp;quot;vertical&amp;quot; android:layout_width=&amp;quot;fill_parent&amp;quot;
	android:layout_height=&amp;quot;fill_parent&amp;quot;&amp;gt;
	&amp;lt;TextView android:id=&amp;quot;@+id/text_view&amp;quot; android:layout_width=&amp;quot;fill_parent&amp;quot;
		android:layout_height=&amp;quot;wrap_content&amp;quot; android:text=&amp;quot;Hello&amp;quot; /&amp;gt;
&amp;lt;/LinearLayout&amp;gt;

Lets start building our client. Open created activity (in src directory, com.cf.jsonrpc package), mine is called Client.

public class Client extends Activity {
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		TextView tv = (TextView) findViewById(R.id.text_view);
	}
}

In onCreate method we create reference to TextView element of our layout where we’ll display our results. Now lets create a method which will call our JSON-RPC server.

private String testMethod() {
	JSONRPCClient client = JSONRPCClient
			.create(&amp;quot;http://10.0.2.2/xmlrpc-test/public/server/json&amp;quot;);
	String string = &amp;quot;&amp;quot;;
	try {
		string = client.callString(&amp;quot;cf.test&amp;quot;);
	} catch (JSONRPCException e) {
		Log.i(&amp;quot;JSON-RPC Client&amp;quot;, e.toString());
	}
	return string;
}

First, we create and initialize JSONRPCClient and give it our server URL. As you can see we are using 10.0.2.2 address to access our own local web server. 127.0.0.1 or localhost is used by the underlying linux OS on emulator.

We’re using try-catch block to catch errors and deal with them. In try block we are calling our cf.test method. To JSONRPCClient we are telling that we expect a string to be returned (client.callString).

After creating this method we have to call it from onCreate method and display its return value to TextView element. Our modified Client activity class should look like this:

public class Client extends Activity {
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		TextView tv = (TextView) findViewById(R.id.text_view);
		tv.setText(testMethod());
	}

	private String testMethod() {
		JSONRPCClient client = JSONRPCClient
				.create(&amp;quot;http://10.0.2.2/xmlrpc-test/public/server/json&amp;quot;);
		String string = &amp;quot;&amp;quot;;
		try {
			string = client.callString(&amp;quot;cf.test&amp;quot;);
		} catch (JSONRPCException e) {
			Log.i(&amp;quot;JSON-RPC Client&amp;quot;, e.toString());
		}
		return string;
	}
}

Lets test this method on our emulator. Select Run->Run configurations and create new Android application configuration for our project and run it. Emulator screen should look similar to this:

If your result equals mine then you have running Android JSON-RPC client.

testMethod is pretty simple, lets upgrade it a bit.

private String getDataMethod(int numRows)
{
	JSONRPCClient client = JSONRPCClient.create(&amp;quot;http://10.0.2.2/xmlrpc-test/public/server/json&amp;quot;);
	String string = &amp;quot;&amp;quot;;
	try {
		JSONArray items = client.callJSONArray(&amp;quot;cf.getData&amp;quot;, numRows);
		for (int i = 0; i &amp;lt; items.length(); i++) {
			try {
				JSONObject item = items.getJSONObject(i);
				string = string + item.getString(&amp;quot;number&amp;quot;) + &amp;quot;. &amp;quot; + item.getString(&amp;quot;title&amp;quot;) + &amp;quot; - &amp;quot; + item.getString(&amp;quot;datetime&amp;quot;) + &amp;quot;\n\n&amp;quot;;
			} catch (JSONException e) {
				Log.i(&amp;quot;JSON-RPC Client&amp;quot;, e.toString());
			}
		}
	} catch (JSONRPCException e) {
		Log.i(&amp;quot;JSON-RPC Client&amp;quot;, e.toString());
	}
	return string;
}

You can see that in line 6 of getDataMethod we tell our client that we expect JSON Array (JSON Object in some other cases could be used). In for loop we are iterating through this JSON array, creating JSON objects for array elements and pulling its data out.

Next step is to switch method calls in onCreate method:

textView.setText(testMethod());

with this one:

textView.setText(getDataMethod(12));

Save and run this configuration again. You should get similar result to this:

That’s it! We’ve covered everything, from PHP JSON-RPC server to Android client.

JSON-RPC vs. XML-RPC

Reason for writting was to check if and how much is JSON-RPC better than XML-RPC. My results are pretty conclusive.

My test procedure was pretty simple. I’ve run getData method on both JSON-RPC and XML-RPC, both of them returned simple data row (200 rows) – ordinal number, ‘Codeforest.net’ string and current date & time (Y-m-d H:i:s format).

Generated JSON data was 14kB, XML data was 52kB. This information alone was enough to convince me that  JSON-RPC was better. While using mobile network connection we should care for single byte, let alone 3x difference.

Second series of test was to determine who is faster. Both in method request-response cycle (combined with iterating through data) and in iterating through returned data alone. JSON-RPC’s method cycle (combined with iterating) was around 2.100ms while XML-RPC’s was 8.700ms. Iteration through data was around 1.200ms for JSON-RPC and around 6.000ms for XML-RPC. Difference in this test is even bigger, around 4x.


Although, my tests were simple and many different parameters affected the results, I think that it certainly shows that JSON-RPC is far better remote procedure than XML-RPC. What do you think?

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon



  • Mr.Vini

    great article, definitely will use similar approach on my next project