Copyright © 2012CommonsWare, LLC
App Integration: Strategies and
Tactics
Copyright © 2012CommonsWare, LLC
Objective: Add Value
● Add Value for Users– More functionality without as much
development effort● Add Value for Third Parties
– Their apps are more valuable when you help drive their adoption
● Add Value for You– Reciprocity from third parties
Copyright © 2012CommonsWare, LLC
Integration Models
● Peers– Apps with value independent of yours– Hard or soft dependencies
● Plugins– Apps with no value independent of yours
Copyright © 2012CommonsWare, LLC
Difficulty Level: One Red Bull
Copyright © 2012CommonsWare, LLC
Activities, Implicit Intents
● Make a Generic Request– ACTION_VIEW, ACTION_SEND, etc.
● User Dictates Terms– What applications are installed that could handle
it– What application to use for this particular
request– What to do with that application
Copyright © 2012CommonsWare, LLC
Activities, Implicit Intents
● Making the Selection– No options? Crash!– One option? Automatic start, no intervention– Multiple options?
● Default chooser● Override chooser (Intent.createChooser())● ShareActionProvider● Apple patent workarounds● DIY
Copyright © 2012CommonsWare, LLC
Activities, Implicit Intents
● DIY– PackageManager queryIntentActivities() returns list of possibilities, given an Intent
– You render resulting List somehow● Avoiding the No-Options Crash
– Same technique: if list empty, startActivity() would fail
Copyright © 2012CommonsWare, LLC
Activities, Explicit Intents
● Hard Dependency, Declared in Code– Craft Intent that will only be handled by peer
application– Use PackageManager queryIntentActivities() to confirm it exists (or handle the exception)
– Use with startActivity() / startActivityForResult()
Copyright © 2012CommonsWare, LLC
UI Integration via Web
● No Activity? How About a Web Site?– Easy: launch browser on URL with ACTION_VIEW– More Interesting: Host a WebView
● Pre-fill in forms using loadUrl(“javascript:...”)
● Warning #1: May be tough to control● Warning #2: Dependencies on non-public “APIs”
Copyright © 2012CommonsWare, LLC
Difficulty Level: Two Red Bulls
Copyright © 2012CommonsWare, LLC
UI Integration via Web
● Reverse Integration: Web to App– Key: BROWSABLE category– Option #1: <data> For Your URL
● Option to launch app if app installed, else URL directs to Web page to go download the app
– Option #2: Something Specific● Intent.toUri() to generate a URL● Custom scheme
Copyright © 2012CommonsWare, LLC
Integrating Resources
● createPackageContext()– Returns a Context that will resolve resources
from some other package– Example Use: theme packs
● APK (possibly paid app) with res0urces representing theme
● Detect existence using PackageManager● Use createPackageContext() to retrieve
resources and apply to your UI
Copyright © 2012CommonsWare, LLC
Integration by ContentProvider
● All You Need is a Uri– And some idea of what the schema is, so you
know what to do with it● Example: plugins implementing a standard schema
that you require
– Getting the Uri● Well-known resource name● Bootstrap API (e.g., broadcast, remote service)
Copyright © 2012CommonsWare, LLC
Integration by ContentProvider
● The Permission Proxy– Problem: Your app needs too many permissions
● Example: Calendar integration
– Solution● Wrap OS/third-party ContentProvider in one of
yours, with same schema● Put that ContentProvider in plugin, to isolate
permission● Check signature to ensure only used by you
Copyright © 2012CommonsWare, LLC
Integration by Service
● Command Pattern– Third Party Supplies Intent Structure
● Action string● Available extras
– Call startService() as Needed● Directly● Via PendingIntent (e.g., AlarmManager)
Copyright © 2012CommonsWare, LLC
Integration by Service
● Binding Pattern– Agreed-Upon AIDL
● Peer: first mover● Plugin: host defines
– Third Party Implements AIDL Binder– You Bind and Use
Copyright © 2012CommonsWare, LLC
Integration by Broadcast
● Agreed-Upon Action, Ordered vs. Regular– Peer: first mover– Plugin: host defines
● One Side Broadcast, Other Side Receives– Manifest-registered receiver– registerReceiver()
Copyright © 2012CommonsWare, LLC
Difficulty Level: Case of Red Bulls
Copyright © 2012CommonsWare, LLC
UI Integration via RemoteViews
● Two Apps' UIs Simultaneously● RemoteViews Host
– Get RemoteViews from third-party● Broadcast? Remote service?● Initially, plus changes over time
– apply() RemoteViews into your desired container
Copyright © 2012CommonsWare, LLC
UI Integration via RemoteViews
● Limitations– Widgets, methods available in RemoteViews– No direct interaction between apps
● Solution: API accessed via PendingIntents
Copyright © 2012CommonsWare, LLC
Difficulty Level: Red Bull Bottling
Plant
Copyright © 2012CommonsWare, LLC
UI Integration via Parcelable
● RemoteViews Got You Down? Roll Your Own!– RemoteViews is a data structure representing
commands to build a UI– Alternative: DIY RemoteViewsEx– Limitations
● Still loosely coupled for events (PendingIntent, Messenger, etc.)
● Effort proportional to the complexity of the UIyou wish to share
Copyright © 2012CommonsWare, LLC
Integrating Code
● Option #1: createPackageContext()– getClassLoader() will return ClassLoader
for accessing classes in other APK● Use CONTEXT_INCLUDE_CODE in createPackageContext() call
– Use reflection from there (e.g., loadClass()) to access foreign code
Copyright © 2012CommonsWare, LLC
Integrating Code
● Option #2: DexClassLoader– Given JAR/APK containing dex'd bytecode,
allows you to load classes just like a regular ClassLoader
● Up to you to get the JAR or APK file
Copyright © 2012CommonsWare, LLC
Integrating Code
● WARNING– You might not know where that code came from
● Code injection attacks
– Executed code runs with your permissions● May do things you rather wish they would not
– Net: very risky technique
Copyright © 2012CommonsWare, LLC
And Now, The Rest of the Story
Copyright © 2012CommonsWare, LLC
Discovery Mechanisms
● Hard-Coded● Discovery via Broadcast
– Host sends a broadcast periodically (first run, package installed, package removed)
– Peers/plugins reply with broadcast about capabilities
– Related: ACTION_PACKAGE_ADDED
Copyright © 2012CommonsWare, LLC
Discovery Mechanisms
● Discovery via Naming Convention– Plugins go in com.myfirm.myapp.plugin.*– Host uses PackageManager to identify– Further Handshaking
● Well-known resource● Well-known “narrowcast” via setPackage()
Copyright © 2012CommonsWare, LLC
More Stuff to Consider
● Custom Permissions– Users should get a vote on data sharing
● Integration Library– JAR to ease third-parties working with your host
● Documentation– Only way anyone will know what to do
● ...and what you would rather they not do
Copyright © 2012CommonsWare, LLC
What the Ecosystem Needs
● Standards– Community-driven implicit Intent actions
● Scaffolding– Library projects, templates for creating these
structures● End-User Discovery
– How do they know what can integrate?