Intents
Proposed "Lune OS Intents"
Rationale
There are a number of common actions that apps should delegate to other apps: sending an email, selecting a picture to insert, sharing a link, picking a contact, etc. webOS provided a few custom mechanisms for critical actions, a general mechanism for an app to call another, known app and a general mechanism to "open" a resource. URL schemes can be used for one-way interations. These don't generalize to request-response scenarios well. Custom mechanisms depend on OS updates. To share a link, an app had to know the correct launchParam for every app for every service. "Opening" a resource does not allow the user to select the handling app.
Overview
The proposal is provide an extensible mechanism similar to Android Intents/Web Intents/Web Activities.
There is a short list of well-known "verbs", such as "share", "edit", "open", "pick", "save", "dial". New verbs should be developed by consensus. Verbs should harmonize with Just Type so far as reasonable. Apps may freely experiment with namespaced verbs, for example "NinjaGroup:slice".
Any app may register to handle any verb, and usually a list of MIME types of data it handles. Some verbs also allow registration by URI scheme. (We do not expect the same app to "edit" "text/plain" and "image/jpeg".) Mime types may be generic, such as text/*, image/* or */*.
Each verb defines a "data" object to be passed, with required and optional properties, with required semantics. Optional means the *client* need not specify the property, but handlers MUST implement it. (For example, if the verb "share" defines an optional "attachment" property, a handler MUST support attachments.) Apps MAY pass additional data properties, but SHOULD first seek consensus, as nonstandard properties are only hints, at best.
Each verb defines the parameters it returns.
Any app may request any Intent. As *any* Intent may require user input to complete, the client app SHOULD NOT block on the request. Intents always return at least success or failure. The simplest failure is that there was no registered handler.
When a client app requests a new Intent, the system
- searches its database to find handlers matching the verb and MIME type (or scheme)
- if there is no match, immediately returns failure to the client and displays system UI to the user, informing her that she must install a handler app, and offering to launch Preware.
- if there is only one match, passes the request to the handler without presenting system UI.
- if the user has previously designated a preferred handler for that verb and MIME type (or scheme), passes the request to the handler without presenting system UI.
- otherwise, the system presents a list of handler apps to the user, plus the option Cancel.
- if the user cancels, the system returns failure to the client
- if the user selects an app, the system closes its UI, requests the handler app to do its thing, and waits for a response
- when the handler responds to the request (which might be hours later), passes the response to the client (without further system UI).
There is no time limit on Intents. They typically involve user action before they can be resolved.
User Experience
The weak point of Intents is that handler apps must be installed before client apps, and the user does not, in general, know she might need a handler app before using a client app. In general, a verb SHOULD NOT be on the "well-known" list until there is a system default handler, such as a generic file picker that can fulfill a "pick" request of any MIME type. System default handlers SHOULD handle common MIME types, but needn't handle every MIME type in existence.
So, handler apps provide either new implementations of actions (for example, an image editor with new features beyond cropping), handle new MIME types, or add new destinations (sharing to Twitter, rather than just via email or messaging). As Handlers extend the OS, we probably need humans to validate that they fully implement the contract of each verb. (We need to keep this from being a time sink.) Users should be warned when installing unvalidated handlers.
A possible future extension would, when there is no registered handler, for the system to search Preware feeds. That would require extending Preware to search for app by handled Intents.
System UI (the list of handlers) should be displayed "over" the client card (perhaps in a popup window, like the USB dialog). In general, Handler UI should be displayed in a separate card. For some verbs such a "pick", it may make sense to display over the client card.
Registering Handlers
An app registers in its appinfo.json.
Sample Schema
{
...
"intents": [
{"name": "edit", "types": ["image/jpeg", "image/png"], "href": "index.html"},
{"name": "open", "types": ["image/*"], "href": "view.html"}
]
...
}
The data object is defined by the verb, not by the app, so it is not documented in appinfo.json.
When the system calls a handler, it passes name, type and data in an intent appParam:
"intent": {
"name": "edit",
"type": "image/jpeg",
"data": {
"original": "/media/internal/DCIM/100PALM/CIMG0711.jpg",
"target": "/media/internal/myArt/autmun.jpg"
}
}
Client Requests
Requests are made on the PalmBus, to org.webosports.intents
with the method new
, with the parameters
name
, type
(optional) and data
(optional).
(or maybe palm://com.palm.applicationManager
and method newIntent
.)
Sample:
luna-send -n 1 luna://org.webosports.intents/new '{"name": "edit", "type": "image/jpeg", "data": {"original": "/media/internal/DCIM/100PALM/CIMG0711.jpg", "target": "/media/internal/myArt/autmun.jpg"} }'
returning
{ "returnValue": true, "modified": "/media/internal/myArt/autmun.jpg" }
Development Phases
Track I
1) basic functionality of service (independent of verbs) 2) implement preferred handlers 3) modify Preware to search by verb and MIME type (or scheme)
Track II (may proceed in parallel to Track I)
Work on one verb (or a group of closely-related verbs) at a time and get it right, before moving to the next. For each verb standardize verb and its data, and write one or more system handlers.
Proposed Initial Verbs, Data & Return Values
Long term, we'd like to supersede everything listed at https://developer.palm.com/content/api/reference/application-apis.html and https://developer.palm.com/content/content/api/reference/services/application-manager.html#command-and-resource-types , but we must get data for each verb right, or we'll regret it forever. Every handler for a verb must be able to meaningfully deal with *all* the verb's standard data parameters.
Standard errorCode values include:
- "NO_HANDLER"
- "USER_CANCEL" (the user cancelled, either in system UI, or handler UI)
- "INVALID_DATA" (the passed data is not valid for its verb, or its type)
Nominally, errorCode is an integer, but some system services pass strings. I don't see why we can't.
Open (View)
Similar to luna://com.palm.applicationManager/open, but allows the user to select a handler. One data parameter: "target", a URI, which may be a file: URI. (See below for possible other parameters.)
This verb is handled specially: first, it tries to find a Handler by URI scheme. (These schemes are relevant: mailto:, sms:, im:, tel:, rtsp:) If there's a match, the system uses that Handler. If the scheme is http: or https: the system makes an HTTP HEAD request to get the MIME type from the Content-Type header. (If the HEAD request is not supported by the server, the system might make an HTTP GET request and close the connection after the header is received.) If the scheme is data:, the MIME type is extracted from the mediatype. (The default is text/plain;charset=US-ASCII.) If the scheme is file: or ftp: the system attempt to extract the MIME type from the file extension. If the scheme is none of the above, the system returns failure. Then then system attempts to find a handler by MIME type. It passes the deduced MIME type to the Handler, along with the target URI.
[We should probably rework applicationManager/open to use this Intent. We may or may not be able to use the data structures for "Default Applications" in the Device Info app. The browser should use this Intent rather than defining its own "helper apps".]
Returns only success / failure. Additional errorCode values: none.
(We might want a typeHint parameter, as a fallback in case the system cannot determine the type. It might or might not be useful to allow a "forceType" parameter, to force the URI to be handled as a particular type, and skip the HTTP HEAD request.)
We should probably disallow 3rd party handlers for the schemes file:, data:, ftp:, http: and https:, or at least strongly warn the user before installation.
Example: a video player might register to handle both scheme "rtsp" and MIME type "video/*". It could handle URIs of scheme rtsp:, http and https URIs with a Content-Type header of video/mp4, video/quicktime, etc., and file URIs with extension .mp4, .mov, .flv, etc.
Pick
Request the user to select a one or more chunks of data, with an optional type. One required boolean data parameter: "multiple". If "multiple" is false, the handler MUST return one chunk of data (or fail). If "multiple" is true, the handler MAY return one or multiple chunks of data (or fail). (A handler doesn't have to support returning multiple chunks of data.)
Returns an array of record objects. Each record MUST contain a "uri", which may be of any scheme. A record MAY contain a "type" (if the Handler can reliably determine it). A record MAY contain a "cachePath", which is the local file path of a cached copy of the chunk (which canonically resides on a remote server). A record MAY contain a preview or thumbnail (TBD), along the lines of Media Indexer.
Clients MUST be prepared to deal with URIs of unknown type (for example, from the file picker). Clients SHOULD understand at least the URI schemes of http:, https:, ftp:, file:, and data:.
Handlers for remote data MUST cache metadata locally, and SHOULD use a Javascript Service to update their cache periodically. When this Intent is requested, a handler MUST immediately display cached info, and allow the user to select. A handler MAY update when this Intent is requested, and append or update its display. Best practice is for a handler to inform the user whether the metadata is fresh.
For example, "pick" with type "image/*" should have at least three system handlers: a thumbnail selector that uses the Media Indexer, the standard Camera app and the standard file dialog.
Presumably, the Memos app will implement a handler for type "text/plain" and/or "text/*"
The standard file dialog should register for type "*/*". A Dropbox app would presumably also contain a handler for type "*/*".
"pick" with some weird type will always match (at least) the standard file dialog.
Handlers SHOULD allow the user to cancel without selection.
Example use case: an email client app has an "attachment" button. When the user clicks it, the email client creates a new "pick" request. When the pick returns, the email client iterates through the results: For data: and file: URIs, it transforms them into email attachments. For http: and https: URIs, it inserts a link into the email (without downloading the chunks).
Save (Copy)
One required parameter: "uri", the source of data. Typically, this will use the file: or data: scheme, but it could be http:, https: or ftp: if the data resides on a remote server.
Return parameters are "newUri", the new location of the saved data. Clients should understand at least the file:, http:, https: and ftp: schemes.
The system will provide a handler (the standard file dialog) for type "*/*".
A Dropbox, Box, etc. app should have a handler for type "*/*".
A photo site should provide a handler for type "image/*" or maybe just "image/jpeg".
There are several paradigms for using pick and save:
A general text editor on a mobile device should probably use pick to select a file to operate on, then autosave periodically and when it quits. (It should also implement Undo.) Thus, it would not need a "Save" command. However, it should probably have a "Save As" command, which would request a "Save" intent. Creating a new document should probably initially cache the data locally, and after an appropriate interval, non-blocking notify the user that she should "Save As".
We might want to implement a "Copy" command in the Launcher, which calls pick and then save.
[Is there common data that IM, SMS, Twitter, Bluetooth sharing, etc. would accept? Do we pass a single chunk of info (for example, text or the path of an image file) and let the user add additional chunks in the handler? Do they all accept text and an image attachment? Do we need one verb ("share"?) for sharing short text, and another ("shareWithAttachment"?) for short text plus attachment? Are there MIME types relevant to this?] ShareUri is probably a different verb. A typical handler would be a QR code displayer or NFC.
(This should be harmonized with opening a URI with scheme sms: or im: )
[It may or may not make sense to allow recipients here - those should probably be filled in by the handler. Typically, client apps won't know anything about recipients. One exception is 3rd-party apps providing a support address.]
(In addition to standard "messaging" apps, presumably email would also register as a handler.)
Handlers SHOULD allow the user to cancel without sending.
Very similar to Share, but data include subject, body and attachments.
Calling OPEN with the mailto scheme will do essentially the same thing. [So is this just syntactical sugar?]
Mapping
[Mapping a location, and mapping a route are probably separate verbs. It's not clear what role MIME types will play here.]
Additional error codes: "NO_RESULTS" (for example, the passed data is a plausible address, but doesn't exist in the map database.)
Verbs Believed To Be Unnecessary
- take a picture (handled by "Pick" "image/*")
- Messaging (handled by "share" verb/verbs)
Further Reading
Some pitfalls to avoid are chronicled here: What Happened to Web Intents?