SettingInjectorServicepublic abstract class SettingInjectorService extends android.app.Service Dynamically specifies the enabled status of a preference injected into
the list of app settings displayed by the system settings app
For use only by apps that are included in the system image, for preferences that affect multiple
apps. Location settings that apply only to one app should be shown within that app,
rather than in the system settings.
To add a preference to the list, a subclass of {@link SettingInjectorService} must be declared in
the manifest as so:
<service android:name="com.example.android.injector.MyInjectorService" >
<intent-filter>
<action android:name="android.location.SettingInjectorService" />
</intent-filter>
<meta-data
android:name="android.location.SettingInjectorService"
android:resource="@xml/my_injected_location_setting" />
</service>
The resource file specifies the static data for the setting:
<injected-location-setting xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/injected_setting_title"
android:icon="@drawable/ic_acme_corp"
android:settingsActivity="com.example.android.injector.MySettingActivity"
/>
Here:
- title: The {@link android.preference.Preference#getTitle()} value. The title should make
it clear which apps are affected by the setting, typically by including the name of the
developer. For example, "Acme Corp. ads preferences."
- icon: The {@link android.preference.Preference#getIcon()} value. Typically this will be a
generic icon for the developer rather than the icon for an individual app.
- settingsActivity: the activity which is launched to allow the user to modify the setting
value. The activity must be in the same package as the subclass of
{@link SettingInjectorService}. The activity should use your own branding to help emphasize
to the user that it is not part of the system settings.
To ensure a good user experience, your {@link android.app.Application#onCreate()},
and {@link #onGetEnabled()} methods must all be fast. If either is slow,
it can delay the display of settings values for other apps as well. Note further that these
methods are called on your app's UI thread.
For compactness, only one copy of a given setting should be injected. If each account has a
distinct value for the setting, then only {@code settingsActivity} should display the value for
each account. |
Fields Summary |
---|
private static final String | TAG | public static final String | ACTION_SERVICE_INTENTIntent action that must be declared in the manifest for the subclass. Used to start the
service to read the dynamic status for the setting. | public static final String | META_DATA_NAMEName of the meta-data tag used to specify the resource file that includes the settings
attributes. | public static final String | ATTRIBUTES_NAMEName of the XML tag that includes the attributes for the setting. | public static final String | ACTION_INJECTED_SETTING_CHANGEDIntent action a client should broadcast when the value of one of its injected settings has
changed, so that the setting can be updated in the UI. | public static final String | ENABLED_KEYName of the bundle key for the string specifying whether the setting is currently enabled. | public static final String | MESSENGER_KEYName of the intent key used to specify the messenger | private final String | mName |
Constructors Summary |
---|
public SettingInjectorService(String name)Constructor.
mName = name;
|
Methods Summary |
---|
public final android.os.IBinder | onBind(android.content.Intent intent)
return null;
| protected abstract boolean | onGetEnabled()Returns the {@link android.preference.Preference#isEnabled()} value. Should not perform
unpredictably-long operations such as network access--see the running-time comments in the
class-level javadoc.
Note that to prevent churn in the settings list, there is no support for dynamically choosing
to hide a setting. Instead you should have this method return false, which will disable the
setting and its link to your setting activity. One reason why you might choose to do this is
if {@link android.provider.Settings.Secure#LOCATION_MODE} is {@link
android.provider.Settings.Secure#LOCATION_MODE_OFF}.
It is possible that the user may click on the setting before this method returns, so your
settings activity must handle the case where it is invoked even though the setting is
disabled. The simplest approach may be to simply call {@link android.app.Activity#finish()}
when disabled.
| protected abstract java.lang.String | onGetSummary()This method is no longer called, because status values are no longer shown for any injected
setting.
| private void | onHandleIntent(android.content.Intent intent)
boolean enabled;
try {
enabled = onGetEnabled();
} catch (RuntimeException e) {
// Exception. Send status anyway, so that settings injector can immediately start
// loading the status of the next setting.
sendStatus(intent, true);
throw e;
}
sendStatus(intent, enabled);
| public final void | onStart(android.content.Intent intent, int startId)
super.onStart(intent, startId);
| public final int | onStartCommand(android.content.Intent intent, int flags, int startId)
onHandleIntent(intent);
stopSelf(startId);
return START_NOT_STICKY;
| private void | sendStatus(android.content.Intent intent, boolean enabled)Send the enabled values back to the caller via the messenger encoded in the
intent.
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putBoolean(ENABLED_KEY, enabled);
message.setData(bundle);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, mName + ": received " + intent
+ ", enabled=" + enabled + ", sending message: " + message);
}
Messenger messenger = intent.getParcelableExtra(MESSENGER_KEY);
try {
messenger.send(message);
} catch (RemoteException e) {
Log.e(TAG, mName + ": sending dynamic status failed", e);
}
|
|