blob: 039e71efb4ce1f3caf512e4c516998acbd850ca5 [file] [log] [blame]
page.title=Android 4.2 APIs
sdk.platform.version=4.2
sdk.platform.apiLevel=17
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#Behaviors">Important Behavior Changes</a></li>
<li><a href="#Daydream">Daydream</a></li>
<li><a href="#SecondaryDisplays">Secondary Displays</a></li>
<li><a href="#Lockscreen">Lockscreen Widgets</a></li>
<li><a href="#MultipleUsers">Multiple Users</a></li>
<li><a href="#RTL">RTL Layout Support</a></li>
<li><a href="#NestedFragments">Nested Fragments</a></li>
<li><a href="#Renderscript">Renderscript</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a
href="{@docRoot}sdk/api_diff/17/changes.html">API
Differences Report &raquo;</a> </li>
</ol>
</div>
</div>
<p>API Level: 17</p>
<p>Android 4.2 ({@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1})
is an update to the Jelly Bean release that offers new features for users and app
developers. This document provides an introduction to the most notable and
useful new APIs for developers.</p>
<p>As an app developer, you should download the Android 4.2 system image and SDK platform from
the <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> as soon as possible. If you
don’t have a device running Android 4.2 on which to test your app, use the Android 4.2 system
image to test your app on the <a href="{@docRoot}tools/devices/emulator.html">Android emulator</a>.
Then build your apps against the Android 4.2 platform to begin using the latest APIs.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3 id="ApiLevel">Declare your app API Level</h3>
<p>To better optimize your app for devices running Android {@sdkPlatformVersion},
you should set your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
<code>"{@sdkPlatformApiLevel}"</code>, install it on an Android {@sdkPlatformVersion} system image,
test it, then publish an update with this change.</p>
<p>You
can use APIs in Android {@sdkPlatformVersion} while also supporting older versions by adding
conditions to your code that check for the system API level before executing
APIs not supported by your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a>.
To learn more about
maintaining backward-compatibility, read <a
href="{@docRoot}training/backward-compatible-ui/index.html">Creating Backward-Compatible
UIs</a>.</p>
<p>More information about how API levels work is available in <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">What is API
Level?</a></p>
</div>
</div>
<h2 id="Behaviors">Important Behavior Changes</h2>
<p>If you have previously published an app for Android, be aware of the following
changes that might affect your app’s behavior:</p>
<ul>
<li><b>Content providers</b> are no longer exported by default. That is, the default value
for the <a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">{@code
android:exported}</a> attribute is now {@code “false"}. If it’s important that other apps be
able to access your content provider, you must now explicitly set <a
href="{@docRoot}guide/topics/manifest/provider-element.html#exported">{@code
android:exported="true"}.</a>
<p>This change takes effect only if you set either <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
android:targetSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
android:minSdkVersion}</a> to 17 or higher. Otherwise, the default value is still {@code “true"}
even when running on Android 4.2 and higher.</p>
</li>
<li>Compared to previous versions of Android, <b>user location</b> results may be less accurate
if your app requests the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} permission but
does not request the {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
<p>To meet the privacy expectations of users when your app requests permission for
coarse location (and not fine location), the system will not provide a user location estimate
that’s more accurate than a city block.</p>
</li>
<li>Some <b>device settings</b> defined by {@link android.provider.Settings.System} are now
read-only. If your app attempts to write changes to settings defined in {@link
android.provider.Settings.System} that have moved to {@link android.provider.Settings.Global},
the write operation will silently fail when running on Android 4.2 and higher.
<p>Even if your value for <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
android:targetSdkVersion}</a> and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
android:minSdkVersion}</a> is lower than 17, your app is not able to modify the settings that have
moved to {@link android.provider.Settings.Global} when running on Android 4.2 and higher.</p>
</li>
</ul>
<h2 id="Daydream">Daydream</h2>
<p>Daydream is a new interactive screensaver mode for Android devices. It activates automatically
when the device is inserted into a dock or when the device is left idle while plugged in to a
charger (instead of turning the screen off). Daydream displays one dream at a time, which may
be a purely visual, passive display that dismisses upon touch, or may be interactive and responsive
to the full suite of input events. Your dreams run in your app’s process and have full access to
the Android UI toolkit, including views, layouts, and animations, so they are more flexible and
powerful than either live wallpapers or app widgets.</p>
<p>You can create a dream for Daydream by implementing a subclass of {@link
android.service.dreams.DreamService}. The {@link android.service.dreams.DreamService} APIs are
designed to be similar to those of {@link android.app.Activity}. To specify the UI for your
dream, pass a layout resource ID or {@link android.view.View} to {@link
android.service.dreams.DreamService#setContentView setContentView()} at any point after you have
a window, such as from the {@link android.service.dreams.DreamService#onAttachedToWindow()}
callback.</p>
<p>The {@link android.service.dreams.DreamService} class provides other important lifecycle callback
methods on top of the base {@link android.app.Service} APIs, such as {@link
android.service.dreams.DreamService#onDreamingStarted()}, {@link
android.service.dreams.DreamService#onDreamingStopped()}, and {@link
android.service.dreams.DreamService#onDetachedFromWindow()}.
You cannot initiate a {@link android.service.dreams.DreamService} from your
app&mdash;it is launched automatically by the system.</p>
<p>If your dream is interactive, you can start an activity from the dream to send the user into
your app’s full UI for more detail or control. You can use {@link
android.service.dreams.DreamService#finish()} to end the dream so the user can see the
new Activity.</p>
<p>To make your daydream available to the system, declare your {@link
android.service.dreams.DreamService} with a <a
href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service>}</a> element
in your manifest file. You must then include an intent filter with the action {@code
"android.service.dreams.DreamService"}. For example:</p>
<pre>
&lt;service android:name=".MyDream" android:exported="true"
android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
&lt;intent-filter>
&lt;action android:name="android.service.dreams.DreamService" />
&lt;category android:name="android.intent.category.DEFAULT" />
&lt;/intent-filter>
&lt;/service>
</pre>
<p>There are some other useful methods in {@link android.service.dreams.DreamService}
to be aware of:</p>
<ul>
<li>{@link android.service.dreams.DreamService#setInteractive(boolean)} controls whether
the dream receives input events or exits immediately upon user input. If the dream is
interactive, the user may use the <em>Back</em> or <em>Home</em> buttons to exit the dream or you can call
{@link android.service.dreams.DreamService#finish()} to stop the dream.</li>
<li>If you want a fully immersive display, you can call {@link
android.service.dreams.DreamService#setFullscreen
setFullscreen()} to hide the status bar.</li>
<li>Before Daydream starts, the display dims to signal to the user that the idle timeout
is approaching. Calling {@link android.service.dreams.DreamService#setScreenBright
setScreenBright(true)} allows you to instead set the display at its usual brightness.</li>
</ul>
<p>For more information, see the {@link android.service.dreams.DreamService} documentation.</p>
<h2 id="SecondaryDisplays">Secondary Displays</h2>
<p>Android now allows your app to display unique content on additional screens that are connected
to the user’s device over either a wired connection or Wi-Fi.
To create unique content for a secondary display, extend the {@link android.app.Presentation}
class and implement the {@link android.app.Presentation#onCreate onCreate()} callback. Within
{@link android.app.Presentation#onCreate onCreate()}, specify your UI for the secondary display
by calling {@link android.app.Presentation#setContentView setContentView()}.
As an extension of the {@link android.app.Dialog} class, the {@link
android.app.Presentation} class provides the region in which your app can display a unique UI on the
secondary display.</p>
<p>To detect secondary displays where you can display your {@link android.app.Presentation},
use either the {@link android.hardware.display.DisplayManager} or {@link android.media.MediaRouter}
APIs. While the {@link android.hardware.display.DisplayManager} APIs allow you to enumerate
multiple displays that may be connected at once, you should usually use {@link
android.media.MediaRouter} instead to quickly access the system’s default display for
presentations.</p>
<p>To get the default display for your presentation, call {@link
android.media.MediaRouter#getSelectedRoute MediaRouter.getSelectedRoute()} and pass it
{@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}. This returns a {@link
android.media.MediaRouter.RouteInfo} object that describes the system’s currently selected route
for video presentations. If the {@link android.media.MediaRouter.RouteInfo} is not null, call
{@link android.media.MediaRouter.RouteInfo#getPresentationDisplay()} to get the {@link
android.view.Display} representing the connected display.</p>
<p>You can then display your presentation by passing the {@link android.view.Display} object
to a constructor for your {@link android.app.Presentation} class. Your presentation will now
appear on the secondary display.</p>
<p>To detect at runtime when a new display has been connected, create an instance of {@link
android.media.MediaRouter.SimpleCallback} in which you implement the {@link
android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged
onRoutePresentationDisplayChanged()} callback method, which the system will call when a new
presentation display is connected. Then register the {@link
android.media.MediaRouter.SimpleCallback} by passing it to {@link
android.media.MediaRouter#addCallback MediaRouter.addCallback()} along with the {@link
android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO} route type. When you receive a call to
{@link android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged
onRoutePresentationDisplayChanged()}, simply call {@link
android.media.MediaRouter#getSelectedRoute MediaRouter.getSelectedRoute()} as mentioned above.</p>
<p>To further optimize the UI in your {@link android.app.Presentation} for
secondary screens, you can apply
a different theme by specifying the {@link
android.R.attr#presentationTheme android:presentationTheme} attribute in the <a
href=”{@docRoot}guide/topics/resources/style-resource.html”>{@code &lt;style>}</a> that you’ve
applied to your application or activity.</p>
<p>Keep in mind that screens connected to the user’s device often have a larger screen size and
likely a different screen density. Because the screen characteristics may different, you should
provide resources that are optimized specifically for such larger displays. If you need
to request additional resources from your {@link
android.app.Presentation}, call {@link android.app.Presentation#getContext()}{@link
android.content.Context#getResources .getResources()} to get the {@link
android.content.res.Resources} object corresponding to the display. This provides
the appropriate resources from your app that are best suited for the
secondary display's screen size and density.</p>
<p>For more information and some code samples, see the {@link android.app.Presentation}
class documentation.</p>
<h2 id="Lockscreen">Lockscreen Widgets</h2>
<p>Android now allows users to add app widgets to the lock screen. To make your <a
href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a> available for use on the
lock screen, add the {@link android.appwidget.AppWidgetProviderInfo#widgetCategory
android:widgetCategory} attribute to your XML file that specifies the {@link
android.appwidget.AppWidgetProviderInfo}. This attribute supports two values: {@code home_screen}
and {@code keyguard}. By default, the attribute is set to {@code home_screen} so users can add your
app widget to the Home screen. If you want your app widget to be also available on the lock
screen, add the {@code keyguard} value:</p>
<pre>
&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:widgetCategory="keyguard|home_screen">
&lt;/appwidget-provider>
</pre>
<p>You should also specify an initial layout for your app widget when on the lock screen with
the {@link android.appwidget.AppWidgetProviderInfo#initialKeyguardLayout
android:initialKeyguardLayout} attribute. This works the same way as the {@link
android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout}, in that it provides
a layout that can appear immediately until your app widget is initialized and able to update the
layout.</p>
<p>For more information about building app widgets for the lock screen, including to properly
size your app widget when on the lock screen, see the <a
href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">App Widgets</a> guide.</p>
<h2 id="MultipleUsers">Multiple Users</h2>
<p>Android now allows multiple user spaces on shareable devices such as tablets. Each user on a
device has his or her own set of accounts, apps, system settings, files, and any other
user-associated data.</p>
<p>As an app developer, there’s nothing different you need to do in order for your app to work
properly with multiple users on a single device. Regardless of how many users may exist on a
device, the data your app saves for a given user is kept separate from the data your app saves
for other users. The system keeps track of which user data belongs to the user process in which
your app is running and provides your app access to only that user’s data and does not allow
access to other users’ data.</p>
<h3>Saving data in a multi-user environment</h3>
<p>Whenever your app saves user preferences, creates a database, or writes a file to the user’s
internal or external storage space, that data is accessible only while running as that user.</p>
<p>To be certain that your app behaves properly in a multi-user environment, do not refer to your
internal app directory or external storage location using hard-coded paths and instead always use
the appropriate APIs:</p>
<ul>
<li>For access to internal storage, use {@link android.content.Context#getFilesDir()}, {@link
android.content.Context#getCacheDir()}, or {@link android.content.Context#openFileOutput
openFileOutput()}.</li>
<li>For access to external storage, use {@link android.content.Context#getExternalFilesDir
getExternalFilesDir()} or {@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()}.
</ul>
<p>No matter which of these APIs you use to save data for a given user, the data will not be
accessible while running as a different user. From your app’s point of view, each user is running
on a completely separate device.</p>
<h3>Identifying users in a multi-user environment</h3>
<p>If your app wants to identify unique users such as to gather analytics or create other account
associations, you should follow the recommended practices for <a
href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">identifying
unique installations</a>. By creating a new {@link java.util.UUID} when your app starts for the
first time, you’re certain to obtain a unique ID for tracking each user, regardless of how many
users install your app on a single device. Alternatively, you can save a local token fetched from
your server or use the registrations ID provided by <a
href="{@docRoot}guide/google/gcm/index.html">Google Cloud Messaging</a>.</p>
<p>Beware that if your app requests one of the hardware device identifiers (such as the WiFi MAC
address, the {@link android.os.Build#SERIAL} number, or the {@link
android.provider.Settings.Secure#ANDROID_ID} number), they will provide the same value for each
user because these identifiers are tied to the hardware and not the user. Not to mention the other
problems these identifiers introduce as discussed in the <a
href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">Identifying
App Installations</a> blog post.</p>
<h3>New Global Settings</h3>
<p>The system settings have been updated to support multiple users with the addition of {@link
android.provider.Settings.Global}. This collection of settings is similar to {@link
android.provider.Settings.Secure} settings because they are read-only, but applies globally across
all user spaces on the device.</p>
<p>Several existing settings were relocated here from either {@link
android.provider.Settings.System} or {@link android.provider.Settings.Secure}. If your app is
currently making changes to settings previously defined in {@link android.provider.Settings.System}
(such as {@link android.provider.Settings.System#AIRPLANE_MODE_ON}), then you should expect that
doing so will no longer work on a device running Android 4.2 or higher if those settings were
moved to {@link android.provider.Settings.Global}. You can continue to read settings that are in
{@link android.provider.Settings.Global}, but because the settings are no longer considered safe
for apps to change, attempting to do so will fail silently and the system will write a warning to
the system log when running your app on Android 4.2 or higher.</p>
<h2 id="RTL">RTL Layout Support</h2>
<p>Android now offers several APIs that allow you to build user interfaces that gracefully
transform layout orientation to support languages that use right-to-left (RTL) UIs and reading
direction, such as Arabic and Hebrew.</p>
<p>To begin supporting RTL layouts in your app, set the {@link android.R.attr#supportsRtl
android:supportsRtl} attribute to the {@code &lt;application>} element in your manifest file
and set it {@code “true"}. Once you enable this, the system will enable various RTL APIs to
display your app with RTL layouts. For instance, the action bar will show the icon and title
on the right side and action buttons on the left, and any layouts you’ve created with the
framework-provided {@link android.view.View} classes will also be reversed.</p>
<p>If you need to further optimize the appearance of your app when displayed with an RTL layout,
there are two basic levels of optimization:</p>
<ol>
<li>Convert left- and right-oriented layout properties to start- and end-oriented layout
properties.
<p>For example, use {@link android.R.attr#layout_marginStart android:layout_marginStart}
in place of {@code android:layout_marginLeft} and {@link android.R.attr#layout_marginEnd
android:layout_marginEnd} in place of {@code android:layout_marginRight}.
<p>The {@link android.widget.RelativeLayout} class also provides the corresponding layout
attributes to replace left/right positions, such as {@code android:layout_alignParentStart} to
replace {@code android:layout_alignParentLeft} and {@code android:layout_toStartOf} instead of
{@code android:layout_toLeftOf}.
</li>
<li>Or to provide complete optimization for RTL layouts, you can provide entirely separate
layout files using the {@code ldrtl} resource qualifier ({@code ldrtl} stands for
layout-direction-right-to-left}). For example, you can save your default layout files in
{@code res/layout/} and your RTL optimized layouts in {@code res/layout-ldrtl/}.
<p>The {@code ldrtl} qualifier is great for drawable resources, so that you can provide
graphics that are oriented in the direction corresponding to the reading direction.</p>
</li>
</ol>
<p>Various other APIs are available across the framework to support RTL layouts, such as in
the {@link android.view.View} class so that you can implement the proper behaviors for custom
views and in {@link android.content.res.Configuration} to query the current layout direction.</p>
<p><strong>Note:</strong> If you are using SQlite and have tables or column names that are
“number only," be
careful: using <a href="{@docRoot}reference/java/lang/String.html#format(String, Object...)">{@code
String.format(String, Object...)}</a> can lead to errors where the numbers
have been converted to their Arabic equivalents if your device has been set to the Arabic locale.
You must use <a href="{@docRoot}reference/java/lang/String.html#format(Locale,String,Object...)">{@code
String.format(Locale,String,Object...)}</a> to ensure numbers are
preserved as ASCII. Also use <a href="{@docRoot}reference/java/lang/String.html#format(String,int)">{@code
String.format("%d", int)}</a> instead of using
<a href="{@docRoot}reference/java/lang/String.html#valueOf(int)">{@code String.valueOf(int)}</a> for
formatting numbers.</p>
<h2 id="NestedFragments">Nested Fragments</h2>
<p>You can now embed fragments inside fragments. This is useful for a variety of situations in
which you want to place dynamic and re-usable UI components into a UI component that is itself
dynamic and re-usable. For example, if you use {@link android.support.v4.view.ViewPager} to
create fragments that swipe left and right and consume a majority of the screen space, you can
now insert fragments into each fragment page.</p>
<p>To nest a fragment, simply call {@link android.app.Fragment#getChildFragmentManager()} on
the {@link android.app.Fragment} in which you want to add a fragment. This returns a {@link
android.app.FragmentManager} that you can use like you normally do from the top-level activity
to create fragment transactions. For example, here’s some code that adds a fragment from within
an existing {@link android.app.Fragment} class:</p>
<pre>
Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();
</pre>
<p>From within a nested fragment, you can get a reference to the parent fragment by calling
{@link android.app.Fragment#getParentFragment()}.</p>
<p>The Android Support Library also now supports nested fragments, so you can implement nested
fragment designs on Android 1.6 and higher.</p>
<p><strong>Note:</strong> You cannot inflate a layout into a fragment when that layout
includes a {@code &lt;fragment>}. Nested fragments are only supported when added to a
fragment dynamically.</p>
<h2 id="Renderscript">Renderscript</h2>
<p>Renderscript computation functionality has been enhanced with the following features:</p>
<dl>
<dt><b>Script intrinsics</b></dt>
<dd><p>You can use Renderscript's built-in script intrinsics that implement
common operations for you such as:</p>
<ul>
<li>{@link android.renderscript.ScriptIntrinsicBlend Blends}</li>
<li>{@link android.renderscript.ScriptIntrinsicBlur Blur}</li>
<li>{@link android.renderscript.ScriptIntrinsicColorMatrix Color matrix}</li>
<li>{@link android.renderscript.ScriptIntrinsicConvolve3x3 3x3 convolve}</li>
<li>{@link android.renderscript.ScriptIntrinsicConvolve5x5 5x5 convolve}</li>
<li>{@link android.renderscript.ScriptIntrinsicLUT Per-channel lookup table}</li>
<li>{@link android.renderscript.ScriptIntrinsicYuvToRGB Converting an Android YUV buffer to RGB}</li>
</ul>
<p>To use a script intrinsic, call the static <code>create()</code> method of each instrinsic
to create an instance of the script. You then call the available <code>set()</code>
methods of each script intrinsic to set any necessary inputs and options.
Finally, call the {@link android.renderscript.ScriptC#forEach forEach()}</code>
method to execute the script.</p>
</dd>
<dt><b>Script Groups</b></dt>
<dd>
<p>{@link android.renderscript.ScriptGroup}s allow you to chain together related Renderscript
scripts and execute them with one call.</p>
<p>Use a {@link android.renderscript.ScriptGroup.Builder} to add all of the scripts to the group
by calling {@link android.renderscript.ScriptGroup.Builder#addKernel addKernel()}. Once you
add all the scripts, create the connections between the
scripts by calling {@link android.renderscript.ScriptGroup.Builder#addConnection addConnection()}.
When you are done adding the connections, call {@link android.renderscript.ScriptGroup.Builder#create create()}
to create the script group. Before executing the script group, specify the input
{@link android.renderscript.Allocation} and initial script to run with the
{@link android.renderscript.ScriptGroup#setInput} method and provide the output
{@link android.renderscript.Allocation} where the result will be written to and final script to
run with {@link android.renderscript.ScriptGroup#setOutput setOutput()}. Finally, call
{@link android.renderscript.ScriptGroup#execute execute()} to run the script group.
</p>
</dd>
<dt><b>Filterscript</b></dt>
<dd>
<p>Filterscript defines constraints on the existing Renderscript APIs that allow the resulting code to run
on a wider variety of processors (CPUs, GPUs, and DSPs). To create Filterscript files, create <code>.fs</code>
files instead of <code>.rs</code> files, and specify <code>#pragma rs_fp_relaxed</code> to
tell the Renderscript runtime your scripts do not require strict IEEE 754-2008 floating point precision.
This precision allows flush-to-zero for denorms and round-towards-zero. In addition, your Filterscript
scripts must not use 32-bit built-in types and must specify a custom root function by using the
<code>__attribute__((kernel))</code> attribute because Filterscript does not support pointers, which
the default signature of the <code>root()</code> function defines.</p>
</dd>
</dl>
<p class="note"><strong>Note:</strong> Although Filterscript support is in the platform, developer
support will be available in ADT and SDK Tools Release 21.0.1. </p>
<p>For a detailed view of all API changes in Android 4.2, see the
<a href="{@docRoot}sdk/api_diff/17/changes.html">API Differences Report</a>.</p>