This guide describes how to convert an existing Android app to an Android add-on. If you are building an Android add-on from scratch, build it as a stand-alone Android app first, then follow these steps to make it an Android add-on.
If you're new to Android app development you may want to begin by following the Android Developer tutorial for Building Your First Android App.
Modify your Android manifest
Exposing add-on functionality from an existing Android app is as easy as adding
an <intent-filter> to your app's Android manifest. In your app's manifest file
, find the activity you’d like to expose as an add-on and add an
<intent-filter> tag indicating your app can handle add-on intents, as
demonstrated in this example:
<activity
android:name="com.example.YourActivityName"
android:label="@string/activity_name" >
<intent-filter
android:label="@string/addon_name"
android:icon="@drawable/addon_icon">
<action android:name="com.google.android.apps.docs.editors.sheets.ADDON" />
</intent-filter>
</activity>
Adding this intent-filter will cause your add-on to be shown in the add-ons
Menu in the Google Sheets app. You should provide an icon and label to be shown
in the add-ons menu by specifying android:label and android:icon attributes
for your intent filter (see
Providing Resources
and
Accessing Resources from XML
).
To have your add-on extend Google Docs instead of Sheets, simply change the
value of the <action> tag in the above example from:
"com.google.android.apps.docs.editors.sheets.ADDON"
to
"com.google.android.apps.docs.editors.docs.ADDON"
If your
activity
can extend both Docs and Sheets, include both <action/> tags in the
intent-filter. Your add-on can determine at runtime which editor triggered it
using your activity's
getCallingPackage()
method.
For more background on the intent-based mechanisms Android apps use to communicate, see Intents and Intent Filters.
Provide a default launcher activity
Most Android apps define a default launcher activity in their manifest. This activity is the first one started when the app is launched from the device's Home screen, and serves as the main entry point to the app.
Always include a launcher activity, even if launching your Android add-on on its own isn't useful. This will handle cases when the add-on is launched directly, for example if a user taps the install notification.
If you do not provide a launcher activity, a user who launches your add-on directly will be taken to a basic screen stating Item not found, with a simple Retry button that will not give them access to your app or explain what is happening. This is a poor user experience you should avoid.
If you are extending an existing Android app to be an Android add-on, chances are you already have a launcher activity and will avoid this issue. If you don't, be sure to create one. If the add-on functionality needs context from the Docs or Sheets apps to function at all, make a simple launcher activity that explains this to the user and provides a button to close the app.
Set Android permissions
Android add-on apps must have the GET_ACCOUNTS Android permission. This is
necessary to allow your app to receive the Google account associated with the
active document.
To request this permission, place the following tag in the <manifest> section
of your app’s Android manifest. Many existing apps already request this
permission.
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
In addition, your add-on should also make use of runtime permissions when possible and follow the runtime permission best practices.
Modify your add-on activity
When a user selects your add-on from the Add-ons menu in a Google Apps
editor, the activity specified in your manifest will be started. In your
activity’s onCreate method you’ll want to grab the intent used to start your
activity as this will contain:
- The document ID of the Doc or Sheet currently open in the editor app
- The session state of that Doc or Sheet (as an encoded String)
- The account of the user calling the add-on
You can get this intent by calling your activity’s getIntent() method. The resulting activity will likely resemble this example:
import android.accounts.Account;
import android.app.Activity;
public class MyAddOnActivity extends Activity {
// Your activity...
String sessionState;
String docId;
Account account;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
docId = getIntent().getStringExtra(
"com.google.android.apps.docs.addons.DocumentId");
sessionState = getIntent().getStringExtra(
"com.google.android.apps.docs.addons.SessionState");
account = (Account) getIntent().getParcelableExtra(
"com.google.android.apps.docs.addons.Account");
// Your activity’s initialization...
}
}
When your activity is finished and is ready to return the user back to the
Google editor, set the result code and call your activity's finish() method,
like so:
setResult(Activity.RESULT_OK);
finish();
Use document context with the Execution API
Most Android add-ons will make use of Apps Script Execution API.
When using the API, including the session state String ensures that Apps Script
functions have the correct document context. This allows the API to call Apps
Script methods that typically require the script to be container-bound
to a particular Doc or Sheet, such as
DocumentApp.getActiveDocument().
In order to ensure the Execution API has the correct context when called from an
Android app, you just have to include the session state string when building
the ExecutionRequest object:
// Acquire the session state String from the calling Intent.
sessionState = getIntent().getStringExtra(
"com.google.android.apps.docs.addons.SessionState");
...
// Construct the API request.
ExecutionRequest request = new ExecutionRequest().
.setFunction(functionName)
.setSessionState(sessionState)
.setParameters(params) // Only needed if the function requires parameters
.setDevMode(true); // Optional
See the Apps Script Execution API Android Quickstart for an example of how to call an Apps Script function from an Android app using the API.
Create OAuth credentials
Android add-ons that make use of the Apps Script Execution API must to enable the API in the Developer Console project that the add-on is associated with. In addition, the add-on needs a valid Android OAuth credential, created using a SHA1 key. For debug builds, this process is described in Step 1 and Step 2 of the Execution API Android Quickstart.
Release builds that will be uploaded to the Google Play Store need to be properly Signed, using a keystore you create and a key specific to that app. Because they depend on a different keystore, release builds need their own Developer Console OAuth credential. This is built using the same steps used to create the debug build credential, except that you can get the SHA1 key using:
$ keytool -exportcert -alias <key_alias> -keystore <path_to_keystore_file> -list -v
This command will ask you for the keystore password you set when you created the keystore (do not share this password with anyone).
Alternatively, you can also get the SHA1 keys for all your defined builds by running a signing report task from within Android Studio:
- Click Gradle on the right side of the IDE window.
- Navigate to MyApplication > Tasks > android and double-click signingReport.
- To view the report, click Gradle Console at the bottom of the IDE window.
A Developer Console project can support multiple Android OAuth credentials, so you can create as many as you need.
Run your unpublished add-on
Only add-ons approved through the curation process are normally visible in the editors’ menus. During development a not-yet-reviewed add-on can be treated as though it were approved by setting the app as the system debug app. Once you have an Android device in developer mode and attached to a development machine via USB, you can set your app as the debug app by running the Android Debug Bridge command:
$ adb shell am set-debug-app --persistent <YOUR_PACKAGE_NAME>
This will allow both debug and release builds of your add-on to run on your device.
The system debug app can be unset with:
$ adb shell am clear-debug-app