Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 1 | page.title=Android 4.2 APIs |
Scott Main | 6afeb0e | 2013-04-16 21:05:51 -0700 | [diff] [blame] | 2 | excludeFromSuggestions=true |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 3 | sdk.platform.version=4.2 |
| 4 | sdk.platform.apiLevel=17 |
| 5 | @jd:body |
| 6 | |
| 7 | <div id="qv-wrapper"> |
| 8 | <div id="qv"> |
| 9 | |
| 10 | <h2>In this document</h2> |
| 11 | <ol> |
| 12 | <li><a href="#Behaviors">Important Behavior Changes</a></li> |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 13 | <li><a href="#Daydream">Daydream</a></li> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 14 | <li><a href="#SecondaryDisplays">Secondary Displays</a></li> |
| 15 | <li><a href="#Lockscreen">Lockscreen Widgets</a></li> |
| 16 | <li><a href="#MultipleUsers">Multiple Users</a></li> |
| 17 | <li><a href="#RTL">RTL Layout Support</a></li> |
| 18 | <li><a href="#NestedFragments">Nested Fragments</a></li> |
| 19 | <li><a href="#Renderscript">Renderscript</a></li> |
| 20 | </ol> |
| 21 | |
| 22 | <h2>See also</h2> |
| 23 | <ol> |
| 24 | <li><a |
| 25 | href="{@docRoot}sdk/api_diff/17/changes.html">API |
| 26 | Differences Report »</a> </li> |
| 27 | </ol> |
| 28 | |
| 29 | </div> |
| 30 | </div> |
| 31 | |
| 32 | |
| 33 | <p>API Level: 17</p> |
| 34 | |
| 35 | <p>Android 4.2 ({@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}) |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 36 | is an update to the Jelly Bean release that offers new features for users and app |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 37 | developers. This document provides an introduction to the most notable and |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 38 | useful new APIs for developers.</p> |
| 39 | |
| 40 | <p>As an app developer, you should download the Android 4.2 system image and SDK platform from |
| 41 | the <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> as soon as possible. If you |
| 42 | don’t have a device running Android 4.2 on which to test your app, use the Android 4.2 system |
| 43 | image to test your app on the <a href="{@docRoot}tools/devices/emulator.html">Android emulator</a>. |
| 44 | Then build your apps against the Android 4.2 platform to begin using the latest APIs.</p> |
| 45 | |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 46 | |
| 47 | |
| 48 | <div class="sidebox-wrapper"> |
| 49 | <div class="sidebox"> |
| 50 | |
| 51 | <h3 id="ApiLevel">Declare your app API Level</h3> |
| 52 | |
| 53 | <p>To better optimize your app for devices running Android {@sdkPlatformVersion}, |
| 54 | you should set your <a |
| 55 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to |
| 56 | <code>"{@sdkPlatformApiLevel}"</code>, install it on an Android {@sdkPlatformVersion} system image, |
| 57 | test it, then publish an update with this change.</p> |
| 58 | |
| 59 | <p>You |
| 60 | can use APIs in Android {@sdkPlatformVersion} while also supporting older versions by adding |
| 61 | conditions to your code that check for the system API level before executing |
| 62 | APIs not supported by your <a |
| 63 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a>. |
| 64 | To learn more about |
| 65 | maintaining backward-compatibility, read <a |
| 66 | href="{@docRoot}training/backward-compatible-ui/index.html">Creating Backward-Compatible |
| 67 | UIs</a>.</p> |
| 68 | |
| 69 | <p>More information about how API levels work is available in <a |
| 70 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">What is API |
| 71 | Level?</a></p> |
| 72 | |
| 73 | </div> |
| 74 | </div> |
| 75 | |
| 76 | |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 77 | |
| 78 | |
| 79 | <h2 id="Behaviors">Important Behavior Changes</h2> |
| 80 | |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 81 | <p>If you have previously published an app for Android, be aware of the following |
| 82 | changes that might affect your app’s behavior:</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 83 | |
| 84 | <ul> |
| 85 | <li><b>Content providers</b> are no longer exported by default. That is, the default value |
| 86 | for the <a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">{@code |
| 87 | android:exported}</a> attribute is now {@code “false"}. If it’s important that other apps be |
| 88 | able to access your content provider, you must now explicitly set <a |
| 89 | href="{@docRoot}guide/topics/manifest/provider-element.html#exported">{@code |
| 90 | android:exported="true"}.</a> |
| 91 | <p>This change takes effect only if you set either <a |
| 92 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code |
| 93 | android:targetSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code |
| 94 | android:minSdkVersion}</a> to 17 or higher. Otherwise, the default value is still {@code “true"} |
| 95 | even when running on Android 4.2 and higher.</p> |
| 96 | </li> |
| 97 | |
| 98 | <li>Compared to previous versions of Android, <b>user location</b> results may be less accurate |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 99 | if your app requests the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} permission but |
| 100 | does not request the {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. |
| 101 | <p>To meet the privacy expectations of users when your app requests permission for |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 102 | coarse location (and not fine location), the system will not provide a user location estimate |
| 103 | that’s more accurate than a city block.</p> |
| 104 | </li> |
| 105 | |
| 106 | <li>Some <b>device settings</b> defined by {@link android.provider.Settings.System} are now |
| 107 | read-only. If your app attempts to write changes to settings defined in {@link |
| 108 | android.provider.Settings.System} that have moved to {@link android.provider.Settings.Global}, |
| 109 | the write operation will silently fail when running on Android 4.2 and higher. |
| 110 | <p>Even if your value for <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code |
| 111 | android:targetSdkVersion}</a> and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code |
| 112 | android:minSdkVersion}</a> is lower than 17, your app is not able to modify the settings that have |
| 113 | moved to {@link android.provider.Settings.Global} when running on Android 4.2 and higher.</p> |
| 114 | </li> |
Scott Main | 488c81a | 2013-02-20 15:32:30 -0800 | [diff] [blame] | 115 | |
| 116 | <li>If your app uses {@link android.webkit.WebView}, Android 4.2 adds an additional layer of |
| 117 | security so you can more safely <b>bind JavaScript to your |
| 118 | Android code</b>. If you set your |
| 119 | <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> |
| 120 | to 17 or higher, you must now add the {@code @JavascriptInterface} annotation to any method that you |
| 121 | want available to your JavaScript (the method must also be public). If you do not provide the |
| 122 | annotation, the method is not accessible by a web page in your {@link android.webkit.WebView} |
| 123 | when running on Android 4.2 or higher. If you set the |
| 124 | <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> |
| 125 | to 16 or lower, the annotation is not required, but we recommend that you update your target version |
| 126 | and add the annotation for additional security. |
| 127 | <p>Read more about <a href="{@docRoot}guide/webapps/webview.html#BindingJavaScript">binding |
| 128 | JavaScript code to Android code</a>.</p></li> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 129 | </ul> |
| 130 | |
| 131 | |
| 132 | |
| 133 | |
| 134 | |
| 135 | |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 136 | <h2 id="Daydream">Daydream</h2> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 137 | |
| 138 | <p>Daydream is a new interactive screensaver mode for Android devices. It activates automatically |
| 139 | when the device is inserted into a dock or when the device is left idle while plugged in to a |
| 140 | charger (instead of turning the screen off). Daydream displays one dream at a time, which may |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 141 | be a purely visual, passive display that dismisses upon touch, or may be interactive and responsive |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 142 | to the full suite of input events. Your dreams run in your app’s process and have full access to |
| 143 | the Android UI toolkit, including views, layouts, and animations, so they are more flexible and |
| 144 | powerful than either live wallpapers or app widgets.</p> |
| 145 | |
| 146 | <p>You can create a dream for Daydream by implementing a subclass of {@link |
| 147 | android.service.dreams.DreamService}. The {@link android.service.dreams.DreamService} APIs are |
| 148 | designed to be similar to those of {@link android.app.Activity}. To specify the UI for your |
| 149 | dream, pass a layout resource ID or {@link android.view.View} to {@link |
| 150 | android.service.dreams.DreamService#setContentView setContentView()} at any point after you have |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 151 | a window, such as from the {@link android.service.dreams.DreamService#onAttachedToWindow()} |
| 152 | callback.</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 153 | |
| 154 | <p>The {@link android.service.dreams.DreamService} class provides other important lifecycle callback |
| 155 | methods on top of the base {@link android.app.Service} APIs, such as {@link |
| 156 | android.service.dreams.DreamService#onDreamingStarted()}, {@link |
| 157 | android.service.dreams.DreamService#onDreamingStopped()}, and {@link |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 158 | android.service.dreams.DreamService#onDetachedFromWindow()}. |
| 159 | You cannot initiate a {@link android.service.dreams.DreamService} from your |
| 160 | app—it is launched automatically by the system.</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 161 | |
| 162 | <p>If your dream is interactive, you can start an activity from the dream to send the user into |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 163 | your app’s full UI for more detail or control. You can use {@link |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 164 | android.service.dreams.DreamService#finish()} to end the dream so the user can see the |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 165 | new Activity.</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 166 | |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 167 | <p>To make your daydream available to the system, declare your {@link |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 168 | android.service.dreams.DreamService} with a <a |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 169 | href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element |
| 170 | in your manifest file. You must then include an intent filter with the action {@code |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 171 | "android.service.dreams.DreamService"}. For example:</p> |
| 172 | |
| 173 | <pre> |
| 174 | <service android:name=".MyDream" android:exported="true" |
| 175 | android:icon="@drawable/dream_icon" android:label="@string/dream_label" > |
| 176 | <intent-filter> |
| 177 | <action android:name="android.service.dreams.DreamService" /> |
| 178 | <category android:name="android.intent.category.DEFAULT" /> |
| 179 | </intent-filter> |
| 180 | </service> |
| 181 | </pre> |
| 182 | |
| 183 | <p>There are some other useful methods in {@link android.service.dreams.DreamService} |
| 184 | to be aware of:</p> |
| 185 | |
| 186 | <ul> |
| 187 | <li>{@link android.service.dreams.DreamService#setInteractive(boolean)} controls whether |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 188 | the dream receives input events or exits immediately upon user input. If the dream is |
| 189 | interactive, the user may use the <em>Back</em> or <em>Home</em> buttons to exit the dream or you can call |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 190 | {@link android.service.dreams.DreamService#finish()} to stop the dream.</li> |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 191 | <li>If you want a fully immersive display, you can call {@link |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 192 | android.service.dreams.DreamService#setFullscreen |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 193 | setFullscreen()} to hide the status bar.</li> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 194 | <li>Before Daydream starts, the display dims to signal to the user that the idle timeout |
| 195 | is approaching. Calling {@link android.service.dreams.DreamService#setScreenBright |
| 196 | setScreenBright(true)} allows you to instead set the display at its usual brightness.</li> |
| 197 | </ul> |
| 198 | |
| 199 | <p>For more information, see the {@link android.service.dreams.DreamService} documentation.</p> |
| 200 | |
| 201 | |
| 202 | |
| 203 | |
| 204 | |
| 205 | |
| 206 | |
| 207 | |
| 208 | |
| 209 | |
| 210 | |
| 211 | <h2 id="SecondaryDisplays">Secondary Displays</h2> |
| 212 | |
| 213 | <p>Android now allows your app to display unique content on additional screens that are connected |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 214 | to the user’s device over either a wired connection or Wi-Fi. |
| 215 | To create unique content for a secondary display, extend the {@link android.app.Presentation} |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 216 | class and implement the {@link android.app.Presentation#onCreate onCreate()} callback. Within |
| 217 | {@link android.app.Presentation#onCreate onCreate()}, specify your UI for the secondary display |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 218 | by calling {@link android.app.Presentation#setContentView setContentView()}. |
| 219 | As an extension of the {@link android.app.Dialog} class, the {@link |
| 220 | android.app.Presentation} class provides the region in which your app can display a unique UI on the |
| 221 | secondary display.</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 222 | |
| 223 | <p>To detect secondary displays where you can display your {@link android.app.Presentation}, |
| 224 | use either the {@link android.hardware.display.DisplayManager} or {@link android.media.MediaRouter} |
| 225 | APIs. While the {@link android.hardware.display.DisplayManager} APIs allow you to enumerate |
| 226 | multiple displays that may be connected at once, you should usually use {@link |
| 227 | android.media.MediaRouter} instead to quickly access the system’s default display for |
| 228 | presentations.</p> |
| 229 | |
Scott Main | 66e642b | 2012-11-13 11:24:35 -0800 | [diff] [blame] | 230 | <p>To get the default display for your presentation, call {@link |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 231 | android.media.MediaRouter#getSelectedRoute MediaRouter.getSelectedRoute()} and pass it |
| 232 | {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}. This returns a {@link |
| 233 | android.media.MediaRouter.RouteInfo} object that describes the system’s currently selected route |
| 234 | for video presentations. If the {@link android.media.MediaRouter.RouteInfo} is not null, call |
| 235 | {@link android.media.MediaRouter.RouteInfo#getPresentationDisplay()} to get the {@link |
| 236 | android.view.Display} representing the connected display.</p> |
| 237 | |
| 238 | <p>You can then display your presentation by passing the {@link android.view.Display} object |
| 239 | to a constructor for your {@link android.app.Presentation} class. Your presentation will now |
| 240 | appear on the secondary display.</p> |
| 241 | |
| 242 | <p>To detect at runtime when a new display has been connected, create an instance of {@link |
| 243 | android.media.MediaRouter.SimpleCallback} in which you implement the {@link |
| 244 | android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged |
| 245 | onRoutePresentationDisplayChanged()} callback method, which the system will call when a new |
| 246 | presentation display is connected. Then register the {@link |
| 247 | android.media.MediaRouter.SimpleCallback} by passing it to {@link |
| 248 | android.media.MediaRouter#addCallback MediaRouter.addCallback()} along with the {@link |
| 249 | android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO} route type. When you receive a call to |
| 250 | {@link android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged |
| 251 | onRoutePresentationDisplayChanged()}, simply call {@link |
| 252 | android.media.MediaRouter#getSelectedRoute MediaRouter.getSelectedRoute()} as mentioned above.</p> |
| 253 | |
| 254 | <p>To further optimize the UI in your {@link android.app.Presentation} for |
| 255 | secondary screens, you can apply |
| 256 | a different theme by specifying the {@link |
| 257 | android.R.attr#presentationTheme android:presentationTheme} attribute in the <a |
Scott Main | 188315c | 2013-01-03 18:02:21 -0800 | [diff] [blame] | 258 | href="{@docRoot}guide/topics/resources/style-resource.html">{@code <style>}</a> that you’ve |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 259 | applied to your application or activity.</p> |
| 260 | |
| 261 | <p>Keep in mind that screens connected to the user’s device often have a larger screen size and |
| 262 | likely a different screen density. Because the screen characteristics may different, you should |
| 263 | provide resources that are optimized specifically for such larger displays. If you need |
| 264 | to request additional resources from your {@link |
| 265 | android.app.Presentation}, call {@link android.app.Presentation#getContext()}{@link |
| 266 | android.content.Context#getResources .getResources()} to get the {@link |
| 267 | android.content.res.Resources} object corresponding to the display. This provides |
| 268 | the appropriate resources from your app that are best suited for the |
| 269 | secondary display's screen size and density.</p> |
| 270 | |
| 271 | <p>For more information and some code samples, see the {@link android.app.Presentation} |
| 272 | class documentation.</p> |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | <h2 id="Lockscreen">Lockscreen Widgets</h2> |
| 284 | |
| 285 | <p>Android now allows users to add app widgets to the lock screen. To make your <a |
| 286 | href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a> available for use on the |
| 287 | lock screen, add the {@link android.appwidget.AppWidgetProviderInfo#widgetCategory |
| 288 | android:widgetCategory} attribute to your XML file that specifies the {@link |
| 289 | android.appwidget.AppWidgetProviderInfo}. This attribute supports two values: {@code home_screen} |
| 290 | and {@code keyguard}. By default, the attribute is set to {@code home_screen} so users can add your |
| 291 | app widget to the Home screen. If you want your app widget to be also available on the lock |
| 292 | screen, add the {@code keyguard} value:</p> |
| 293 | |
| 294 | <pre> |
| 295 | <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" |
| 296 | ... |
| 297 | android:widgetCategory="keyguard|home_screen"> |
| 298 | </appwidget-provider> |
| 299 | </pre> |
| 300 | |
| 301 | <p>You should also specify an initial layout for your app widget when on the lock screen with |
| 302 | the {@link android.appwidget.AppWidgetProviderInfo#initialKeyguardLayout |
| 303 | android:initialKeyguardLayout} attribute. This works the same way as the {@link |
| 304 | android.appwidget.AppWidgetProviderInfo#initialLayout android:initialLayout}, in that it provides |
| 305 | a layout that can appear immediately until your app widget is initialized and able to update the |
| 306 | layout.</p> |
| 307 | |
| 308 | <p>For more information about building app widgets for the lock screen, including to properly |
| 309 | size your app widget when on the lock screen, see the <a |
| 310 | href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">App Widgets</a> guide.</p> |
| 311 | |
| 312 | |
| 313 | |
| 314 | |
| 315 | |
| 316 | |
| 317 | |
| 318 | <h2 id="MultipleUsers">Multiple Users</h2> |
| 319 | |
| 320 | <p>Android now allows multiple user spaces on shareable devices such as tablets. Each user on a |
| 321 | device has his or her own set of accounts, apps, system settings, files, and any other |
| 322 | user-associated data.</p> |
| 323 | |
| 324 | <p>As an app developer, there’s nothing different you need to do in order for your app to work |
| 325 | properly with multiple users on a single device. Regardless of how many users may exist on a |
| 326 | device, the data your app saves for a given user is kept separate from the data your app saves |
| 327 | for other users. The system keeps track of which user data belongs to the user process in which |
| 328 | your app is running and provides your app access to only that user’s data and does not allow |
| 329 | access to other users’ data.</p> |
| 330 | |
| 331 | <h3>Saving data in a multi-user environment</h3> |
| 332 | |
| 333 | <p>Whenever your app saves user preferences, creates a database, or writes a file to the user’s |
| 334 | internal or external storage space, that data is accessible only while running as that user.</p> |
| 335 | |
| 336 | <p>To be certain that your app behaves properly in a multi-user environment, do not refer to your |
| 337 | internal app directory or external storage location using hard-coded paths and instead always use |
| 338 | the appropriate APIs:</p> |
| 339 | <ul> |
| 340 | <li>For access to internal storage, use {@link android.content.Context#getFilesDir()}, {@link |
| 341 | android.content.Context#getCacheDir()}, or {@link android.content.Context#openFileOutput |
| 342 | openFileOutput()}.</li> |
| 343 | <li>For access to external storage, use {@link android.content.Context#getExternalFilesDir |
| 344 | getExternalFilesDir()} or {@link android.os.Environment#getExternalStoragePublicDirectory |
| 345 | getExternalStoragePublicDirectory()}. |
| 346 | </ul> |
| 347 | |
| 348 | <p>No matter which of these APIs you use to save data for a given user, the data will not be |
| 349 | accessible while running as a different user. From your app’s point of view, each user is running |
| 350 | on a completely separate device.</p> |
| 351 | |
| 352 | <h3>Identifying users in a multi-user environment</h3> |
| 353 | |
| 354 | <p>If your app wants to identify unique users such as to gather analytics or create other account |
| 355 | associations, you should follow the recommended practices for <a |
| 356 | href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">identifying |
| 357 | unique installations</a>. By creating a new {@link java.util.UUID} when your app starts for the |
| 358 | first time, you’re certain to obtain a unique ID for tracking each user, regardless of how many |
| 359 | users install your app on a single device. Alternatively, you can save a local token fetched from |
| 360 | your server or use the registrations ID provided by <a |
Dirk Dougherty | 2b286bb | 2012-11-29 17:25:09 -0800 | [diff] [blame] | 361 | href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a>.</p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 362 | |
| 363 | <p>Beware that if your app requests one of the hardware device identifiers (such as the WiFi MAC |
Scott Rowe | ff42437 | 2014-05-16 10:54:04 -0700 | [diff] [blame] | 364 | address or the {@link android.os.Build#SERIAL} number), they will provide the same value for each |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 365 | user because these identifiers are tied to the hardware and not the user. Not to mention the other |
| 366 | problems these identifiers introduce as discussed in the <a |
| 367 | href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">Identifying |
| 368 | App Installations</a> blog post.</p> |
| 369 | |
| 370 | <h3>New Global Settings</h3> |
| 371 | |
| 372 | <p>The system settings have been updated to support multiple users with the addition of {@link |
| 373 | android.provider.Settings.Global}. This collection of settings is similar to {@link |
| 374 | android.provider.Settings.Secure} settings because they are read-only, but applies globally across |
| 375 | all user spaces on the device.</p> |
| 376 | |
| 377 | <p>Several existing settings were relocated here from either {@link |
| 378 | android.provider.Settings.System} or {@link android.provider.Settings.Secure}. If your app is |
| 379 | currently making changes to settings previously defined in {@link android.provider.Settings.System} |
| 380 | (such as {@link android.provider.Settings.System#AIRPLANE_MODE_ON}), then you should expect that |
| 381 | doing so will no longer work on a device running Android 4.2 or higher if those settings were |
| 382 | moved to {@link android.provider.Settings.Global}. You can continue to read settings that are in |
| 383 | {@link android.provider.Settings.Global}, but because the settings are no longer considered safe |
| 384 | for apps to change, attempting to do so will fail silently and the system will write a warning to |
| 385 | the system log when running your app on Android 4.2 or higher.</p> |
| 386 | |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | |
| 392 | |
| 393 | |
| 394 | |
| 395 | <h2 id="RTL">RTL Layout Support</h2> |
| 396 | |
| 397 | <p>Android now offers several APIs that allow you to build user interfaces that gracefully |
| 398 | transform layout orientation to support languages that use right-to-left (RTL) UIs and reading |
| 399 | direction, such as Arabic and Hebrew.</p> |
| 400 | |
| 401 | <p>To begin supporting RTL layouts in your app, set the {@link android.R.attr#supportsRtl |
| 402 | android:supportsRtl} attribute to the {@code <application>} element in your manifest file |
| 403 | and set it {@code “true"}. Once you enable this, the system will enable various RTL APIs to |
| 404 | display your app with RTL layouts. For instance, the action bar will show the icon and title |
| 405 | on the right side and action buttons on the left, and any layouts you’ve created with the |
| 406 | framework-provided {@link android.view.View} classes will also be reversed.</p> |
| 407 | |
| 408 | <p>If you need to further optimize the appearance of your app when displayed with an RTL layout, |
| 409 | there are two basic levels of optimization:</p> |
| 410 | |
| 411 | <ol> |
| 412 | <li>Convert left- and right-oriented layout properties to start- and end-oriented layout |
| 413 | properties. |
| 414 | <p>For example, use {@link android.R.attr#layout_marginStart android:layout_marginStart} |
| 415 | in place of {@code android:layout_marginLeft} and {@link android.R.attr#layout_marginEnd |
| 416 | android:layout_marginEnd} in place of {@code android:layout_marginRight}. |
| 417 | <p>The {@link android.widget.RelativeLayout} class also provides the corresponding layout |
| 418 | attributes to replace left/right positions, such as {@code android:layout_alignParentStart} to |
| 419 | replace {@code android:layout_alignParentLeft} and {@code android:layout_toStartOf} instead of |
| 420 | {@code android:layout_toLeftOf}. |
| 421 | </li> |
| 422 | <li>Or to provide complete optimization for RTL layouts, you can provide entirely separate |
| 423 | layout files using the {@code ldrtl} resource qualifier ({@code ldrtl} stands for |
| 424 | layout-direction-right-to-left}). For example, you can save your default layout files in |
| 425 | {@code res/layout/} and your RTL optimized layouts in {@code res/layout-ldrtl/}. |
| 426 | <p>The {@code ldrtl} qualifier is great for drawable resources, so that you can provide |
| 427 | graphics that are oriented in the direction corresponding to the reading direction.</p> |
| 428 | </li> |
| 429 | </ol> |
| 430 | |
| 431 | <p>Various other APIs are available across the framework to support RTL layouts, such as in |
| 432 | the {@link android.view.View} class so that you can implement the proper behaviors for custom |
| 433 | views and in {@link android.content.res.Configuration} to query the current layout direction.</p> |
| 434 | |
| 435 | <p><strong>Note:</strong> If you are using SQlite and have tables or column names that are |
| 436 | “number only," be |
| 437 | careful: using <a href="{@docRoot}reference/java/lang/String.html#format(String, Object...)">{@code |
| 438 | String.format(String, Object...)}</a> can lead to errors where the numbers |
| 439 | have been converted to their Arabic equivalents if your device has been set to the Arabic locale. |
| 440 | You must use <a href="{@docRoot}reference/java/lang/String.html#format(Locale,String,Object...)">{@code |
| 441 | String.format(Locale,String,Object...)}</a> to ensure numbers are |
| 442 | preserved as ASCII. Also use <a href="{@docRoot}reference/java/lang/String.html#format(String,int)">{@code |
| 443 | String.format("%d", int)}</a> instead of using |
| 444 | <a href="{@docRoot}reference/java/lang/String.html#valueOf(int)">{@code String.valueOf(int)}</a> for |
| 445 | formatting numbers.</p> |
| 446 | |
| 447 | |
| 448 | |
| 449 | |
| 450 | |
| 451 | |
| 452 | |
| 453 | |
| 454 | |
| 455 | |
| 456 | |
| 457 | |
| 458 | |
| 459 | <h2 id="NestedFragments">Nested Fragments</h2> |
| 460 | |
| 461 | <p>You can now embed fragments inside fragments. This is useful for a variety of situations in |
| 462 | which you want to place dynamic and re-usable UI components into a UI component that is itself |
| 463 | dynamic and re-usable. For example, if you use {@link android.support.v4.view.ViewPager} to |
| 464 | create fragments that swipe left and right and consume a majority of the screen space, you can |
| 465 | now insert fragments into each fragment page.</p> |
| 466 | |
| 467 | <p>To nest a fragment, simply call {@link android.app.Fragment#getChildFragmentManager()} on |
| 468 | the {@link android.app.Fragment} in which you want to add a fragment. This returns a {@link |
| 469 | android.app.FragmentManager} that you can use like you normally do from the top-level activity |
| 470 | to create fragment transactions. For example, here’s some code that adds a fragment from within |
| 471 | an existing {@link android.app.Fragment} class:</p> |
| 472 | |
| 473 | <pre> |
| 474 | Fragment videoFragment = new VideoPlayerFragment(); |
| 475 | FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); |
| 476 | transaction.add(R.id.video_fragment, videoFragment).commit(); |
| 477 | </pre> |
| 478 | |
| 479 | <p>From within a nested fragment, you can get a reference to the parent fragment by calling |
| 480 | {@link android.app.Fragment#getParentFragment()}.</p> |
| 481 | |
| 482 | <p>The Android Support Library also now supports nested fragments, so you can implement nested |
| 483 | fragment designs on Android 1.6 and higher.</p> |
| 484 | |
| 485 | <p><strong>Note:</strong> You cannot inflate a layout into a fragment when that layout |
| 486 | includes a {@code <fragment>}. Nested fragments are only supported when added to a |
| 487 | fragment dynamically.</p> |
| 488 | |
| 489 | |
| 490 | |
| 491 | |
| 492 | |
| 493 | |
| 494 | <h2 id="Renderscript">Renderscript</h2> |
| 495 | |
| 496 | <p>Renderscript computation functionality has been enhanced with the following features:</p> |
| 497 | <dl> |
| 498 | <dt><b>Script intrinsics</b></dt> |
| 499 | <dd><p>You can use Renderscript's built-in script intrinsics that implement |
| 500 | common operations for you such as:</p> |
| 501 | <ul> |
| 502 | <li>{@link android.renderscript.ScriptIntrinsicBlend Blends}</li> |
| 503 | <li>{@link android.renderscript.ScriptIntrinsicBlur Blur}</li> |
| 504 | <li>{@link android.renderscript.ScriptIntrinsicColorMatrix Color matrix}</li> |
| 505 | <li>{@link android.renderscript.ScriptIntrinsicConvolve3x3 3x3 convolve}</li> |
| 506 | <li>{@link android.renderscript.ScriptIntrinsicConvolve5x5 5x5 convolve}</li> |
| 507 | <li>{@link android.renderscript.ScriptIntrinsicLUT Per-channel lookup table}</li> |
| 508 | <li>{@link android.renderscript.ScriptIntrinsicYuvToRGB Converting an Android YUV buffer to RGB}</li> |
| 509 | </ul> |
| 510 | <p>To use a script intrinsic, call the static <code>create()</code> method of each instrinsic |
| 511 | to create an instance of the script. You then call the available <code>set()</code> |
| 512 | methods of each script intrinsic to set any necessary inputs and options. |
| 513 | Finally, call the {@link android.renderscript.ScriptC#forEach forEach()}</code> |
| 514 | method to execute the script.</p> |
| 515 | </dd> |
| 516 | |
| 517 | |
| 518 | <dt><b>Script Groups</b></dt> |
| 519 | <dd> |
| 520 | <p>{@link android.renderscript.ScriptGroup}s allow you to chain together related Renderscript |
| 521 | scripts and execute them with one call.</p> |
| 522 | |
| 523 | <p>Use a {@link android.renderscript.ScriptGroup.Builder} to add all of the scripts to the group |
| 524 | by calling {@link android.renderscript.ScriptGroup.Builder#addKernel addKernel()}. Once you |
| 525 | add all the scripts, create the connections between the |
| 526 | scripts by calling {@link android.renderscript.ScriptGroup.Builder#addConnection addConnection()}. |
| 527 | When you are done adding the connections, call {@link android.renderscript.ScriptGroup.Builder#create create()} |
| 528 | to create the script group. Before executing the script group, specify the input |
| 529 | {@link android.renderscript.Allocation} and initial script to run with the |
| 530 | {@link android.renderscript.ScriptGroup#setInput} method and provide the output |
| 531 | {@link android.renderscript.Allocation} where the result will be written to and final script to |
| 532 | run with {@link android.renderscript.ScriptGroup#setOutput setOutput()}. Finally, call |
| 533 | {@link android.renderscript.ScriptGroup#execute execute()} to run the script group. |
| 534 | </p> |
| 535 | </dd> |
| 536 | |
| 537 | <dt><b>Filterscript</b></dt> |
| 538 | <dd> |
| 539 | <p>Filterscript defines constraints on the existing Renderscript APIs that allow the resulting code to run |
| 540 | on a wider variety of processors (CPUs, GPUs, and DSPs). To create Filterscript files, create <code>.fs</code> |
| 541 | files instead of <code>.rs</code> files, and specify <code>#pragma rs_fp_relaxed</code> to |
| 542 | tell the Renderscript runtime your scripts do not require strict IEEE 754-2008 floating point precision. |
| 543 | This precision allows flush-to-zero for denorms and round-towards-zero. In addition, your Filterscript |
| 544 | scripts must not use 32-bit built-in types and must specify a custom root function by using the |
| 545 | <code>__attribute__((kernel))</code> attribute because Filterscript does not support pointers, which |
| 546 | the default signature of the <code>root()</code> function defines.</p> |
| 547 | </dd> |
| 548 | |
| 549 | </dl> |
| 550 | |
Scott Main | ca211c7 | 2012-11-13 09:08:42 -0800 | [diff] [blame] | 551 | <p class="note"><strong>Note:</strong> Although Filterscript support is in the platform, developer |
| 552 | support will be available in ADT and SDK Tools Release 21.0.1. </p> |
Scott Main | 5765525 | 2012-11-13 00:44:17 -0800 | [diff] [blame] | 553 | |
| 554 | |
| 555 | <p>For a detailed view of all API changes in Android 4.2, see the |
| 556 | <a href="{@docRoot}sdk/api_diff/17/changes.html">API Differences Report</a>.</p> |
| 557 | |
| 558 | |
| 559 | |