API Level: 19
Android 4.4 (
KITKAT
) is a new release for the Android platform that offers new features for users and app developers. This document provides an introduction to the most notable new APIs.
As an app developer, you should download the Android 4.4 system image and SDK platform from the SDK Manager as soon as possible. If you don't have a device running Android 4.4 on which to test your app, use the Android 4.4 system image to test your app on the Android emulator . Then build your apps against the Android 4.4 platform to begin using the latest APIs.
Update your target API level
To better optimize your app for devices running Android 4.4,
you should set your
targetSdkVersion
to
"19"
, install it on an Android 4.4 system image,
test it, then publish an update with this change.
You can use APIs in Android 4.4 while also supporting older versions by adding
conditions to your code that check for the system API level before executing
APIs not supported by your
minSdkVersion
.
To learn more about maintaining backward compatibility, read
Supporting Different
Platform Versions
.
For more information about how API levels work, read What is API Level?
Important Behavior Changes
If you have previously published an app for Android, be aware that your app might be affected by changes in Android 4.4.
If your app reads from external storage...
Your app can not read shared files on the external storage when running on Android 4.4, unless your app has the
READ_EXTERNAL_STORAGE
permission. That is, files within the directory returned by
getExternalStoragePublicDirectory()
are no longer accessible without the permission. However, if you need to access only your app-specific directories, provided by
getExternalFilesDir()
, then you do not need the
READ_EXTERNAL_STORAGE
permission.
If your app uses WebView...
Your app might behave differently when running on Android 4.4, especially when you update your app's
targetSdkVersion
to "19" or higher.
The code underlying the
WebView
class and related APIs has been upgraded to be based on a modern snapshot of the Chromium source code. This brings a variety of improvements for performance, support for new HTML5 features, and support for remote debugging of your
WebView
content. The scope of this upgrade means that if your app uses
WebView
, it's behavior may be impacted in some cases. Although known behavior changes are documented and mostly affect your app only when you update your app's
targetSdkVersion
to "19" or higher—the new
WebView
operates in "quirks mode" to provide some legacy functionality in apps that target API level 18 and lower—it's possible that your app depends on unknown behaviors from the previous version of
WebView
.
So if your existing app uses
WebView
, it's important that you test on Android 4.4 as soon as possible and consult
Migrating to WebView in Android 4.4
for information about how your app might be affected when you update your
targetSdkVersion
to "19" or higher.
If your app uses AlarmManager...
When you set your app's
targetSdkVersion
to "19" or higher, alarms that you create using either
set()
or
setRepeating()
will be inexact.
To improve power efficiency, Android now batches together alarms from all apps that occur at reasonably similar times so the system wakes the device once instead of several times to handle each alarm.
If your alarm is not associated with an exact clock time, but it's still important that your alarm be invoked during a specific time range (such as between 2pm and 4pm), then you can use the new
setWindow()
method, which accepts an "earliest" time for the alarm and a "window" of time following the earliest time within which the system should invoke the alarm.
If your alarm must be pinned to an exact clock time (such as for a calendar event reminder), then you can use the new
setExact()
method.
This inexact batching behavior applies only to updated apps. If you've set the
targetSdkVersion
to "18" or lower, your alarms will continue behave as they have on previous versions when running on Android 4.4.
If your app syncs data using ContentResolver...
When you set your app's
targetSdkVersion
to "19" or higher, creating a sync with
addPeriodicSync()
will perform your sync operations within a default flex interval of approximately 4% of the period you specify. For example, if your poll frequency is 24 hours, then your sync operation may occur within roughly a one-hour window of time each day, instead of at exactly the same time each day.
To specify your own flex interval for sync operations, you should begin using the new
requestSync()
method. For more details, see the section below about
Sync Adapters
.
This flex interval behavior applies only to updated apps. If you've set the
targetSdkVersion
to "18" or lower, your existing sync requests will continue to behave as they have on previous versions when running on Android 4.4.
Printing Framework
Android now includes a complete framework that allows users to print any document using a printer connected over Wi-Fi, Bluetooth, or other services. The system handles the transaction between an app that wants to print a document and the services that deliver print jobs to a printer. The
android.print
framework provides all the APIs necessary to specify a print document and deliver it to the system for printing. Which APIs you actually need for a given print job depends on your content.
Printing generic content
If you want to print content from your UI as a document, you need to first create a subclass of
PrintDocumentAdapter
. Within this class, you must implement a few callback methods, including
onLayout()
to establish your layout based on the provided printing properties, and
onWrite()
to serialize your printable content into a
ParcelFileDescriptor
.
In order to write your content to the
ParcelFileDescriptor
you must pass it a PDF. The new
PdfDocument
APIs offer a convenient way to do this by providing a
Canvas
from
getCanvas()
, on which you can draw your printable content. Then write the
PdfDocument
to the
ParcelFileDescriptor
using the
writeTo()
method.
Once you've defined your implementation for
PrintDocumentAdapter
, you can execute print jobs upon the user's request using the
PrintManager
method,
print()
, which takes the
PrintDocumentAdapter
as one of its arguments.
Printing images
If you want to print just a photo or other bitmap, then the helper APIs in the support library do all the work for you. Simply create a new instance of
PrintHelper
, set the scale mode with
setScaleMode()
, then pass your
Bitmap
to
printBitmap()
. That's it. The library handles all the remaining interaction with the system to deliver the bitmap to the printer.
Building print services
As a printer OEM, you can use the
android.printservice
framework to provide interoperability with your printers from Android devices. You can build and distribute print services as APKs, which users can install on their devices . A print service app operates primarily as a headless service by subclassing the
PrintService
class, which receives print jobs from the system and communicates the jobs to its printers using the appropriate protocols.
For more information about how to print your app content, read Printing Content .
SMS Provider
The
Telephony
content provider (the "SMS Provider") allows apps to read and write SMS and MMS messages on the device. It includes tables for SMS and MMS messages received, drafted, sent, pending, and more.
Beginning with Android 4.4, the system settings allow users to select a "default SMS app." Once selected, only the default SMS app is able to write to the SMS Provider and only the default SMS app receives the
SMS_DELIVER_ACTION
broadcast when the user receives an SMS or the
WAP_PUSH_DELIVER_ACTION
broadcast when the user receives an MMS. The default SMS app is responsible for writing details to the SMS Provider when it receives or sends a new message.
Other apps that are not selected as the default SMS app can only read the SMS Provider, but may also be notified when a new SMS arrives by listening for the
SMS_RECEIVED_ACTION
broadcast, which is a non-abortable broadcast that may be delivered to multiple apps. This broadcast is intended for apps that---while not selected as the default SMS app---need to read special incoming messages such as to perform phone number verification.
For more information, read the blog post, Getting Your SMS Apps Ready for KitKat .
Wireless and Connectivity
Host card emulation
Android apps can now emulate ISO14443-4 (ISO-DEP) NFC cards that use APDUs for data exchange (as specified in ISO7816-4). This allows an NFC-enabled device running Android 4.4 to emulate multiple NFC cards at the same time, and allows an NFC payment terminal or other NFC reader to initiate a transaction with the appropriate NFC card based on the application identifier (AID).
If you want to emulate an NFC card that is using these protocols in your app, create a service component based on the
HostApduService
class. Whereas if your app instead uses a secure element for card emulation, you need to create a service based on the
OffHostApduService
class, which will not directly be involved in the transactions but is necessary to register the AIDs that should be handled by the secure element.
For more information, read the NFC Card Emulation guide.
NFC reader mode
A new NFC reader mode allows an activity to restrict all NFC activity to only reading the types of tags the activity is interested in while in the foreground. You can enable reader mode for your activity with
enableReaderMode()
, providing an implementation of
NfcAdapter.ReaderCallback
that receives a callback when new tags are detected.
This new capability, in conjunction with host card emulation, allows Android to operate on both ends of a mobile payment interface: One devices operates as the payment terminal (a device running a reader mode activity) and another device operates as the payment client (a device emulating an NFC card).
Infrared transmitters
When running on a device that includes an infrared (IR) transmitter, you can now transmit IR signals using the
ConsumerIrManager
APIs. To get an instance of
ConsumerIrManager
, call
getSystemService()
with
CONSUMER_IR_SERVICE
as the argument. You can then query the device's supported IR frequencies with
getCarrierFrequencies()
and transmit signals by passing your desired frequency and signal pattern with
transmit()
.
You should always first check whether a device includes an IR transmitter by calling
hasIrEmitter()
, but if your app is compatible only with devices that do have one, you should include a
<uses-feature>
element in your manifest for
"android.hardware.consumerir"
(
FEATURE_CONSUMER_IR
).
Multimedia
Adaptive playback
Support for adaptive video playback is now available with the
MediaCodec
APIs, enabling seamless change in resolution during playback onto a
Surface
—you can feed the decoder input frames of a new resolution and the resolution of the output buffers change without a significant gap.
You can enable adaptive playback by adding two keys to
MediaFormat
that specify the maximum resolution that your app requires from the codec:
KEY_MAX_WIDTH
and
KEY_MAX_HEIGHT
. With these added to your
MediaFormat
, pass the
MediaFormat
to your
MediaCodec
instance with
configure()
.
The codec will transition between resolutions that are the same as or smaller than these values in a seamless fashion. The codec may also support resolutions larger than the specified maximums (as long as it is within the limits of supported profiles), but transitions to larger resolutions may not be seamless.
To change the resolution while decoding H.264 video, continue to queue frames using MediaCodec.queueInputBuffer(), but be certain that you provide the new Sequence Parameter Set (SPS) and Picture Parameter Set (PPS) values together with the Instantaneous Decoder Refresh (IDR) frame in a single buffer.
However, before you attempt to configure your codec for adaptive playback, you must verify that the device supports adaptive playback by calling
isFeatureSupported(String)
with
FEATURE_AdaptivePlayback
.
Note: Support for adaptive playback is vendor specific. Some codecs may require more memory for larger resolution hints. Therefore, you should set the resolution maximums based on the source material you are decoding.
On-demand audio timestamps
To facilitate audio-video synchronization, the new
AudioTimestamp
class provides timeline details about a specific "frame" in an audio stream handled by
AudioTrack
. To get the most recent timestamp available, instantiate an
AudioTimestamp
object and pass it to
getTimestamp()
. If the request for the timestamp succeeds, the
AudioTrack
instance is filled in with a position in frame units, together with the estimated time when that frame either was presented or is committed to be presented.
You can use the value of
nanoTime
in the
AudioTimestamp
(which is monotonic) to find the closest associated video frame compared to
framePosition
so you can drop, duplicate, or interpolate video frames to match the audio. Alternatively, you can determine the delta time between the value of
nanoTime
and a future video frame’s expected time (with consideration for the sample rate) to predict which audio frame is expected at the same moment as a video frame.
Surface image reader
The new
ImageReader
API provides you direct access to image buffers as they are rendered into a
Surface
. You can acquire an
ImageReader
with the static method
newInstance()
. Then call
getSurface()
to create a new
Surface
and deliver your image data with a producer such as
MediaPlayer
or
MediaCodec
. To be notified when new images are available from the surface, implement the
ImageReader.OnImageAvailableListener
interface and register it with
setOnImageAvailableListener()
.
Now as you draw content to your
Surface
, your
ImageReader.OnImageAvailableListener
receives a call to
onImageAvailable()
as each new image frame becomes available, providing you with the corresponding
ImageReader
. You can use the
ImageReader
to acquire the frame's image data as an
Image
object by calling
acquireLatestImage()
or
acquireNextImage()
.
The
Image
object provides direct access to the image's timestamp, format, dimensions, and pixel data in a
ByteBuffer
. However, in order for the
Image
class to interpret your images, they must be formatted according to one of the types defined by constants in either
ImageFormat
or
PixelFormat
.
Peak and RMS measurement
You can now query the peak and RMS of the current audio stream from
Visualizer
by creating a new instance of
Visualizer.MeasurementPeakRms
and passing it to
getMeasurementPeakRms()
. When you call this method, the peak and RMS values of the given
Visualizer.MeasurementPeakRms
are set to the latest measured values.
Loudness enhancer
The
LoudnessEnhancer
is a new subclass of
AudioEffect
that allows you to increase the audible volume of your
MediaPlayer
or
AudioTrack
. This can be especially useful in conjunction with the new
getMeasurementPeakRms()
method mentioned above, in order to increase the volume of spoken audio tracks while other media is currently playing.
Remote controllers
Android 4.0 (API level 14) introduced the
RemoteControlClient
APIs that allow media apps to consume media controller events from remote clients such as media controls on the lock screen. Now the new
RemoteController
APIs allow you to build your own remote controller, enabling the creation of innovative new apps and peripherals that can control the playback of any media app that integrates with
RemoteControlClient
.
To build a remote controller, you can implement your user interface any way you want to, but to deliver the media button events to the user's media app you must create a service that extends the
NotificationListenerService
class and implements the
RemoteController.OnClientUpdateListener
interface. Using the
NotificationListenerService
as the basis is important because it provides the appropriate privacy restrictions, which require users to enable your app as a notification listener within the system security settings.
The
NotificationListenerService
class includes a couple abstract methods you must implement, but if you are only concerned with the media controller events for handling media playback, you can leave your implementation for those empty and instead focus on the
RemoteController.OnClientUpdateListener
methods.
Ratings from remote controllers
Android 4.4 builds upon the existing capabilities for remote control clients (apps that receive media control events with the
RemoteControlClient
) by adding the ability for users to rate the current track from the remote controller.
The new
Rating
class encapsulates information about a user rating. A rating is defined by its rating style (either
RATING_HEART
,
RATING_THUMB_UP_DOWN
,
RATING_3_STARS
,
RATING_4_STARS
,
RATING_5_STARS
or
RATING_PERCENTAGE
) and the rating value that's appropriate for that style.
To allow users to rate your tracks from a remote controller:
-
Signal that you'd like to expose the rating UI to the user (if applicable) by adding the
FLAG_KEY_MEDIA_RATING
flag insetTransportControlFlags()
. -
Call
editMetadata()
to retrieve aRemoteControlClient.MetadataEditor
and pass itRATING_KEY_BY_USER
withaddEditableKey()
. -
Then specify the rating style by calling
putObject()
and passing itRATING_KEY_BY_USER
as the key and one of the above rating styles as the value.
To receive a callback when the user changes the rating from the remote controller, implement the new
RemoteControlClient.OnMetadataUpdateListener
interface and pass an instance to
setMetadataUpdateListener()
. When the user changes the rating, your
RemoteControlClient.OnMetadataUpdateListener
receives a call to
onMetadataUpdate()
, passing
RATING_KEY_BY_USER
as the key and a
Rating
object as the value.
Closed captions
VideoView
now supports
WebVTT
subtitle tracks when playing HTTP Live Stream (HLS) videos, displaying the subtitle track according to the closed caption preferences the user has defined in system settings.
You can also provide
VideoView
with your WebVTT subtitle tracks using the
addSubtitleSource()
method. This method accepts an
InputStream
that carries the subtitle data and a
MediaFormat
object that specifies the format for the subtitle data, which you can specify using
createSubtitleFormat()
. These subtitles also appear over the video according to the user's preferences.
If you do not use
VideoView
to display your video content, you should make your subtitle overlay match the user's closed captioning preference as closely as possible. A new
CaptioningManager
API allows you to query the user’s closed captioning preferences, including styles defined by
CaptioningManager.CaptionStyle
, such as typeface and color. In case the user adjusts some preferences once your video has already started, you should listen for changes to the preferences by registering an instance of
CaptioningManager.CaptioningChangeListener
to receive a callback when any of the preferences change, then update your subtitles as necessary.
Animation & Graphics
Scenes and transitions
The new
android.transition
framework provides APIs that facilitate animations between different states of your user interface. A key feature is the ability for you to define distinct states of your UI, known as "scenes," by creating a separate layout for each one. When you want to animate from one scene to another, execute a "transition," which calculates the necessary animation to change the layout from the current scene to the next scene.
To transition between two scenes, you generally need to perform the following:
-
Specify the
ViewGroup
containing the UI components you want to change. - Specify the layout representing the end-result of the change (the next scene).
- Specify the type of transition that should animate the layout change.
- Execute the transition.
You can use a
Scene
object to accomplish steps 1 and 2. A
Scene
contains metadata describing the properties of a layout that are necessary to perform a transition, including the scene's parent view and the scene's layout. You can create a
Scene
using a class constructor or the static method
getSceneForLayout()
.
You must then use the
TransitionManager
to accomplish steps 3 and 4. One way is to pass your
Scene
to the static method
go()
. This finds the scene's parent view in the current layout and performs a transition on the child views in order to reach the layout defined by the
Scene
.
Alternatively, you don't need to create a
Scene
object at all, but can instead call
beginDelayedTransition()
, specifying a
ViewGroup
that contains the views you want to change. Then add, remove, or reconfigure the target views. After the system lays out the changes as necessary, a transition starts to animate all the affected views.
For additional control, you can define sets of transitions that should occur between pre-defined scenes, using an XML file in your project
res/transition/
directory. Inside a
<transitionManager>
element, specify one or more
<transition>
tags that each specify a scene (a reference to a layout file) and the transition to apply when entering and/or exiting that scene. Then inflate this set of transitions using
inflateTransitionManager()
. Use the returned
TransitionManager
to execute each transition with
transitionTo()
, passing a
Scene
that is represented by one of the
<transition>
tags. You can also define sets of transitions programmatically with the
TransitionManager
APIs.
When specifying a transition, you can use several predefined types defined by subclasses of
Transition
, such as
Fade
and
ChangeBounds
. If you don't specify a transition type, the system uses
AutoTransition
by default, which automatically fades, moves, and resizes views as necessary. Additionally, you can create custom transitions by extending any of these classes to perform the animations however you'd like. A custom transition can track any property changes you'd like, and create any animation you want to based on those changes. For example, you could provide a subclass of
Transition
that listens for changes to the "rotation" property of a view then animate any changes.
For more information, see the
TransitionManager
documentation.
Animator pausing
The
Animator
APIs now allow you to pause and resume an ongoing animation with methods
pause()
and
resume()
.
To track the state of an animation, you can implement the
Animator.AnimatorPauseListener
interface, which provides callbacks when an animation is paused and resumed:
pause()
and
resume()
. Then add the listener to an
Animator
object with
addPauseListener()
.
Alternatively, you can subclass the
AnimatorListenerAdapter
abstract class, which now includes empty implementations for the pause and resume callbacks defined by
Animator.AnimatorPauseListener
.
Reusable bitmaps
You can now reuse any mutable bitmap in
BitmapFactory
to decode any other bitmap—even when the new bitmap is a different size---as long as the resulting byte count of the decoded bitmap (available from
getByteCount()
) is less than or equal to the allocated byte count of the reused bitmap (available from
getAllocationByteCount()
. For more information, see
inBitmap
.
New APIs for
Bitmap
allow similar reconfiguration for reuse outside of
BitmapFactory
(for manual bitmap generation or custom decoding logic). You can now set a bitmap’s dimensions with methods
setHeight()
and
setWidth()
, and specify specify a new
Bitmap.Config
with
setConfig()
without affecting the underlying bitmap allocation. The
reconfigure()
method also provides a convenient way to combine these changes with one call.
However, you should not reconfigure a bitmap that's currently used by the view system, because the underlying pixel buffer will not be remapped in a predictable way.
User Content
Storage access framework
On previous versions of Android, if you want your app to retrieve a specific type of file from another app, it must invoke an intent with the
ACTION_GET_CONTENT
action. This action is still the appropriate way to request a file that you want to
import
into your app. However, Android 4.4 introduces the
ACTION_OPEN_DOCUMENT
action, which allows the user to select a file of a specific type and grant your app long-term read access to that file (possibly with write access) without importing the file to your app.
If you're developing an app that provides storage services for files (such as a cloud save service), you can participate in this unified UI for picking files by implementing a content provider as a subclass of the new
DocumentsProvider
class. Your subclass of
DocumentsProvider
must include an intent filter that accepts the
PROVIDER_INTERFACE
action (
"android.content.action.DOCUMENTS_PROVIDER"
). You must then implement the four abstract methods in the
DocumentsProvider
:
-
queryRoots()
-
This must return a
Cursor
that describes all the root directories of your document storage, using columns defined inDocumentsContract.Root
. -
queryChildDocuments()
-
This must return a
Cursor
that describes all the files in the specified directory, using columns defined inDocumentsContract.Document
. -
queryDocument()
-
This must return a
Cursor
that describes the specified file, using columns defined inDocumentsContract.Document
. -
openDocument()
-
This must return a
ParcelFileDescriptor
representing the specified file. The system calls this method once the user selects a file and the client app requests access to it by callingopenFileDescriptor()
.
For more information, see the Storage Access Framework guide.
External storage access
You can now read and write app-specific files on secondary external storage media, such as when a device provides both emulated storage and an SD card. The new method
getExternalFilesDirs()
works the same as the existing
getExternalFilesDir()
method except it returns an array of
File
objects. Before reading or writing to any of the paths returned by this method, pass the
File
object to the new
getStorageState()
method to verify the storage is currently available.
Other methods for accessing your app-specific cache directory and OBB directory also now have corresponding versions that provide access to secondary storage devices:
getExternalCacheDirs()
and
getObbDirs()
, respectively.
The first entry in the returned
File
array is considered the device's primary external storage, which is the same as the
File
returned by existing methods such as
getExternalFilesDir()
.
Note:
Beginning with Android 4.4, the platform no longer requires that your app acquire the
WRITE_EXTERNAL_STORAGE
or
READ_EXTERNAL_STORAGE
when you need to access only your app-specific regions of the external storage using the methods above. However, the permissions are required if you want to access the shareable regions of the external storage, provided by
getExternalStoragePublicDirectory()
.
Sync adapters
The new
requestSync()
method in
ContentResolver
simplifies some of the procedure for defining a sync request for your
ContentProvider
by encapsulating requests in the new
SyncRequest
object, which you can create with
SyncRequest.Builder
. The properties in
SyncRequest
provide the same functionality as the existing
ContentProvider
sync calls, but adds the ability to specify that a sync should be dropped if the network is metered, by enabling
setDisallowMetered()
.
User Input
New sensor types
The new
TYPE_GEOMAGNETIC_ROTATION_VECTOR
sensor provides rotation vector data based on a magnetometer, which is a useful alternative to the
TYPE_ROTATION_VECTOR
sensor when a gyroscope is not available or when used with
batched sensor events
to record the device's orientation while the phone is sleeping. This sensor requires less power than
TYPE_ROTATION_VECTOR
, but may be prone to noisy event data and is most effective while the user is outdoors.
Android also now supports built-in step sensors in hardware:
-
TYPE_STEP_DETECTOR
- This sensor triggers an event each time the user takes a step. Upon each user step, this sensor delivers an event with a value of 1.0 and a timestamp indicating when the step occurred.
-
TYPE_STEP_COUNTER
- This sensor also triggers an event upon each detected step, but instead delivers the total accumulated number of steps since this sensor was first registered by an app.
Be aware that these two step sensors don't always deliver the same results. The
TYPE_STEP_COUNTER
events occur with a higher latency than those from
TYPE_STEP_DETECTOR
, but that's because the
TYPE_STEP_COUNTER
algorithm does more processing to eliminate false positives. So the
TYPE_STEP_COUNTER
may be slower to deliver events, but its results should be more accurate.
Both step sensors are hardware dependent (Nexus 5 is the first device to support them), so you should check for availability with
hasSystemFeature()
, using the
FEATURE_SENSOR_STEP_DETECTOR
and
FEATURE_SENSOR_STEP_COUNTER
constants.
Batched sensor events
To better manage device power, the
SensorManager
APIs now allow you to specify the frequency at which you'd like the system to deliver batches of sensor events to your app. This doesn't reduce the number of actual sensor events available to your app for a given period of time, but instead reduces the frequency at which the system calls your
SensorEventListener
with sensor updates. That is, instead of delivering each event to your app the moment it occurs, the system saves up all the events that occur over a period of time, then delivers them to your app all at once.
To provide batching, the
SensorManager
class adds two new versions of the
registerListener()
method that allow you to specify the "maximum report latency." This new parameter specifies the maximum delay that your
SensorEventListener
will tolerate for delivery of new sensor events. For example, if you specify a batch latency of one minute, the system will deliver the recent set of batched events at an interval no longer than one minute by making consecutive calls to your
onSensorChanged()
method—once for each event that was batched. The sensor events will never be delayed longer than your maximum report latency value, but may arrive sooner if other apps have requested a shorter latency for the same sensor.
However, be aware that the sensor will deliver your app the batched events based on your report latency
only while the CPU is awake
. Although a hardware sensor that supports batching will continue to collect sensor events while the CPU is asleep, it will not wake the CPU to deliver your app the batched events. When the sensor eventually runs out of its memory for events, it will begin dropping the oldest events in order to save the newest events. You can avoid losing events by waking the device before the sensor fills its memory then call
flush()
to capture the latest batch of events. To estimate when the memory will be full and should be flushed, call
getFifoMaxEventCount()
to get the maximum number of sensor events it can save, and divide that number by the rate at which your app desires each event. Use that calculation to set wake alarms with
AlarmManager
that invoke your
Service
(which implements the
SensorEventListener
) to flush the sensor.
Note:
Not all devices support batching sensor events because it requires support by the hardware sensor. However, beginning with Android 4.4, you should always use the new
registerListener()
methods, because if the device does not support batching, then the system gracefully ignores the batch latency argument and delivers sensor events in real time.
Controller identities
Android now identifies each connected controller with a unique integer that you can query with
getControllerNumber()
, making it easier for you to associate each controller to a different player in a game. The number for each controller may change due to controllers being disconnected, connected, or re-configured by the user, so you should track which controller number corresponds to each input device by registering an instance of
InputManager.InputDeviceListener
. Then call
getControllerNumber()
for each
InputDevice
when a change occurs.
Connected devices also now provide product and vendor IDs that are available from
getProductId()
and
getVendorId()
. If you need to modify your key mappings based on the available set of keys on a device, you can query the device to check whether certain keys are available with
hasKeys(int...)
.
User Interface
Immersive full-screen mode
To provide your app with a layout that fills the entire screen, the new
SYSTEM_UI_FLAG_IMMERSIVE
flag for
setSystemUiVisibility()
(when combined with
SYSTEM_UI_FLAG_HIDE_NAVIGATION
) enables a new
immersive
full-screen mode. While immersive full-screen mode is enabled, your activity continues to receive all touch events. The user can reveal the system bars with an inward swipe along the region where the system bars normally appear. This clears the
SYSTEM_UI_FLAG_HIDE_NAVIGATION
flag (and the
SYSTEM_UI_FLAG_FULLSCREEN
flag, if applied) so the system bars remain visible. However, if you'd like the system bars to hide again after a few moments, you can instead use the
SYSTEM_UI_FLAG_IMMERSIVE_STICKY
flag.
Translucent system bars
You can now make the system bars partially translucent with new themes,
Theme.Holo.NoActionBar.TranslucentDecor
and
Theme.Holo.Light.NoActionBar.TranslucentDecor
. By enabling translucent system bars, your layout will fill the area behind the system bars, so you must also enable
fitsSystemWindows
for the portion of your layout that should not be covered by the system bars.
If you're creating a custom theme, set one of these themes as the parent theme or include the
windowTranslucentNavigation
and
windowTranslucentStatus
style properties in your theme.
Enhanced notification listener
Android 4.3 added the
NotificationListenerService
APIs, allowing apps to receive information about new notifications as they are posted by the system. In Android 4.4, notification listeners can retrieve additional metadata for the notification and complete details about the notification's actions:
The new
Notification.extras
field includes a
Bundle
to deliver your notification builder additional metadata such as
EXTRA_TITLE
and
EXTRA_PICTURE
.
The new
Notification.Action
class defines the characteristics of an action attached to the notification, which you can retrieve from the new
actions
field.
Drawable mirroring for RTL layouts
On previous versions of Android, if your app includes images that should reverse their horizontal orientation for right-to-left layouts, you must include the mirrored image in a
drawables-ldrtl/
resource directory. Now, the system can automatically mirror images for you by enabling the
autoMirrored
attribute on a drawable resource or by calling
setAutoMirrored()
. When enabled, the
Drawable
is automatically mirrored when the layout direction is right-to-left.
Accessibility
The
View
class now allows you to declare "live regions" for portions of your UI that dynamically update with new text content, by adding the new
accessibilityLiveRegion
attribute to your XML layout or calling
setAccessibilityLiveRegion()
. For example, a login screen with a text field that displays an "incorrect password" notification should be marked as a live region, so the screen reader will recite the message when it changes.
Apps that provide an
accessibility service
can now also enhance their capabilities with new APIs that provide information about view collections such as list or grid views using
AccessibilityNodeInfo.CollectionInfo
and
AccessibilityNodeInfo.CollectionItemInfo
.
App Permissions
The following are new permissions that your app must request with the
<uses-permission>
tag to use certain new APIs:
-
INSTALL_SHORTCUT
- Allows an application to install a shortcut in Launcher
-
UNINSTALL_SHORTCUT
- Allows an application to uninstall a shortcut in Launcher
-
TRANSMIT_IR
- Allows an applicaiton to use the device's IR transmitter, if available
Note:
Beginning with Android 4.4, the platform no longer requires that your app acquire the
WRITE_EXTERNAL_STORAGE
or
READ_EXTERNAL_STORAGE
when you want to access your app-specific regions of the external storage using methods such as
getExternalFilesDir()
. However, the permissions are still required if you want to access the shareable regions of the external storage, provided by
getExternalStoragePublicDirectory()
.
Device Features
The following are new device features that you can declare with the
<uses-feature>
tag to declare your app requirements and enable filtering on Google Play or check for at runtime:
-
FEATURE_CONSUMER_IR
- The device is capable of communicating with consumer IR devices.
-
FEATURE_DEVICE_ADMIN
- The device supports device policy enforcement via device admins.
-
FEATURE_NFC_HOST_CARD_EMULATION
- The device supports host- based NFC card emulation.
-
FEATURE_SENSOR_STEP_COUNTER
- The device includes a hardware step counter.
-
FEATURE_SENSOR_STEP_DETECTOR
- The device includes a hardware step detector.
For a detailed view of all API changes in Android 4.4, see the API Differences Report .