*API Level:* **14**

Android 4.0 ([ICE_CREAM_SANDWICH](https://developer.android.com/reference/android/os/Build.VERSION_CODES#ICE_CREAM_SANDWICH)) is a major platform release that adds a variety of new features for users and app developers. Besides all the new features and APIs discussed below, Android 4.0 is an important platform release because it brings the extensive set of APIs and Holographic themes from Android 3.x to smaller screens. As an app developer, you now have a single platform and unified API framework that enables you to develop and publish your application with a single APK that provides an optimized user experience for handsets, tablets, and more, when running the same version of Android---Android 4.0 (API level 14) or greater.

For developers, the Android 4.0 platform is available as a downloadable component for the Android SDK. The downloadable platform includes an Android library and system image, as well as a set of emulator skins and more. To get started developing or testing against Android 4.0, use the Android SDK Manager to download the platform into your SDK.

## API Overview

The sections below provide a technical overview of new APIs in Android 4.0.
**Table of Contents**

1. [Social APIs in Contacts Provider](https://developer.android.com/about/versions/android-4.0#Contacts)
2. [Calendar Provider](https://developer.android.com/about/versions/android-4.0#Calendar)
3. [Voicemail Provider](https://developer.android.com/about/versions/android-4.0#Voicemail)
4. [Multimedia](https://developer.android.com/about/versions/android-4.0#Multimedia)
5. [Camera](https://developer.android.com/about/versions/android-4.0#Camera)
6. [Android Beam (NDEF Push with NFC)](https://developer.android.com/about/versions/android-4.0#AndroidBeam)
7. [Wi-Fi P2P](https://developer.android.com/about/versions/android-4.0#WiFiDirect)
8. [Bluetooth Health Devices](https://developer.android.com/about/versions/android-4.0#Bluetooth)
9. [Accessibility](https://developer.android.com/about/versions/android-4.0#A11y)
10. [Spell Checker Services](https://developer.android.com/about/versions/android-4.0#SpellChecker)
11. [Text-to-speech Engines](https://developer.android.com/about/versions/android-4.0#TTS)
12. [Network Usage](https://developer.android.com/about/versions/android-4.0#NetworkUsage)
13. [RenderScript](https://developer.android.com/about/versions/android-4.0#RenderScript)
14. [Enterprise](https://developer.android.com/about/versions/android-4.0#Enterprise)
15. [Device Sensors](https://developer.android.com/about/versions/android-4.0#Sensors)
16. [Action Bar](https://developer.android.com/about/versions/android-4.0#ActionBar)
17. [User Interface and Views](https://developer.android.com/about/versions/android-4.0#UI)
18. [Input Framework](https://developer.android.com/about/versions/android-4.0#Input)
19. [Properties](https://developer.android.com/about/versions/android-4.0#Properties)
20. [Hardware Acceleration](https://developer.android.com/about/versions/android-4.0#HwAccel)
21. [JNI Changes](https://developer.android.com/about/versions/android-4.0#Jni)
22. [WebKit](https://developer.android.com/about/versions/android-4.0#WebKit)
23. [Permissions](https://developer.android.com/about/versions/android-4.0#Permissions)
24. [Device Features](https://developer.android.com/about/versions/android-4.0#DeviceFeatures)

### Social APIs in Contacts Provider

The contact APIs defined by the[ContactsContract](https://developer.android.com/reference/android/provider/ContactsContract)provider have been extended to support new social-oriented features such as a personal profile for the device owner and the ability for users to invite individual contacts to social networks that are installed on the device.

#### User Profile

Android now includes a personal profile that represents the device owner, as defined by the[ContactsContract.Profile](https://developer.android.com/reference/android/provider/ContactsContract.Profile)table. Social apps that maintain a user identity can contribute to the user's profile data by creating a new[ContactsContract.RawContacts](https://developer.android.com/reference/android/provider/ContactsContract.RawContacts)entry within the[ContactsContract.Profile](https://developer.android.com/reference/android/provider/ContactsContract.Profile). That is, raw contacts that represent the device user do not belong in the traditional raw contacts table defined by the[ContactsContract.RawContacts](https://developer.android.com/reference/android/provider/ContactsContract.RawContacts)Uri; instead, you must add a profile raw contact in the table at[CONTENT_RAW_CONTACTS_URI](https://developer.android.com/reference/android/provider/ContactsContract.Profile#CONTENT_RAW_CONTACTS_URI). Raw contacts in this table are then aggregated into the single user-visible profile labeled "Me".

Adding a new raw contact for the profile requires the android.Manifest.permission#WRITE_PROFILE permission. Likewise, in order to read from the profile table, you must request the android.Manifest.permission#READ_PROFILE permission. However, most apps should not need to read the user profile, even when contributing data to the profile. Reading the user profile is a sensitive permission and you should expect users to be skeptical of apps that request it.

#### Invite Intent

The[INVITE_CONTACT](https://developer.android.com/reference/android/provider/ContactsContract.Intents#INVITE_CONTACT)intent action allows an app to invoke an action that indicates the user wants to add a contact to a social network. The app receiving the app uses it to invite the specified contact to that social network. Most apps will be on the receiving-end of this operation. For example, the built-in People app invokes the invite intent when the user selects "Add connection" for a specific social app that's listed in a person's contact details.

To make your app visible as in the "Add connection" list, your app must provide a sync adapter to sync contact information from your social network. You must then indicate to the system that your app responds to the[INVITE_CONTACT](https://developer.android.com/reference/android/provider/ContactsContract.Intents#INVITE_CONTACT)intent by adding the`inviteContactActivity`attribute to your app's sync configuration file, with a fully-qualified name of the activity that the system should start when sending the invite intent. The activity that starts can then retrieve the URI for the contact in question from the intent's data and perform the necessary work to invite that contact to the network or add the person to the user's connections.

#### Large photos

Android now supports high resolution photos for contacts. Now, when you push a photo into a contact record, the system processes it into both a 96x96 thumbnail (as it has previously) and a 256x256 "display photo" that's stored in a new file-based photo store (the exact dimensions that the system chooses may vary in the future). You can add a large photo to a contact by putting a large photo in the usual[PHOTO](https://developer.android.com/reference/android/provider/ContactsContract.CommonDataKinds.Photo#PHOTO)column of a data row, which the system will then process into the appropriate thumbnail and display photo records.

#### Contact Usage Feedback

The new[ContactsContract.DataUsageFeedback](https://developer.android.com/reference/android/provider/ContactsContract.DataUsageFeedback)APIs allow you to help track how often the user uses particular methods of contacting people, such as how often the user uses each phone number or e-mail address. This information helps improve the ranking for each contact method associated with each person and provide better suggestions for contacting each person.

### Calendar Provider

The new calendar APIs allow you to read, add, modify and delete calendars, events, attendees, reminders and alerts, which are stored in the Calendar Provider.

A variety of apps and widgets can use these APIs to read and modify calendar events. However, some of the most compelling use cases are sync adapters that synchronize the user's calendar from other calendar services with the Calendar Provider, in order to offer a unified location for all the user's events. Google Calendar events, for example, are synchronized with the Calendar Provider by the Google Calendar Sync Adapter, allowing these events to be viewed with Android's built-in Calendar app.

The data model for calendars and event-related information in the Calendar Provider is defined by[CalendarContract](https://developer.android.com/reference/android/provider/CalendarContract). All the user's calendar data is stored in a number of tables defined by various subclasses of[CalendarContract](https://developer.android.com/reference/android/provider/CalendarContract):

- The[CalendarContract.Calendars](https://developer.android.com/reference/android/provider/CalendarContract.Calendars)table holds the calendar-specific information. Each row in this table contains the details for a single calendar, such as the name, color, sync information, and so on.
- The[CalendarContract.Events](https://developer.android.com/reference/android/provider/CalendarContract.Events)table holds event-specific information. Each row in this table contains the information for a single event, such as the event title, location, start time, end time, and so on. The event can occur one time or recur multiple times. Attendees, reminders, and extended properties are stored in separate tables and use the event's`_ID`to link them with the event.
- The[CalendarContract.Instances](https://developer.android.com/reference/android/provider/CalendarContract.Instances)table holds the start and end time for occurrences of an event. Each row in this table represents a single occurrence. For one-time events there is a one-to-one mapping of instances to events. For recurring events, multiple rows are automatically generated to correspond to the multiple occurrences of that event.
- The[CalendarContract.Attendees](https://developer.android.com/reference/android/provider/CalendarContract.Attendees)table holds the event attendee or guest information. Each row represents a single guest of an event. It specifies the type of guest the person is and the person's response for the event.
- The[CalendarContract.Reminders](https://developer.android.com/reference/android/provider/CalendarContract.Reminders)table holds the alert/notification data. Each row represents a single alert for an event. An event can have multiple reminders. The number of reminders per event is specified in`MAX_REMINDERS`, which is set by the sync adapter that owns the given calendar. Reminders are specified in number-of-minutes before the event is scheduled and specify an alarm method such as to use an alert, email, or SMS to remind the user.
- The[CalendarContract.ExtendedProperties](https://developer.android.com/reference/android/provider/CalendarContract.ExtendedProperties)table hold opaque data fields used by the sync adapter. The provider takes no action with items in this table except to delete them when their related events are deleted.

To access a user's calendar data with the Calendar Provider, your application must request the[READ_CALENDAR](https://developer.android.com/reference/android/Manifest.permission#READ_CALENDAR)permission (for read access) and[WRITE_CALENDAR](https://developer.android.com/reference/android/Manifest.permission#WRITE_CALENDAR)(for write access).

#### Event intent

If all you want to do is add an event to the user's calendar, you can use an[ACTION_INSERT](https://developer.android.com/reference/android/content/Intent#ACTION_INSERT)intent with the data defined by[Events.CONTENT_URI](https://developer.android.com/reference/android/provider/CalendarContract.Events#CONTENT_URI)in order to start an activity in the Calendar app that creates new events. Using the intent does not require any permission and you can specify event details with the following extras:

- [Events.TITLE](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#TITLE): Name for the event
- [CalendarContract.EXTRA_EVENT_BEGIN_TIME](https://developer.android.com/reference/android/provider/CalendarContract#EXTRA_EVENT_BEGIN_TIME): Event begin time in milliseconds from the epoch
- [CalendarContract.EXTRA_EVENT_END_TIME](https://developer.android.com/reference/android/provider/CalendarContract#EXTRA_EVENT_END_TIME): Event end time in milliseconds from the epoch
- [Events.EVENT_LOCATION](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#EVENT_LOCATION): Location of the event
- [Events.DESCRIPTION](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#DESCRIPTION): Event description
- [Intent.EXTRA_EMAIL](https://developer.android.com/reference/android/content/Intent#EXTRA_EMAIL): Email addresses of those to invite
- [Events.RRULE](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#RRULE): The recurrence rule for the event
- [Events.ACCESS_LEVEL](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#ACCESS_LEVEL): Whether the event is private or public
- [Events.AVAILABILITY](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns#AVAILABILITY): Whether the time period of this event allows for other events to be scheduled at the same time

### Voicemail Provider

The new Voicemail Provider allows applications to add voicemails to the device, in order to present all the user's voicemails in a single visual presentation. For instance, it's possible that a user has multiple voicemail sources, such as one from the phone's service provider and others from VoIP or other alternative voice services. These apps can use the Voicemail Provider APIs to add their voicemails to the device. The built-in Phone application then presents all voicemails to the user in a unified presentation. Although the system's Phone application is the only application that can read all the voicemails, each application that provides voicemails can read those that it has added to the system (but cannot read voicemails from other services).

Because the APIs currently do not allow third-party apps to read all the voicemails from the system, the only third-party apps that should use the voicemail APIs are those that have voicemail to deliver to the user.

The[VoicemailContract](https://developer.android.com/reference/android/provider/VoicemailContract)class defines the content provider for the Voicemail Provder. The subclasses[VoicemailContract.Voicemails](https://developer.android.com/reference/android/provider/VoicemailContract.Voicemails)and[VoicemailContract.Status](https://developer.android.com/reference/android/provider/VoicemailContract.Status)provide tables in which apps can insert voicemail data for storage on the device. For an example of a voicemail provider app, see the[Voicemail Provider Demo](https://developer.android.com/resources/samples/VoicemailProviderDemo).

### Multimedia

Android 4.0 adds several new APIs for applications that interact with media such as photos, videos, and music.

#### Media Effects

A new media effects framework allows you to apply a variety of visual effects to images and videos. For example, image effects allow you to easily fix red-eye, convert an image to grayscale, adjust brightness, adjust saturation, rotate an image, apply a fisheye effect, and much more. The system performs all effects processing on the GPU to obtain maximum performance.

For maximum performance, effects are applied directly to OpenGL textures, so your application must have a valid OpenGL context before it can use the effects APIs. The textures to which you apply effects may be from bitmaps, videos or even the camera. However, there are certain restrictions that textures must meet:

1. They must be bound to a[GL_TEXTURE_2D](https://developer.android.com/reference/android/opengl/GLES20#GL_TEXTURE_2D)texture image
2. They must contain at least one mipmap level

An[Effect](https://developer.android.com/reference/android/media/effect/Effect)object defines a single media effect that you can apply to an image frame. The basic workflow to create an[Effect](https://developer.android.com/reference/android/media/effect/Effect)is:

1. Call[EffectContext.createWithCurrentGlContext()](https://developer.android.com/reference/android/media/effect/EffectContext#createWithCurrentGlContext())from your OpenGL ES 2.0 context.
2. Use the returned[EffectContext](https://developer.android.com/reference/android/media/effect/EffectContext)to call[EffectContext.getFactory()](https://developer.android.com/reference/android/media/effect/EffectContext#getFactory()), which returns an instance of[EffectFactory](https://developer.android.com/reference/android/media/effect/EffectFactory).
3. Call[createEffect()](https://developer.android.com/reference/android/media/effect/EffectFactory#createEffect(java.lang.String)), passing it an effect name from @link android.media.effect.EffectFactory}, such as[EFFECT_FISHEYE](https://developer.android.com/reference/android/media/effect/EffectFactory#EFFECT_FISHEYE)or[EFFECT_VIGNETTE](https://developer.android.com/reference/android/media/effect/EffectFactory#EFFECT_VIGNETTE).

You can adjust an effect's parameters by calling[setParameter()](https://developer.android.com/reference/android/media/effect/Effect#setParameter(java.lang.String, java.lang.Object))and passing a parameter name and parameter value. Each type of effect accepts different parameters, which are documented with the effect name. For example,[EFFECT_FISHEYE](https://developer.android.com/reference/android/media/effect/EffectFactory#EFFECT_FISHEYE)has one parameter for the`scale`of the distortion.

To apply an effect on a texture, call[apply()](https://developer.android.com/reference/android/media/effect/Effect#apply(int, int, int, int))on the[Effect](https://developer.android.com/reference/android/media/effect/Effect)and pass in the input texture, it's width and height, and the output texture. The input texture must be bound to a[GL_TEXTURE_2D](https://developer.android.com/reference/android/opengl/GLES20#GL_TEXTURE_2D)texture image (usually done by calling the[glTexImage2D()](https://developer.android.com/reference/android/opengl/GLES20#glTexImage2D(int, int, int, int, int, int, int, int, java.nio.Buffer))function). You may provide multiple mipmap levels. If the output texture has not been bound to a texture image, it will be automatically bound by the effect as a[GL_TEXTURE_2D](https://developer.android.com/reference/android/opengl/GLES20#GL_TEXTURE_2D)and with one mipmap level (0), which will have the same size as the input.

All effects listed in[EffectFactory](https://developer.android.com/reference/android/media/effect/EffectFactory)are guaranteed to be supported. However, some additional effects available from external libraries are not supported by all devices, so you must first check if the desired effect from the external library is supported by calling[isEffectSupported()](https://developer.android.com/reference/android/media/effect/EffectFactory#isEffectSupported(java.lang.String)).

#### Remote control client

The new[RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient)allows media players to enable playback controls from remote control clients such as the device lock screen. Media players can also expose information about the media currently playing for display on the remote control, such as track information and album art.

To enable remote control clients for your media player, instantiate a[RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient)with its constructor, passing it a[PendingIntent](https://developer.android.com/reference/android/app/PendingIntent)that broadcasts[ACTION_MEDIA_BUTTON](https://developer.android.com/reference/android/content/Intent#ACTION_MEDIA_BUTTON). The intent must also declare the explicit[BroadcastReceiver](https://developer.android.com/reference/android/content/BroadcastReceiver)component in your app that handles the[ACTION_MEDIA_BUTTON](https://developer.android.com/reference/android/content/Intent#ACTION_MEDIA_BUTTON)event.

To declare which media control inputs your player can handle, you must call[setTransportControlFlags()](https://developer.android.com/reference/android/media/RemoteControlClient#setTransportControlFlags(int))on your[RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient), passing a set of`FLAG_KEY_MEDIA_*`flags, such as[FLAG_KEY_MEDIA_PREVIOUS](https://developer.android.com/reference/android/media/RemoteControlClient#FLAG_KEY_MEDIA_PREVIOUS)and[FLAG_KEY_MEDIA_NEXT](https://developer.android.com/reference/android/media/RemoteControlClient#FLAG_KEY_MEDIA_NEXT).

You must then register your[RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient)by passing it to[MediaManager.registerRemoteControlClient()](https://developer.android.com/reference/android/media/AudioManager#registerRemoteControlClient(android.media.RemoteControlClient)). Once registered, the broadcast receiver you declared when you instantiated the[RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient)will receive[ACTION_MEDIA_BUTTON](https://developer.android.com/reference/android/content/Intent#ACTION_MEDIA_BUTTON)events when a button is pressed from a remote control. The intent you receive includes the[KeyEvent](https://developer.android.com/reference/android/view/KeyEvent)for the media key pressed, which you can retrieve from the intent with[getParcelableExtra(Intent.EXTRA_KEY_EVENT)](https://developer.android.com/reference/android/content/Intent#getParcelableExtra(java.lang.String)).

To display information on the remote control about the media playing, call[editMetaData()](https://developer.android.com/reference/android/media/RemoteControlClient#editMetadata(boolean))and add metadata to the returned[RemoteControlClient.MetadataEditor](https://developer.android.com/reference/android/media/RemoteControlClient.MetadataEditor). You can supply a bitmap for media artwork, numerical information such as elapsed time, and text information such as the track title. For information on available keys see the`METADATA_KEY_*`flags in[MediaMetadataRetriever](https://developer.android.com/reference/android/media/MediaMetadataRetriever).

For a sample implementation, see the[Random Music Player](https://developer.android.com/resources/samples/RandomMusicPlayer), which provides compatibility logic such that it enables the remote control client on Android 4.0 devices while continuing to support devices back to Android 2.1.

#### Media player

- Streaming online media from[MediaPlayer](https://developer.android.com/reference/android/media/MediaPlayer)now requires the[INTERNET](https://developer.android.com/reference/android/Manifest.permission#INTERNET)permission. If you use[MediaPlayer](https://developer.android.com/reference/android/media/MediaPlayer)to play content from the Internet, be sure to add the[INTERNET](https://developer.android.com/reference/android/Manifest.permission#INTERNET)permission to your manifest or else your media playback will not work beginning with Android 4.0.
- [setSurface()](https://developer.android.com/reference/android/media/MediaPlayer#setSurface(android.view.Surface))allows you define a[Surface](https://developer.android.com/reference/android/view/Surface)to behave as the video sink.
- [setDataSource()](https://developer.android.com/reference/android/media/MediaPlayer#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>))allows you to send additional HTTP headers with your request, which can be useful for HTTP(S) live streaming
- HTTP(S) live streaming now respects HTTP cookies across requests

#### Media types

Android 4.0 adds support for:

- HTTP/HTTPS live streaming protocol version 3
- ADTS raw AAC audio encoding
- WEBP images
- Matroska video

For more info, see[Supported Media Formats](https://developer.android.com/guide/appendix/media-formats).

### Camera

The[Camera](https://developer.android.com/reference/android/hardware/Camera)class now includes APIs for detecting faces and controlling focus and metering areas.

#### Face detection

Camera apps can now enhance their abilities with Android's face detection APIs, which not only detect the face of a subject, but also specific facial features, such as the eyes and mouth.

To detect faces in your camera application, you must register a[Camera.FaceDetectionListener](https://developer.android.com/reference/android/hardware/Camera.FaceDetectionListener)by calling[setFaceDetectionListener()](https://developer.android.com/reference/android/hardware/Camera#setFaceDetectionListener(android.hardware.Camera.FaceDetectionListener)). You can then start your camera surface and start detecting faces by calling[startFaceDetection()](https://developer.android.com/reference/android/hardware/Camera#startFaceDetection()).

When the system detects one or more faces in the camera scene, it calls the[onFaceDetection()](https://developer.android.com/reference/android/hardware/Camera.FaceDetectionListener#onFaceDetection(android.hardware.Camera.Face[], android.hardware.Camera))callback in your implementation of[Camera.FaceDetectionListener](https://developer.android.com/reference/android/hardware/Camera.FaceDetectionListener), including an array of[Camera.Face](https://developer.android.com/reference/android/hardware/Camera.Face)objects.

An instance of the[Camera.Face](https://developer.android.com/reference/android/hardware/Camera.Face)class provides various information about the face detected, including:

- A[Rect](https://developer.android.com/reference/android/graphics/Rect)that specifies the bounds of the face, relative to the camera's current field of view
- An integer between 1 and 100 that indicates how confident the system is that the object is a human face
- A unique ID so you can track multiple faces
- Several[Point](https://developer.android.com/reference/android/graphics/Point)objects that indicate where the eyes and mouth are located

**Note:** Face detection may not be supported on some devices, so you should check by calling[getMaxNumDetectedFaces()](https://developer.android.com/reference/android/hardware/Camera.Parameters#getMaxNumDetectedFaces())and ensure the return value is greater than zero. Also, some devices may not support identification of eyes and mouth, in which case, those fields in the[Camera.Face](https://developer.android.com/reference/android/hardware/Camera.Face)object will be null.

#### Focus and metering areas

Camera apps can now control the areas that the camera uses for focus and for metering white balance and auto-exposure. Both features use the new[Camera.Area](https://developer.android.com/reference/android/hardware/Camera.Area)class to specify the region of the camera's current view that should be focused or metered. An instance of the[Camera.Area](https://developer.android.com/reference/android/hardware/Camera.Area)class defines the bounds of the area with a[Rect](https://developer.android.com/reference/android/graphics/Rect)and the area's weight---representing the level of importance of that area, relative to other areas in consideration---with an integer.

Before setting either a focus area or metering area, you should first call[getMaxNumFocusAreas()](https://developer.android.com/reference/android/hardware/Camera.Parameters#getMaxNumFocusAreas())or[getMaxNumMeteringAreas()](https://developer.android.com/reference/android/hardware/Camera.Parameters#getMaxNumMeteringAreas()), respectively. If these return zero, then the device does not support the corresponding feature.

To specify the focus or metering areas to use, simply call[setFocusAreas()](https://developer.android.com/reference/android/hardware/Camera.Parameters#setFocusAreas(java.util.List<android.hardware.Camera.Area>))or[setMeteringAreas()](https://developer.android.com/reference/android/hardware/Camera.Parameters#setMeteringAreas(java.util.List<android.hardware.Camera.Area>)). Each take a[List](https://developer.android.com/reference/java/util/List)of[Camera.Area](https://developer.android.com/reference/android/hardware/Camera.Area)objects that indicate the areas to consider for focus or metering. For example, you might implement a feature that allows the user to set the focus area by touching an area of the preview, which you then translate to an[Camera.Area](https://developer.android.com/reference/android/hardware/Camera.Area)object and request that the camera focus on that area of the scene. The focus or exposure in that area will continually update as the scene in the area changes.

#### Continuous auto focus for photos

You can now enable continuous auto focusing (CAF) when taking photos. To enable CAF in your camera app, pass[FOCUS_MODE_CONTINUOUS_PICTURE](https://developer.android.com/reference/android/hardware/Camera.Parameters#FOCUS_MODE_CONTINUOUS_PICTURE)to[setFocusMode()](https://developer.android.com/reference/android/hardware/Camera.Parameters#setFocusMode(java.lang.String)). When ready to capture a photo, call[autoFocus()](https://developer.android.com/reference/android/hardware/Camera#autoFocus(android.hardware.Camera.AutoFocusCallback)). Your[Camera.AutoFocusCallback](https://developer.android.com/reference/android/hardware/Camera.AutoFocusCallback)immediately receives a callback to indicate whether focus was achieved. To resume CAF after receiving the callback, you must call[cancelAutoFocus()](https://developer.android.com/reference/android/hardware/Camera#cancelAutoFocus()).

**Note:** Continuous auto focus is also supported when capturing video, using[FOCUS_MODE_CONTINUOUS_VIDEO](https://developer.android.com/reference/android/hardware/Camera.Parameters#FOCUS_MODE_CONTINUOUS_VIDEO), which was added in API level 9.

#### Other camera features

- While recording video, you can now call[takePicture()](https://developer.android.com/reference/android/hardware/Camera#takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback))to save a photo without interrupting the video session. Before doing so, you should call[isVideoSnapshotSupported()](https://developer.android.com/reference/android/hardware/Camera.Parameters#isVideoSnapshotSupported())to be sure the hardware supports it.
- You can now lock auto exposure and white balance with[setAutoExposureLock()](https://developer.android.com/reference/android/hardware/Camera.Parameters#setAutoExposureLock(boolean))and[setAutoWhiteBalanceLock()](https://developer.android.com/reference/android/hardware/Camera.Parameters#setAutoWhiteBalanceLock(boolean))to prevent these properties from changing.
- You can now call[setDisplayOrientation()](https://developer.android.com/reference/android/hardware/Camera#setDisplayOrientation(int))while the camera preview is running. Previously, you could call this only before beginning the preview, but you can now change the orientation at any time.

#### Camera broadcast intents

- [Camera.ACTION_NEW_PICTURE](https://developer.android.com/reference/android/hardware/Camera#ACTION_NEW_PICTURE): This indicates that the user has captured a new photo. The built-in Camera app invokes this broadcast after a photo is captured and third-party camera apps should also broadcast this intent after capturing a photo.
- [Camera.ACTION_NEW_VIDEO](https://developer.android.com/reference/android/hardware/Camera#ACTION_NEW_VIDEO): This indicates that the user has captured a new video. The built-in Camera app invokes this broadcast after a video is recorded and third-party camera apps should also broadcast this intent after capturing a video.

### Android Beam (NDEF Push with NFC)

Android Beam is a new NFC feature that allows you to send NDEF messages from one device to another (a process also known as "NDEF Push"). The data transfer is initiated when two Android-powered devices that support Android Beam are in close proximity (about 4 cm), usually with their backs touching. The data inside the NDEF message can contain any data that you wish to share between devices. For example, the People app shares contacts, YouTube shares videos, and Browser shares URLs using Android Beam.

To transmit data between devices using Android Beam, you need to create an[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)that contains the information you want to share while your activity is in the foreground. You must then pass the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to the system in one of two ways:

- Define a single[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to push while in the activity:

  Call[setNdefPushMessage()](https://developer.android.com/reference/android/nfc/NfcAdapter#setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...))at any time to set the message you want to send. For instance, you might call this method and pass it your[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)during your activity's[onCreate()](https://developer.android.com/reference/android/app/Activity#onCreate(android.os.Bundle))method. Then, whenever Android Beam is activated with another device while the activity is in the foreground, the system sends the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to the other device.
- Define the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to push at the time that Android Beam is initiated:

  Implement[NfcAdapter.CreateNdefMessageCallback](https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback), in which your implementation of the[createNdefMessage()](https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback#createNdefMessage(android.nfc.NfcEvent))method returns the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)you want to send. Then pass the[NfcAdapter.CreateNdefMessageCallback](https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback)implementation to[setNdefPushMessageCallback()](https://developer.android.com/reference/android/nfc/NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...)).

  In this case, when Android Beam is activated with another device while your activity is in the foreground, the system calls[createNdefMessage()](https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback#createNdefMessage(android.nfc.NfcEvent))to retrieve the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)you want to send. This allows you to define the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to deliver only once Android Beam is initiated, in case the contents of the message might vary throughout the life of the activity.

In case you want to run some specific code once the system has successfully delivered your NDEF message to the other device, you can implement[NfcAdapter.OnNdefPushCompleteCallback](https://developer.android.com/reference/android/nfc/NfcAdapter.OnNdefPushCompleteCallback)and set it with[setNdefPushCompleteCallback()](https://developer.android.com/reference/android/nfc/NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...)). The system will then call[onNdefPushComplete()](https://developer.android.com/reference/android/nfc/NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete(android.nfc.NfcEvent))when the message is delivered.

On the receiving device, the system dispatches NDEF Push messages in a similar way to regular NFC tags. The system invokes an intent with the[ACTION_NDEF_DISCOVERED](https://developer.android.com/reference/android/nfc/NfcAdapter#ACTION_NDEF_DISCOVERED)action to start an activity, with either a URL or a MIME type set according to the first[NdefRecord](https://developer.android.com/reference/android/nfc/NdefRecord)in the[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage). For the activity you want to respond, you can declare intent filters for the URLs or MIME types your app cares about. For more information about Tag Dispatch see the[NFC](https://developer.android.com/guide/topics/connectivity/nfc#dispatch)developer guide.

If you want your[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)to carry a URI, you can now use the convenience method[createUri](https://developer.android.com/reference/android/nfc/NdefRecord#createUri(android.net.Uri))to construct a new[NdefRecord](https://developer.android.com/reference/android/nfc/NdefRecord)based on either a string or a[Uri](https://developer.android.com/reference/android/net/Uri)object. If the URI is a special format that you want your application to also receive during an Android Beam event, you should create an intent filter for your activity using the same URI scheme in order to receive the incoming NDEF message.

You should also pass an "Android application record" with your[NdefMessage](https://developer.android.com/reference/android/nfc/NdefMessage)in order to guarantee that your application handles the incoming NDEF message, even if other applications filter for the same intent action. You can create an Android application record by calling[createApplicationRecord()](https://developer.android.com/reference/android/nfc/NdefRecord#createApplicationRecord(java.lang.String)), passing it your application's package name. When the other device receives the NDEF message with the application record and multiple applications contain activities that handle the specified intent, the system always delivers the message to the activity in your application (based on the matching application record). If the target device does not currently have your application installed, the system uses the Android application record to launch Google Play and take the user to the application in order to install it.

If your application doesn't use NFC APIs to perform NDEF Push messaging, then Android provides a default behavior: When your application is in the foreground on one device and Android Beam is invoked with another Android-powered device, then the other device receives an NDEF message with an Android application record that identifies your application. If the receiving device has the application installed, the system launches it; if it's not installed, Google Play opens and takes the user to your application in order to install it.

You can read more about Android Beam and other NFC features in the[NFC Basics](https://developer.android.com/guide/topics/connectivity/nfc/nfc)developer guide. For some example code using Android Beam, see the[Android Beam Demo](https://developer.android.com/resources/samples/AndroidBeamDemo/src/com/example/android/beam/Beam).

### Wi-Fi P2P

Android now supports Wi-Fi peer-to-peer (P2P) connections between Android-powered devices and other device types (in compliance with the Wi-Fi Alliance's[Wi-Fi Direct™](http://www.wi-fi.org/discover-and-learn/wi-fi-direct)certification program) without a hotspot or Internet connection. The Android framework provides a set of Wi-Fi P2P APIs that allow you to discover and connect to other devices when each device supports Wi-Fi P2P, then communicate over a speedy connection across distances much longer than a Bluetooth connection.

A new package,[android.net.wifi.p2p](https://developer.android.com/reference/android/net/wifi/p2p/package-summary), contains all the APIs for performing peer-to-peer connections with Wi-Fi. The primary class you need to work with is[WifiP2pManager](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager), which you can acquire by calling[getSystemService(WIFI_P2P_SERVICE)](https://developer.android.com/reference/android/content/Context#getSystemService(java.lang.Class<T>)). The[WifiP2pManager](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager)includes APIs that allow you to:

- Initialize your application for P2P connections by calling[initialize()](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener))
- Discover nearby devices by calling[discoverPeers()](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener))
- Start a P2P connection by calling[connect()](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener))
- And more

Several other interfaces and classes are necessary as well, such as:

- The[WifiP2pManager.ActionListener](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.ActionListener)interface allows you to receive callbacks when an operation such as discovering peers or connecting to them succeeds or fails.
- [WifiP2pManager.PeerListListener](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.PeerListListener)interface allows you to receive information about discovered peers. The callback provides a[WifiP2pDeviceList](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pDeviceList), from which you can retrieve a[WifiP2pDevice](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pDevice)object for each device within range and get information such as the device name, address, device type, the WPS configurations the device supports, and more.
- The[WifiP2pManager.GroupInfoListener](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.GroupInfoListener)interface allows you to receive information about a P2P group. The callback provides a[WifiP2pGroup](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pGroup)object, which provides group information such as the owner, the network name, and passphrase.
- [WifiP2pManager.ConnectionInfoListener](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.ConnectionInfoListener)interface allows you to receive information about the current connection. The callback provides a[WifiP2pInfo](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pInfo)object, which has information such as whether a group has been formed and who is the group owner.

In order to use the Wi-Fi P2P APIs, your app must request the following user permissions:

- [ACCESS_WIFI_STATE](https://developer.android.com/reference/android/Manifest.permission#ACCESS_WIFI_STATE)
- [CHANGE_WIFI_STATE](https://developer.android.com/reference/android/Manifest.permission#CHANGE_WIFI_STATE)
- [INTERNET](https://developer.android.com/reference/android/Manifest.permission#INTERNET)(although your app doesn't technically connect to the Internet, communicating to Wi-Fi P2P peers with standard java sockets requires Internet permission).

The Android system also broadcasts several different actions during certain Wi-Fi P2P events:

- [WIFI_P2P_CONNECTION_CHANGED_ACTION](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION): The P2P connection state has changed. This carries[EXTRA_WIFI_P2P_INFO](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#EXTRA_WIFI_P2P_INFO)with a[WifiP2pInfo](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pInfo)object and[EXTRA_NETWORK_INFO](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#EXTRA_NETWORK_INFO)with a[NetworkInfo](https://developer.android.com/reference/android/net/NetworkInfo)object.
- [WIFI_P2P_STATE_CHANGED_ACTION](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION): The P2P state has changed between enabled and disabled. It carries[EXTRA_WIFI_STATE](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#EXTRA_WIFI_STATE)with either[WIFI_P2P_STATE_DISABLED](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_STATE_DISABLED)or[WIFI_P2P_STATE_ENABLED](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_STATE_ENABLED)
- [WIFI_P2P_PEERS_CHANGED_ACTION](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION): The list of peer devices has changed.
- [WIFI_P2P_THIS_DEVICE_CHANGED_ACTION](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION): The details for this device have changed.

See the[WifiP2pManager](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager)documentation for more information. Also look at the[Wi-Fi P2P Demo](https://android.googlesource.com/platform/development/+/master/samples/WiFiDirectDemo/)sample application.

### Bluetooth Health Devices

Android now supports Bluetooth Health Profile devices, so you can create applications that use Bluetooth to communicate with health devices that support Bluetooth, such as heart-rate monitors, blood meters, thermometers, and scales.

Similar to regular headset and A2DP profile devices, you must call[getProfileProxy()](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int))with a[BluetoothProfile.ServiceListener](https://developer.android.com/reference/android/bluetooth/BluetoothProfile.ServiceListener)and the[HEALTH](https://developer.android.com/reference/android/bluetooth/BluetoothProfile#HEALTH)profile type to establish a connection with the profile proxy object.

Once you've acquired the Health Profile proxy (the[BluetoothHealth](https://developer.android.com/reference/android/bluetooth/BluetoothHealth)object), connecting to and communicating with paired health devices involves the following new Bluetooth classes:

- [BluetoothHealthCallback](https://developer.android.com/reference/android/bluetooth/BluetoothHealthCallback): You must extend this class and implement the callback methods to receive updates about changes in the application's registration state and Bluetooth channel state.
- [BluetoothHealthAppConfiguration](https://developer.android.com/reference/android/bluetooth/BluetoothHealthAppConfiguration): During callbacks to your[BluetoothHealthCallback](https://developer.android.com/reference/android/bluetooth/BluetoothHealthCallback), you'll receive an instance of this object, which provides configuration information about the available Bluetooth health device, which you must use to perform various operations such as initiate and terminate connections with the[BluetoothHealth](https://developer.android.com/reference/android/bluetooth/BluetoothHealth)APIs.

For more information about using the Bluetooth Health Profile, see the documentation for[BluetoothHealth](https://developer.android.com/reference/android/bluetooth/BluetoothHealth).

### Accessibility

Android 4.0 improves accessibility for sight-impaired users with new explore-by-touch mode and extended APIs that allow you to provide more information about view content or develop advanced accessibility services.

#### Explore-by-touch mode

Users with vision loss can now explore the screen by touching and dragging a finger across the screen to hear voice descriptions of the content. Because the explore-by-touch mode works like a virtual cursor, it allows screen readers to identify the descriptive text the same way that screen readers can when the user navigates with a d-pad or trackball---by reading information provided by[android:contentDescription](https://developer.android.com/reference/android/R.attr#contentDescription)and[setContentDescription()](https://developer.android.com/reference/android/view/View#setContentDescription(java.lang.CharSequence))upon a simulated "hover" event. So, consider this is a reminder that you should provide descriptive text for the views in your application, especially for[ImageButton](https://developer.android.com/reference/android/widget/ImageButton),[EditText](https://developer.android.com/reference/android/widget/EditText),[ImageView](https://developer.android.com/reference/android/widget/ImageView)and other widgets that might not naturally contain descriptive text.

#### Accessibility for views

To enhance the information available to accessibility services such as screen readers, you can implement new callback methods for accessibility events in your custom[View](https://developer.android.com/reference/android/view/View)components.

It's important to first note that the behavior of the[sendAccessibilityEvent()](https://developer.android.com/reference/android/view/View#sendAccessibilityEvent(int))method has changed in Android 4.0. As with previous version of Android, when the user enables accessibility services on the device and an input event such as a click or hover occurs, the respective view is notified with a call to[sendAccessibilityEvent()](https://developer.android.com/reference/android/view/View#sendAccessibilityEvent(int)). Previously, the implementation of[sendAccessibilityEvent()](https://developer.android.com/reference/android/view/View#sendAccessibilityEvent(int))would initialize an[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent)and send it to[AccessibilityManager](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager). The new behavior involves some additional callback methods that allow the view and its parents to add more contextual information to the event:

1. When invoked, the[sendAccessibilityEvent()](https://developer.android.com/reference/android/view/View#sendAccessibilityEvent(int))and[sendAccessibilityEventUnchecked()](https://developer.android.com/reference/android/view/View#sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent))methods defer to[onInitializeAccessibilityEvent()](https://developer.android.com/reference/android/view/View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)).

   Custom implementations of[View](https://developer.android.com/reference/android/view/View)might want to implement[onInitializeAccessibilityEvent()](https://developer.android.com/reference/android/view/View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent))to attach additional accessibility information to the[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent), but should also call the super implementation to provide default information such as the standard content description, item index, and more. However, you should not add additional text content in this callback---that happens next.
2. Once initialized, if the event is one of several types that should be populated with text information, the view then receives a call to[dispatchPopulateAccessibilityEvent()](https://developer.android.com/reference/android/view/View#dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent)), which defers to the[onPopulateAccessibilityEvent()](https://developer.android.com/reference/android/view/View#onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent))callback.

   Custom implementations of[View](https://developer.android.com/reference/android/view/View)should usually implement[onPopulateAccessibilityEvent()](https://developer.android.com/reference/android/view/View#onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent))to add additional text content to the[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent)if the[android:contentDescription](https://developer.android.com/reference/android/R.attr#contentDescription)text is missing or insufficient. To add more text description to the[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent), call[getText()](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord#getText()).[add()](https://developer.android.com/reference/java/util/List#add(E)).
3. At this point, the[View](https://developer.android.com/reference/android/view/View)passes the event up the view hierarchy by calling[requestSendAccessibilityEvent()](https://developer.android.com/reference/android/view/ViewGroup#requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent))on the parent view. Each parent view then has the chance to augment the accessibility information by adding an[AccessibilityRecord](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord), until it ultimately reaches the root view, which sends the event to the[AccessibilityManager](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager)with[sendAccessibilityEvent()](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager#sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent)).

In addition to the new methods above, which are useful when extending the[View](https://developer.android.com/reference/android/view/View)class, you can also intercept these event callbacks on any[View](https://developer.android.com/reference/android/view/View)by extending[AccessibilityDelegate](https://developer.android.com/reference/android/view/View.AccessibilityDelegate)and setting it on the view with[setAccessibilityDelegate()](https://developer.android.com/reference/android/view/View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)). When you do, each accessibility method in the view defers the call to the corresponding method in the delegate. For example, when the view receives a call to[onPopulateAccessibilityEvent()](https://developer.android.com/reference/android/view/View#onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent)), it passes it to the same method in the[View.AccessibilityDelegate](https://developer.android.com/reference/android/view/View.AccessibilityDelegate). Any methods not handled by the delegate are given right back to the view for default behavior. This allows you to override only the methods necessary for any given view without extending the[View](https://developer.android.com/reference/android/view/View)class.

If you want to maintain compatibility with Android versions prior to 4.0, while also supporting the new the accessibility APIs, you can do so with the latest version of the*v4 support library* (in[Compatibility Package, r4](https://developer.android.com/tools/support-library)) using a set of utility classes that provide the new accessibility APIs in a backward-compatible design.

#### Accessibility services

If you're developing an accessibility service, the information about various accessibility events has been significantly expanded to enable more advanced accessibility feedback for users. In particular, events are generated based on view composition, providing better context information and allowing accessibility services to traverse view hierarchies to get additional view information and deal with special cases.

If you're developing an accessibility service (such as a screen reader), you can access additional content information and traverse view hierarchies with the following procedure:

1. Upon receiving an[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent)from an application, call the[AccessibilityEvent.getRecord()](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent#getRecord(int))to retrieve a specific[AccessibilityRecord](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord)(there may be several records attached to the event).
2. From either[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent)or an individual[AccessibilityRecord](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord), you can call[getSource()](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord#getSource())to retrieve a[AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo)object.

   An[AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo)represents a single node of the window content in a format that allows you to query accessibility information about that node. The[AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo)object returned from[AccessibilityEvent](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent)describes the event source, whereas the source from an[AccessibilityRecord](https://developer.android.com/reference/android/view/accessibility/AccessibilityRecord)describes the predecessor of the event source.
3. With the[AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo), you can query information about it, call[getParent()](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#getParent())or[getChild()](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#getChild(int))to traverse the view hierarchy, and even add child views to the node.

In order for your application to publish itself to the system as an accessibility service, it must declare an XML configuration file that corresponds to[AccessibilityServiceInfo](https://developer.android.com/reference/android/accessibilityservice/AccessibilityServiceInfo). For more information about creating an accessibility service, see[AccessibilityService](https://developer.android.com/reference/android/accessibilityservice/AccessibilityService)and[SERVICE_META_DATA](https://developer.android.com/reference/android/accessibilityservice/AccessibilityService#SERVICE_META_DATA)for information about the XML configuration.

#### Other accessibility APIs

If you're interested in the device's accessibility state, the[AccessibilityManager](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager)has some new APIs such as:

- [AccessibilityManager.AccessibilityStateChangeListener](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager.AccessibilityStateChangeListener)is an interface that allows you to receive a callback whenever accessibility is enabled or disabled.
- [getEnabledAccessibilityServiceList()](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager#getEnabledAccessibilityServiceList(int))provides information about which accessibility services are currently enabled.
- [isTouchExplorationEnabled()](https://developer.android.com/reference/android/view/accessibility/AccessibilityManager#isTouchExplorationEnabled())tells you whether the explore-by-touch mode is enabled.

### Spell Checker Services

A new spell checker framework allows apps to create spell checkers in a manner similar to the input method framework (for IMEs). To create a new spell checker, you must implement a service that extends[SpellCheckerService](https://developer.android.com/reference/android/service/textservice/SpellCheckerService)and extend the[SpellCheckerService.Session](https://developer.android.com/reference/android/service/textservice/SpellCheckerService.Session)class to provide spelling suggestions based on text provided by the interface's callback methods. In the[SpellCheckerService.Session](https://developer.android.com/reference/android/service/textservice/SpellCheckerService.Session)callback methods, you must return the spelling suggestions as[SuggestionsInfo](https://developer.android.com/reference/android/view/textservice/SuggestionsInfo)objects.

Applications with a spell checker service must declare the[BIND_TEXT_SERVICE](https://developer.android.com/reference/android/Manifest.permission#BIND_TEXT_SERVICE)permission as required by the service. The service must also declare an intent filter with`<action
android:name="android.service.textservice.SpellCheckerService" />`as the intent's action and should include a`<meta-data>`element that declares configuration information for the spell checker.

See the sample[Spell Checker Service](https://developer.android.com/resources/samples/SpellChecker/SampleSpellCheckerService)app and sample[Spell Checker Client](https://developer.android.com/resources/samples/SpellChecker/HelloSpellChecker)app for example code.

### Text-to-speech Engines

Android's text-to-speech (TTS) APIs have been significantly extended to allow applications to more easily implement custom TTS engines, while applications that want to use a TTS engine have a couple new APIs for selecting an engine.

#### Using text-to-speech engines

In previous versions of Android, you could use the[TextToSpeech](https://developer.android.com/reference/android/speech/tts/TextToSpeech)class to perform text-to-speech (TTS) operations using the TTS engine provided by the system or set a custom engine using[setEngineByPackageName()](https://developer.android.com/reference/android/speech/tts/TextToSpeech#setEngineByPackageName(java.lang.String)). In Android 4.0, the[setEngineByPackageName()](https://developer.android.com/reference/android/speech/tts/TextToSpeech#setEngineByPackageName(java.lang.String))method has been deprecated and you can now specify the engine to use with a new[TextToSpeech](https://developer.android.com/reference/android/speech/tts/TextToSpeech)constructor that accepts the package name of a TTS engine.

You can also query the available TTS engines with[getEngines()](https://developer.android.com/reference/android/speech/tts/TextToSpeech#getEngines()). This method returns a list of[TextToSpeech.EngineInfo](https://developer.android.com/reference/android/speech/tts/TextToSpeech.EngineInfo)objects, which include meta data such as the engine's icon, label, and package name.

#### Building text-to-speech engines

Previously, custom engines required that the engine be built using an undocumented native header file. In Android 4.0, there is a complete set of framework APIs for building TTS engines.

The basic setup requires an implementation of[TextToSpeechService](https://developer.android.com/reference/android/speech/tts/TextToSpeechService)that responds to the[INTENT_ACTION_TTS_SERVICE](https://developer.android.com/reference/android/speech/tts/TextToSpeech.Engine#INTENT_ACTION_TTS_SERVICE)intent. The primary work for a TTS engine happens during the[onSynthesizeText()](https://developer.android.com/reference/android/speech/tts/TextToSpeechService#onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback))callback in a service that extends[TextToSpeechService](https://developer.android.com/reference/android/speech/tts/TextToSpeechService). The system delivers this method two objects:

- [SynthesisRequest](https://developer.android.com/reference/android/speech/tts/SynthesisRequest): This contains various data including the text to synthesize, the locale, the speech rate, and voice pitch.
- [SynthesisCallback](https://developer.android.com/reference/android/speech/tts/SynthesisCallback): This is the interface by which your TTS engine delivers the resulting speech data as streaming audio. First the engine must call[start()](https://developer.android.com/reference/android/speech/tts/SynthesisCallback#start(int, int, int))to indicate that the engine is ready to deliver the audio, then call[audioAvailable()](https://developer.android.com/reference/android/speech/tts/SynthesisCallback#audioAvailable(byte[], int, int)), passing it the audio data in a byte buffer. Once your engine has passed all audio through the buffer, call[done()](https://developer.android.com/reference/android/speech/tts/SynthesisCallback#done()).

Now that the framework supports a true API for creating TTS engines, support for the native code implementation has been removed. Look for a blog post about a compatibility layer that you can use to convert your old TTS engines to the new framework.

For an example TTS engine using the new APIs, see the[Text To Speech Engine](https://developer.android.com/resources/samples/TtsEngine)sample app.

### Network Usage

Android 4.0 gives users precise visibility of how much network data their applications are using. The Settings app provides controls that allow users to manage set limits for network data usage and even disable the use of background data for individual apps. In order to avoid users disabling your app's access to data from the background, you should develop strategies to use the data connection efficiently and adjust your usage depending on the type of connection available.

If your application performs a lot of network transactions, you should provide user settings that allow users to control your app's data habits, such as how often your app syncs data, whether to perform uploads/downloads only when on Wi-Fi, whether to use data while roaming, etc. With these controls available to them, users are much less likely to disable your app's access to data when they approach their limits, because they can instead precisely control how much data your app uses. If you provide a preference activity with these settings, you should include in its manifest declaration an intent filter for the[ACTION_MANAGE_NETWORK_USAGE](https://developer.android.com/reference/android/content/Intent#ACTION_MANAGE_NETWORK_USAGE)action. For example:  

```transact-sql
<activity android:name="DataPreferences" android:label="@string/title_preferences">
    <intent-filter>
       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
```

This intent filter indicates to the system that this is the activity that controls your application's data usage. Thus, when the user inspects how much data your app is using from the Settings app, a "View application settings" button is available that launches your preference activity so the user can refine how much data your app uses.

Also beware that[getBackgroundDataSetting()](https://developer.android.com/reference/android/net/ConnectivityManager#getBackgroundDataSetting())is now deprecated and always returns true---use[getActiveNetworkInfo()](https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetworkInfo())instead. Before you attempt any network transactions, you should always call[getActiveNetworkInfo()](https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetworkInfo())to get the[NetworkInfo](https://developer.android.com/reference/android/net/NetworkInfo)that represents the current network and query[isConnected()](https://developer.android.com/reference/android/net/NetworkInfo#isConnected())to check whether the device has a connection. You can then check other connection properties, such as whether the device is roaming or connected to Wi-Fi.

### Enterprise

Android 4.0 expands the capabilities for enterprise application with the following features.

#### VPN services

The new[VpnService](https://developer.android.com/reference/android/net/VpnService)allows applications to build their own VPN (Virtual Private Network), running as a[Service](https://developer.android.com/reference/android/app/Service). A VPN service creates an interface for a virtual network with its own address and routing rules and performs all reading and writing with a file descriptor.

To create a VPN service, use[VpnService.Builder](https://developer.android.com/reference/android/net/VpnService.Builder), which allows you to specify the network address, DNS server, network route, and more. When complete, you can establish the interface by calling[establish()](https://developer.android.com/reference/android/net/VpnService.Builder#establish()), which returns a[ParcelFileDescriptor](https://developer.android.com/reference/android/os/ParcelFileDescriptor).

Because a VPN service can intercept packets, there are security implications. As such, if you implement[VpnService](https://developer.android.com/reference/android/net/VpnService), then your service must require the[BIND_VPN_SERVICE](https://developer.android.com/reference/android/Manifest.permission#BIND_VPN_SERVICE)to ensure that only the system can bind to it (only the system is granted this permission---apps cannot request it). To then use your VPN service, users must manually enable it in the system settings.

#### Device policies

Applications that manage the device restrictions can now disable the camera using[setCameraDisabled()](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean))and the[USES_POLICY_DISABLE_CAMERA](https://developer.android.com/reference/android/app/admin/DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA)property (applied with a`<disable-camera />`element in the policy configuration file).

#### Certificate management

The new[KeyChain](https://developer.android.com/reference/android/security/KeyChain)class provides APIs that allow you to import and access certificates in the system key store. Certificates streamline the installation of both client certificates (to validate the identity of the user) and certificate authority certificates (to verify server identity). Applications such as web browsers or email clients can access the installed certificates to authenticate users to servers. See the[KeyChain](https://developer.android.com/reference/android/security/KeyChain)documentation for more information.

### Device Sensors

Two new sensor types have been added in Android 4.0:

- [TYPE_AMBIENT_TEMPERATURE](https://developer.android.com/reference/android/hardware/Sensor#TYPE_AMBIENT_TEMPERATURE): A temperature sensor that provides the ambient (room) temperature in degrees Celsius.
- [TYPE_RELATIVE_HUMIDITY](https://developer.android.com/reference/android/hardware/Sensor#TYPE_RELATIVE_HUMIDITY): A humidity sensor that provides the relative ambient (room) humidity as a percentage.

If a device has both[TYPE_AMBIENT_TEMPERATURE](https://developer.android.com/reference/android/hardware/Sensor#TYPE_AMBIENT_TEMPERATURE)and[TYPE_RELATIVE_HUMIDITY](https://developer.android.com/reference/android/hardware/Sensor#TYPE_RELATIVE_HUMIDITY)sensors, you can use them to calculate the dew point and the absolute humidity.

The previous temperature sensor,[TYPE_TEMPERATURE](https://developer.android.com/reference/android/hardware/Sensor#TYPE_TEMPERATURE), has been deprecated. You should use the[TYPE_AMBIENT_TEMPERATURE](https://developer.android.com/reference/android/hardware/Sensor#TYPE_AMBIENT_TEMPERATURE)sensor instead.

Additionally, Android's three synthetic sensors have been greatly improved so they now have lower latency and smoother output. These sensors include the gravity sensor ([TYPE_GRAVITY](https://developer.android.com/reference/android/hardware/Sensor#TYPE_GRAVITY)), rotation vector sensor ([TYPE_ROTATION_VECTOR](https://developer.android.com/reference/android/hardware/Sensor#TYPE_ROTATION_VECTOR)), and linear acceleration sensor ([TYPE_LINEAR_ACCELERATION](https://developer.android.com/reference/android/hardware/Sensor#TYPE_LINEAR_ACCELERATION)). The improved sensors rely on the gyroscope sensor to improve their output, so the sensors appear only on devices that have a gyroscope.

### Action Bar

The[ActionBar](https://developer.android.com/reference/android/app/ActionBar)has been updated to support several new behaviors. Most importantly, the system gracefully manages the action bar's size and configuration when running on smaller screens in order to provide an optimal user experience on all screen sizes. For example, when the screen is narrow (such as when a handset is in portrait orientation), the action bar's navigation tabs appear in a "stacked bar," which appears directly below the main action bar. You can also opt-in to a "split action bar," which places all action items in a separate bar at the bottom of the screen when the screen is narrow.

#### Split action bar

If your action bar includes several action items, not all of them will fit into the action bar on a narrow screen, so the system will place more of them into the overflow menu. However, Android 4.0 allows you to enable "split action bar" so that more action items can appear on the screen in a separate bar at the bottom of the screen. To enable split action bar, add[android:uiOptions](https://developer.android.com/reference/android/R.attr#uiOptions)with`"splitActionBarWhenNarrow"`to either your[`<application>`](https://developer.android.com/guide/topics/manifest/application-element)tag or individual[`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element)tags in your manifest file. When enabled, the system will add an additional bar at the bottom of the screen for all action items when the screen is narrow (no action items will appear in the primary action bar).

If you want to use the navigation tabs provided by the[ActionBar.Tab](https://developer.android.com/reference/android/app/ActionBar.Tab)APIs, but don't need the main action bar on top (you want only the tabs to appear at the top), then enable the split action bar as described above and also call[setDisplayShowHomeEnabled(false)](https://developer.android.com/reference/android/app/ActionBar#setDisplayShowHomeEnabled(boolean))to disable the application icon in the action bar. With nothing left in the main action bar, it disappears---all that's left are the navigation tabs at the top and the action items at the bottom of the screen.

#### Action bar styles

If you want to apply custom styling to the action bar, you can use new style properties[backgroundStacked](https://developer.android.com/reference/android/R.attr#backgroundStacked)and[backgroundSplit](https://developer.android.com/reference/android/R.attr#backgroundSplit)to apply a background drawable or color to the stacked bar and split bar, respectively. You can also set these styles at runtime with[setStackedBackgroundDrawable()](https://developer.android.com/reference/android/app/ActionBar#setStackedBackgroundDrawable(android.graphics.drawable.Drawable))and[setSplitBackgroundDrawable()](https://developer.android.com/reference/android/app/ActionBar#setSplitBackgroundDrawable(android.graphics.drawable.Drawable)).

#### Action provider

The new[ActionProvider](https://developer.android.com/reference/android/view/ActionProvider)class allows you to create a specialized handler for action items. An action provider can define an action view, a default action behavior, and a submenu for each action item to which it is associated. When you want to create an action item that has dynamic behaviors (such as a variable action view, default action, or submenu), extending[ActionProvider](https://developer.android.com/reference/android/view/ActionProvider)is a good solution in order to create a reusable component, rather than handling the various action item transformations in your fragment or activity.

For example, the[ShareActionProvider](https://developer.android.com/reference/android/widget/ShareActionProvider)is an extension of[ActionProvider](https://developer.android.com/reference/android/view/ActionProvider)that facilitates a "share" action from the action bar. Instead of using traditional action item that invokes the[ACTION_SEND](https://developer.android.com/reference/android/content/Intent#ACTION_SEND)intent, you can use this action provider to present an action view with a drop-down list of applications that handle the[ACTION_SEND](https://developer.android.com/reference/android/content/Intent#ACTION_SEND)intent. When the user selects an application to use for the action,[ShareActionProvider](https://developer.android.com/reference/android/widget/ShareActionProvider)remembers that selection and provides it in the action view for faster access to sharing with that app.

To declare an action provider for an action item, include the`android:actionProviderClass`attribute in the[`<item>`](https://developer.android.com/guide/topics/resources/menu-resource#item-element)element for your activity's options menu, with the class name of the action provider as the value. For example:  

```scdoc
<item android:id="@+id/menu_share"
      android:title="Share"
      android:showAsAction="ifRoom"
      android:actionProviderClass="android.widget.ShareActionProvider" />
```

In your activity's[onCreateOptionsMenu()](https://developer.android.com/reference/android/app/Activity#onCreateOptionsMenu(android.view.Menu))callback method, retrieve an instance of the action provider from the menu item and set the intent:  

### Kotlin

```kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options, menu)
    val shareActionProvider = menu.findItem(R.id.menu_share)?.actionProvider as? ShareActionProvider
    // Set the share intent of the share action provider.
    shareActionProvider?.setShareIntent(createShareIntent())
    ...
    return super.onCreateOptionsMenu(menu)
}
```

### Java

```java
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    ShareActionProvider shareActionProvider =
          (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
    // Set the share intent of the share action provider.
    shareActionProvider.setShareIntent(createShareIntent());
    ...
    return super.onCreateOptionsMenu(menu);
}
```

For an example using the[ShareActionProvider](https://developer.android.com/reference/android/widget/ShareActionProvider), see[ActionBarShareActionProviderActivity](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/ActionBarShareActionProviderActivity)in ApiDemos.

#### Collapsible action views

Action items that provide an action view can now toggle between their action view state and traditional action item state. Previously only the[SearchView](https://developer.android.com/reference/android/widget/SearchView)supported collapsing when used as an action view, but now you can add an action view for any action item and switch between the expanded state (action view is visible) and collapsed state (action item is visible).

To declare that an action item that contains an action view be collapsible, include the`"collapseActionView"`flag in the`android:showAsAction`attribute for the[`<item>`](https://developer.android.com/guide/topics/resources/menu-resource#item-element)element in the menu's XML file.

To receive callbacks when an action view switches between expanded and collapsed, register an instance of[MenuItem.OnActionExpandListener](https://developer.android.com/reference/android/view/MenuItem.OnActionExpandListener)with the respective[MenuItem](https://developer.android.com/reference/android/view/MenuItem)by calling[setOnActionExpandListener()](https://developer.android.com/reference/android/view/MenuItem#setOnActionExpandListener(android.view.MenuItem.OnActionExpandListener)). Typically, you should do so during the[onCreateOptionsMenu()](https://developer.android.com/reference/android/app/Activity#onCreateOptionsMenu(android.view.Menu))callback.

To control a collapsible action view, you can call[collapseActionView()](https://developer.android.com/reference/android/view/MenuItem#collapseActionView())and[expandActionView()](https://developer.android.com/reference/android/view/MenuItem#expandActionView())on the respective[MenuItem](https://developer.android.com/reference/android/view/MenuItem).

When creating a custom action view, you can also implement the new[CollapsibleActionView](https://developer.android.com/reference/android/view/CollapsibleActionView)interface to receive callbacks when the view is expanded and collapsed.

#### Other APIs for action bar

- [setHomeButtonEnabled()](https://developer.android.com/reference/android/app/ActionBar#setHomeButtonEnabled(boolean))allows you to specify whether the icon/logo behaves as a button to navigate home or "up" (pass "true" to make it behave as a button).
- [setIcon()](https://developer.android.com/reference/android/app/ActionBar#setIcon(android.graphics.drawable.Drawable))and[setLogo()](https://developer.android.com/reference/android/app/ActionBar#setLogo(android.graphics.drawable.Drawable))allow you to define the action bar icon or logo at runtime.
- [Fragment.setMenuVisibility()](https://developer.android.com/reference/android/app/Fragment#setMenuVisibility(boolean))allows you to enable or disable the visibility of the options menu items declared by the fragment. This is useful if the fragment has been added to the activity, but is not visible, so the menu items should be hidden.
- [FragmentManager.invalidateOptionsMenu()](https://developer.android.com/reference/android/app/FragmentManager#invalidateOptionsMenu())allows you to invalidate the activity options menu during various states of the fragment lifecycle in which using the equivalent method from[Activity](https://developer.android.com/reference/android/app/Activity)might not be available.

### User Interface and Views

Android 4.0 introduces a variety of new views and other UI components.

#### GridLayout

[GridLayout](https://developer.android.com/reference/android/widget/GridLayout)is a new view group that places child views in a rectangular grid. Unlike[TableLayout](https://developer.android.com/reference/android/widget/TableLayout),[GridLayout](https://developer.android.com/reference/android/widget/GridLayout)relies on a flat hierarchy and does not make use of intermediate views such as table rows for providing structure. Instead, children specify which row(s) and column(s) they should occupy (cells can span multiple rows and/or columns), and by default are laid out sequentially across the grid's rows and columns. The[GridLayout](https://developer.android.com/reference/android/widget/GridLayout)orientation determines whether sequential children are by default laid out horizontally or vertically. Space between children may be specified either by using instances of the new[Space](https://developer.android.com/reference/android/widget/Space)view or by setting the relevant margin parameters on children.

See[ApiDemos](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view)for samples using[GridLayout](https://developer.android.com/reference/android/widget/GridLayout).

#### TextureView

[TextureView](https://developer.android.com/reference/android/view/TextureView)is a new view that allows you to display a content stream, such as a video or an OpenGL scene. Although similar to[SurfaceView](https://developer.android.com/reference/android/view/SurfaceView),[TextureView](https://developer.android.com/reference/android/view/TextureView)is unique in that it behaves like a regular view, rather than creating a separate window, so you can treat it like any other[View](https://developer.android.com/reference/android/view/View)object. For example, you can apply transforms, animate it using[ViewPropertyAnimator](https://developer.android.com/reference/android/view/ViewPropertyAnimator), or adjust its opacity with[setAlpha()](https://developer.android.com/reference/android/view/View#setAlpha(float)).

Beware that[TextureView](https://developer.android.com/reference/android/view/TextureView)works only within a hardware accelerated window.

For more information, see the[TextureView](https://developer.android.com/reference/android/view/TextureView)documentation.

#### Switch widget

The new[Switch](https://developer.android.com/reference/android/widget/Switch)widget is a two-state toggle that users can drag to one side or the other (or simply tap) to toggle an option between two states.

You can use the`android:textOn`and`android:textOff`attributes to specify the text to appear on the switch when in the on and off setting. The`android:text`attribute also allows you to place a label alongside the switch.

For a sample using switches, see the[switches.xml](https://developer.android.com/resources/samples/ApiDemos/res/layout/switches)layout file and respective[Switches](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/Switches)activity.

#### Popup menus

Android 3.0 introduced[PopupMenu](https://developer.android.com/reference/android/widget/PopupMenu)to create short contextual menus that pop up at an anchor point you specify (usually at the point of the item selected). Android 4.0 extends the[PopupMenu](https://developer.android.com/reference/android/widget/PopupMenu)with a couple useful features:

- You can now easily inflate the contents of a popup menu from an XML[menu resource](https://developer.android.com/guide/topics/resources/menu-resource)with[inflate()](https://developer.android.com/reference/android/widget/PopupMenu#inflate(int)), passing it the menu resource ID.
- You can also now create a[PopupMenu.OnDismissListener](https://developer.android.com/reference/android/widget/PopupMenu.OnDismissListener)that receives a callback when the menu is dismissed.

#### Preferences

A new[TwoStatePreference](https://developer.android.com/reference/android/preference/TwoStatePreference)abstract class serves as the basis for preferences that provide a two-state selection option. The new[SwitchPreference](https://developer.android.com/reference/android/preference/SwitchPreference)is an extension of[TwoStatePreference](https://developer.android.com/reference/android/preference/TwoStatePreference)that provides a[Switch](https://developer.android.com/reference/android/widget/Switch)widget in the preference view to allow users to toggle a setting on or off without the need to open an additional preference screen or dialog. For example, the Settings application uses a[SwitchPreference](https://developer.android.com/reference/android/preference/SwitchPreference)for the Wi-Fi and Bluetooth settings.

#### System themes

The default theme for all applications that target Android 4.0 (by setting either[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)or[`minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)to`"14"`or higher) is now the "device default" theme:[Theme.DeviceDefault](https://developer.android.com/reference/android/R.style#Theme_DeviceDefault). This may be the dark Holo theme or a different dark theme defined by the specific device.

The[Theme.Holo](https://developer.android.com/reference/android/R.style#Theme_Holo)family of themes are guaranteed to not change from one device to another when running the same version of Android. If you explicitly apply any of the[Theme.Holo](https://developer.android.com/reference/android/R.style#Theme_Holo)themes to your activities, you can rest assured that these themes will not change character on different devices within the same platform version.

If you wish for your app to blend in with the overall device theme (such as when different OEMs provide different default themes for the system), you should explicitly apply themes from the[Theme.DeviceDefault](https://developer.android.com/reference/android/R.style#Theme_DeviceDefault)family.

#### Options menu button

Beginning with Android 4.0, you'll notice that handsets no longer require a Menu hardware button. However, there's no need for you to worry about this if your existing application provides an[options menu](https://developer.android.com/guide/topics/ui/menus#options-menu)and expects there to be a Menu button. To ensure that existing apps continue to work as they expect, the system provides an on-screen Menu button for apps that were designed for older versions of Android.

For the best user experience, new and updated apps should instead use the[ActionBar](https://developer.android.com/reference/android/app/ActionBar)to provide access to menu items and set[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)to`"14"`to take advantage of the latest framework default behaviors.

#### Controls for system UI visibility

Since the early days of Android, the system has managed a UI component known as the*status bar* , which resides at the top of handset devices to deliver information such as the carrier signal, time, notifications, and so on. Android 3.0 added the*system bar* for tablet devices, which resides at the bottom of the screen to provide system navigation controls (Home, Back, and so forth) and also an interface for elements traditionally provided by the status bar. In Android 4.0, the system provides a new type of system UI called the*navigation bar*. You might consider the navigation bar a re-tuned version of the system bar designed for handsets---it provides navigation controls for devices that don't have hardware counterparts for navigating the system, but it leaves out the system bar's notification UI and setting controls. As such, a device that provides the navigation bar also has the status bar at the top.

To this day, you can hide the status bar on handsets using the[FLAG_FULLSCREEN](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_FULLSCREEN)flag. In Android 4.0, the APIs that control the system bar's visibility have been updated to better reflect the behavior of both the system bar and navigation bar:

- The[SYSTEM_UI_FLAG_LOW_PROFILE](https://developer.android.com/reference/android/view/View#SYSTEM_UI_FLAG_LOW_PROFILE)flag replaces the`STATUS_BAR_HIDDEN`flag. When set, this flag enables "low profile" mode for the system bar or navigation bar. Navigation buttons dim and other elements in the system bar also hide. Enabling this is useful for creating more immersive games without distraction for the system navigation buttons.
- The[SYSTEM_UI_FLAG_VISIBLE](https://developer.android.com/reference/android/view/View#SYSTEM_UI_FLAG_VISIBLE)flag replaces the`STATUS_BAR_VISIBLE`flag to request the system bar or navigation bar be visible.
- The[SYSTEM_UI_FLAG_HIDE_NAVIGATION](https://developer.android.com/reference/android/view/View#SYSTEM_UI_FLAG_HIDE_NAVIGATION)is a new flag that requests the navigation bar hide completely. Be aware that this works only for the*navigation bar* used by some handsets (it does**not**hide the system bar on tablets). The navigation bar returns to view as soon as the system receives user input. As such, this mode is useful primarily for video playback or other cases in which the whole screen is needed but user input is not required.

You can set each of these flags for the system bar and navigation bar by calling[setSystemUiVisibility()](https://developer.android.com/reference/android/view/View#setSystemUiVisibility(int))on any view in your activity. The window manager combines (OR-together) all flags from all views in your window and apply them to the system UI as long as your window has input focus. When your window loses input focus (the user navigates away from your app, or a dialog appears), your flags cease to have effect. Similarly, if you remove those views from the view hierarchy their flags no longer apply.

To synchronize other events in your activity with visibility changes to the system UI (for example, hide the action bar or other UI controls when the system UI hides), you should register a[View.OnSystemUiVisibilityChangeListener](https://developer.android.com/reference/android/view/View.OnSystemUiVisibilityChangeListener)to be notified when the visibility of the system bar or navigation bar changes.

See the[OverscanActivity](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/OverscanActivity)class for a demonstration of different system UI options.

### Input Framework

Android 4.0 adds support for cursor hover events and new stylus and mouse button events.

#### Hover events

The[View](https://developer.android.com/reference/android/view/View)class now supports "hover" events to enable richer interactions through the use of pointer devices (such as a mouse or other devices that drive an on-screen cursor).

To receive hover events on a view, implement the[View.OnHoverListener](https://developer.android.com/reference/android/view/View.OnHoverListener)and register it with[setOnHoverListener()](https://developer.android.com/reference/android/view/View#setOnHoverListener(android.view.View.OnHoverListener)). When a hover event occurs on the view, your listener receives a call to[onHover()](https://developer.android.com/reference/android/view/View.OnHoverListener#onHover(android.view.View, android.view.MotionEvent)), providing the[View](https://developer.android.com/reference/android/view/View)that received the event and a[MotionEvent](https://developer.android.com/reference/android/view/MotionEvent)that describes the type of hover event that occurred. The hover event can be one of the following:

- [ACTION_HOVER_ENTER](https://developer.android.com/reference/android/view/MotionEvent#ACTION_HOVER_ENTER)
- [ACTION_HOVER_EXIT](https://developer.android.com/reference/android/view/MotionEvent#ACTION_HOVER_EXIT)
- [ACTION_HOVER_MOVE](https://developer.android.com/reference/android/view/MotionEvent#ACTION_HOVER_MOVE)

Your[View.OnHoverListener](https://developer.android.com/reference/android/view/View.OnHoverListener)should return true from[onHover()](https://developer.android.com/reference/android/view/View.OnHoverListener#onHover(android.view.View, android.view.MotionEvent))if it handles the hover event. If your listener returns false, then the hover event will be dispatched to the parent view as usual.

If your application uses buttons or other widgets that change their appearance based on the current state, you can now use the`android:state_hovered`attribute in a[state list drawable](https://developer.android.com/guide/topics/resources/drawable-resource#StateList)to provide a different background drawable when a cursor hovers over the view.

For a demonstration of the new hover events, see the[Hover](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/Hover)class in ApiDemos.

#### Stylus and mouse button events

Android now provides APIs for receiving input from a stylus input device such as a digitizer tablet peripheral or a stylus-enabled touch screen.

Stylus input operates in a similar manner to touch or mouse input. When the stylus is in contact with the digitizer, applications receive touch events just like they would when a finger is used to touch the display. When the stylus is hovering above the digitizer, applications receive hover events just like they would when a mouse pointer was being moved across the display when no buttons are pressed.

Your application can distinguish between finger, mouse, stylus and eraser input by querying the "tool type" associated with each pointer in a[MotionEvent](https://developer.android.com/reference/android/view/MotionEvent)using[getToolType()](https://developer.android.com/reference/android/view/MotionEvent#getToolType(int)). The currently defined tool types are:[TOOL_TYPE_UNKNOWN](https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_UNKNOWN),[TOOL_TYPE_FINGER](https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_FINGER),[TOOL_TYPE_MOUSE](https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_MOUSE),[TOOL_TYPE_STYLUS](https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_STYLUS), and[TOOL_TYPE_ERASER](https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_ERASER). By querying the tool type, your application can choose to handle stylus input in different ways from finger or mouse input.

Your application can also query which mouse or stylus buttons are pressed by querying the "button state" of a[MotionEvent](https://developer.android.com/reference/android/view/MotionEvent)using[getButtonState()](https://developer.android.com/reference/android/view/MotionEvent#getButtonState()). The currently defined button states are:[BUTTON_PRIMARY](https://developer.android.com/reference/android/view/MotionEvent#BUTTON_PRIMARY),[BUTTON_SECONDARY](https://developer.android.com/reference/android/view/MotionEvent#BUTTON_SECONDARY),[BUTTON_TERTIARY](https://developer.android.com/reference/android/view/MotionEvent#BUTTON_TERTIARY),[BUTTON_BACK](https://developer.android.com/reference/android/view/MotionEvent#BUTTON_BACK), and[BUTTON_FORWARD](https://developer.android.com/reference/android/view/MotionEvent#BUTTON_FORWARD). For convenience, the back and forward mouse buttons are automatically mapped to the[KEYCODE_BACK](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_BACK)and[KEYCODE_FORWARD](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_FORWARD)keys. Your application can handle these keys to support mouse button based back and forward navigation.

In addition to precisely measuring the position and pressure of a contact, some stylus input devices also report the distance between the stylus tip and the digitizer, the stylus tilt angle, and the stylus orientation angle. Your application can query this information using[getAxisValue()](https://developer.android.com/reference/android/view/MotionEvent#getAxisValue(int))with the axis codes[AXIS_DISTANCE](https://developer.android.com/reference/android/view/MotionEvent#AXIS_DISTANCE),[AXIS_TILT](https://developer.android.com/reference/android/view/MotionEvent#AXIS_TILT), and[AXIS_ORIENTATION](https://developer.android.com/reference/android/view/MotionEvent#AXIS_ORIENTATION).

For a demonstration of tool types, button states and the new axis codes, see the[TouchPaint](https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint)class in ApiDemos.

### Properties

The new[Property](https://developer.android.com/reference/android/util/Property)class provides a fast, efficient, and easy way to specify a property on any object that allows callers to generically set/get values on target objects. It also allows the functionality of passing around field/method references and allows code to set/get values of the property without knowing the details of what the fields/methods are.

For example, if you want to set the value of field`bar`on object`foo`, you would previously do this:  

### Kotlin

```kotlin
foo.bar = value
```

### Java

```java
foo.bar = value;
```

If you want to call the setter for an underlying private field`bar`, you would previously do this:  

### Kotlin

```kotlin
foo.setBar(value)
```

### Java

```java
foo.setBar(value);
```

However, if you want to pass around the`foo`instance and have some other code set the`bar`value, there is really no way to do it prior to Android 4.0.

Using the[Property](https://developer.android.com/reference/android/util/Property)class, you can declare a[Property](https://developer.android.com/reference/android/util/Property)object`BAR`on class`Foo`so that you can set the field on instance`foo`of class`Foo`like this:  

### Kotlin

```kotlin
BAR.set(foo, value)
```

### Java

```java
BAR.set(foo, value);
```

The[View](https://developer.android.com/reference/android/view/View)class now leverages the[Property](https://developer.android.com/reference/android/util/Property)class to allow you to set various fields, such as transform properties that were added in Android 3.0 ([ROTATION](https://developer.android.com/reference/android/view/View#ROTATION),[ROTATION_X](https://developer.android.com/reference/android/view/View#ROTATION_X),[TRANSLATION_X](https://developer.android.com/reference/android/view/View#TRANSLATION_X), etc.).

The[ObjectAnimator](https://developer.android.com/reference/android/animation/ObjectAnimator)class also uses the[Property](https://developer.android.com/reference/android/util/Property)class, so you can create an[ObjectAnimator](https://developer.android.com/reference/android/animation/ObjectAnimator)with a[Property](https://developer.android.com/reference/android/util/Property), which is faster, more efficient, and more type-safe than the string-based approach.

### Hardware Acceleration

Beginning with Android 4.0, hardware acceleration for all windows is enabled by default if your application has set either[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)or[`minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)to`"14"`or higher. Hardware acceleration generally results in smoother animations, smoother scrolling, and overall better performance and response to user interaction.

If necessary, you can manually disable hardware acceleration with the[`hardwareAccelerated`](https://developer.android.com/guide/topics/manifest/activity-element#hwaccel)attribute for individual[`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element)elements or the[`<application>`](https://developer.android.com/guide/topics/manifest/application-element)element. You can alternatively disable hardware acceleration for individual views by calling[setLayerType(LAYER_TYPE_SOFTWARE)](https://developer.android.com/reference/android/view/View#setLayerType(int, android.graphics.Paint)).

For more information about hardware acceleration, including a list of unsupported drawing operations, see the[Hardware Acceleration](https://developer.android.com/guide/topics/graphics/hardware-accel)document.

### JNI Changes

In previous versions of Android, JNI local references weren't indirect handles; Android used direct pointers. This wasn't a problem as long as the garbage collector didn't move objects, but it seemed to work because it made it possible to write buggy code. In Android 4.0, the system now uses indirect references in order to detect these bugs.

The ins and outs of JNI local references are described in "Local and Global References" in[JNI Tips](https://developer.android.com/guide/practices/jni). In Android 4.0,[CheckJNI](http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html)has been enhanced to detect these errors. Watch the[Android Developers Blog](http://android-developers.blogspot.com/)for an upcoming post about common errors with JNI references and how you can fix them.

This change in the JNI implementation only affects apps that target Android 4.0 by setting either the[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)or[`minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)to`"14"`or higher. If you've set these attributes to any lower value, then JNI local references behave the same as in previous versions.

### WebKit

- WebKit updated to version 534.30
- Support for Indic fonts (Devanagari, Bengali, and Tamil, including the complex character support needed for combining glyphs) in[WebView](https://developer.android.com/reference/android/webkit/WebView)and the built-in Browser
- Support for Ethiopic, Georgian, and Armenian fonts in[WebView](https://developer.android.com/reference/android/webkit/WebView)and the built-in Browser
- Support for[WebDriver](http://google-opensource.blogspot.com/2009/05/introducing-webdriver.html)makes it easier for you to test apps that use[WebView](https://developer.android.com/reference/android/webkit/WebView)

#### Android Browser

The Browser application adds the following features to support web applications:

- Updated V8 JavaScript compiler for faster performance
- Plus other notable enhancements carried over from[Android 3.0](https://developer.android.com/about/versions/android-3.0)are now available for handsets:
  - Support for fixed position elements on all pages
  - [HTML media capture](http://dev.w3.org/2009/dap/camera/)
  - [Device orientation events](http://dev.w3.org/geo/api/spec-source-orientation.html)
  - [CSS 3D transformations](http://www.w3.org/TR/css3-3d-transforms/)

### Permissions

The following are new permissions:

- [ADD_VOICEMAIL](https://developer.android.com/reference/android/Manifest.permission#ADD_VOICEMAIL): Allows a voicemail service to add voicemail messages to the device.
- [BIND_TEXT_SERVICE](https://developer.android.com/reference/android/Manifest.permission#BIND_TEXT_SERVICE): A service that implements[SpellCheckerService](https://developer.android.com/reference/android/service/textservice/SpellCheckerService)must require this permission for itself.
- [BIND_VPN_SERVICE](https://developer.android.com/reference/android/Manifest.permission#BIND_VPN_SERVICE): A service that implements[VpnService](https://developer.android.com/reference/android/net/VpnService)must require this permission for itself.
- android.Manifest.permission#READ_PROFILE: Provides read access to the[ContactsContract.Profile](https://developer.android.com/reference/android/provider/ContactsContract.Profile)provider.
- android.Manifest.permission#WRITE_PROFILE: Provides write access to the[ContactsContract.Profile](https://developer.android.com/reference/android/provider/ContactsContract.Profile)provider.

### Device Features

The following are new device features:

- [FEATURE_WIFI_DIRECT](https://developer.android.com/reference/android/content/pm/PackageManager#FEATURE_WIFI_DIRECT): Declares that the application uses Wi-Fi for peer-to-peer communications.

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

## Previous APIs

In addition to everything above, Android 4.0 naturally supports all APIs from previous releases. Because the Android 3.x platform is available only for large-screen devices, if you've been developing primarily for handsets, then you might not be aware of all the APIs added to Android in these recent releases.

Here's a look at some of the most notable APIs you might have missed that are now available on handsets as well:

[Android 3.0](https://developer.android.com/about/versions/android-3.0)
:
    - [Fragment](https://developer.android.com/reference/android/app/Fragment): A framework component that allows you to separate distinct elements of an activity into self-contained modules that define their own UI and lifecycle. See the[Fragments](https://developer.android.com/guide/components/fragments)developer guide.
    - [ActionBar](https://developer.android.com/reference/android/app/ActionBar): A replacement for the traditional title bar at the top of the activity window. It includes the application logo in the left corner and provides a new interface for menu items. See the[Action Bar](https://developer.android.com/guide/topics/ui/actionbar)developer guide.
    - [Loader](https://developer.android.com/reference/android/content/Loader): A framework component that facilitates asynchronous loading of data in combination with UI components to dynamically load data without blocking the main thread. See the[Loaders](https://developer.android.com/guide/components/loaders)developer guide.
    - System clipboard: Applications can copy and paste data (beyond mere text) to and from the system-wide clipboard. Clipped data can be plain text, a URI, or an intent. See the[Copy and Paste](https://developer.android.com/guide/topics/text/copy-paste)developer guide.
    - Drag and drop: A set of APIs built into the view framework that facilitates drag and drop operations. See the[Drag and Drop](https://developer.android.com/guide/topics/ui/drag-drop)developer guide.
    - An all new flexible animation framework allows you to animate arbitrary properties of any object (View, Drawable, Fragment, Object, or anything else) and define animation aspects such as duration, interpolation, repeat and more. The new framework makes Animations in Android simpler than ever. See the[Property Animation](https://developer.android.com/guide/topics/graphics/prop-animation)developer guide.
    - RenderScript graphics and compute engine: RenderScript offers a high performance 3D graphics rendering and compute API at the native level, which you write in the C (C99 standard), providing the type of performance you expect from a native environment while remaining portable across various CPUs and GPUs. See the[RenderScript](https://developer.android.com/guide/topics/renderscript)developer guide.
    - Hardware accelerated 2D graphics: You can now enable the OpenGL renderer for your application by setting {android:hardwareAccelerated="true"} in your manifest element's[`<application>`](https://developer.android.com/guide/topics/manifest/application-element)element or for individual[`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element)elements. This results in smoother animations, smoother scrolling, and overall better performance and response to user interaction.

      **Note:** If you set your application's[`minSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#min)or[`targetSdkVersion`](https://developer.android.com/guide/topics/manifest/uses-sdk-element#target)to`"14"`or higher, hardware acceleration is enabled by default.
    - And much, much more. See the[Android 3.0 Platform](https://developer.android.com/about/versions/android-3.0)notes for more information.

[Android 3.1](https://developer.android.com/about/versions/android-3.1)
:
    - USB APIs: Powerful new APIs for integrating connected peripherals with Android applications. The APIs are based on a USB stack and services that are built into the platform, including support for both USB host and device interactions. See the[USB Host and Accessory](https://developer.android.com/guide/topics/connectivity/usb)developer guide.
    - MTP/PTP APIs: Applications can interact directly with connected cameras and other PTP devices to receive notifications when devices are attached and removed, manage files and storage on those devices, and transfer files and metadata to and from them. The MTP API implements the PTP (Picture Transfer Protocol) subset of the MTP (Media Transfer Protocol) specification. See the[android.mtp](https://developer.android.com/reference/android/mtp/package-summary)documentation.
    - RTP APIs: Android exposes an API to its built-in RTP (Real-time Transport Protocol) stack, which applications can use to manage on-demand or interactive data streaming. In particular, apps that provide VOIP, push-to-talk, conferencing, and audio streaming can use the API to initiate sessions and transmit or receive data streams over any available network. See the[android.net.rtp](https://developer.android.com/reference/android/net/rtp/package-summary)documentation.
    - Support for joysticks and other generic motion inputs.
    - See the[Android 3.1 Platform](https://developer.android.com/about/versions/android-3.1)notes for many more new APIs.

[Android 3.2](https://developer.android.com/about/versions/android-3.2)
:
    - New screens support APIs that give you more control over how your applications are displayed across different screen sizes. The API extends the existing screen support model with the ability to precisely target specific screen size ranges by dimensions, measured in density-independent pixel units (such as 600dp or 720dp wide), rather than by their generalized screen sizes (such as large or xlarge). For example, this is important in order to help you distinguish between a 5" device and a 7" device, which would both traditionally be bucketed as "large" screens. See the blog post,[New Tools for Managing Screen Sizes](http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html).
    - New constants for[`<uses-feature>`](https://developer.android.com/guide/topics/manifest/uses-feature-element)to declare landscape or portrait screen orientation requirements.
    - The device "screen size" configuration now changes during a screen orientation change. If your app targets API level 13 or higher, you must handle the`"screenSize"`configuration change if you also want to handle the`"orientation"`configuration change. See[`android:configChanges`](https://developer.android.com/guide/topics/manifest/activity-element#config)for more information.
    - See the[Android 3.2 Platform](https://developer.android.com/about/versions/android-3.2)notes for other new APIs.

### API Level

The Android 4.0 API is assigned an integer identifier---**14**---that is stored in the system itself. This identifier, called the "API level", allows the system to correctly determine whether an application is compatible with the system, prior to installing the application.

To use APIs introduced in Android 4.0 in your application, you need compile the application against an Android platform that supports API level 14 or higher. Depending on your needs, you might also need to add an`android:minSdkVersion="14"`attribute to the[`<uses-sdk>`](https://developer.android.com/guide/topics/manifest/uses-sdk-element)element.

For more information, read[What is API Level?](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)