Code Examples


There are several ways to call MXQuery from Android.  This document explains the most common ways of using MXQuery in Android with code examples for each.



Asynchronous XQuery

Calling XQuery asynchronously from Android is the preferred method.  There are several implementation options for asynchronous XQuery processing.  We outline a few of the most common options here:

Android Service

There many options for how to implement a service for XQuery.  This example uses a local bound service with callback functions:

First define an interface which will serve as the callback for the asynchronous query execution:

XQueryListener.java

package ch.ethz.mxquery.android.examples;

/**
 * This interface is used to provide callback functions by the XQueryService.
 */
public interface XQueryListener {
    public void newXQueryResult(final String result);
}


Then define the Service:

XQueryService.java

package ch.ethz.mxquery.android.examples;

import java.io.StringWriter;

import ch.ethz.mxquery.android.examples.XQueryListener;
import ch.ethz.mxquery.xqj.MXQueryXQDataSource;
import ch.ethz.xquery.XQConnection;
import ch.ethz.xquery.XQDataSource;
import ch.ethz.xquery.XQException;
import ch.ethz.xquery.XQExpression;
import ch.ethz.xquery.XQSequence;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class XQueryService extends Service {
    private final XQDataSource xqjd = new MXQueryXQDataSource();
    private final IBinder mBinder = new XQueryServiceBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class XQueryServiceBinder extends Binder {
        XQueryService getService() {
            // Return this instance of XQueryService so clients can call public methods
            return XQueryService.this;
        }
    }

    /**
     * Runnable thread to process query asyncronously and call callback method.
     */
    private class QueryThread extends Thread {
        private String query;
        private XQueryListener listener;
        
        public QueryThread(String query, XQueryListener listener) {
            this.query = query;
            this.listener = listener;
        }

        public void run() {
            String result = doQuery(this.query);
            listener.newXQueryResult(result);
        }
    }

    /**
     * Executes the query synchronously.
     */
    protected String doQuery(String query) {
        StringWriter result = new StringWriter();

        try {
            XQConnection xqjc = xqjd.getConnection();
            XQExpression xqje = xqjc.createExpression();
            XQSequence xqjs = xqje.executeQuery(query);

            xqjs.writeSequence(result, null);
            xqjc.close();
        } catch (XQException xqe) {
            xqe.printStackTrace();
        }

        return result.toString();
    }

    
    /**
     * Public method for clients.
     * Runs query asynchronously.
     * Query will run in separate thread and this method will return immediately.
     */
    public void runQuery(String query, XQueryListener listener) {
        QueryThread queryThread = new QueryThread(query, listener);
        queryThread.start();
    }
}


Then define the Activity:

ServiceExample.java

package ch.ethz.mxquery.android.examples;

import android.R;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.TextView;
import ch.ethz.mxquery.android.examples.XQueryService.XQueryServiceBinder;

public class ServiceExample extends Activity {
    protected TextView mTextView;
    protected XQueryService mService;
    protected boolean mIsBound = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTextView = (TextView) findViewById(R.id.textView1);
       
        // Start service
        if(!mIsBound) {
            doBindService();
        }
       
        // Note: Query will be executed in onServiceConnected()
    }

    /* Defines callback for runQuery() */
    protected XQueryListener queryListener = new XQueryListener() {
        public void newXQueryResult(final String result) {
            runOnUiThread(new Runnable() {
                public void run() {
                    mTextView.setText(result);
                }
            });
        }
    };
   
    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to XQueryService, cast the IBinder and get XQueryService instance
            XQueryServiceBinder binder = (XQueryServiceBinder) service;
            mService = binder.getService();
            mIsBound = true;
           
            // Run the query
            String query = "Hello XQuery";
            mService.runQuery(query, queryListener);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mIsBound = false;
        }
    };
   
    void doBindService() {
        bindService(new Intent(ServiceExample.this, XQueryService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }
}


Download sample project: ServiceExample Project


Android AsyncTask

Android's AsyncTask class can make it easy to perform long-running operations in the background.  However, for actions that require UI updates, AsyncTasks can be difficult to work with in combination with the Activity lifecycle.  Therefore we generally recommend running MXQuery in a Service rather than in an AsyncTask.  If AsyncTask is the right choice for your application, this example will help get you started:

AsyncTaskExample.java

package ch.ethz.mxquery.android.examples;

import java.io.StringWriter;

import android.R;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import ch.ethz.mxquery.xqj.MXQueryXQDataSource;
import ch.ethz.xquery.XQConnection;
import ch.ethz.xquery.XQDataSource;
import ch.ethz.xquery.XQException;
import ch.ethz.xquery.XQExpression;
import ch.ethz.xquery.XQSequence;

public class AsyncTaskExample extends Activity {
    protected final Activity mActivity = this;
    protected TextView mTextView;

   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTextView = (TextView) findViewById(R.id.textView1);

        // Run query with ASyncTask
        String query = "Hello XQuery";
        new XQueryAsyncTask().execute(query);
    }

    /**
     * AsyncTask for running query on background thread.
     */
    protected class XQueryAsyncTask extends AsyncTask<String, Integer, String> {

        @Override
        protected void onPreExecute() {
            // Clear results
            mTextView.setText("");
        }

        @Override
        protected void onPostExecute(String result) {
            // Update UI with result
            mTextView.setText(result);
        }

        @Override
        protected String doInBackground(String... query) {
            StringWriter result = new StringWriter();

            try {
                XQDataSource xqjd = new MXQueryXQDataSource();
                XQConnection xqjc = xqjd.getConnection();
                XQExpression xqje = xqjc.createExpression();
                XQSequence xqjs = xqje.executeQuery(query);

                xqjs.writeSequence(result, null);
                xqjc.close();
            } catch (XQException xqe) {
                xqe.printStackTrace();
            }

            return result.toString();
        }
    }
}




Synchronous XQuery

It is generally recommended to use MXQuery on Android asynchronously, however it is also possible to call MXQuery syncronously.  Be aware that long-running XQuery queries may cause the application to become unresponsive (if run in the main UI thread); see Designing for Responsiveness for more information. 

XQJ

This simple example runs a query in an Activity and returns the result as a String, which is displayed in the Activity's view.


XQJExample

package ch.ethz.mxquery.android.examples;

import java.io.StringWriter;

import android.R;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import ch.ethz.mxquery.xqj.MXQueryXQDataSource;
import ch.ethz.xquery.XQConnection;
import ch.ethz.xquery.XQDataSource;
import ch.ethz.xquery.XQException;
import ch.ethz.xquery.XQExpression;
import ch.ethz.xquery.XQSequence;

public class XQJExample extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        // Run the XQuery query
        String query = "Hello XQuery";
        String queryResult = doQuery(query);
       
        //Set the result in the UI
        TextView mTextView = (TextView) findViewById(R.id.textView1);
        mTextView.setText(queryResult);
    }
   
    /**
     *  Executes an XQuery expression using XQJ API
     */
    public String doQuery(String query) {
        StringWriter result = new StringWriter();

        try {
            XQDataSource xqjd = new MXQueryXQDataSource();
            XQConnection xqjc = xqjd.getConnection();
            XQExpression xqje = xqjc.createExpression();
            XQSequence xqjs = xqje.executeQuery(query);

            xqjs.writeSequence(result, null);
            xqjc.close();
        } catch (XQException xqe) {
            xqe.printStackTrace();
        }

        return result.toString();
    }
}


Download sample project: XQJExample Project

Comments