com.twofortyfouram
Class Intent

java.lang.Object
  extended by com.twofortyfouram.Intent

public final class Intent
extends java.lang.Object

Contains Intent constants for use with the Locale Developer Platform. This class cannot be instantiated.

Plug-in

Overview

Locale offers plug-in interfaces for both conditions and settings. Plug-ins must do the following to integrate with Locale:

  1. Participate in Registration
  2. Provide UI Activity for editing
  3. Provide BroacastReceiver for querying conditions or firing settings

Registration

Locale's registration process uses the Android PackageManager, so plug-ins must implement several things in their AndroidManifest:

  1. "Edit" Activity exporting:
  2. BroadcastReceiver receiver for ACTION_QUERY_CONDITION or ACTION_FIRE_SETTING Intent action.
  3. Stable Package and Class: The package and class names for the edit Activity are very important and MUST remain consistent across different versions of the plug-in. If they do not remain consistent, then saved instances of the plug-ins created previously will be orphaned.

A plug-in condition's AndroidManifest may look something like this:

 <?xml version="1.0" encoding="utf-8"?>
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yourcompany.yourcondition" >
     <application
         android:label="@string/app_name" >
         <!-- Listen for the "edit" action -->
         <activity
               android:name=".EditActivity"
               android:label="@string/setting_name"
               android:icon="@drawable/icon_plugin"
               android:exported="true" >
               <intent-filter>
                   <action android:name="com.twofortyfouram.locale.intent.action.EDIT_CONDITION" />
               </intent-filter>
         </activity>
         <!-- Listen for the "query" action-->
         <receiver android:name=".QueryReceiver" >
             <intent-filter>
                 <action android:name="com.twofortyfouram.locale.intent.action.QUERY_CONDITION" />
             </intent-filter>
         </receiver>
     </application>
 </manifest>
 

A plug-in setting's AndroidManifest may look something like this:

 <?xml version="1.0" encoding="utf-8"?>
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yourcompany.yoursetting" >
     <application
         android:label="@string/app_name" >
         <!-- Listen for the "edit" action -->
         <activity
               android:name=".EditActivity"
               android:label="@string/setting_name"
               android:icon="@drawable/icon_plugin"
               android:exported="true" >
               <intent-filter>
                   <action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
               </intent-filter>
         </activity>
         <!-- Listen for the "fire" action-->
         <receiver android:name=".FireReceiver" >
             <intent-filter>
                 <action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
             </intent-filter>
         </receiver>
     </application>
 </manifest>
 

Note: multiple plug-ins within a single APK are not supported.

UI Activity for Editing

Once registration is complete, the plug-in will be listed in the Locale UI. When the user taps on the plug-in in Locale, the "edit" action (either ACTION_EDIT_CONDITION or ACTION_EDIT_SETTING) is broadcast to launch the Activity exported by the plug-in's AndroidManifest.

Once the user has completed configuring the plug-in, the Activity result Intent back to Locale must contain the following:

  1. Result Code: Tells Locale whether the plug-in should be saved or not.
  2. Blurb Extra: Constant key value EXTRA_STRING_BLURB maps to a String extra that represents a concise, human-readable status of the plug-in instance. For example, Locale's Volume setting might have a blurb that says "50%."
  3. Bundle Extra: Constant key value EXTRA_BUNDLE maps to a Bundle that represents the entire state of the plug-in. This Bundle is stored and forwarded back to the plug-in whenever the plug-in is edited again or eventually queried/fired. Think of this Bundle as sending a message to yourself, with Locale as an intermediary. Locale guarantees that the Bundle extras will not be modified in any way. Because this Bundle will be stored long-term, do not place short-term data (e.g. Parcelable) into the Bundle. Parcelables should be represented as Serializable instead. In addition, only objects that are part of the standard Android platform may be stored because Locale's class loader will need to serialize and deserialize these objects.

