Wednesday, April 10, 2013

Launching an Android App from an Adobe AIR App

A while back I figured out how to setup an Adobe AIR app as an Android Device's launcher. Surprisingly, the tricky part of that project was figuring out how I can allow my customer to remove the app as launcher when they are done testing. I'm able to use adb to install and uninstall the app at will, but as tools go, that is way too complicated for my client to figure out.

While rocking out last night it hit me: if I could convince my AIR app to launch the Android Package Manager app, then my client could trivially uninstall our launcher app. After all, installing a new launcher doesn't take away any functionality, it just removes access to it. One hitch: to my knowledge the AIR SDK doesn't offer an API call I could invoke to kick off the package manager. But, as the music was blaring, I had my second epiphany: I bet I could use some magic URL convention to kick off the specific app I had in mind.

I spent the morning Googling around looking for Android specific URI prefixes. After all, if tel: would kick off the dialer, maybe there's some similar convention for apps themselves?

My first clue came with this comment:

Alternatively, there is the "intent:" scheme. This allows you to describe nearly any Intent as a URI, which the browser will try to launch when clicked. To build such a scheme, the best way is to just write the code to construct the Intent you want launched, and then print the result of intent.toUri(Intent.URI_INTENT_SCHEME).

Aha! There is a magic URI structure, it seems, and it starts with intent:. As I continued to Google around, I had no luck finding the syntax for this seemingly useful URI structure.

And then I found my second clue. Buried in this answer was the following snippet:

 <a href="intent:#Intent;action=android.intent.action.VIEW;category=android.intent.c‌​ategory.DEFAULT;category=android.intent.category.BROWSABLE;package=com.test.proje‌​ct;end">Click link to launch</a>

It wasn't much to go on, but at least gave me hope and clue what a intent: URI looked like.

After much experimentation I finally arrived at:

var url:String = ("intent:#Intent;" +
                  "action=android.intent.action.MAIN;" +
                  "category=android.intent.category.LAUNCHER;" +
                  "component=com.android.settings/.Settings;" +
                  "end");
navigateToURL(new URLRequest(url));

To my shock, it worked flawlessly!

I found the values to set for action, category and component by watching the log output of adb.exe logcat while pressing the "Settings" icon on my tablet.

The above syntax should be extensible to invoke pretty much any intent you want. I'm really surprised I wasn't able to find any documentation on this, as it seems hugely powerful.

By the way, Plan B was to examine this native extension, and expand on it to add in invocation or uninstall capabilities. Though, it looks like that won't be necessary.

