Let’s Talk: Efficient Communication for PHP and Android, Part 1

Share this article

The mobile space has exploded in the last several years, prompting the realization that service-oriented architecture is a great way to implement business logic for consumption by both web and mobile applications. While mobile devices have evolved dramatically, their increased availability to consumers has added strain on networks and service providers who are still struggling to make capacity meet demand. To keep hardware costs down, developers must now pinch bytes of bandwidth just as they did with memory back in the early days of computing. This two-part article will guide you through the process of building an efficient PHP-based REST web service to be consumed by an Android-based application. Some of the concepts presented here are also applicable to other mobile platforms, such as iOS. I assume you already know the basics of PHP and Android development and that you have a suitable development environments set up for both. I’ll focus mainly on showing you how to handle data serialization and compression in both environments.

A Common Request

Here are the particular parts of a typical HTTP operation that we’re interested in:
  1. The client (e.g. the Android application) sends an HTTP request to the REST service (e.g. the server) and uses request headers to indicate which data serialization and compression formats it supports.
  2. Based on the request headers, the server determines which data serialization and compression formats it has in common with the client, selects one of each, applies them to the requested data, and sends a response containing headers specifying its selections and the data back to the client.
  3. Based on the response headers, the client applies the corresponding decompression and deserialization routines to the data to restore it to its original state and can then use it for its intended purpose.
Let’s start at the beginning and go through each step.

Requesting Data

In order to make HTTP requests, your Android application needs permission to access the Internet. You need to declare this in your project’s AndroidManifest.xml file like so:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
 <uses-permission android:name="android.permission.INTERNET" />
</manifest>
Afterwards, you need a class that actually handles making the HTTP requests and processing the responses. For this I will use the native AndroidHttpClient
class which comes with a default configuration suitable for most purposes including use of a thread-safe connection manager. The AndroidHttpClient class is only available in Android 2.2 (API level 8) and above. To support older versions, look at the DefaultHttpClient class from the Apache Harmony library that Android has included since its first version.
import android.net.http.AndroidHttpClient;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;

public class DataModel {
    protected AndroidHttpClient httpClient;
    protected HttpGet httpRequest;

    public DataModel() {
        this.httpClient = AndroidHttpClient.newInstance(
            "Android " + android.os.Build.VERSION.RELEASE
            // Your app name would also be an acceptable value here
        );
    }

    public DataValueObject getData() throws IOException {
        HttpGet httpRequest = new HttpGet(
            "http://10.0.2.2/php-android/");
        httpRequest.addHeader("Accept", 
            "application/json;q=1,application/x-msgpack;q=0.9");
        httpRequest.addHeader("Accept-Encoding", 
            "bzip2,gzip,deflate");
        HttpResponse httpResponse = this.httpClient.execute(httpRequest);
        // ...
    }
}
When this class is instantiated, it internally creates an instance of AndroidHttpClient. When the getData()
method is called to request data, it creates an instance of HttpGet, populates it with request data, and uses the AndroidHttpClient instance to send it. Included in the request data are the following:
  1. The URL of the resource being requested (i.e. your REST endpoint). If you host this on the same machine hosting your Android development environment, you can access it from the emulator using the IP address 10.0.2.2 (as in the above example) and from a physical device plugged in via USB using the IP address 10.0.1.2.
  2. The data serialization formats supported by the client, in this case JSON and MessagePack, and their respective quality factors, floating point numbers between 0 and 1 with higher numbers indicating a higher preference for that particular format. More information on these can be found in RFC 2616 Section 12.
  3. The data encoding formats supported by the client, in this case bzip2, gzip, and deflate. More information on these can be found in RFC 2616 Section 3.5.
  4. It’s possible for the AndroidHttpClient instance to encounter issues, such as the server not being available. Its execute() method can throw an IOException to indicate this, which the code calling getData() can catch and handle as appropriate. We’ll come back to the rest of the getData() method in a later section when we examine processing the response, but for now we need to implement use of this class in an Android activity.

    Implementing a Background Task

    Requesting and processing data in the context of a mobile application is an asynchronous operation. That is, we want the application to send the request for the data and then take some action once the response is received, such as populating the user interface with the data. By default, Android contains each individual app in its own process and thread, the latter of which is often called the UI thread because user interface operations run on it. As such, intensive operations like obtaining and processing data from a web service should be run on a separate thread so as not to block UI operations, which generally results in irritated users. To do this, we need to write a subclass of AsyncTask to encapsulate the process.
    import java.io.IOException;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.ProgressDialog;
    import android.content.DialogInterface;
    import android.os.AsyncTask;
    
    public class GetDataTask extends AsyncTask<Void, Void, DataValueObject> {
        ProgressDialog progressDialog;
        Activity activity;
        String error;
        
        public GetDataTask(Activity activity) {
            super();
            this.activity = activity;
        }
        
        protected String getString(int id) {
            return this.activity.getResources().getString(id);
        }
        
        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(
                this.activity,
                "", 
                getString(R.string.loading),
                true,
                false
            );
        }
    
        @Override
        protected DataValueObject doInBackground(Void... params) {
            DataModel dataModel = new DataModel();
            DataValueObject dvo = null;
            try {
                dvo = dataModel.getData();
            } catch (IOException e) {
                this.error = getString(R.string.error); // or e.getMessage() when debugging
            }
            return dvo;
        }
        
        @Override
        protected void onPostExecute(DataValueObject dvo) {
            if (dvo != null) {
                // Do something useful with dvo here
                
                // Dismiss the progress dialog when done
                progressDialog.dismiss();
            } else {
                // Dismiss the progress dialog
                progressDialog.dismiss();
                
                // Display a simple error dialog to the user
                new AlertDialog.Builder(this.activity)
                    .setMessage(this.error)
                    .setNeutralButton(
                        getString(R.string.ok),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        }
                    )
                    .create()
                    .show();
            }
        }
    }
    As part of extending AsyncTask, this class specifies that the result of the operation will be an instance of the DataValueObject class which the getData() method of the DataModel class returns. The class constructor takes as its only parameter the activity instance that’s invoking it. This is used later to access localized strings and use the activity in other context-specific tasks. The onPreExecute() and onPostExecute() methods will vary depending on what you want to do before and after the background operation starts. My examples above show a simple use case of displaying a progress dialog and potentially an alert dialog when an error occurs. doInBackground() contains the logic that needs to run in a background thread, in this case calling getData(). It returns an instance of DataValueObject or null if an error occurs. That value is then passed to onPostExecute() when it’s invoked so you can do something useful with it.

    Executing the Background Task

    Now that we’ve properly encapsulated the background task we want to run to fetch the data, we need to actually invoke it in an activity. Part of this will require checking that a network connection is available so that the request for data can actually get to the server. Doing this requires adding an additional permission to your AndroidManifest.xml file:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    </manifest>
    An activity class that kicks off the background task when the activity is created might look like this:
    import android.app.Activity;
    import android.content.Context;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.os.Bundle;
    
    public class MyActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (networkIsAvailable()) {
                new GetDataTask(this).execute();
            } else {
                // Display an error to the user about network unavailability
            }
        }
    
        public boolean networkIsAvailable() {
            ConnectivityManager cm = (ConnectivityManager) 
                getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            return networkInfo != null && networkInfo.isConnected();
        }
    }
    The networkIsAvailable() method simply queries the appropriate service to determine if a network connection is available. If your application has a base activity class, this may be a useful method to include in it. The onCreate() activity hook uses networkIsAvailable() to either execute the background task or display an appropriate error message to the user. Executing the task is simply a matter of instantiating it with a reference to the activity and calling its execute() method.

    Next Time

    Part 1 of this article has focused mainly on setting up the Android application to make the request. In part 2 of this article coming up, we’ll get into the meat of handling data serialization and compression in both environments. Stay tuned! Image via Fotolia

