Suppose you want create an Android application (the main application) and several other applications that use your main application. The other applications bring data for your main application, extending it (so further on, I will call them extensions). Basically you need to solve two issues:
- The main applications needs to know whether there are other applications that extend it.
- The applications need to communicate with one another.
First of all, I tried to copy the data from the extension to the private data of the application upon installation of the extension. That means I searched for a kind of an onInstall event where I could execute custom code. This does not seem to be possible in Android.
Then I stumbled upon services and receivers. Now, my main application (package=“com.example“) sends a broadcast with an intent:
Intent intent = new Intent(action);
activity.sendBroadcast(intent);
The action string could be something like: your application package name + actions + a verb, such as COLLECT, e.g. com.example.actions.COLLECT.
My extension (package=“com.example.extensions.test“) uses a broadcast receiver with an onReceive() method to receive the sent broadcast of the main application:
public class TestReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast toast = Toast.makeText(context, "Received message", Toast.LENGTH_LONG);
toast.show();
...
Beside the Java code, you also need to configure the AndroidManifest.xml of the extension to make the receiver react to the above action:
<application>
<receiver android:name="com.example.TestReceiver">
<intent-filter>
<action android:name="com.example.plugins.COLLECT"></action>
</intent-filter>
</receiver>
</application>
In the next step, I copy the data of the extension to the private area of the main application. This is possible by creating the context of the package of the main application. The new context can access the private data of the main application.
@Override public void onReceive(Context context, Intent intent) {
...
AssetManager am = context.getAssets();
FileOutputStream fos;
Context ctx;
try {
ctx = context.createPackageContext("com.example", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
InputStream is = am.open(...);
...
fos = ctx.openFileOutput(..., Context.MODE_PRIVATE);
To make the code above work, a sharedUserId has to be provided in both AndroidManifests, that of the main application and that of the extension.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.example" ... >
In the main application, it is possible to list all private files:
String[] fileList = fileList();
for (String string : fileList) {
...
}