15 comments:

  1. Anonymous1:33 PM

    thanks for the info. I took your info to
    use in Adobe Flash CC punblishing Air3.6
    for a tablet running android OS 4.1.2.

    my as3 code:
    var htm:String ='intent:#Intent;component=com.android.settings/.Settings;end'
    navigateToURL(new URLRequest(htm));

    this works! it launches the settings panel.
    with or with out intent filers in my app.

    i have searched online and tried to modify
    the string to launch [camera,play music, contacts etc] with no success. Do you have
    any suggestions to to do this?

    ReplyDelete
  2. This was really handy, thanks Ben! Worked a treat on the Samsung Tab 2 7".

    ReplyDelete
  3. Thanks so much, was debating the ANE route, but this is so much easier.

    FYI. modified to launch the default Android Launcher instead:

    var url:String = ("intent:#Intent;" +
    "action=android.intent.action.MAIN;" +
    "category=android.intent.category.LAUNCHER;" +
    "component=com.android.launcher/com.android.launcher2.Launcher;" +
    "end");

    ReplyDelete
    Replies
    1. Hi Kirby.
      Your solution don't work to me. Anything new to launch the chooser?

      Delete
  4. YOU ROCK MAN!

    This is how I launched another AIR app using your method:

    var url:String = ("intent:#Intent;" + "action=android.intent.action.MAIN;" + "category=android.intent.category.LAUNCHER;" + "component=air.com.AIRLaunchTest/.AppEntry;" + "end");

    ReplyDelete
  5. Does anybody know how to pass extra parameters to the launched app?

    ReplyDelete
  6. Any way to retrieve a list of installed apps? Then combined with this you could make a launcher in AIR

    ReplyDelete
  7. Its working fine with AIR apps but I cant open other apps (Like unity3d or facebook)
    How to solve this problem?

    var url:String = ("intent:#Intent;" +
    "action=android.intent.action.MAIN;" +
    "category=android.intent.category.LAUNCHER;" +
    "component=air.TestApp/.AppEntry;" + "end");

    ReplyDelete
    Replies
    1. Hi! did you managed to launch unity3d app from air? thx

      Delete
  8. intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;component=com.android.settings/;end



    .AccessibilitySettings
    .ActivityPicker
    .AirplaneModeEnabler
    .ApnEditor
    .ApnPreference
    .ApnSettings
    .AppWidgetPickActivity
    .ApplicationSettings
    .BandMode
    .BatteryInfo
    .BrightnessPreference
    .ChooseLockPattern
    .ChooseLockPatternExample
    .ChooseLockPatternTutorial
    .ConfirmLockPattern
    .CreateShortcut
    .CredentialInstaller
    .DateTimeSettings
    .DateTimeSettingsSetupWizard
    .DebugIntentSender
    .DefaultRingtonePreference
    .DevelopmentSettings
    .DeviceInfoSettings
    .Display
    .DockSettings
    .EditPinPreference
    .IccLockSettings
    .IconPreferenceScreen
    .InstalledAppDetails
    .LanguageSettings
    .LauncherAppWidgetBinder
    .LocalePicker
    .LocalePickerInSetupWizard
    .ManageApplications
    .MasterClear
    .MediaFormat
    .PhysicalKeyboardSettings
    .PrivacySettings
    .ProgressCategory
    .ProxySelector
    .RadioInfo
    .RingerVolumePreference
    .RunningServices
    .SdCardIntentReceiver
    .SdCardSettings
    .SecuritySettings
    .Settings
    .SettingsLicenseActivity
    .SettingsSafetyLegalActivity
    .SoundAndDisplaySettings
    .TestingSettings
    .TestingSettingsBroadcastReceiver
    .TextToSpeechSettings
    .UsageStats
    .UserDictionarySettings
    .Utils
    .WirelessSettings
    .ZoneList
    .ZonePicker
    .bluetooth.BluetoothDevicePreference
    .bluetooth.BluetoothDiscoverableEnabler
    .bluetooth.BluetoothEnabler
    .bluetooth.BluetoothEventRedirector
    .bluetooth.BluetoothNamePreference
    .bluetooth.BluetoothPairingDialog
    .bluetooth.BluetoothPairingRequest
    .bluetooth.BluetoothSettings
    .bluetooth.CachedBluetoothDevice
    .bluetooth.CachedBluetoothDeviceManager
    .bluetooth.ConnectSpecificProfilesActivity
    .bluetooth.DockEventReceiver
    .bluetooth.DockService
    .bluetooth.LocalBluetoothManager
    .bluetooth.LocalBluetoothProfileManager
    .bluetooth.RequestPermissionActivity
    .bluetooth.RequestPermissionHelperActivity
    .bluetooth.SettingsBtStatus
    .vpn.AuthenticationActor
    .vpn.L2tpEditor
    .vpn.L2tpIpsecEditor
    .vpn.L2tpIpsecPskEditor
    .vpn.PptpEditor
    .vpn.Util
    .vpn.VpnEditor
    .vpn.VpnProfileActor
    .vpn.VpnProfileEditor
    .vpn.VpnSettings
    .vpn.VpnTypeSelection
    .wifi.AccessPointDialog
    .wifi.AccessPointPreference
    .wifi.AccessPointState
    .wifi.AdvancedSettings
    .wifi.WifiEnabler
    .wifi.WifiLayer
    .wifi.WifiSettings
    .wifi.WifiStatus

    ReplyDelete
  9. I managed to launch an air app from air but I could not launch non air apps like Unity3d. Anyone know to solve this problem? And I have another question, If somebody knows how can I find if an air app is installed on mobile only by knowing its package id (to be done trought air application) ?

    ReplyDelete
    Replies
    1. Hello Tziuka - were you ever able to find a solution to this problem?

      Delete
  10. Shameless plug for an opensource solution:
    https://github.com/jakehilton/PackageManagerANE

    I think this is a great alternative if an ANE is overboard. If you know the app is installed and you need to launch it then this is great!

    ReplyDelete
    Replies
    1. Hey Jake! Would this work within Adobe Flash Professional CC 2015?

      Delete
  11. How to send some string value also along with this instance of Intent (intent.putExtra("keyname","keyvalue")) ?

    ReplyDelete