Frequently Asked Questions (FAQs) about Converting PHP Project to Android App

What are the prerequisites for converting a PHP project to an Android app?

Before you start converting your PHP project to an Android app, you need to have a clear understanding of both PHP and Android development. You should be familiar with PHP syntax, object-oriented programming, and MySQL for database management. For Android development, knowledge of Java or Kotlin is essential. Additionally, you should have Android Studio installed on your computer, which is the official integrated development environment (IDE) for Android app development.

Can I convert my PHP project directly into an Android app?

Direct conversion of a PHP project into an Android app is not possible because Android does not support PHP natively. However, you can create a webview app in Android that loads your PHP website. Alternatively, you can rewrite your PHP project in a language that Android supports, such as Java or Kotlin.

What is a webview app and how does it work?

A webview app is a type of Android app that displays web content. It uses the Webview class in Android to load a web page inside the app. This is a common method used to convert a PHP website into an Android app. However, it’s worth noting that a webview app may not provide the same level of user experience as a native Android app.

How can I convert my PHP project into a native Android app?

To convert your PHP project into a native Android app, you need to rewrite your PHP code in a language that Android supports, such as Java or Kotlin. This involves translating the logic of your PHP code into the new language. You also need to design the user interface of your app using XML, which is the markup language used for Android app layout design.

Can I use any tools to convert my PHP project into an Android app?

There are several online tools and services that claim to convert a PHP website into an Android app. However, these tools often create a webview app, which may not provide the best user experience. For a native Android app, manual conversion is usually the best approach.

What are the challenges in converting a PHP project into an Android app?

Converting a PHP project into an Android app can be challenging, especially if you’re not familiar with Android development. The process involves not only translating the PHP code into a new language, but also designing the user interface, managing the database, and handling user interactions. Additionally, you need to consider the differences between a web environment and a mobile environment, such as screen size, network connectivity, and user interaction patterns.

How can I optimize my Android app for better performance?

To optimize your Android app for better performance, you should minimize the use of memory and CPU, optimize your database queries, and use efficient algorithms. You should also test your app on various devices and network conditions to ensure it performs well under different scenarios.

How can I secure my Android app?

To secure your Android app, you should encrypt sensitive data, use secure network protocols, and validate user input. You should also follow the best practices for Android app security, such as using the latest version of Android and its development tools, and regularly updating your app to fix any security vulnerabilities.

Can I monetize my Android app?

Yes, you can monetize your Android app in several ways, such as in-app purchases, ads, and subscriptions. You can also sell your app on the Google Play Store. However, you need to follow the policies of the Google Play Store and any other platforms you use for monetization.

How can I distribute my Android app?

The most common way to distribute an Android app is through the Google Play Store. You can also distribute your app through other app stores, your own website, or direct downloads. However, you need to consider the security and compatibility issues associated with each distribution method.

Matt TurlandMatt Turland
View Author

Matthew Turland has been working with PHP since 2002. He has been both an author and technical editor for php|architect Magazine, spoken at multiple conferences including Confoo and php|tek, served as an instructor for php|architect training courses, and contributed to Zend Framework. He holds the PHP 5 and Zend Framework ZCE certifications and is the author of "php|architect's Guide to Web Scraping with PHP." He currently works as a Senior Engineer for Synacor. In his spare time, Matt likes to bend PHP to his will to scrape web pages and run IRC bots.

Advanced
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week