Android SDK M5 Release - API Changes Overview
This is a high level description of the changes in the M5 release of the Android SDK since
the last public release, M3.
AndroidManifest.xml
There are several changes to the AndroidManifest.xml file that will hit you immediately when
porting an application to M5 and will need to be updated. The most likely ones you will see are:
- The
class= parameter throughout the AndroidManifest.xml file has been renamed,
replace all instances of class= with android:name=.
- The
android:value= parameters used throughout the AndroidManifest.xml file
have been renamed, replace all android:value= occurrences with
android:name=.
- The
android:id= parameters used throughout the AndroidManifest.xml file
have been renamed, replace all android:id= occurrences with
android:name=.
- In
<intent-filter>, the previous <type>, <scheme>,
<authority> and <path> tags are now replaced with a single <data> tag and
uses attributes android:mimeType, android:scheme,
android:host and android:path to replace those tags respectively. A
new attribute: android:port has been added as well.
Without these changes, intent-filters will not work correctly.
So, for example:
<intent-filter>
<action android:value="android.intent.action.INSERT" />
<category android:value="android.intent.category.DEFAULT" />
<type android:value="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
Would be replaced with:
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
Take a look at the AndroidManifest.xml
document for more details.
Layout
Layout Files also need to be updated before they will work correctly:
- The main change is that
id= has been replaced with android:id= and
all occurrences of id= should be changed.
Adapters
- android.widget.SimpleCursorAdapter
has been improved:
- Now supports ImageViews.
- The user can specify which column in the Cursor should be used to convert the Cursor
to a String.
- Alternatively, the user can supply a
CursorToStringConverter
explicitly.
- A FilterQueryProvider
can be passed to the adapter to generate filtering queries for AutoCompleteTextView.
- While SimpleCursorAdapter supports only TextView and ImageView, the user can now
supply a ViewBinder to easily add
support for any sort of View.
- These new features greatly reduce the need to extend SimpleCursorAdapter or one of its
parents.
Widgets and Views
- Classes:
- Coordinates:
- The "window coordinates", represented in android.view.View by
the fields mWindowLeft and mWindowTop, have been removed. The public accessor methods
getWindowLeft(), getWindowTop(), getWindowRight() and getWindowBottom() have likewise
been removed.
- Threading:
- Events:
- Touch Mode:
- Touch mode is a mode of operation where it is not necessary to explicitly give focus to
or control focus of actionable items such as buttons, so the user can see what item will
take input. A touch capable device will enter "touch mode" when the user touches the screen.
From this point forwards, only views for which isFocusableInTouchMode() is
true will
be focusable, such as text editing widgets, other views like buttons will only take focus
when touched. If the user hits a directional key, like the D-pad, the device will exit touch
mode, and all views will become focusable. See Touch Mode and Focus Handling in android.view.View for more details.
- Request Focus:
- android.view.View.takeFocus() has been removed. android.view.View.requestFocus() should be used in one of its forms instead. requestFocus()
now behaves like the old takeFocus() method did, including returning a
boolean
indicating whether the call was successful.
- Replace all calls to takeFocus() with requestFocus().
- Existing calls to requestFocus() will work as long as what you are
calling it on are focusable, and if in touch mode, focusable in touch
mode.
- Update overrides of requestFocus() to return a
boolean indicating whether or
not the view you are forwarding the request to took it (usually just by putting a return
statement in front of the forwarding calls to requestFocus).
- Scrolling:
- Finer Grained Focus Passing:
- View.requestFocus()
and View.onFocusChanged() work together to give a newly focused item a hint about the most
interesting rectangle of the previously focused view. Take a look at the
InternalSelectionFocus example in the ApiDemos sample.
- ListView and GridView:
- android.widget.ListView and android.widget.GridView now allow their content to be stacked from
the bottom edge. You can enable this feature using the
setStackFromBottom()
method. This feature formerly existed in ListView as the gravity (ListView.setGravity()).
The gravity variation has been removed.
- ListActivity:
- View:
- ExpandableListView:
- android.widget.ExpandableListView is a new
widget that provides a two-level tree-type widget. The top-level items are groups and are
each expandable/collapsible to reveal the group's children. It shows indicators (by default)
to the left of each item to show the current state of the item. The indicators along with
the position they should be drawn are settable.
- The android.widget.ExpandableListAdapter
provides data to this widget. It is similar to a regular Adapter,
but has two sets of methods: one for groups and one for children.
- There is an example in the API Demos > Views > Lists > Expandable > 1, 2, 3.
- Internally, this widget inherits from
android.widget.ListView and has a connector to translate
between "flat list" positions to group + child positions. Some methods will be available
from ListView that return the "flat list" position, so developers should probably be
aware of this. Worst case, there are methods exposed
(getExpandableListPosition and getFlatListPosition) to convert between the two.
- The expandable list position is usually represented as a "packed position"
containing the type of position (either child, group, or null), and a group position
(for both group and children), and a child position (for children).
Methods starting with
getPackedPosition... help with unpacking.
- SurfaceView:
- When using android.view.SurfaceView
it is no longer necessary to force the window to be transparent or otherwise do anything
special. See the SurfaceView examples in ApiDemos to see how the class should be used.
- Drawing Cache:
- android.view.View now offers a drawing cache: when the drawing
cache is enabled (see android.view.View.setDrawingCacheEnabled()), the View copies itself into a Bitmap when
getDrawingCache() is invoked. This can be used to improve drawing performance for complex
views as ViewGroup will automatically query the drawing cache of its children to attempt
faster drawing. It is also possible to control the quality of the drawing cache using android.view.View.setDrawingCacheQuality() or the
corresponding XML attribute.
- android.view.ViewGroup can enable or disable the drawing
cache of all of its children at once using ViewGroup.setChildrenDrawingCacheEnabled().
- ViewGroup now offers a layout animation (see Layout Animations for more information
about layout animations) cache: if enabled, the children's drawing caches are enabled when a
layout animation starts, thus offering better performance. The layout animation cache can be
disabled using ViewGroup.setAnimationCacheEnabled().
- android.widget.AbsListView
(and therefore ListView and GridView) now offers a scrolling cache: if
enabled, the children's drawing caches are enabled when a scroll operation starts, thus
offering better performance. The scrolling cache can be disabled using
AbsListView.setScrollingCacheEnabled().
- The persistence of the drawing cache can be set using ViewGroup.setPersistentDrawingCache(). A
persistent drawing cache means that the Bitmap used by the children as a drawing cache is
kept in memory after the cache was used. For instance, with the persistent drawing cache set
to
PERSISTENT_SCROLLING_CACHE, the drawing caches of a ListView's children are
kept in memory after a scroll operation. This avoids creating new Bitmaps over and over
again, thus providing better performance.
- By default, android.view.ViewGroup will always try to
draw its children using their drawing cache. For instance, you have a ListView with a
persistent scrolling cache. A scroll operation will create the cache for all of the children
and this cache will be used to draw the children during scrolling. When the scrolling is
over, the cache is kept and ViewGroup reuses the cache to draw the children on screen. In
some situations however, you might want to keep the cache in memory but not use it for
drawing outside of specific operations (like animations or scrolling); this is usually what
you want if you set the cache quality to low. In that case you can call ViewGroup.setAlwaysDrawnWithCacheEnabled() to prevent the ViewGroup from drawing with the
cache.
Menus
- There are three new menu types: the icon menu, the expanded menu, and context menus.
- Icon and expanded menus:
- Icon menus are the first menu to appear when pressing the menu button. A maximum of six
menu items will be shown; if the user has more than six items in the options menu, the sixth
item will be a 'More' item which will launch the expanded menu. Icon menus will not show
checkbox or radio buttons, nor shortcuts.
- Expanded menus list all of the menu items (although when shown it will start at the
sixth item since the first five were shown in the icon menu). This menu type shows
checkboxes, radio buttons, and item shortcut keys. Pressing the menu key here will collapse
the entire menu system, pressing the back key will go back to the icon menu.
- From either of these two types of menu, a submenu can be opened that only shows its
items.
- The API is similar to the previous Menu API with a couple of notes:
- Divider/separators have been removed.
- Icons have been added to each menu item. An icon will be shown in both of these
menu types.
- Internally, Views and Drawables are lazy loaded, so performance should have
increased.
- Context Menus:
- These are pop-up style menus initiated by long pressing (either clicking the center
button or touching for roughly 2 seconds) existing Views in an application.
- Example use: when long pressing a contact in the Contacts application, a context menu
appears with 'View contact', 'Call Mobile', 'Add star', 'Edit contact', 'Delete
contact'.
- The API for adding to a context menu is similar to the regular Menu API (in fact, the
ContextMenu interface extends the Menu interface with the additional functionality for
setting the header).
- See android.view.ContextMenu for usage
information.
- The API for setting the triggers to launch a context menu are new:
- A View is the starting point for launching a context menu. When a user long presses a
View, the View and its parents begin populating the context menu (via View.onPopulateContextMenu()). However, each View
can also have a android.view.View.OnPopulateContextMenuListener which will be called when this populating
sequence occurs for the View. This listener will most likely be a developer's hook into
populating a context menu for his application.
- The parameters to the method in this listener:
- The ContextMenu menu that should be populated (very similar API to the options Menu,
with added functionality to set the header of the context menu to either a title,
title+icon, or a custom View).
- The View v that triggered the context menu. In some cases such as a ListView, it
makes more sense to add a OnPopulateContextMenuListener to a parent View than to
individual child Views. v will be the ListView in this example.
- Object menuInfo that contains extra information relevant to the triggering of the
context menu. Most AdapterViews will pass android.widget.AdapterView.ContextMenuInfo,
while an ExpandableListView will pass android.widget.ExpandableListView.ExpandableListContextMenuInfo. In these cases, the
object will have the child's exact information: the child View, its ID, and its position
in the adapter.
- Finally, when all of the Views and their OnPopulateContextMenuListeners have populated
the ContextMenu, it will be shown. At the top will be a header that is
developer-settable.
- When the user clicks or closes the menu, the
Activity#onContextItemSelected
and Activity#onContextMenuClosed will
be called respectively. To get the extra information contained in the menuInfo object,
use Menu.Item.getMenuInfo().
- Unlike options menu, the object implementing ContextMenu is freshly created each time
the ContextMenu is shown and each item needs to be re-added to the menu.
- Specific Menu API Changes:
Animations
- In android.view.View,
setCurrentAnimation() and getCurrentAnimation() have been renamed
setAnimation() and
getAnimation().
- android.view.animation.Animation is now an
abstract class and not an interface anymore.
- android.view.animation.BaseAnimation has been
removed, animations implementer should extend the android.view.animation.Animation class instead.
- Animation interpolators can now be defined in XML.
- android.view.ViewGroup can now keep its children's
animations after they are over. This is useful when you are using an animation whose
fillAfter property is set to true and when the final state of the animation is different from
the normal state of the child. See
ViewGroup.setKeepAnimations() for more
details.
- Animation listeners are working now.
- Layout Animations:
- Layouts (and more generally descendants of ViewGroup) can be animated using an
android.view.animation.LayoutAnimationController. See ViewGroup and ApiDemos for more details.
A LayoutAnimationController is associated with a regular Animation and the ViewGroup will
query the controller for a copy of that Animation for each of its children. Every child will
have the same animated behavior (for instance, fade in or fade out) each individual's
animation will start at a different time. The role of a LayoutAnimationController is to
compute the start time of each child's animation. For instance,
GridLayoutAnimationController
will compute the start time based on the X and Y position of a child in a GridView whereas
LayoutAnimationController will simply use the index of the child in the ViewGroup. The
controller lets you specify the order (normal, reverse or random) and priority of the
animations (columns first, rows first or both).
Alerts
As an alternative to the android.app.AlertDialog.show()
methods, there is now an
android.app.AlertDialog.Builder
which you can use instead, for example:
AlertDialog.show(this, getResources().getString(R.string.delete_title),
getResources().getString(R.string.delete_message),
getResources().getString(R.string.yes_button), new OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
Cursor c = mCursor;
c.deleteRow();
managedCommitUpdates(c);
setResult(RESULT_OK);
finish();
}
},
getResources().getString(R.string.no_button), new OnClickListener(){
public void onClick(DialogInterface dialog, int arg1) {
// do nothing
}
},
true, new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
// do nothing
}
});
}
with code like this:
new AlertDialog.Builder(this)
.setTitle(getResources().getString(R.string.delete_title))
.setMessage(R.string.delete_message)
.setPositiveButton(R.string.no_button, new OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
Cursor c = mCursor;
c.deleteRow();
managedCommitUpdates(c);
setResult(RESULT_OK);
finish();
}
})
.setNegativeButton(R.string.yes_button, new OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
// do nothing
}
})
.show();
This way it is only necessary to define those listeners that you wish to use.
SQLite/Content Provider
- The QueryBuilder class has been moved to the android.database.sqlite package and renamed SQLiteQueryBuilder as it now is responsible for building the SQL that is passed to
android.database.sqlite.SQLiteDatabase.
- The android.net.ContentURI class has be replaced with the new
android.net.Uri class. This is not a 1:1 replacement
and engenders a number of necessary changes in the way you use and manipulate URIs in
Android applications.
android.content.ContentUris provides some static
helper methods for appending and parsing IDs. android.net.Uri.Builder is a builder class to help with creating new Uris (from
existing ones if necessary). Take a look at the Notepad sample from the SDK to see how to
use these classes to replace the ContentURI usage.
Some suggested replacements:
| Old | New |
new ContentURI(String) |
Uri.parse(String) |
ContentURI.create(String) |
Uri.parse(String) |
ContentUri.countPathSegments() |
Uri.getPathSegments().size() |
ContentUri.getPathSegment() |
Uri.getPathSegments().get()
or
Uri.getLastPathSegment() |
ContentURI.addPath() |
Uri.Builder.appendPath() |
ContentURI.addId(id) |
uri = Uri.withAppendedPath(SOME_URI, id);
or
uri = ContentUris.appendId(uri.buildUpon(), id).build(); |
- The previously unused
groupBy and having parameters have been
removed from ContentProvider.query().
- ContentProvider has a new method, openFile() that takes a URI and returns a file descriptor to the opened file. The ContentProvider.openFileHelper() method covers
the common case, override openFile and call it if you don't need anything fancy. It is now
the responsibility of the ContentProvider to open the file, it no longer needs to have
a special column with the file name, can open any file it wants, and also no longer needs
to make the files world-readable. A file descriptor is returned to the client.
- android.content.ContentURIParser has been removed, use
android.content.UriMatcher instead.
- ContentProvider.onSyncStart()
and ContentProvider.onSyncStop()
now each take an account parameter.
- SQLiteCursor.supportsUpdates()
could have returned true when updates were not supported, this is fixed.
- SQLiteCursor.commitUpdates()
now returns true when there are no updates to commit.
- SQLiteCursor has a new method, hasUpdates() which returns true if any updates were made to the cursor.
- The custom Android SQLite functions are now available in the sqlite3 shell tool.
- SQLiteDatabase.query() may also
take a SQLiteDatabase.CursorFactory
now as well as the constructor.
- android.database.Cursor has the new method
getWantsAllOnMoveCalls() which tells the
client side to send move notifications to the content provider for all moves, not just ones that
cross window boundaries.
- Cursor has the new method getExtras() which lets
the cursor provide out of band data to the users.
- Cursor has the new method respond() which lets the
user send out of band data back to the Cursor implementation.
- android.database.ArrayCursor has been replaced by android.database.ArrayListCursor.
- Reading floating point and long values from android.database.sqlite.SQLiteCursor now works correctly.
Geographical and Location Based
- The location manager now allows a provider to be selected directly by name:
android.location.LocationManager.getProvider(String name).
- The Geo APIs now require permissions to be set on the calling activity:
android.Manifest.permission.ACCESS_LOCATION - required to access any location-based services
android.Manifest.permission.ACCESS_GPS
- required to access the "gps" provider, if it exists
android.Manifest.permission.ACCESS_ASSISTED_GPS - requires to access the "agps" provider,
if it exists
android.Manifest.permission.ACCESS_CELL_ID - required to access the "cell" provider, if it
exists.
Activities must obtain all relevant permissions; for example, to access assisted GPS requires
all of the first three permissions listed above.
- There are new APIs for forward and reverse geocoding in the android.location package:
- These APIs are currently mocks only and are subject to change before release. Details on how to specify data for the API to playback to you is described below.
- android.location.Address defines a postal address.
- android.location.Location (which existed in M3)
defines a location via latitude/longitude.
- android.location.Geocoder defines interfaces to obtain a
Location from an Address (geocoding) or an address from a Location (reverse geocoding). It
also supports business search.
- Geocoding can be mocked by creating a file in
/data/misc/location/geodb.
The file syntax is:
address <id number>
line <line number> "<text>"
locality "<text>"
region" <text>"
postalCode" <text>"
countryCode" <text>"
countryName" <text>"
latitude "<number>"
longitude "<text>"
phone "<text>"
url "<text>"
extra "<key>" "<data>"
location <center latitude> <center longitude> <latitude span> <longitude span> <id> [<id> ...] "<text>"
business <latitude> <longitude> <latitude span> <longitude span> <id> [<id> ...] "<text>"
For example:
address 3
latitude "38.898763"
longitude "-77.036655"
line 0 "1600 Pennsylvania Ave NW"
line 1 "Washington, DC 20006"
locality "Washington"
region "DC"
postalCode "20006"
countryCode "US"
countryName "United States"
location 0 0 180 360 3 "1600 Pennsylvania Avenue, Washington DC"
location 0 0 180 360 3 "1600 Pennsylvania Ave, Washington DC"
location 0 0 180 360 3 "1600 Pennsylvania Avenue, Washington D.C."
location 0 0 180 360 3 "1600 Pennsylvania Ave, Washington D.C."
business 38.898763 -77.036655 50 50 3 "White House"
This defines four query strings that will all return the address with id "3" for a location
search anywhere in the world (because the latitude span is 180 and the longitude span is 360).
Additionally, a business search for "White House" centered within 50 degrees of the actual
location will return the same address.
Notification Manager
- Transient notifications are not called notifications anymore. They are now called
android.widget.Toasts.
This name may not be permanent, but the rest of the API should be quite settled:
- The notification UI for the status bar has changed. You should make sure that your
notification behaves correctly with the new UI. In particular, the notification used to be
displayed in a bubble but is now an entry in a list and should behave accordingly.
Browser
- The version of webkit used in Android has been updated through a series of incremental
patches. This should not affect most developers since the changes are primarily bug fixes to
the rendering engine.
- BrowserCallback has been removed and the functionality has been separated with two new
classes: android.webkit.WebViewClient and
android.webkit.WebChromeClient.
- BrowserCallbackAdapter has also been removed.
GTalk (formerly XMPP)
- The com.google.android.xmppService package has been replaced by the com.google.android.gtalkservice package.
This was done to better reflect the fact that this is a Google-specific
service, and not part of the Android core.
This service has two goals: to provide a convenient way for
developers to send peer-to-peer messages from their applications between
handsets, and to provide an API for sending and receiving instant messages
from Google's Talk servers. Since it is not intended to be a generic XMPP
API or gateway, and since in the future it will likely move to a binary protocol
that will not be compatible with XMPP, we have renamed the Service to
avoid confusion.
Developers who need standards-compliant XMPP functionality are encouraged to use a
third-party library that provides that functionality.
- As an extension to the above change, all use of XMPP naming has been purged in favor of
GTalk. For example, com.google.android.xmppService.IXmppService has been renamed
com.google.android.gtalkservice.IGTalkService.
- IGTalkService now has group chat
support. This is not 100% compatible with XMPP multi-user chat (MUC), but rather implements
a subset of the XMPP MUC spec. This is consistent with Google's GTalk service and what other
GTalk clients support. In particular, only private chat rooms are supported.
- The GTalkService APIs for message sending have changed. com.google.android.gtalkservice.IChatSession has
been created specifically for chat related functionality. The sendDataMessage() method has been
replicated (for convenience) in the new IChatSession interface.
- Added com.google.android.gtalkservice.IRosterListener for controlling message/roster/presence
notification in the GTalkService API, so the GTalk app can control whether new messages (or
roster and presence updates) are notified through a callback interface (using Binder) or post
the message on the statusbar. This allows the GTalk app to be in control of how the user sees
new messages, etc.
- Miscellaneous API clean up, for example:
IGTalkSession.blockContact(String contact, boolean block)
to
IGTalkSession.blockContact(String contact) and
IGTalkSession.unblockContact(String contact)
OpenGL
Media
- MediaPlayer:
- Added support for OGG Vorbis (.ogg) and MIDI (.mid, .smf), XMF (.xmf, .mxmf),
iMelody (.imy), RTTTL/RTX (.rtttl, .rtx) and OTA (.ota) audio file formats.
- Added convenience methods for creating a
android.media.MediaPlayer object from a Uri. See
MediaPlayer.create(Context, Uri) and MediaPlayer.create(Context, Uri, Surface) for more details.
- Added method for grabbing a frame from a video clip to use a thumbnail.
- Added method to set power management behavior.
- Added method to determine whether media is currently playing.
- Added support for http streaming of MP4 media.
- MediaPlayer.prepare() is now called from
MediaPlayer.create() and you will get an exception
if you call MediaPlayer.prepare() after using create().
- MidiFile has been deleted in favor of android.media.MediaPlayer which offers improved functionality and a unified API for all
multimedia files and streams.
- There are numerous bugfixes in the media framework.
Search Manager
- A new early-look API, android.app.SearchManager, is now
available. This provides the ability to search for user, system or network based data,
making search a seamless, system-wide feature.
- There are two example activities, SearchInvoke and SearchQueryResults, which can be found
under the App / Search section in the ApiDemos SDK Sample.