Note: Although Locale keeps store-and-forward Bundles secure, there are ways to isolate a plug-in's extras from Locale. Remember that each app on Android with a unique digital signature will run in its own process and will have its own secure data storage space. To improve security of private data, such as usernames and passwords, only minimal information needs to be passed to Locale via EXTRA_BUNDLE. Consider the Twitter plug-in, for example. It could store the username and password in a private SharedPreference file, and only include the Tweet message in the store-and-forward Bundle.

UI Guidelines

In order for plug-ins to consistently match the Locale UI, there are a few UI guidelines. The Screen condition and Toast setting provide examples on how to implement these guidelines.

Breadcrumbs

The title bar of every Activity in Locale contains a series of breadcrumbs, so that the user knows where he came from. These breadcrumbs are represented by a " > " separated listed of Activity names. For example, "Main Activity > Sub Activity > Sub Activity 2." When your Activity is started, the edit Intent will contain an extra with the key EXTRA_STRING_BREADCRUMB that maps to a String representing the stack of previous Activity names with the oldest first.

Look and Feel

Locale consistently uses a frame with a white background to hold UI elements. To fit in with the Locale UI, implementing this frame is recommended. This frame can be loaded dynamically at runtime.

Menu

Every setting and condition Activity in Locale has at least three menu items:

  1. Help: Open a context-sensitive help screen by launching the Help Activity. For more information, see the Help section.
  2. Don't Save: Closes the Activity without saving by returning the Activity.RESULT_CANCELED result code.
  3. Save: closes the Activity and saves by returning the Activity.RESULT_OK result code.

During usability testing, we discovered that users would look in the menu whenever they were stuck. When asked why, one user said, "Because that's where you find commands." Most often, they'd be looking for a way to go back or to save their work, which is why the Don't Save and Save items are in the menu. The Help menu item also makes sense, since the user opens the menu when he isn't sure what to do next.

In a 3-item menu, all the icons will appear in a single row. From left to right, the order is Help, Don't Save, and Save.

In a 4-item menu, the Help item may shift to the upper row but it should still be placed as the leftmost item of that row. Don't Save and Save should still be at the bottom of the menu, with Don't Save to the left of Save.

For menus with 5 or more items, the Help, Don't Save, and Save menu items should always appear in the bottom row of the menu.

Android UI guidelines call for grayscale menu icons, which forces users to rely on shape alone to distinguish menu items. In our own usability testing, we've found that color speeds up the user's ability to search for familiar items in the menu. The icons for Locale's standard menu can be loaded dynamically.

Help

Locale provides a Help Activity based on a WebView to assist with this. To launch the Help Activity, simply fire an Intent with the action ACTION_HELP. This Intent must also contain two extras:

  1. Help URL: EXTRA_STRING_HELP_URL maps to a String extra that represents a URL to your help HTML file. For example, this could point to www.yourcompany.com/yoursetting/help.html
  2. Breadcrumb: EXTRA_STRING_BREADCRUMB maps to an String of previous Activity names (please see the Breadcrumbs section). Simply append your Activity name to the String and add the extra to the Intent.

Android Market

If your plug-in is not a standalone application and does not provide a launcher screen Activity--such as the Twitter and SMS settings--you should also implement an Activity that gives users an entrypoint to your setting from the Android Market. Without such an entrypoint, the Android Market will give a "launch error" when users try to open the plug-in and you'll receive hundreds--no thousands--of annoying emails.

The entrypoint activity might look like this in your Android Manifest:

         <activity
             android:name="com.twofortyfouram.MarketActivity"
             android:label="@string/plugin_name"
             android:icon="@drawable/icon_plugin"
             android:theme="@android:style/Theme.Translucent.NoTitleBar"
         >
             <intent-filter>
                 <action
                     android:name="android.intent.action.MAIN" />
                 <category
                     android:name="android.intent.category.INFO" />
             </intent-filter>
         </activity>
 

Querying the Condition

