Using the Activity Starter (App Inventor 2)
Using the Activity Starter Component (AI2)
The activity starter component lets you combine applications by having one application start up other applications. Activity Starter is mostly for advanced developers, but it's a key way to extend the App Inventor, because it means lets you take advantage of applications written by others, and created with other development frameworks.
The apps you start can be App Inventor apps created by you or others; apps like Camera and Maps that are pre-installed on the device; or any app at all, created using App Inventor or not, as long as you have the necessary information to supply to the activity starter.
For applications that are appropriately designed, you can pass values to the applications when starting it. You can also start an application and get back a result from it to use in further processing, provided that the application is designed to return a result. Presently, you can pass and receive text values only.
To start another application, you must supply certain control information to the Android operating system. You do this by setting various properties of Activity Starter before calling the StartActivity method. This section gives some examples.
Starting Another App Inventor Application from your App Inventor App
You can start another app that was created with App Inventor if you know its package name and class name. If you have the source code of the app, you can find these names as follows:
- Download the source code to your computer.
- Using a file explorer or unzip utility, find the file
youngandroidproject/project.properties
- The first line will start with "
main=
". Everything after that is the package and class name.
For example, here is a first line you might see for an App named HelloPurr.:
main=appinventor.ai_HomerSimpson.HelloPurr
The HomerSimpson
part of the name comes from the App Inventor user account.
To start this app, you would use an activity starter component with these properties:
ActivityPackage: appinventor.ai_HomerSimpson.HelloPurr
ActivityClass: appinventor.ai_HomerSimpson.HelloPurr.Screen1
Invoking the activity starter's StartActivity
method will start HelloPurr. When HelloPurr finishes (if it does), the original app's ActivityStarter.AfterActivity
method will be invoked.
Note: If you are going to start another App Inventor app, make sure you use the correct package name. For example, if someone posts the source code (zip file) for an app, and you repackage that app, you'll end up with a different package name than he had. In cases of doubt, or if you don't have the source code, start the activity by hand on the phone and run "adb logcat" to view the Android system log and see what was actually started, as explained below in "Figuring out how to set the properties".
Note: If you will be starting a second App Inventor app that you yourself are writing, it's generally easier and more convenient to design the whole thing as a single multiple screen app, rather than creating two separate apps. See the section below on "Activity Starter versus Multiple Screen Apps".
Starting a Builtin Phone Application from your App Inventor App
Apps that come with the phone can be invoked using package names and class names, as above. Android apps can also launch responses to an intent , which is the Android operating system's way of specifying something to do without necessarily designating a particular app. You can find information about intents (written for advanced developers) in the Android system documentation.
Some apps are designed to take extra information when they are launched. For example, maps can take geographic information that specifies which map to display. Another example is launching a Web search with extra information that specifies the text to search for. You must consult the documentation for the particular app to learn what this extra information is and how to specify it. Generally, you specify the information by setting the activity starter's properties just before the other app is launched.
Here are some examples:
Start the Camera
To launch the Android Camera app, use an activity starter with these properties:
Action: android.intent.action.MAIN
ActivityPackage: com.google.android.camera
ActivityClass: com.android.camera.Camera
This is pretty much what the App Inventor Camera component does, although it is much more convenient to use the Camera component.
Launch a Web search
To launch a Web search for a particular query, such as "Homer Simpson", use an activity starter with these properties:
Action: android.intent.action.WEB_SEARCH
ExtraKey: query
ExtraValue: Homer Simpson
ActivityPackage: com.google.android.providers.enhancedgooglesearch
ActivityClass: com.google.android.providers.enhancedgooglesearch.Launcher
Open the browser to a Web page
Use these activity starter properties to open a specific web page:
Action: android.intent.action.VIEW
DataUri: http://news.google.com
Start the mailer with pre-addressed message
To start the Android mailer application, use the action android.intent.action.VIEW
. You can use Activity starter's DataUri
property to specify the recipient, the subject, and the body of the message. In each case, starting the activity will bring up the Android mailer, and you can complete the message and then press "Send".
For example, if you specify:
Action: android.intent.action.VIEW
DataUri: mailto:santa@northpole.com
then starting the activity will bring up the mailer, with the addressee filed in.
If you specify:
Action: android.intent.action.VIEW
DataUri: mailto:santa@northpole.com?subject=Please Santa&body=Bring me a pony
then starting the activity will bring up the mailer, with the addressee, the subject, and the body filled in. You can use the mailer to edit these before sending the message, if you prefer.
The DataURI here must be a URL encoded message designed to work with the internet mailto service. Search the Web to find appropriate documentation and tools for creating these, for example Elements of a Mailto: URL
Show a map for a location
If you know the latitude and a longitude of a location, you can show a map using an activity starter with these properties to show a map of the area:
Action: android.intent.action.VIEW
DataUri: geo:37.8,-122.23?z=23
The format of the DataURI is specific to the app. In this example, the URI specifies a z (zoom) of 23, which is the largest zoom value. Zoom value is optional and ranges from 1 (the entire Earth) to 23.
If you know the zip code, you can set the activity starter properties as follows:
Action: android.intent.action.VIEW
DataUri: geo:0,0&q=94043
If you have a street address, you can use a DataUri that encodes the address with a scheme called URL encoding:
Action: android.intent.action.VIEW
DataUri: geo:0,0&q=5000% 20MacArthurBlvd%20Oakland%2CCA
Generally in URI encoding the only characters you have to replace are spaces ( %20 ) and punctuation marks, such as comma ( %2C ) and period ( %2E ).
Play a YouTube video
You'll need to know the URI of the YouTube video. Then set the Activity Starter properties as
Action: android.intent.action.VIEW
ActivityPackage: com.google.android.youtube
ActivityClass: com.google.android.youtube.PlayerActivity
and set the Data URI to the URI of the video to be played, for example:
DataUri: http://www.youtube.com/watch?v=8ADwPLSFeY8
Figuring out how to set the properties
If you can't find documentation for the activities you want to start, one way to figure out how to set the properties is to start up the activity manually and look at what appears in the Android System Log. For example, if you use YouTube to play a video, you'll see in the log:
I/ActivityManager( 86): Starting activity: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.youtube.com/watch?v=8ADwPLSFeY8 flg=0x3800000 cmp=com.google.android.youtube/.PlayerActivity }
If you can find the "cmp=" string, then the ActivityPackage is the part before the slash, and the ActivityClass is is the entire "cmp=" part, without the slash character. As in the YouTube example, there may also be "dat=" information that can specify with the DataUri property.
Starting arbitrary apps
You can use the Activity Starter to start any activity at all if you know the package name and class name, or the appropriate intent. Some developers document these intents for the benefit of other Android developers. For hints on starting other apps using intents, see the Android API documentation or search the Android developer forums.
If you have an app on your phone and you don't have the source code, you might still be able figure out the package name and class name (and sometimes the intent) by launching the app and inspecting the Android system log, as indicated above.
Receiving results from apps that you start
Some apps are constructed to return a result. You can see that result as the result argument of the activity starter's AfterActivity
event. Currently, App Inventor can receive text results only.
Returning results from App Inventor apps, and getting the result
You can create App Inventor apps that return a (text) result to their callers, so they can be used as subroutines. To return a result, invoke the command close screen with plain text
(located in the Control drawer). Your subroutine app will terminate, and the argument of close screen with plain text
will become available to the app that called it. If the calling app was itself an App Inventor app that used an activity starter, it will see that text as the argument to the activity starter's AfterActivity
event.
In more detail, suppose there are two App Inventor apps: A SubroutineApp
designed to be started with an activity starter and return a value, and a CallerApp
that uses an ActivityStarter to call SubroutineApp
. To return the result, SubroutineApp
executes close screen with plain text
, giving it as argument the result (text only) that should be returned to the caller.
On the caller side, CallerApp
sets up its Activity Starter with the correct package name and class name for starting SubroutineApp
. It must also set the ActivityStarter.ResultName
property to the special text string APP_INVENTOR_RESULT
. Then CallerApp
starts the SubroutineApp
activity. When the subroutine finishes, the Activity Starter's AfterActivity
event triggers, and the result that was passed back from SubroutineApp
will be available as the result
argument to AfterActivity
. That same information is available as the ActivityStarter's Result
property.
Calling App Inventor Apps and passing values to them
If you are writing an App Inventor CallerApp
to call an App Inventor SubroutineApp
, you can pass a text value to SubroutineApp
. To do this, use an Activity Starter in CallerApp
with the ExtraKey property to set to the special tag APP_INVENTOR_START
and the ExtraValue property set to the text you want to pass. The SubroutineApp
can retrieve that value by using the get start plain text
block from the Control drawer.
By passing and returning results, you can combine several App Inventor apps, both apps you write, as well as apps you share with others.
Returning results from arbitrary applications
Getting values back from other applications is like getting values back from App Inventor apps. In general in Android, an activity will return a result that is designated by a name, where the result is designated by a name, where the name is specified with the Activity Starter's ResultName
property. The name to use for App Inventor apps is APP_INVENTOR_RESULT
, as described above. Other applications, not created with App Inventor, will use other names, and you'll need to know those names in order get values back from those applications. In general, you'll need to consult documentation about the app you want to use as a subroutine. Some developers provide this information, or sometimes you'll have access to the source code.
Not all Android apps use the Result
and ResultName
mechanism. For example, some apps return information via the properties ResultType
and ResultUri
. Again, you'll need to have information from the app developer to know which of these to use.
For advanced developers: More specifically (with reference to the Android developer documentation) an app can be designed to return an intent. The Activity starter uses the specified ResultName
to access intent.getStringExtra(resultName)
to produce the result. The values for ResultType
and ResultUri
come from intent.getType()
and intent.getType()
.
Example: Picking files from the SD Card
Here's an example that illustrates using a third-party application:
AndExplorer from Lysesoft is an application that lets you pick files for your SD card. You can call AndExplorer with an activity starter to add a file picking capability to your application. You'll need to have AndExplorer installed on your phone. You can get it from the Android Market.
To start AndExplorer to pick a file, use an ActivityStarter with:
Action: android.intent.action.PICK
dataType: vnd.android.cursor.dir/lysesoft.andexplorer.file
dataURI: file:///sdcard
When you start the activity and pick a file, the resulting file name will be available as ResultUri
. Also, ResultType
will give the type of the file, for example, image/jpeg or audio/mpeg. Using this, you can write an app that lets you pick a file from the SD card and either displays the image or plays the music track as appropriate.
Is the application available?
If your app calls other apps as activities, you'll want to check that those other apps are available on your user's phone before trying to start them. You can check this using the Activity Starter method ResolveActivity
, which returns the name of the Activity that would be started, given the package or intent information you've provided. If this name is blank, then the required application is not present, and you can warn your user.
Using the Activity Starter versus using multiple screens
The sections above explain how you can create an App Inventor app that calls another App Inventor app, perhaps with passing and returning text values. If you will be writing both apps, it's probably better to make a single multiscreen app rather than create two apps and use the Activity Starter. This will simplify things for your users, because they will need install only one app on their device. Also, with multiple screen apps, you can pass and return lists as values rather than just text, and you can share values between the screens with TinyDB. See the documentation on multiple screen apps for details.
Note on upgrading old apps:
The activity starter commands described here have changed from earlier releases, which used close screen with result
and get start text
, rather than the newer close screen with plain text
and get start plain text
. If you load the source for an app from before 2012 and release 66, App Inventor will flag the old blocks and require you to replace them with the new versions.