API Level: 17

Android 4.2 ([JELLY_BEAN_MR1](https://developer.android.com/reference/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.

As an app developer, you should download the Android 4.2 system image and SDK platform from the[SDK Manager](https://developer.android.com/tools/help/sdk-manager)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[Android emulator](https://developer.android.com/tools/devices/emulator). Then build your apps against the Android 4.2 platform to begin using the latest APIs.

To better optimize your app for devices running Android 4.2, you should set your[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)to`"17"`, install it on an Android 4.2 system image, test it, then publish an update with this change.

You can use APIs in Android 4.2 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[`minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min). To learn more about maintaining backward-compatibility, read[Creating Backward-Compatible UIs](https://developer.android.com/training/backward-compatible-ui).

More information about how API levels work is available in[What is API Level?](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)

## Important Behavior Changes

If you have previously published an app for Android, be aware of the following changes that might affect your app's behavior:

- **Content providers** are no longer exported by default. That is, the default value for the[`android:exported`](https://developer.android.com/guide/topics/manifest/provider-element#exported)attribute is now`"false"`. If it's important that other apps be able to access your content provider, you must now explicitly set[`android:exported="true"`.](https://developer.android.com/guide/topics/manifest/provider-element#exported)

  This change takes effect only if you set either[`android:targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)or[`android:minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)to 17 or higher. Otherwise, the default value is still`"true"`even when running on Android 4.2 and higher.
- Compared to previous versions of Android,**user location** results may be less accurate if your app requests the[ACCESS_COARSE_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_COARSE_LOCATION)permission but does not request the[ACCESS_FINE_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION)permission.

  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.
- Some**device settings** defined by[Settings.System](https://developer.android.com/reference/android/provider/Settings.System)are now read-only. If your app attempts to write changes to settings defined in[Settings.System](https://developer.android.com/reference/android/provider/Settings.System)that have moved to[Settings.Global](https://developer.android.com/reference/android/provider/Settings.Global), the write operation will silently fail when running on Android 4.2 and higher.

  Even if your value for[`android:targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)and[`android:minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)is lower than 17, your app is not able to modify the settings that have moved to[Settings.Global](https://developer.android.com/reference/android/provider/Settings.Global)when running on Android 4.2 and higher.
- If your app uses[WebView](https://developer.android.com/reference/android/webkit/WebView), Android 4.2 adds an additional layer of security so you can more safely**bind JavaScript to your Android code** . If you set your[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)to 17 or higher, you must now add the`@JavascriptInterface`annotation to any method that you want available to your JavaScript (the method must also be public). If you do not provide the annotation, the method is not accessible by a web page in your[WebView](https://developer.android.com/reference/android/webkit/WebView)when running on Android 4.2 or higher. If you set the[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)to 16 or lower, the annotation is not required, but we recommend that you update your target version and add the annotation for additional security.

  Read more about[binding JavaScript code to Android code](https://developer.android.com/guide/webapps/webview#BindingJavaScript).

## Daydream

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.

You can create a dream for Daydream by implementing a subclass of[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService). The[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)APIs are designed to be similar to those of[Activity](https://developer.android.com/reference/android/app/Activity). To specify the UI for your dream, pass a layout resource ID or[View](https://developer.android.com/reference/android/view/View)to[setContentView()](https://developer.android.com/reference/android/service/dreams/DreamService#setContentView(android.view.View))at any point after you have a window, such as from the[onAttachedToWindow()](https://developer.android.com/reference/android/service/dreams/DreamService#onAttachedToWindow())callback.

The[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)class provides other important lifecycle callback methods on top of the base[Service](https://developer.android.com/reference/android/app/Service)APIs, such as[onDreamingStarted()](https://developer.android.com/reference/android/service/dreams/DreamService#onDreamingStarted()),[onDreamingStopped()](https://developer.android.com/reference/android/service/dreams/DreamService#onDreamingStopped()), and[onDetachedFromWindow()](https://developer.android.com/reference/android/service/dreams/DreamService#onDetachedFromWindow()). You cannot initiate a[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)from your app---it is launched automatically by the system.

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[finish()](https://developer.android.com/reference/android/service/dreams/DreamService#finish())to end the dream so the user can see the new Activity.

To make your daydream available to the system, declare your[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)with a[`<service>`](https://developer.android.com/guide/topics/manifest/service-element)element in your manifest file. You must then include an intent filter with the action`"android.service.dreams.DreamService"`. For example:  

```gdscript
<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>
```

There are some other useful methods in[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)to be aware of:

- [setInteractive(boolean)](https://developer.android.com/reference/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*Back* or*Home* buttons to exit the dream or you can call[finish()](https://developer.android.com/reference/android/service/dreams/DreamService#finish())to stop the dream.
- If you want a fully immersive display, you can call[setFullscreen()](https://developer.android.com/reference/android/service/dreams/DreamService#setFullscreen(boolean))to hide the status bar.
- Before Daydream starts, the display dims to signal to the user that the idle timeout is approaching. Calling[setScreenBright(true)](https://developer.android.com/reference/android/service/dreams/DreamService#setScreenBright(boolean))allows you to instead set the display at its usual brightness.

For more information, see the[DreamService](https://developer.android.com/reference/android/service/dreams/DreamService)documentation.

## Secondary Displays

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[Presentation](https://developer.android.com/reference/android/app/Presentation)class and implement the[onCreate()](https://developer.android.com/reference/android/app/Dialog#onCreate(android.os.Bundle))callback. Within[onCreate()](https://developer.android.com/reference/android/app/Dialog#onCreate(android.os.Bundle)), specify your UI for the secondary display by calling[setContentView()](https://developer.android.com/reference/android/app/Dialog#setContentView(android.view.View)). As an extension of the[Dialog](https://developer.android.com/reference/android/app/Dialog)class, the[Presentation](https://developer.android.com/reference/android/app/Presentation)class provides the region in which your app can display a unique UI on the secondary display.

To detect secondary displays where you can display your[Presentation](https://developer.android.com/reference/android/app/Presentation), use either the[DisplayManager](https://developer.android.com/reference/android/hardware/display/DisplayManager)or[MediaRouter](https://developer.android.com/reference/android/media/MediaRouter)APIs. While the[DisplayManager](https://developer.android.com/reference/android/hardware/display/DisplayManager)APIs allow you to enumerate multiple displays that may be connected at once, you should usually use[MediaRouter](https://developer.android.com/reference/android/media/MediaRouter)instead to quickly access the system's default display for presentations.

To get the default display for your presentation, call[MediaRouter.getSelectedRoute()](https://developer.android.com/reference/android/media/MediaRouter#getSelectedRoute(int))and pass it[ROUTE_TYPE_LIVE_VIDEO](https://developer.android.com/reference/android/media/MediaRouter#ROUTE_TYPE_LIVE_VIDEO). This returns a[MediaRouter.RouteInfo](https://developer.android.com/reference/android/media/MediaRouter.RouteInfo)object that describes the system's currently selected route for video presentations. If the[MediaRouter.RouteInfo](https://developer.android.com/reference/android/media/MediaRouter.RouteInfo)is not null, call[getPresentationDisplay()](https://developer.android.com/reference/android/media/MediaRouter.RouteInfo#getPresentationDisplay())to get the[Display](https://developer.android.com/reference/android/view/Display)representing the connected display.

You can then display your presentation by passing the[Display](https://developer.android.com/reference/android/view/Display)object to a constructor for your[Presentation](https://developer.android.com/reference/android/app/Presentation)class. Your presentation will now appear on the secondary display.

To detect at runtime when a new display has been connected, create an instance of[MediaRouter.SimpleCallback](https://developer.android.com/reference/android/media/MediaRouter.SimpleCallback)in which you implement the[onRoutePresentationDisplayChanged()](https://developer.android.com/reference/android/media/MediaRouter.Callback#onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo))callback method, which the system will call when a new presentation display is connected. Then register the[MediaRouter.SimpleCallback](https://developer.android.com/reference/android/media/MediaRouter.SimpleCallback)by passing it to[MediaRouter.addCallback()](https://developer.android.com/reference/android/media/MediaRouter#addCallback(int, android.media.MediaRouter.Callback))along with the[ROUTE_TYPE_LIVE_VIDEO](https://developer.android.com/reference/android/media/MediaRouter#ROUTE_TYPE_LIVE_VIDEO)route type. When you receive a call to[onRoutePresentationDisplayChanged()](https://developer.android.com/reference/android/media/MediaRouter.Callback#onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo)), simply call[MediaRouter.getSelectedRoute()](https://developer.android.com/reference/android/media/MediaRouter#getSelectedRoute(int))as mentioned above.

To further optimize the UI in your[Presentation](https://developer.android.com/reference/android/app/Presentation)for secondary screens, you can apply a different theme by specifying the[android:presentationTheme](https://developer.android.com/reference/android/R.attr#presentationTheme)attribute in the[`<style>`](https://developer.android.com/guide/topics/resources/style-resource)that you've applied to your application or activity.

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[Presentation](https://developer.android.com/reference/android/app/Presentation), call[getContext()](https://developer.android.com/reference/android/app/Dialog#getContext())[.getResources()](https://developer.android.com/reference/android/content/Context#getResources())to get the[Resources](https://developer.android.com/reference/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.

For more information and some code samples, see the[Presentation](https://developer.android.com/reference/android/app/Presentation)class documentation.

## Lockscreen Widgets

Android now allows users to add app widgets to the lock screen. To make your[App Widget](https://developer.android.com/guide/topics/appwidgets)available for use on the lock screen, add the[android:widgetCategory](https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo#widgetCategory)attribute to your XML file that specifies the[AppWidgetProviderInfo](https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo). This attribute supports two values:`home_screen`and`keyguard`. By default, the attribute is set to`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`keyguard`value:  

```scdoc
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>
```

You should also specify an initial layout for your app widget when on the lock screen with the[android:initialKeyguardLayout](https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo#initialKeyguardLayout)attribute. This works the same way as the[android:initialLayout](https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo#initialLayout), in that it provides a layout that can appear immediately until your app widget is initialized and able to update the layout.

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[App Widgets](https://developer.android.com/guide/topics/appwidgets#lockscreen)guide.

## Multiple Users

Android now allows multiple user spaces on shareable devices such as tablets. Each user on a device has their own set of accounts, apps, system settings, files, and any other user-associated data.

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.

### Saving data in a multi-user environment

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.

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:

- For access to internal storage, use[getFilesDir()](https://developer.android.com/reference/android/content/Context#getFilesDir()),[getCacheDir()](https://developer.android.com/reference/android/content/Context#getCacheDir()), or[openFileOutput()](https://developer.android.com/reference/android/content/Context#openFileOutput(java.lang.String, int)).
- For access to external storage, use[getExternalFilesDir()](https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String))or[getExternalStoragePublicDirectory()](https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)).

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.

### Identifying users in a multi-user environment

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[identifying unique installations](http://android-developers.blogspot.com/2011/03/identifying-app-installations.html). By creating a new[UUID](https://developer.android.com/reference/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[Google Cloud Messaging](https://developer.android.com/google/gcm).

Beware that if your app requests one of the hardware device identifiers (such as the WiFi MAC address or the[SERIAL](https://developer.android.com/reference/android/os/Build#SERIAL)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[Identifying App Installations](http://android-developers.blogspot.com/2011/03/identifying-app-installations.html)blog post.

### New Global Settings

The system settings have been updated to support multiple users with the addition of[Settings.Global](https://developer.android.com/reference/android/provider/Settings.Global). This collection of settings is similar to[Settings.Secure](https://developer.android.com/reference/android/provider/Settings.Secure)settings because they are read-only, but applies globally across all user spaces on the device.

Several existing settings were relocated here from either[Settings.System](https://developer.android.com/reference/android/provider/Settings.System)or[Settings.Secure](https://developer.android.com/reference/android/provider/Settings.Secure). If your app is currently making changes to settings previously defined in[Settings.System](https://developer.android.com/reference/android/provider/Settings.System)(such as[AIRPLANE_MODE_ON](https://developer.android.com/reference/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[Settings.Global](https://developer.android.com/reference/android/provider/Settings.Global). You can continue to read settings that are in[Settings.Global](https://developer.android.com/reference/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.

## RTL Layout Support

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.

To begin supporting RTL layouts in your app, set the[android:supportsRtl](https://developer.android.com/reference/android/R.attr#supportsRtl)attribute to the`<application>`element in your manifest file and set it`"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[View](https://developer.android.com/reference/android/view/View)classes will also be reversed.

If you need to further optimize the appearance of your app when displayed with an RTL layout, there are two basic levels of optimization:

1. Convert left- and right-oriented layout properties to start- and end-oriented layout properties.For example, use[android:layout_marginStart](https://developer.android.com/reference/android/R.attr#layout_marginStart)in place of`android:layout_marginLeft`and[android:layout_marginEnd](https://developer.android.com/reference/android/R.attr#layout_marginEnd)in place of`android:layout_marginRight`.

   The[RelativeLayout](https://developer.android.com/reference/android/widget/RelativeLayout)class also provides the corresponding layout attributes to replace left/right positions, such as`android:layout_alignParentStart`to replace`android:layout_alignParentLeft`and`android:layout_toStartOf`instead of`android:layout_toLeftOf`.
2. Or to provide complete optimization for RTL layouts, you can provide entirely separate layout files using the`ldrtl`resource qualifier (`ldrtl`stands for layout-direction-right-to-left}). For example, you can save your default layout files in`res/layout/`and your RTL optimized layouts in`res/layout-ldrtl/`.

   The`ldrtl`qualifier is great for drawable resources, so that you can provide graphics that are oriented in the direction corresponding to the reading direction.

Various other APIs are available across the framework to support RTL layouts, such as in the[View](https://developer.android.com/reference/android/view/View)class so that you can implement the proper behaviors for custom views and in[Configuration](https://developer.android.com/reference/android/content/res/Configuration)to query the current layout direction.

**Note:** If you are using SQlite and have tables or column names that are "number only," be careful: using[`String.format(String, Object...)`](https://developer.android.com/reference/java/lang/String#format(String, Object...))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[`String.format(Locale,String,Object...)`](https://developer.android.com/reference/java/lang/String#format(Locale,String,Object...))to ensure numbers are preserved as ASCII. Also use[`String.format("%d", int)`](https://developer.android.com/reference/java/lang/String#format(String,int))instead of using[`String.valueOf(int)`](https://developer.android.com/reference/java/lang/String#valueOf(int))for formatting numbers.

## Nested Fragments

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[ViewPager](https://developer.android.com/reference/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.

To nest a fragment, simply call[getChildFragmentManager()](https://developer.android.com/reference/android/app/Fragment#getChildFragmentManager())on the[Fragment](https://developer.android.com/reference/android/app/Fragment)in which you want to add a fragment. This returns a[FragmentManager](https://developer.android.com/reference/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[Fragment](https://developer.android.com/reference/android/app/Fragment)class:  

### Kotlin

```kotlin
val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}
```

### Java

```java
Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();
```

From within a nested fragment, you can get a reference to the parent fragment by calling[getParentFragment()](https://developer.android.com/reference/android/app/Fragment#getParentFragment()).

The Android Support Library also now supports nested fragments, so you can implement nested fragment designs on Android 1.6 and higher.

**Note:** You cannot inflate a layout into a fragment when that layout includes a`<fragment>`. Nested fragments are only supported when added to a fragment dynamically.

## Renderscript

Renderscript computation functionality has been enhanced with the following features:

**Script intrinsics**

:   You can use Renderscript's built-in script intrinsics that implement common operations for you such as:

    - [Blends](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicBlend)
    - [Blur](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicBlur)
    - [Color matrix](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicColorMatrix)
    - [3x3 convolve](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicConvolve3x3)
    - [5x5 convolve](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicConvolve5x5)
    - [Per-channel lookup table](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicLUT)
    - [Converting an Android YUV buffer to RGB](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicYuvToRGB)

    To use a script intrinsic, call the static`create()`method of each instrinsic to create an instance of the script. You then call the available`set()`methods of each script intrinsic to set any necessary inputs and options. Finally, call the[forEach()](https://developer.android.com/reference/android/renderscript/Script#forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker))method to execute the script.

**Script Groups**

:   [ScriptGroup](https://developer.android.com/reference/android/renderscript/ScriptGroup)s allow you to chain together related Renderscript scripts and execute them with one call.

    Use a[ScriptGroup.Builder](https://developer.android.com/reference/android/renderscript/ScriptGroup.Builder)to add all of the scripts to the group by calling[addKernel()](https://developer.android.com/reference/android/renderscript/ScriptGroup.Builder#addKernel(android.renderscript.Script.KernelID)). Once you add all the scripts, create the connections between the scripts by calling[addConnection()](https://developer.android.com/reference/android/renderscript/ScriptGroup.Builder#addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID)). When you are done adding the connections, call[create()](https://developer.android.com/reference/android/renderscript/ScriptGroup.Builder#create())to create the script group. Before executing the script group, specify the input[Allocation](https://developer.android.com/reference/android/renderscript/Allocation)and initial script to run with the[setInput(Script.KernelID, Allocation)](https://developer.android.com/reference/android/renderscript/ScriptGroup#setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation))method and provide the output[Allocation](https://developer.android.com/reference/android/renderscript/Allocation)where the result will be written to and final script to run with[setOutput()](https://developer.android.com/reference/android/renderscript/ScriptGroup#setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation)). Finally, call[execute()](https://developer.android.com/reference/android/renderscript/ScriptGroup#execute())to run the script group.

**Filterscript**

:   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`.fs`files instead of`.rs`files, and specify`#pragma rs_fp_relaxed`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`__attribute__((kernel))`attribute because Filterscript does not support pointers, which the default signature of the`root()`function defines.

**Note:**Although Filterscript support is in the platform, developer support will be available in SDK Tools Release 21.0.1.

For a detailed view of all API changes in Android 4.2, see the[API Differences Report](https://developer.android.com/sdk/api_diff/17/changes).