When it comes time to for Locale to query your condition, Locale will send an ordered broadcast with the Intent action ACTION_QUERY_CONDITION directly to the BroadcastReceiver exported by the plug-in's AndroidManifest. This ordered Intent will contain the EXTRA_BUNDLE extra that was previously saved by the "edit" Activity. There will be one broadcast for each plug-in instance. Using the Display Condition example, let's say the user has created two situations in Locale, each with a single Display condition. Locale will broadcast two ACTION_QUERY_CONDITION Intents, each with a different EXTRA_BUNDLE. Plug-ins should not keep any state about what sort of instances have been created, as the user could delete these from within Locale at any time. A plug-in should simply process each ordered broadcast as it comes.

Locale makes no guarantees as to how often or if your plug-in will be queried. Typically, a plug-in will be queried once when Locale first starts up, and additional queries may happen somewhere on the order of every 10 minutes. If a situation in Locale contains multiple conditions, the order in which conditions are queried is unspecified. Locale may choose to stop evaluating conditions in a situation if one condition is not satisfied, at which point a plug-in may never be queried.

In addition to waiting for Locale to query the plug-in, a plug-in can signal to Locale that it is ready to be queried via the ACTION_REQUEST_QUERY Intent. Again, there is no guarantee that the plug-in will be queried.

It may not be possible to implement all conceivable plug-in conditions with this interface. Plug-ins that operate asynchronously (e.g. they receive actions like Intent.ACTION_POWER_CONNECTED and then broadcast ACTION_REQUEST_QUERY to Locale) or plug-ins that can respond to a query Intent immediately such as a Calendar, will work best. Plug-ins that require a background service to operate are not recommended, as a mobile phone is limited in how many services can be run simultaneously.

Below is a code sample showing how that BroadcastReceiver might try to handle the "query" Intent.

 public final class QueryReceiver extends BroadcastReceiver
 {
        @Override
     public void onReceive(final Context context, final Intent intent)
     {
         if (com.twofortyfouram.Intent.ACTION_QUERY_CONDITION.equals(intent.getAction()))
         {
            [your implementation here...]
         }
     }
 }
 

Applying the Setting

When it comes time to apply your setting to the phone, Locale will broadcast the Intent action ACTION_FIRE_SETTING directly to the BroadcastReceiver exported by the plug-in's AndroidManifest.

Below is a code sample showing how that BroadcastReceiver might try to handle the "fire" Intent and apply the setting.

 public final class FireReceiver extends BroadcastReceiver
 {
        @Override
     public void onReceive(final Context context, final Intent intent)
     {
         if (com.twofortyfouram.Intent.ACTION_FIRE_SETTING.equals(intent.getAction()))
         {
            [your implementation here...]
         }
     }
 }
 

Android development guidelines for BroadcastReceivers apply here. Your BroadcastReceiver has 10 seconds to complete before an "Androd Not Responding" dialog will appear. Any longer tasks, such as making a request to an Internet server, will require a Service. In addition, Locale may send broadcasts to your receiver when the phone is asleep. If you have a long-running task that launches a service, you'll also need to acquire a WakeLock in your BroadcastReceiver to ensure that your task completes.


Field Summary
static java.lang.String ACTION_EDIT_CONDITION
          Intent action String broadcast by Locale to create or edit a plug-in condition.
static java.lang.String ACTION_EDIT_SETTING
          Intent action String broadcast by Locale to create or edit a plug-in setting.
static java.lang.String ACTION_FIRE_SETTING
          Intent action String broadcast by Locale to fire a plug-in setting.
static java.lang.String ACTION_HELP
          Intent action String to launch the Locale help viewer Activity.
static java.lang.String ACTION_QUERY_CONDITION
          Ordered Intent action String broadcast by Locale to query a plug-in condition.
static java.lang.String ACTION_REQUEST_QUERY
          Intent action String to notify Locale that a plug-in condition is requesting that Locale query it via ACTION_QUERY_CONDITION.
static java.lang.String ACTION_START_LOCALE
          Intent action String to start the Locale UI.
static java.lang.String BREADCRUMB_SEPARATOR
          The separator in-between breadcrumbs in the Locale UI.
static java.lang.String EXTRA_ACTIVITY
          Type: String
static java.lang.String EXTRA_BUNDLE
          Type: Bundle
