Find file History

README.md

"App Engine Java Endpoints Module" Template

This backend template employs Google Cloud Endpoints to define a RESTful backend API from very simple annotations of the server-side Java code. Google Cloud Endpoints also provide automated Java object marshalling/unmarshalling to JSON, generation of strongly-typed client libraries that can be called from your Android app, built-in authentication support and so on.

1. Adding a backend in Android Studio

To add the backend to your existing Android app from this backend template, open Android Studio (installation instructions) and navigate to "File → New Module..." or right-click on your project and choose "New → Module".

Tools → Google Cloud Tools → Add App Engine Backend

In the "New Module" wizard that appears, choose "Google Cloud Module":

Add App Engine Backend Choose Module

Then choose "App Engine Java Endpoints Module".

Tools → Google Cloud Tools → Add App Engine Backend

Enter the module/package names for your new backend, and choose the "client" module in your project which contains your Android app. The client module will be set up to call your newly generated backend. Module name which you've entered above (marked with red 1) will be used in your Android Studio project. Package name (marked with red 2) will be used for all classes imported from this template and (reversed) for Endpoints API namespace. In turn, Endpoints API namespace will be used to derive the name of the autogenerated Android client libraries, hence this ensures that the names of generated client libraries will match your package name.

Added "HelloWorld" backend. Red numbers 1 and 2 indicate that the module name and the package name came from "New App Engine Module" dialog

1.1. Debugging the backend locally

As soon as the backend module is added to your project and Gradle sync finishes, a new run configuration with your backend's module name should be created:

Created run configuration

Rebuild your project (via "Build → Rebuild Project") and launch this run configuration. It will invoke appengineRun task in Gradle plug-in for App Engine, which in turn will start the local App Engine Java development server.

To ensure that your backend started successfully, navigate to http://localhost:8080. If everything went well, you should see the following page:

"HelloWorld" backend running in local Java development server

2. Connecting your Android app to the backend

When you created a backend module, strongly-typed client libraries have been automatically generated for you. These client libraries are re-built together with your backend module. Furthermore, your Android app ("client") module has been set up to include compile dependencies to these generated client libraries, access internet and so on.

To start sending requests to the added Cloud Endpoints backend API, you can use the following code snippet. In particular, this snippet illustrates how to create an AsyncTask which makes the request to the backend and prints the incoming result string to a toast in a given context:

class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
    private static MyApi myApiService = null;
    private Context context;

    @Override
    protected String doInBackground(Pair<Context, String>... params) {
        if(myApiService == null) {  // Only do this once
            MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
                    new AndroidJsonFactory(), null)
                // options for running against local devappserver
                // - 10.0.2.2 is localhost's IP address in Android emulator
                // - turn off compression when running against local devappserver
                .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                    @Override
                    public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                        abstractGoogleClientRequest.setDisableGZipContent(true);
                    }
                });
                // end options for devappserver

            myApiService = builder.build();
        }

        context = params[0].first;
        String name = params[0].second;

        try {
            return myApiService.sayHi(name).execute().getData();
        } catch (IOException e) {
            return e.getMessage();
        }
    }

    @Override
    protected void onPostExecute(String result) {
        Toast.makeText(context, result, Toast.LENGTH_LONG).show();
    }
}

To make the actual call, invoke this EndpointsAsyncTask from one of your Android activities. For example, to execute it from MainActivity class, add the following code snippet to MainActivity.onCreate method:

new EndpointsAsyncTask().execute(new Pair<Context, String>(this, "Manfred"));

2.1. Testing your app in an emulator

If you have granted the internet access permission to your AndroidManifest.xml file, added compile dependencies to Android app's build.gradle file, and added an EndpointsAsyncTask invokation to one of your Android app activities as per steps above, you should be all set to test your backend locally!

First, launch your backend locally as described in section 1.1. and ensure that you can access it via http://localhost:8080. Then, change the run configuration back to your Android app and run the Android emulator.

If everything goes well, you should see the following toast in your app:

"HelloWorld" backend connected to Android emulator

2.1.1. Testing device registration on a physical device

Testing on a physical device with a local development server requires minor changes to your configuration.

  1. You must make your development server accessible to the network by setting it to listen to external connections. You can do this by editing the build.gradle for the backend project and setting the httpAddress.

    appengine {
      ....
      httpAddress = "0.0.0.0"
      ....
    }
  2. You must also change the endpoint root url to point to your computer's ip address when creating the endpoint .

    Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
            new AndroidJsonFactory(), null)
            .setRootUrl("http://<my-computer-address>:8080/_ah/api/")
            ....

2.2. Deploying the backend live to App Engine

If your backend is working locally, you can deploy it to Google App Engine.

  1. Stop the backend, if it is running locally, by selecting Run > Stop.

  2. Run Build > Deploy Module to App Engine.

Deploy module to App Engine

  1. In the Deploy to App Engine dialog, select your module. From the Deploy To: dropdown list, choose "Click here to create a new Google Developers Console project." This will open Google Developers Console

    • If you are running this task for the first time, you will be prompted to sign-in with your Google Account. Choose an account and sign in.
  2. Create a new project and switch back to the Deploy to App Engine dialog in Android Studio.

  3. This would probably be a good time to update your src/main/webapp/WEB-INF/appengine-web.xml file's <application> property and replace myApplicationId with the ID of the project that you just created. This will be important if you try to deploy from the command line.

  4. Click the Refresh button Deploy module to App Engine in the bottom right corner of the Deploy To: dropdown list and then select the project you just created.

  5. Click Deploy. You can monitor the status of your deployment in the Android Studio console.

2.3. Testing against a deployed backend

Once you have deployed your backend to App Engine, you can connect your Android app to it by modifying EndpointsAsyncTask class defined in section 2 above. In particular, replace the lines

MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
        .setRootUrl("http://10.0.2.2:8080/_ah/api/") // 10.0.2.2 is localhost's IP address in Android emulator
        .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
            @Override
            public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                abstractGoogleClientRequest.setDisableGZipContent(true);
            }
        });

with these two lines

MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
        .setRootUrl("https://android-app-backend.appspot.com/_ah/api/");

where android-app-backend corresponds to your own Project ID created in section 2.2.

At this point you should be all set to run your Android app in an emulator or on the physical device, and successfully communicate with your new App Engine backend!