class ServerController extends Zend_Controller_Action
{
public function indexAction()
{
$this->_helper->viewRenderer->setNoRender();
$server = new Zend_XmlRpc_Server();
$server->setClass('Application_Model_Data', 'cf');
echo $server->handle();
}
}
First, we disable our view. We instantiate Zend_XmlRpc_Server and add class which will respond to calls from client, this will be our Application_Model_Data class and we will set its namespace as cf.
We echo the servers handle method, and voila, our very simple and basic XMLRPC server is done.
Now let’s open our model (application/models/Data.php) and create some test method for returning dummy data.
class Application_Model_Data
{
/**
* Test method
*
* @return string
*/
public function test()
{
return 'Hello XMLRPC!';
}
}
This class, Application_Model_Data is classic PHP class, the most important thing here is to notice the comments. They are mandatory, because when call occurs, Zend_XmlRpc_Server will be doing reflection of this class before running it, checking if called method exists and if its arguments are matching defined ones and are correct type. So, we have to define types of all input parameters (none in this test method) as well as method return type.
Let’s write XML RPC client to check if everything is OK so far.
XMLRPC PHP client
Earlier we created ClientController class (located in application/controller/Client.php) with default indexAction method and now we’ll add our code in it.
class ClientController extends Zend_Controller_Action
{
public function indexAction()
{
$client = new Zend_XmlRpc_Client('http://localhost/xmlrpc-test/public/server/');
try {
$data = $client->call('cf.test');
$this->view->data = $data;
} catch (Zend_XmlRpc_Client_HttpException $e) {
require_once 'Zend/Exception.php';
throw new Zend_Exception($e);
} catch (Zend_XmlRpc_Client_FaultException $e) {
require_once 'Zend/Exception.php';
throw new Zend_Exception($e);
}
}
}
First we instantiate Zend_XmlRpc_Client and provide its constructor URI of our XML RPC server. Then we try to make a call to a test method (‘cf’ is a namespace defined for our Application_Model_Data class). We’ll forward returned data to our view.
Our view is located in application/views/scripts/client/index.phtml. In it we are only echoing data returned from our test method.
<h1>Via XMLRPC</h1>
<?php echo $this->escape($this->data); ?>
If we run http://localhost/xmlrpc-test/public/client in our browser we should get something like this:
Let’s add another method to our Application_Model_Data class which will be expecting single Integer parameter and it will be returning an associative array.
/**
* Fetches data
*
* @param integer $num
* @return array
*/
public function getData($num)
{
$data = array();
for ($a = 0; $a < $num; $a++) {
$data[] = array(
'title' => 'Codeforest.net',
'number' => $a + 1,
'datetime' => date('Y-m-d H:i:s')
);
}
return $data;
}
Method is called getData (yes, very creative) and it’s pretty simple. Again, notice the comments with defined @param and @return lines.
We also have to upgrade our ClientController class and instead of calling cf.test method will be calling cf.getData method. We only have to supstitute one line (7th):
$data = $client->call('cf.test');
with this one:
$data = $client->call('cf.getData’, 15);
Everything else in the ClientController class stays the same.
We have to update our view script with something like this:
<h1>Via XMLRPC</h1>
<?php if (count($this->data) > 0):?>
<ul>
<?php foreach ($this->data as $row):?>
<li><?php echo $this->escape($row['number'])?> - <?php echo $this->escape($row['title'])?>, <?php echo $this->escape($row['datetime'])?></li>
<?php endforeach;?>
</ul>
<?php endif; ?>
Again, we go to our browser to test http://localhost/xmlrpc-test/public/client.
This concludes our PHP and Zend Framework part of the article.XMLRPC Android client
If using Eclipse switch to Android workspace (File->Switch Workspace, pick your Android workspace).
After you have switched workspace go to File->New->Android Project, enter project name, select build target and fill the rest of the properties.Download Android XML-RPC client library from http://code.google.com/p/android-xmlrpc/.Create new package in our project (right mouse click on project name in Package explorer and select New->Package). Name this package org.xmlrpc.android and copy files form archive directory android-xmlrpc/src/org/xmlrpc/android into this newly created package.Now our directory structure should be similar to picture below:Because we’ll be needing internet connection (to connect to our XML-RPC server) we need to add internet permission to our 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:<?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" > <TextView android:id="@+id/text_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
Now we can start building our Android Client. Open Client.java in our com.cf.xmlrpc package and enter:
public class Client extends Activity {
private XMLRPCClient client;
private URI uri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
uri = URI.create("http://10.0.2.2/xmlrpc-test/public/server/");
client = new XMLRPCClient(uri);
TextView textView = (TextView) findViewById(R.id.text_view);
}
}
First, we create class variables which will hold our XMLRPC Client and URI for our server. We can access this variables throughout our class.
In onCreate method we assign our uri variable URI object. 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.
Then we create our XMLRPCClient and give its constructor our uri variable.
We’ll also get reference to TextView element of our layout where we’ll display our results.
If Eclipse is signaling for some error due to not having imported needed classes press Ctrl+Shift+O, this will import all needed classes automatically.
Next, we’ll create method which will call test method on our XML-RPC server (built earlier with Zend Framework).
private String testMethod() {
String text = "";
try {
text = (String) client.call("cf.test");
} catch (XMLRPCException e) {
Log.w("XMLRPC Test", "Error", e);
text = "XMLRPC error";
}
return text;
}
We’re using try – catch block to catch errors and to deal with them. 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 {
private XMLRPCClient client;
private URI uri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
uri = URI.create("http://10.0.2.2/xmlrpc-test/public/server/");
client = new XMLRPCClient(uri);
TextViewtextView = (TextView) findViewById(R.id.text_view);
textView.setText(testMethod());
}
private String testMethod() {
String text = "";
try {
text = (String) client.call("cf.test");
} catch (XMLRPCException e) {
Log.w("XMLRPC Test", "Error", e);
text = "XMLRPC error";
}
return text;
}
}
We are ready to test our Android client. Select Run->Run configurations and create new Android application configuration for our project:
After the emulator boots up we should have something similar to this:
Hoorah! Our Android client is using our XML RPC web service!
Lets now create method which will call our other server function getData.
private String getDataMethod(int num) {
String text = "";
try {
Object[] data = (Object[]) client.call("cf.getData", num);
for(Object o: data) {
HashMap map = (HashMap) o;
text = text + "'datetime' => " + map.get("datetime") + ", 'number' => " + map.get("number") + ", 'title' => " + map.get("title") + "\n\n";
}
} catch (XMLRPCException e) {
Log.w("XMLRPC Test", "Error", e);
text = "XMLRPC error";
}
return text;
}
Method we are calling (cf.getData) expects one parameter (integer) and returns an associative array (from PHP’s perspective). In Java we received array with map items.
If you are having trouble figuring out what your custom XML RPC service is returning you be sure to check out great post at Inchoo. It describes how to parse the data returned from XMLRPC.
Next step is to switch method calls in onCreate method:
textView.setText(testMethod());
to this one:
textView.setText(getDataMethod(12));














No user commented in " How to build PHP XML-RPC Server, Client and Android application "
Follow-up comment rss or Leave a Trackback