static java.lang.String EXTRA_STRING_ACTION_FIRE
          Deprecated. 
static java.lang.String EXTRA_STRING_BLURB
          Type: String
static java.lang.String EXTRA_STRING_BREADCRUMB
          Type: String
static java.lang.String EXTRA_STRING_HELP_URL
          Type: String
static int MAXIMUM_BLURB_LENGTH
          The maximum length of the blurb returned from the edit Activity.
static int RESULT_CONDITION_SATISFIED
          Ordered broadcast result code indicating that a plug-in condition is satisfied (true).
static int RESULT_CONDITION_UNKNOWN
          Ordered broadcast result code indicating that a plug-in condition's state is unknown (neither true nor false).
static int RESULT_CONDITION_UNSATISFIED
          Ordered broadcast result code indicating that a plug-in condition is not satisfied (false).
static int RESULT_REMOVE
          Activity result code indicating that a setting or condition should be deleted when the Locale situation editor resumes.
 
Method Summary
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

RESULT_REMOVE

public static final int RESULT_REMOVE
Activity result code indicating that a setting or condition should be deleted when the Locale situation editor resumes. If this return code is set, then the setting or condition does not need to provide any of the other required Intent extras.

See Also:
Activity.setResult(int), Constant Field Values

RESULT_CONDITION_SATISFIED

public static final int RESULT_CONDITION_SATISFIED
Ordered broadcast result code indicating that a plug-in condition is satisfied (true).

See Also:
ACTION_QUERY_CONDITION, Constant Field Values

RESULT_CONDITION_UNSATISFIED

public static final int RESULT_CONDITION_UNSATISFIED
Ordered broadcast result code indicating that a plug-in condition is not satisfied (false).

See Also:
ACTION_QUERY_CONDITION, Constant Field Values

RESULT_CONDITION_UNKNOWN

public static final int RESULT_CONDITION_UNKNOWN
Ordered broadcast result code indicating that a plug-in condition's state is unknown (neither true nor false).

See Also:
ACTION_QUERY_CONDITION, Constant Field Values

ACTION_EDIT_SETTING

public static final java.lang.String ACTION_EDIT_SETTING
Intent action String broadcast by Locale to create or edit a plug-in setting. When Locale broadcasts this Intent, it will be sent directly to the package and class of the plug-in's Activity. The Intent may contain a store-and-forward EXTRA_BUNDLE that was previously set by the Activity result of ACTION_EDIT_SETTING.

There can only be one Activity per APK that implements this Intent.

See Also:
EXTRA_BUNDLE, EXTRA_STRING_BREADCRUMB, Constant Field Values

ACTION_FIRE_SETTING

public static final java.lang.String ACTION_FIRE_SETTING
Intent action String broadcast by Locale to fire a plug-in setting. When Locale broadcasts this Intent, it will be sent directly to the package and class of the plug-in's BroadcastReceiver. The Intent will contain store-and-forward extras that were previously set by the Activity result of ACTION_EDIT_SETTING.

There can only be one BroadcastReceiver per APK that implements this Intent.

Since:
Locale 0.63 beta
See Also:
Constant Field Values

ACTION_EDIT_CONDITION

public static final java.lang.String ACTION_EDIT_CONDITION
Intent action String broadcast by Locale to create or edit a plug-in condition. When Locale broadcasts this Intent, it will be sent directly to the package and class of the plug-in's Activity. The Intent may contain a store-and-forward EXTRA_BUNDLE that was previously set by the Activity result of ACTION_EDIT_CONDITION.

There can only be one Activity per APK that implements this Intent.

See Also:
EXTRA_BUNDLE, EXTRA_STRING_BREADCRUMB, Constant Field Values

ACTION_QUERY_CONDITION

public static final java.lang.String ACTION_QUERY_CONDITION
Ordered Intent action String broadcast by Locale to query a plug-in condition. When Locale broadcasts this Intent, it will be sent directly to the package and class of the plug-in's BroadcastReceiver. The Intent will contain store-and-forward extras that were previously set by the Activity result of ACTION_EDIT_CONDITION.

Since this is an ordered broadcast, the receiver is expected to set an appropriate result code from RESULT_CONDITION_SATISFIED, RESULT_CONDITION_UNSATISFIED, and RESULT_CONDITION_UNKNOWN.

There can only be one BroadcastReceiver per APK that implements this Intent.

Since:
Locale 1.0
See Also:
EXTRA_BUNDLE, RESULT_CONDITION_SATISFIED, RESULT_CONDITION_UNSATISFIED, RESULT_CONDITION_UNKNOWN, Constant Field Values

ACTION_START_LOCALE

public static final java.lang.String ACTION_START_LOCALE
Intent action String to start the Locale UI.

This is useful for providing an entry point to Locale for plug-ins downloaded from the Android Market.

See Also:
Constant Field Values

ACTION_HELP

public static final java.lang.String ACTION_HELP
Intent action String to launch the Locale help viewer Activity.

The Intent should contain both EXTRA_STRING_BREADCRUMB and EXTRA_STRING_HELP_URL.

See Also:
EXTRA_STRING_BREADCRUMB, EXTRA_STRING_HELP_URL, Constant Field Values

ACTION_REQUEST_QUERY

public static final java.lang.String ACTION_REQUEST_QUERY
Intent action String to notify Locale that a plug-in condition is requesting that Locale query it via ACTION_QUERY_CONDITION. This action merely serves as a hint to Locale that a condition wants to be updated. There is no guarantee as to when or if the plug-in will be queried after this Intent is broadcast.

The extra EXTRA_ACTIVITY is required.

Plug-ins conditions should NOT use this unless there is some sort of asynchronous event that has occurred, such as a broadcast Intent being received by the plug-in. (See the Display condition example for when using this would be appropriate).

Since:
Locale 1.0
See Also:
EXTRA_ACTIVITY, Constant Field Values

EXTRA_STRING_HELP_URL

public static final java.lang.String EXTRA_STRING_HELP_URL
Type: String

Maps to a String that represents the URL where the Locale help viewer can load an HTML page from.

See Also:
ACTION_HELP, Constant Field Values

EXTRA_STRING_BREADCRUMB

public static final java.lang.String EXTRA_STRING_BREADCRUMB
Type: String

Maps to a String that represents the Activity breadcrumb path.

See Also:
Constant Field Values

EXTRA_STRING_BLURB

public static final java.lang.String EXTRA_STRING_BLURB
Type: String

Maps to a String that represents a blurb. This is returned as an Activity result extra.

See Also:
MAXIMUM_BLURB_LENGTH, Constant Field Values

EXTRA_BUNDLE

public static final java.lang.String EXTRA_BUNDLE
Type: Bundle

Maps to a Bundle that contains all of a plug-ins store-and-forward extras.

Note: Do NOT store Parcelable objects in this Bundle, because Parcelable is not a long-term storage format. Also, be sure that the class of any object serialized in this Bundle are accessible by the public Android class loader.

See Also:
Constant Field Values

EXTRA_ACTIVITY

public static final java.lang.String EXTRA_ACTIVITY
Type: String

Maps to a String that represents the name of your plug-in's Activity.

Since:
Locale 1.0
See Also:
ACTION_EDIT_CONDITION, ACTION_REQUEST_QUERY, Constant Field Values

EXTRA_STRING_ACTION_FIRE

@Deprecated
public static final java.lang.String EXTRA_STRING_ACTION_FIRE
Deprecated. 
Type: String

Maps to a String that represents the action String when a setting is applied.

See Also:
Constant Field Values

BREADCRUMB_SEPARATOR

public static final java.lang.String BREADCRUMB_SEPARATOR
The separator in-between breadcrumbs in the Locale UI.

See Also:
EXTRA_STRING_BREADCRUMB, Constant Field Values

MAXIMUM_BLURB_LENGTH

public static final int MAXIMUM_BLURB_LENGTH
The maximum length of the blurb returned from the edit Activity.

See Also:
EXTRA_STRING_BLURB, Constant Field Values