Skip to content

Software Development Blogs: Programming, Software Testing, Agile Project Management

Methods & Tools

Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

Android Developers Blog
Syndicate content
An Open Handset Alliance Project.
Updated: 9 hours 35 min ago

The fastest route between voice search and your app

Wed, 10/29/2014 - 20:49
By Jarek Wilkiewicz, Developer Advocate, Google Search

How many lines of code will it take to let your users say Ok Google, and search for something in your app? Hardly any. Starting today, all you need is a small addition to your AndroidManifest.xml in order to connect the Google Now SEARCH_ACTION with your searchable activity:

<activity android:name=".SearchableActivity">
    <intent-filter>
        <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Once you make these changes, your app can receive the SEARCH_ACTION intent containing the SearchManager.QUERY extra with the search expression.

At Google, we always look for innovative ways to help you improve mobile search and drive user engagement back to your app. For example, users can now say to the Google app: “Ok Google, search pizza on Eat24” or “Ok Google, search for hotels in Maui on TripAdvisor.”

This feature is available on English locale Android devices running Jelly Bean and above with the Google app v3.5 or greater. Last but not least, users can enable the Ok Google hot-word detection from any screen, which offers them the fastest route between their search command and your app!


Join the discussion on
+Android Developers


Categories: Programming

Tips for integrating with Google Accounts on Android

Tue, 10/28/2014 - 18:24
By Laurence Moroney, Developer Advocate

Happy Tuesday! We've had a few questions come in recently regarding Google Accounts on Android, so we've put this post together to show you some of our best practices. The tips today will focus on Android-based authentication, which is easily achieved through the integration of Google Play services. Let's get started.

Unique Identifiers

A common confusion happens when developers use the account name (a.k.a. email address) as the primary key to a Google Account. For instance, when using GoogleApiClient to sign in a user, a developer might use the following code inside of the onConnected callback for a registered GoogleApiClient.ConnectedCallbacks listener:

[Error prone pseudocode]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
// createLocalAccount() is specific to the app's local storage strategy.
createLocalAccount(accountName);

While it is OK to store the email address for display or caching purposes, it is possible for users to change the primary email address on a Google Account. This can happen with various types of accounts, but these changes happen most often with Google Apps For Work accounts.

So what's a developer to do? Use the Google Account ID (as opposed to the Account name) to key any data for your app that is associated to a Google Account. For most apps, this simply means storing the Account ID and comparing the value each time the onConnected callback is invoked to ensure the data locally matches the currently logged in user. The API provides methods that allow you to get the Account ID from the Account Name. Here is an example snippet you might use:

[Google Play Services 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
String accountID = GoogleAuthUtil.getAccountId(accountName);
createLocalAccount(accountID);
[Earlier Versions of Google Play Services (please upgrade your client)]
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String accountID = currentUser.getID();
createLocalAccount(accountID);

This will key the local data against a Google Account ID, which is unique and stable for the user even after changing an email address.

So, in the above scenario, if your data was keyed on an ID, you wouldn’t have to worry if your users change their email address. When they sign back in, they’ll still get the same ID, and you won’t need to do anything with your data.

Multiple Accounts

If your app supports multiple account connections simultaneously (like the Gmail user interface shown below), you are calling setAccountName on the GoogleApiClient.Builder when constructing GoogleApiClients. This requires you to store the account name as well as the Google Account ID within your app. However, the account name you’ve stored will be different if the user changes their primary email address. The easiest way to deal with this is to prompt the user to re-login. Then, update the account name when onConnected is called after login. Any time a login occurs you, can use code such as this to compare Account IDs and update the email address stored locally for the Account ID.

[Google Play Services 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
String accountID = GoogleAuthUtil.getAccountId(accountName);
// isExistingLocalAccount(), createLocalAccount(), 
// getLocalDataAccountName(), and updateLocalAccountName() 
// are all specific to the app's local storage strategy.
boolean existingLocalAccountData = isExistingLocalAccount(accountID);
if (!existingLocalAccountData) {
    // New Login.
    createLocalAccount(accountID, accountName);
} else {
    // Existing local data for this Google Account.
    String cachedAccountName = getLocalDataAccountName(accountID);    
    if (!cachedAccountName.equals(accountName)) {
        updateLocalAccountName(accountID, accountName);
    }
}

This scenario reinforces the importance of using the Account ID to store data all data in your app.

Online data

The same best practices above apply to storing data for Google Accounts in web servers for your app. If you are storing data on your servers in this manner and treating the email address as the primary key:

ID [Primary Key] Field 1 Field 2 Field 3 user1@gmail.com Value 1 Value 2 Value 3

You need to migrate to this model where the primary key is the Google Account ID.:

ID [Primary Key] Email Field 1 Field 2 Field 3 108759069548186989918 user1@gmail.com Value 1 Value 2 Value 3

If you don't make Google API calls from your web server, you might be able to depend on the Android application to notify your web server of changes to the primary email address when implementing the updateLocalAccountName method referenced in the multiple accounts sample code above. If you make Google API calls from your web server, you likely implemented it using the Cross-client authentication and can detect changes via the OAuth2 client libraries or REST endpoints on your server as well.

Conclusion

When using Google Account authentication for your app, it’s definitely a best practice to use the account ID, as opposed to the account name to distinguish data for the user. In this post, we saw three scenarios where you may need to make changes to make your apps more robust. With the growing adoption of Google for Work, users who are changing their email address, but keeping the same account ID, may occur more frequently, so we encourage all developers to make plans to update their code as soon as possible.


Join the discussion on
+Android Developers


Categories: Programming

Material Design on Android Checklist

Tue, 10/28/2014 - 14:48
ul.checklist { list-style-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxMC41IiB2aWV3Qm94PSIwIDYuOSAxNiAxMiI+DQogIDxwYXRoIGQ9Ik01LDE2LjRsLTMuOC0zLjhMMCwxMy45bDUsNUwxNS45LDguMWwtMS4zLTEuM0w1LDE2LjR6Ii8+DQo8L3N2Zz4NCg=='); clear: left; } .sectionintro { max-width: 400px; border: 1px solid #ccc; position: relative; padding: 10px 10px 10px 90px; font-style: italic; margin-top: 10px; margin-bottom: 10px; min-height: 75px; } .sectionintro img { position: absolute; left: 5px; top: 5px; border: 0 !important; box-shadow: 0 !important; } h3 { margin-top: 20px; font-size: 150%; } h4 { margin-top: 20px; } ul.checklist li { margin-top: 10px; } div.in-code { color: #aaa; padding-left: 20px; } div.in-code em { color: #c60; font-weight: bold; font-style: normal; }

By Roman Nurik, Design Advocate

Android 5.0 brings in material design as the new design system for the platform and system apps. Consumers will soon start getting Android 5.0 and they’re already seeing glimpses of material design with apps like Google Play Newsstand, Inbox by Gmail and Tumblr. Meanwhile, developers now have the Android 5.0 SDK, along with AppCompat for backward compatibility. And designers now have access to Photoshop, Illustrator and Sketch templates. All this means that now—yes now!—is the time to start implementing material design in your Android apps. Today, let’s talk about what implementing material design really boils down to.

Below, you’ll find a material design checklist that you can use to mark progress as you implement the new design system. The checklist is divided into 4 key sections based on the 4 key aspects of material design.

If you include a good chunk of the items in the checklist below, especially the ones indicated as signature elements, and follow traditional Android design best practices (i.e. these, these, and things we discussed on ADiA), you’ll be well on your way to material design awesomeness!

Tangible Surfaces UIs consist of surfaces (pieces of “digital paper”) arranged at varying elevations, casting shadows on surfaces behind them.
Figure 1. Surfaces and layering.
  • Signature element: Shadows are used to communicate which surfaces are in front of others, helping focus attention and establish hierarchy. Read more on depth and layering in UIs. In code: This is the android:elevation and android:translationZ attribute in Android 5.0. On earlier versions, shadows are normally provided as PNG assets.
  • Shadows and surfaces are used in a consistent and structured way. Each shadow indicates a new surface. Surfaces are created thoughtfully and carefully.
  • There are generally between 2 and 10 surfaces on the screen at once; avoid too much layering/nesting of surfaces.
  • Scrollable content either scrolls to the edges of the screen or behind another surface that casts a shadow over the content’s surface. Never clip an element against an invisible edge—elements don’t just scroll off into nowhere. Put another way, you rarely scroll the ink on a surface; you scroll the surface itself. In code: android:clipToPadding=false often helps with this when using ListView and ScrollView.
  • Surfaces have simple, single-color backgrounds.
A Bold, Print-Like Aesthetic The “digital ink” you draw on those pieces of digital paper is informed by classic print design, with an emphasis on bold use of color and type, contextual imagery, and structured whitespace.
Figure 2. Primary and accent colors.

Figure 3. Keylines.
  • Signature element: Apps use a primary color and an accent color (Figure 2) to color surface backgrounds and key UI widgets such as text fields and checkboxes. The accent color contrasts very well with the primary color (for example an app can use a dark blue primary color and a neon pink accent color). The accent color is high-contrast and is used to call attention to key UI elements, like a circular floating action button, selected tab strips, or form fields. In code: Set the android:colorPrimary and android:colorAccent attributes in your theme (drop the android prefix if using AppCompat). AppCompat automatically colors text fields, checkboxes, and more on pre-L devices.
  • Signature element: On Android 5.0, the status bar is colored to match the app’s primary color, or the current screen’s content. For full-bleed imagery, the status bar can be translucent. In code: Set the android:colorPrimaryDark or android:statusBarColor attribute in your theme (drop the android prefix if using AppCompat) or call Window.setStatusBarColor.
  • Icons, photos/images, text, and other foreground elements are colored “ink” on their surfaces. They don’t have shadows and don’t use gradients.
  • Colors extracted from images can be used to color adjacent UI elements or surfaces. In code: This can be done using the Palette support library.
  • Signature element: Icons in the app follow the system icon guidelines, and standard icons use the material design icon set.
  • Photos are generally immersive and full-bleed. For example, for detail screens, run edge-to-edge and can even appear behind the app bar or status bar. In code: The new Toolbar widget (and its AppCompat equivalent) can be transparent and placed directly in your layout. For the status bar, check this Stack Overflow post.
  • Signature element: Where appropriate, elements like body text, thumbnails, app bar titles, etc. are aligned to 3 keylines (Figure 3). On phones, those keylines are 16dp and 72dp from the left edge and 16dp from the right edge of the screen. On tablets those values are 24dp and 80dp.
  • UI elements are aligned to and sized according to an 8dp baseline grid. For example, app bars are 56dp tall on phones and 64dp tall on tablets. Padding and margins can take on values like 8dp, 16dp, 24dp, etc. More precise text positioning uses a 4dp grid.
Authentic Motion Motion helps communicate what’s happening in the UI, providing visual continuity across app contexts and states. Motion also adds delight using smaller-scale transitions. Motion isn’t employed simply for motion’s sake.
Figure 4. "Hero" transitions.
  • In general, UI and content elements don’t just appear or disappear—they animate into place, either together as a unit, or individually.
  • Signature element: When touching an item to see its details, there’s a “hero” transition (Figure 4) that moves and scales the item between its position in the browsing screen and its position in the detail screen. In code: These are called “shared element transitions” in the SDK. The support version of FragmentTransaction also includes some shared element support.
  • Signature element: Ripple effects originating from where you touched the screen are used to show touch feedback on an item. In code: The default android:selectableItemBackground and android:selectableItemBackgroundBorderless have this, or you can use RippleDrawable (<ripple>) to customize the effect. On pre-5.0 devices, ripples aren’t an expected feature, so defer to the default android:selectableItemBackground behavior.
  • Signature element: UI elements can appear using a circular “reveal” animation. In code: See this doc or the ViewAnimationUtils class for more.
  • Signature element: Animations are used in more subtle, delightful ways, such as to convey the transition between icon states or text states. For example, a “+” icon can morph into an “x” symbol, or an outlined heart icon can be filled using a paint-bucket fill effect. In code: Icon transitions can be implemented using AnimatedStateListDrawable and its XML counterpart. An example can be found in the Google I/O app source. There’s also support for animated vector icons.
  • Animations and transitions are fast—generally under 300ms.
  • Crossfades are often replaced by translate/slide transitions: vertical slides for descendant navigation and horizontal slides for lateral navigation. For slide transitions, prefer quick acceleration and gentle ease-in deceleration over simple linear moves. See the material design spec on motion for more.
Adaptive Design (and UI Patterns) Tangible surfaces, bold graphic design, and meaningful motion work together to bring a consistent experience across any screen, be it phones, tablets, laptops, desktops, TVs, wearables, or even cars. Additionally, the key UI patterns below help establish a consistent character for the app across devices.
Figure 5. The floating action button.
  • The app uses responsive design best practices to ensure screens lay themselves out appropriately on any screen size, in any orientation. See the Tablet App Quality Checklist for a list of ways to optimize for tablets, and this blog post for high-level tablet optimization tips.
    • In material design, detail screens are often presented as popups that appear using “hero” transitions (see above).
    • In multi-pane layouts, the app can use multiple toolbars to place actions contextually next to their related content.
  • Signature element: Where appropriate, the app promotes the key action on a screen using a circular floating action button (FAB). The FAB (Figure 5) is a circular surface, so it casts a shadow. It is colored with a bright, accent color (see above). It performs a primary action such as send, compose, create, add, or search. It floats in front of other surfaces, and is normally at an 8dp elevation. It frequently appears at the bottom right of the screen, or centered on an edge where two surfaces meet (a seam or a step).

App bar
  • Signature element: The app uses a standard Android app bar. The app bar doesn’t have an app icon. Color and typography are used for branding instead. The app bar casts a shadow (or has a shadow cast on it by a surface below and behind it). The app bar normally has a 4dp elevation. In code: Use the new Toolbar widget in Android 5.0 that is placed directly into the activity’s view hierarchy. AppCompat also provides android.support.v7.widget.Toolbar, which supports all modern platform versions.
  • The app bar might be for example 2 or 3 times taller than the standard height; on scroll, the app bar can smoothly collapse into its normal height.
  • The app bar might be completely transparent in some cases, with the text and actions overlaying an image behind it. For example, see the Google Play Newsstand app.
  • App bar titles align to the 2nd keyline (see more info on keylines above) In code: when using the Toolbar widget, use the android:contentInsetStart attribute.
  • Where appropriate, upon scrolling down, the app bar can scroll off the screen, leaving more vertical space for content. Upon scrolling back up, the app bar should be shown again.
Tabs
Figure 6. Tabs with material design.
  • Signature element: Tabs follow the newer material design interactions and styling (Figure 6). There are no vertical separators between tabs. If the app uses top-level tabs, tabs are visually a part of the app bar; tabs are a part of the app bar’s surface. In code: See the SlidingTabsBasic sample code in the SDK or the Google I/O app source (particularly the "My Schedule" section for phones).
  • Tabs should support a swipe gesture for moving between them. In code: All tabs should be swipeable using the ViewPager widget, which is available in the support library.
  • Selected tabs are indicated by a foreground color change and/or a small strip below the tab text (or icon) colored with an accent color. The tab strip should smoothly slide as you swipe between tabs.
Navigation drawer
Figure 7. Navigation drawers
with material design.
  • Signature element: If the app uses a navigation drawer, it follows the newer material design interactions and styling (Figure 7). The drawer appears in front of the app bar. It also appears semitransparent behind the status bar. In code: Implement drawers using the DrawerLayout widget from the support library, along with the new Toolbar widget discussed above. See this Stack Overflow post for more.
  • Signature element: The leftmost icon in the app bar is a navigation drawer indicator; the app icon is not visible in the app bar. Optionally, on earlier versions of the platform, if the app has a drawer, the top-left icon can remain the app icon and narrower drawer indicator, as in Android 4.0.
  • The drawer is a standard width: No wider than 320dp on phones and 400dp on tablets, but no narrower than the screen width minus the standard toolbar height (360dp - 56dp = 304dp on the Nexus 5)
  • Item heights in the drawer follow the baseline grid: 48dp tall rows, 8dp above list sections and 8dp above and below dividers.
  • Text and icons should follow the keylines discussed above.

More and more apps from Google and across the Google Play ecosystem will be updating with material design soon, so expect Winter 2014 to be a big quarter for design on Android. For more designer resources on material design, check out the DesignBytes series. For additional developer resources, check the Creating Apps with Material Design docs!

Join the discussion on

+Android Developers
Categories: Programming

Implementing material design in your Android app

Fri, 10/24/2014 - 20:18
By Chris Banes and Nick Butcher, Android Developer Relations

Material design is a comprehensive approach to visual, interaction and motion design for the multi-screen world. Android 5.0 Lollipop and the updated support libraries help you to create material UIs. Here’s a rundown of some of the major elements of material design and the APIs and widgets that you can use to implement them in your app.

Tangible surfaces

In material design, UIs are composed of pieces of digital paper & ink. The surfaces and the shadows they cast provide visual cues to the structure of the application, what you can touch and how it will move. This digital material can move, expand and reform to create flexible UIs.

Shadows

A surface’s position and depth result in subtle changes in lighting and shadows. The new elevation property lets you specify a view’s position on the Z-axis and the framework then casts a real-time dynamic shadow on items behind it. You can set the elevation declaratively in your layouts, defined in dips:

<ImageView …
    android:elevation="8dp" />

You can also set this from code using getElevation()/setElevation() (with shims in ViewCompat). The shadow a view casts is defined by its outline, which by default is derived from its background. For example if you set a circular shape drawable as the background for a floating action button, then it would cast an appropriate shadow. If you need finer control of a view’s shadow, you can set a ViewOutlineProvider which can customise the Outline in getOutline().

Cards

Cards are a common pattern for creating surfaces holding a distinct piece of information. The new CardView support library allows you to create them easily, providing outlines and shadows for you (with equivalent behaviour on prior platforms).

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <!-- Your card content -->

</android.support.v7.widget.CardView>

CardView extends FrameLayout and provides default elevation and corner radius for you so that cards have a consistent appearance across the platform. You can customise these via the cardElevation and cardCornerRadius attributes, if required. Note that Cards are not the only way of achieving dimensionality and you should be wary of over-cardifying your UI!

Print-like Design

Material utilises classic principles from print design to create clean, simple layouts that put your content front and center. Bold deliberate color choices, intentional whitespace, tasteful typography and a strong baseline grid create hierarchy, meaning and focus.

Typography

Android 5.0 updates the system font Roboto to beautifully and clearly display text no matter the display size. A new medium weight has been added (android:fontFamily=”sans-serif-medium”) and new TextAppearance styles implement the recommended typographic scale for balancing content density and reading comfort. For instance you can easily use the ‘Title’ style by setting android:textAppearance=”@android:style/TextAppearance.Material.Title”. These styles are available on older platforms through the AppCompat support library, e.g. “@style/TextAppearance.AppCompat.Title”.

Color

Your application’s color palette brings branding and personality to your app so we’ve made it simple to colorize UI controls by using the following theme attributes:

  • colorPrimary. The primary branding color for the app; used as the action bar background, recents task title and in edge effects.
  • colorAccent. Vibrant complement to the primary branding color. Applied to framework controls such as EditText and Switch.
  • colorPrimaryDark. Darker variant of the primary branding color; applied to the status bar.

Further attributes give fine grained control over colorizing controls, see: colorControlNormal, colorControlActivated, colorControlHighlight, colorButtonNormal, colorSwitchThumbNormal, colorEdgeEffect, statusBarColor and navigationBarColor.

AppCompat provides a large subset of the functionality above, allowing you to colorize controls on pre-Lollipop platforms.

Dynamic color

Material Design encourages dynamic use of color, especially when you have rich images to work with. The new Palette support library lets you extract a small set of colors from an image to style your UI controls to match; creating an immersive experience. The extracted palette will include vibrant and muted tones as well as foreground text colors for optimal legibility. For example:

Palette.generateAsync(bitmap,
        new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {
         Palette.Swatch vibrant =
                 palette.getVibrantSwatch();
          if (swatch != null) {
              // If we have a vibrant color
              // update the title TextView
              titleView.setBackgroundColor(
                  vibrant.getRgb());
              titleView.setTextColor(
                  vibrant.getTitleTextColor());
          }
    }
});
Authentic Motion

Tangible surfaces don’t just appear out of nowhere like a jump-cut in a movie; they move into place helping to focus attention, establish spatial relationships and maintain continuity. Materials respond to touch to confirm your interaction and all changes radiate outward from your touch point. All motion is meaningful and intimate, aiding the user’s comprehension.

Activity + Fragment Transitions

By declaring ‘shared elements’ that are common across two screens you can create a smooth transition between the two states.

album_grid.xml
…
    <ImageView
        …
        android:transitionName="@string/transition_album_cover" />
album_details.xml
…
    <ImageView
        …
        android:transitionName="@string/transition_album_cover" />

AlbumActivity.java
Intent intent = new Intent();
String transitionName = getString(R.string.transition_album_cover);
…
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
    albumCoverImageView,   // The view which starts the transition
    transitionName    // The transitionName of the view we’re transitioning to
    );
ActivityCompat.startActivity(activity, intent, options.toBundle());

Here we define the same transitionName in two screens. When starting the new Activity and this transition is animated automatically. In addition to shared elements, you can now also choreograph entering and exiting elements.

Ripples

Materials respond to users’ touch with an ink ripple surface reaction. Interactive controls such as Buttons exhibit this behaviour by default when you use or inherit from Theme.Material (as will ?android:selectableItemBackground). You can add this feedback to your own drawables by simply wrapping them in a ripple element:

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/accent_dark">
    <item>
        <shape
            android:shape="oval">
            <solid android:color="?android:colorAccent" />
        </shape>
    </item>
</ripple>

Custom views should propagate touch location down to their drawables in the View#drawableHotspotChanged callback so that the ripple can start from the touch point.

StateListAnimator

Materials also respond to touch by raising up to meet your finger, like a magnetic attraction. You can achieve this effect by animating the translationZ attribute which is analogous to elevation but intended for transient use; such that Z = elevation + translationZ. The new stateListAnimator attribute allows you to easily animate the translationZ on touch (Buttons do this by default):

layout/your_layout.xml
<ImageButton …
    android:stateListAnimator="@anim/raise" />
anim/raise.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:state_pressed="true">
        <objectAnimator
            android:duration="@android:integer/config_shortAnimTime"
            android:propertyName="translationZ"
            android:valueTo="@dimen/touch_raise"
            android:valueType="floatType" />
    </item>
    <item>
        <objectAnimator
            android:duration="@android:integer/config_shortAnimTime"
            android:propertyName="translationZ"
            android:valueTo="0dp"
            android:valueType="floatType" />
    </item>
</selector>
Reveal

A hallmark material transition for showing new content is to reveal it with an expanding circular mask. This helps to reinforce the user’s touchpoint as the start of all transitions, with its effects radiating outward radially. You can implement this using the following Animator:

Animator reveal = ViewAnimationUtils.createCircularReveal(
                    viewToReveal, // The new View to reveal
                    centerX,      // x co-ordinate to start the mask from
                    centerY,      // y co-ordinate to start the mask from
                    startRadius,  // radius of the starting mask
                    endRadius);   // radius of the final mask
reveal.start();
Interpolators

Motion should be deliberate, swift and precise. Unlike typical ease-in-ease-out transitions, in Material Design, objects tend to start quickly and ease into their final position. Over the course of the animation, the object spends more time near its final destination. As a result, the user isn’t left waiting for the animation to finish, and the negative effects of motion are minimized. A new fast-in-slow-out interpolator has been added to achieve this motion.

For elements entering and exiting the screen (which should do so at peak velocity), check out the linear-out-slow-in and fast-out-linear-in interpolators respectively.

Adaptive design

Our final core concept of material is creating a single adaptive design that works across devices of all sizes and shapes, from watches to giant TVs. Adaptive design techniques help us realize the vision that each device reflects a different view of the same underlying system. Each view is tailored to the size and interaction appropriate for that device. Colors, iconography, hierarchy, and spatial relationships remain constant. The material design system provides flexible components and patterns to help you build a design that scales.

Toolbar

The toolbar is a generalization of the action bar pattern, providing similar functionality, but much more flexibility. Unlike the standard action bar, toolbar is a view in your hierarchy just like any other, so you can place instances wherever you like, interleave them with the rest of your views, animate, react to scroll events and so on. You can make the Toolbar act as your Activity’s Action Bar by calling Activity.setActionBar().

In this example, the blue toolbar is an extended height, overlaid by the screen content and provides the navigation button. Note that two further toolbars are used in the list and detail views.

For details of implementing toolbars, see this post.

Go Forth and Materialize

Material Design helps you to build understandable, beautiful and adaptive apps, which are alive with motion. Hopefully, this post has inspired you to apply these principles to your app and signposted some of the new (and compatibility) APIs to achieve this.

Join the discussion on

+Android Developers
Categories: Programming

Getting Your Apps Ready for Nexus 6 and Nexus 9

Fri, 10/24/2014 - 00:53

By Katherine Kuan, Developer Advocate

Updated material design Tumblr app on Nexus 6.

Last week, we unveiled the Nexus 6 and Nexus 9, the newest additions to our Nexus family that will ship with Android 5.0 Lollipop. Together, they deliver a pure Google experience, showcasing fresh visual styles with material design, improved performance, and additional features.

Let’s make sure your apps and games are optimized to give your users the best mobile experience on these devices. We’ve outlined some best practices below.

Nexus 6 Screen

The Nexus 6 boasts an impressive 5.96” Quad HD screen display at a resolution of 2560 x 1440 (493 ppi). This translates to ~ 730 x 410 dp (density independent pixels).

Check your assets

It has a quantized density of 560 dpi, which falls in between the xxhdpi and xxxhdpi primary density buckets. For the Nexus 6, the platform will scale down xxxhdpi assets, but if those aren’t available, then it will scale up xxhdpi assets.

Provide at least an xxxhdpi app icon because devices can display large app icons on the launcher. It’s best practice to place your app icons in mipmap- folders (not the drawable- folders) because they are used at resolutions different from the device’s current density. For example, an xxxhdpi app icon can be used on the launcher for an xxhdpi device.

res/
   mipmap-mdpi/
      ic_launcher.png
   mipmap-hdpi/
      ic_launcher.png
   mipmap-xhdpi/
      ic_launcher.png  
   mipmap-xxhdpi/
      ic_launcher.png
   mipmap-xxxhdpi/   
      ic_launcher.png  # App icon used on Nexus 6 device launcher

Choosing to add xxxhdpi versions for the rest of your assets will provide a sharper visual experience on the Nexus 6, but does increase apk size, so you should make an appropriate decision for your app.

res/
   drawable-mdpi/
      ic_sunny.png
   drawable-hdpi/
      ic_sunny.png
   drawable-xhdpi/   
      ic_sunny.png
   drawable-xxhdpi/  # Fall back to these if xxxhdpi versions aren’t available
      ic_sunny.png 
   drawable-xxxhdpi/ # Higher resolution assets for Nexus 6
      ic_sunny.png
Make sure you are not filtered on Google Play

If you are using the <compatible-screens> element in the AndroidManifest.xml file, you should stop using it because it’s not scalable to re-compile and publish your app each time new devices come out. However, if you must use it, make sure to update the manifest to add the configuration for these devices (by screen size and density). Otherwise your app may be excluded from Google Play search results on these devices.

Nexus 9 Screen

The Nexus 9 is a premium 8.9” tablet with a screen size of 2048 x 1536 pixels (288 ppi), which translates to 1024 x 768 dip. This is a 4:3 aspect ratio, which is unique compared to earlier tablets. The Nexus 9 falls into the xhdpi density bucket, and you should already have assets in the drawable-xhdpi folder.

Updated Material Design Wall Street Journal app on Nexus 9.

Enable NDK apps for 64-bit

The Nexus 9 runs on a 64-bit Dual Core processor, which makes it the first Android device to ship with a 64-bit ARM instruction set. Support for 64-bit processors was just added in Android 5.0, so if you have an NDK app, enable it by updating the APP_ABI value in your Application.mk file:

APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64

More detailed instructions are provided in the developer site. You can test your 64-bit enabled app on a physical device with a 64-bit processor running Android 5.0, or take advantage of the recently announced 64-bit emulator in Android Studio.

Update your hardware keyboard support

The Nexus 9 Keyboard Folio will be available as an accessory in Google Play. It’s very important that you don’t lock your app to a single orientation. The Nexus 9’s natural orientation is portrait mode, while it’s used in landscape mode with the keyboard. If you lock to the device’s natural orientation, the app may appear sideways for devices with keyboards.

Users should be able to navigate around the main content of the app with the keyboard, while relying on touch input or keyboard shortcuts for toolbar actions and button bars. Therefore, ensure that your app has proper keyboard navigation and shortcuts for primary actions. Keyboard shortcuts that are invoked with Ctrl + [shortcut] combo can be defined via menu items using:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_create"
        android:title="@string/menu_create"
        android:alphabeticShortcut="c” />
</menu/>

Alternatively, shortcuts can be defined using Activity#onKeyShortcut or View#onKeyShortcut. Learn more about keyboard actions here.

In MainActivity.java:

@Override
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_R:
            Toast.makeText(this, "Reply", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onKeyShortcut(keyCode, event);
    }
}
Responsive layouts with w- and sw- qualifiers

In order to take advantage of the screen real estate on the Nexus 6 and Nexus 9, we emphasize the importance of responsive design. In the past, if you assumed that landscape mode is significantly wider than portrait mode, you may run into problems on a device like the Nexus 9, which has an aspect ratio of 4:3. Instead of declaring layouts using the layout-land or layout-port resource folder qualifiers, we strongly recommend switching to the w<N>dp width resource folder qualifier so that content is laid out based on available screen width.

Think about content first and foremost. Decide on min and max screen real estate that your content requires, and determine cutoff points at different screen widths where you can modify the layout composition for your app (# of grid columns, multi-pane layout, etc…).

For example, a single pane layout for your main activity on phones can be defined in:

res/layout/activity_main.xml

On larger screen devices, where the current orientation is at least 600dp in width, a new two-pane layout with a list alongside a detail pane could be declared in:

res/layout-w600dp/activity_main.xml

On even larger screen devices, where the current orientation is at least 720dp in width, a new multi-pane layout where the detail pane requires even more horizontal space could be declared in:

res/layout-w720dp/activity_main.xml

As for attributes based on form factor, instead of declaring them in values-large or values-xlarge resource directories, use the sw<N>dp smallest width qualifier. For example, you could style your TextViews to have a medium font size on phones.

In res/values/styles.xml:

<style name="DescriptionTextStyle">
  <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
</style>

Meanwhile, TextViews could have a large font size when the smallest width of the device (taking the minimum of the landscape and portrait widths) is 600dp or wider. This ensures the font size of your app doesn’t change when you rotate this large screen device.

In res/values-sw600dp/styles.xml:

<style name="DescriptionTextStyle">
  <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
</style> 
Take advantage of 5.0 and Material

Set your android:targetSdkVersion to "21". Take note of the important behavior changes in Android 5.0 Lollipop including ART, the new Android runtime, to ensure that your app continues to run well. You can also leverage new platform APIs like richer notifications.

Nexus 6 and Nexus 9 users will be immersed in the new world of material design, and they’ll expect the same seamless transitions, bold colors, and delightful details from your app. As you invest time in bringing your app up to date with our latest design language, there’s a whole host of resources to help you make the leap, including important new updates to the support library, videos, and a getting started guide. Good luck and we can’t wait to see your apps!

Join the discussion on

+Android Developers
Categories: Programming

GPS on Android Wear Devices

Fri, 10/24/2014 - 00:03

By Wayne Piekarski, Developer Advocate

With the latest release of Android Wear, wearables with built-in GPS like the Sony Smartwatch 3 can now give you a GPS location update directly from the wearable, without a paired phone nearby. You can now build an app like MyTracks that lets a user track their run even when they leave their phone at home. For wearable devices that do not have built-in GPS, a software solution has always existed in Google Play Services that automatically uses the GPS from your connected phone.

The Golfshot wearable app uses built-in GPS to calculate your distance to the next hole, even when you don’t have your phone with you.


Implementing GPS location updates

Implementing GPS location updates for Android Wear is simple. On the wearable, use the FusedLocationProviderApi from Google Play services to request location updates. This is the same API that has been available on mobile, so you can easily reuse your existing code and samples.

FusedLocationProviderApi automatically makes the most power-efficient decision about where to get location updates. If the phone is connected to the wearable, it uses the GPS on the phone and sends the updates to the wearable. If the phone is not connected to the wearable and the wearable has a built-in GPS, then it uses the wearable’s GPS.

One case you’ll need to handle is if the phone is not connected to the wearable and the wearable does not have built-in GPS. You will need to detect this and provide a graceful recovery mechanism, such as a message telling the user to bring their phone with them. However, for the most part, deciding which GPS to use, and sending the position from the phone to the wearable, is handled automatically. You do not need to deal with the low-level implementation details yourself.

Data synchronization

When writing an app that runs on the wearable, you will eventually want to synchronize the data it collects with the paired phone. When the wearable is being taken out for a run, especially with the built-in GPS, there may not be a phone present. So you will want to store your location data using the Data Layer API, and when the phone reconnects with the wearable later, the data will be automatically synchronized.

For more details about how to use the location API, check out the extensive documentation and sample here.

Android Wear apps on Google Play

Also, as a heads up, starting on November 3 with the public release of Android 5.0, you will be able to submit your apps for clearer designation as Android Wear apps on Google Play. If your apps follow the criteria in the Wear App Quality checklist and are accepted as Wear apps on Play, it will be easier for Android Wear users to discover your apps. Stay tuned for more information about how to submit your apps for Android Wear review through the Google Play Developer Console.

Join the discussion on

+Android Developers
Categories: Programming

AppCompat v21 — Material Design for Pre-Lollipop Devices!

Wed, 10/22/2014 - 22:58

By Chris Banes, Android Developer Relations

The Android 5.0 SDK was released last Friday, featuring new UI widgets and material design, our visual language focused on good design. To enable you to bring your latest designs to older Android platforms we have expanded our support libraries, including a major update to AppCompat, as well as new RecyclerView, CardView and Palette libraries.

In this post we'll take a look at what’s new in AppCompat and how you can use it to support material design in your apps.

What's new in AppCompat?

AppCompat (aka ActionBarCompat) started out as a backport of the Android 4.0 ActionBar API for devices running on Gingerbread, providing a common API layer on top of the backported implementation and the framework implementation. AppCompat v21 delivers an API and feature-set that is up-to-date with Android 5.0

In this release, Android introduces a new Toolbar widget. This is a generalization of the Action Bar pattern that gives you much more control and flexibility. Toolbar is a view in your hierarchy just like any other, making it easier to interleave with the rest of your views, animate it, and react to scroll events. You can also set it as your Activity’s action bar, meaning that your standard options menu actions will be display within it.

You’ve likely already been using the latest update to AppCompat for a while, it has been included in various Google app updates over the past few weeks, including Play Store and Play Newsstand. It has also been integrated into the Google I/O Android app, pictured above, which is open-source.

Setup

If you’re using Gradle, add appcompat as a dependency in your build.gradle file:

dependencies {
    compile "com.android.support:appcompat-v7:21.0.+"
}
New integration

If you are not currently using AppCompat, or you are starting from scratch, here's how to set it up:

  • All of your Activities must extend from ActionBarActivity, which extends from FragmentActivity from the v4 support library, so you can continue to use fragments.
  • All of your themes (that want an Action Bar/Toolbar) must inherit from Theme.AppCompat. There are variants available, including Light and NoActionBar.
  • When inflating anything to be displayed on the action bar (such as a SpinnerAdapter for list navigation in the toolbar), make sure you use the action bar’s themed context, retrieved via getSupportActionBar().getThemedContext().
  • You must use the static methods in MenuItemCompat for any action-related calls on a MenuItem.

For more information, see the Action Bar API guide which is a comprehensive guide on AppCompat.

Migration from previous setup

For most apps, you now only need one theme declaration, in values/:

values/themes.xml:

<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- Set AppCompat’s actionBarStyle -->
    <item name="actionBarStyle">@style/MyActionBarStyle</item>

    <!-- Set AppCompat’s color theming attrs -->
    <item name=”colorPrimary”>@color/my_awesome_red</item>
    <item name=”colorPrimaryDark”>@color/my_awesome_darker_red</item>
    
    <!-- The rest of your attributes -->
</style>

You can now remove all of your values-v14+ Action Bar styles.

Theming

AppCompat has support for the new color palette theme attributes which allow you to easily customize your theme to fit your brand with primary and accent colors. For example:

values/themes.xml:

<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- colorPrimary is used for the default action bar background -->
    <item name=”colorPrimary”>@color/my_awesome_color</item>

    <!-- colorPrimaryDark is used for the status bar -->
    <item name=”colorPrimaryDark”>@color/my_awesome_darker_color</item>

    <!-- colorAccent is used as the default value for colorControlActivated,
         which is used to tint widgets -->
    <item name=”colorAccent”>@color/accent</item>

    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight, and colorSwitchThumbNormal. -->
    
</style>

When you set these attributes, AppCompat automatically propagates their values to the framework attributes on API 21+. This automatically colors the status bar and Overview (Recents) task entry.

On older platforms, AppCompat emulates the color theming where possible. At the moment this is limited to coloring the action bar and some widgets.

Widget tinting

When running on devices with Android 5.0, all of the widgets are tinted using the color theme attributes we just talked about. There are two main features which allow this on Lollipop: drawable tinting, and referencing theme attributes (of the form ?attr/foo) in drawables.

AppCompat provides similar behaviour on earlier versions of Android for a subset of UI widgets:

You don’t need to do anything special to make these work, just use these controls in your layouts as usual and AppCompat will do the rest (with some caveats; see the FAQ below).

Toolbar Widget

Toolbar is fully supported in AppCompat and has feature and API parity with the framework widget. In AppCompat, Toolbar is implemented in the android.support.v7.widget.Toolbar class. There are two ways to use Toolbar:

  • Use a Toolbar as an Action Bar when you want to use the existing Action Bar facilities (such as menu inflation and selection, ActionBarDrawerToggle, and so on) but want to have more control over its appearance.
  • Use a standalone Toolbar when you want to use the pattern in your app for situations that an Action Bar would not support; for example, showing multiple toolbars on the screen, spanning only part of the width, and so on.
Action Bar

To use Toolbar as an Action Bar, first disable the decor-provided Action Bar. The easiest way is to have your theme extend from Theme.AppCompat.NoActionBar (or its light variant).

Second, create a Toolbar instance, usually via your layout XML:

<android.support.v7.widget.Toolbar
    android:id=”@+id/my_awesome_toolbar”
    android:layout_height=”wrap_content”
    android:layout_width=”match_parent”
    android:minHeight=”?attr/actionBarSize”
    android:background=”?attr/colorPrimary” />

The height, width, background, and so on are totally up to you; these are just good examples. As Toolbar is just a ViewGroup, you can style and position it however you want.

Then in your Activity or Fragment, set the Toolbar to act as your Action Bar:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.blah);

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);
}

From this point on, all menu items are displayed in your Toolbar, populated via the standard options menu callbacks.

Standalone

The difference in standalone mode is that you do not set the Toolbar to act as your action bar. For this reason, you can use any AppCompat theme and you do not need to disable the decor-provided Action Bar.

In standalone mode, you need to manually populate the Toolbar with content/actions. For instance, if you want it to display actions, you need to inflate a menu into it:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.blah);

    Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);

    // Set an OnMenuItemClickListener to handle menu item clicks
    toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            // Handle the menu item
            return true;
        }
    });

    // Inflate a menu to be displayed in the toolbar
    toolbar.inflateMenu(R.menu.your_toolbar_menu);
}

There are many other things you can do with Toolbar. For more information, see the Toolbar API reference.

Styling

Styling of Toolbar is done differently to the standard action bar, and is set directly onto the view.

Here's a basic style you should be using when you're using a Toolbar as your action bar:

<android.support.v7.widget.Toolbar  
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

The app:theme declaration will make sure that your text and items are using solid colors (i.e 100% opacity white).

DarkActionBar

You can style Toolbar instances directly using layout attributes. To achieve a Toolbar which looks like 'DarkActionBar' (dark content, light overflow menu), provide the theme and popupTheme attributes:

<android.support.v7.widget.Toolbar
    android:layout_height=”wrap_content”
    android:layout_width=”match_parent”
    android:minHeight=”@dimen/triple_height_toolbar”
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
SearchView Widget

AppCompat offers Lollipop’s updated SearchView API, which is far more customizable and styleable (queue the applause). We now use the Lollipop style structure instead of the old searchView* theme attributes.

Here’s how you style SearchView:

values/themes.xml:
<style name=”Theme.MyTheme” parent=”Theme.AppCompat”>
    <item name=”searchViewStyle”>@style/MySearchViewStyle</item>
</style>
<style name=”MySearchViewStyle” parent=”Widget.AppCompat.SearchView”>
    <!-- Background for the search query section (e.g. EditText) -->
    <item name="queryBackground">...</item>
    <!-- Background for the actions section (e.g. voice, submit) -->
    <item name="submitBackground">...</item>
    <!-- Close button icon -->
    <item name="closeIcon">...</item>
    <!-- Search button icon -->
    <item name="searchIcon">...</item>
    <!-- Go/commit button icon -->
    <item name="goIcon">...</item>
    <!-- Voice search button icon -->
    <item name="voiceIcon">...</item>
    <!-- Commit icon shown in the query suggestion row -->
    <item name="commitIcon">...</item>
    <!-- Layout for query suggestion rows -->
    <item name="suggestionRowLayout">...</item>
</style>

You do not need to set all (or any) of these, the defaults will work for the majority of apps.

Toolbar is coming...

Hopefully this post will help you get up and running with AppCompat and let you create some awesome material apps. Let us know in the comments/G+/Twitter if you’re have questions about AppCompat or any of the support libraries, or where we could provide more documentation.

FAQ
Why is my EditText (or other widget listed above) not being tinted correctly on my pre-Lollipop device?

The widget tinting in AppCompat works by intercepting any layout inflation and inserting a special tint-aware version of the widget in its place. For most people this will work fine, but I can think of a few scenarios where this won’t work, including:

  • You have your own custom version of the widget (i.e. you’ve extended EditText)
  • You are creating the EditText without a LayoutInflater (i.e., calling new EditText()).

The special tint-aware widgets are currently hidden as they’re an unfinished implementation detail. This may change in the future.

Why has X widget not been material-styled when running on pre-Lollipop?
Only some of the most common widgets have been updated so far. There are more coming in future releases of AppCompat.
Why does my Action Bar have a shadow on Android Lollipop? I’ve set android:windowContentOverlay to null.
On Lollipop, the action bar shadow is provided using the new elevation API. To remove it, either call getSupportActionBar().setElevation(0), or set the elevation attribute in your Action Bar style.
Why are there no ripples on pre-Lollipop?
A lot of what allows RippleDrawable to run smoothly is Android 5.0’s new RenderThread. To optimize for performance on previous versions of Android, we've left RippleDrawable out for now.
How do I use AppCompat with Preferences?
You can continue to use PreferenceFragment in your ActionBarActivity when running on an API v11+ device. For devices before that, you will need to provide a normal PreferenceActivity which is not material-styled.
Join the discussion on

+Android Developers
Categories: Programming

What's New in Android 5.0 Lollipop

Tue, 10/21/2014 - 09:06

By Ankur Kotwal, Developer Advocate

Android 5.0 Lollipop is the biggest update of Android to date, introducing an all new visual style, improved performance, and much more. Android 5.0 Lollipop also extends across screens big and small, including phones, tablets, wearables, TVs and cars, to give your users access to information when they need it most.

To get you started on developing and testing on Android 5.0 Lollipop, here are some of the developer highlights with links to related videos and documentation.

User experience
  • Material design for the multiscreen world — Material Design is a new approach for designing apps in today’s multi-device world that takes a comprehensive strategy to visual, motion, and interaction design across a number of platforms and form factors. Android 5.0 brings Material Design to the platform, with a full set of tools for implementing material design in your apps. The system is incredibly flexible, allowing your app to express its individual character and brand with bold colors and a variety of responsive UI patterns and themeable elements.
  • Enhanced notifications — New lockscreen notifications let you surface content, updates, and actions to users at a glance, without needing to unlock their device. Heads-up notifications let you display content and actions in a small floating window managed by the system, no matter which app is in the foreground. Notifications are refreshed for Material Design and you can use accent colors to express your brand.
  • Concurrent documents in Overview — Now you can organize your app by tasks and present these concurrently as individual “documents” on the Overview screen. For example, instant messaging apps could declare each chat as a separate document. Users can flip through these on the Overview screen to find the specific chat they want and jump straight to it.
Performance
  • Android Runtime (ART) — Android 5.0 runs exclusively on the ART runtime. ART offers ahead-of-time (AOT) compilation, more efficient garbage collection, and improved development and debugging features. In many cases it improves performance of the device, without you having to change your code.
  • 64-bit support — Support for 64-bit ABIs provides additional address space and improved performance with certain compute workloads. Apps written in the Java language can run immediately on 64-bit architectures with no modifications required. NDK r10c includes 64-bit support, for apps and games using native code.
  • Project Volta — New tools and APIs help you build battery-efficient apps. Battery Historian, a tool included in the SDK, lets you visualize power events over time and understand how your app is using battery. The JobScheduler API lets you set the conditions under which your background tasks and other jobs should run, such as when the device is idle or connected to an unmetered network or to a charger, to minimize battery impact. More in this I/O video.
  • OpenGL ES 3.1 and Android Extension Pack — With OpenGL ES 3.1, you get compute shaders, stencil textures, and texture gather for your games. Android Extension Pack (AEP) is a new set of extensions to OpenGL ES that bring desktop-class graphics to Android including tessellation and geometry shaders, and use ASTC texture compression across GPU technologies. More on what's new for game developers in this DevBytes video.
  • WebView updates — We’ve updated WebView to support WebRTC, WebAudio and WebGL will be supported. WebView also includes native support for all of the Web Components specifications: Custom Elements, Shadow DOM, HTML Imports, and Templates. WebView is now unbundled from the system and will be regularly updated through Google Play.
Workplace
  • Managed provisioning and unified view of apps — to make it easier for employees to have a single device for personal and work use, framework enhancements offer a unified view of apps, notifications & recents across work apps and personal apps. Profile owner APIs, in the workplace context, let administrators create and manage work profiles and defined as part of a new managed provisioning process. More in this I/O video.
Media
  • Advanced camera capabilities — A new camera API gives you new capabilities for advanced image capture and processing. On supported devices, your app can capture uncompressed YUV capture at full 8 megapixel resolution at 30 FPS. You can also capture raw sensor data and control parameters such as exposure time, ISO sensitivity, and frame duration, on a per-frame basis.
  • Audio improvements — The sound architecture has been enhanced, with lower input latency in OpenSL, the addition of multichannel-mixing, and USB digital audio mode support. More in this I/O video.
Connectivity
  • BLE Peripheral Mode — Android devices can now function in Bluetooth Low Energy (BLE) peripheral mode. Apps can use this capability to broadcast their presence to nearby devices — for example, you can now build apps that let a device function as a beacon and transmit data to another BLE device. More in this I/O video.
  • Multi-networking — Apps can dynamically request networks based on capabilities such as metered or unmetered. This is useful when you want to use a specific network, such as cellular. Apps can also request platform to re-evaluate networks for an internet connection. This is useful when your app sees unusually high latency on a particular network, it can enable the platform to switch to a better network (if available) sooner with a graceful handoff.
Get started!

You can get started developing and testing on Android 5.0 right away by downloading the Android 5.0 Platform (API level 21), as well as the SDK Tools, Platform Tools, and Support Package from the Android SDK Manager.

Check out the DevByte video below for more of what’s new in Lollipop!



Join the discussion on
+Android Developers


Categories: Programming

Android 5.0 Lollipop SDK and Nexus Preview Images

Sun, 10/19/2014 - 07:12

Two more weeks!

By Jamal Eason, Product Manager, Android

At Google I/O last June, we gave you an early version of Android 5.0 with the L Developer Preview, running on Nexus 5, Nexus 7 and Android TV. Over the course of the L Developer Preview program, you’ve given us great feedback and we appreciate the engagement from you, our developer community. Thanks!

This week, we announced Android 5.0 Lollipop. Starting today, you can download the full release of the Android 5.0 SDK, along with updated developer images for Nexus 5, Nexus 7 (2013), ADT-1, and the Android emulator.

The first set of devices to run this new version of Android -- Nexus 6, Nexus 9, and Nexus Player -- will be available in early November. In the same timeframe, we'll also roll out the Android 5.0 update worldwide to Nexus 4, 5, 7 (2012 & 2013), and 10 devices, as well as to Google Play edition devices.

Therefore, now is the time to test your apps on the new platform. You have two more weeks to get ready!

What’s in Lollipop?

Android 5.0 Lollipop introduces a host of new APIs and features including:

There's much more, so check out the Android 5.0 platform highlights for a complete overview.

What’s in the Android 5.0 SDK?

The Android 5.0 SDK includes updated tools and new developer system images for testing. You can develop against the latest Android platform using API level 21 and take advantage of the updated support library to implement Material Design as well as the leanback user interface for TV apps.

You can download these components through the Android SDK Manager and develop your app in Android Studio:

  • Android 5.0 SDK Platform & Tools
  • Android 5.0 Emulator System Image - 32-bit & 64-bit (x86)
  • Android 5.0 Emulator System Image for Android TV (32-bit)
  • Android v7 appcompat Support Library for Material Design theme backwards capability
  • Android v17 leanback library for Android TV app support

For developers using the Android NDK for native C/C++ Android apps we have:

For developers on Android TV devices we have:

  • Android 5.0 system image over the air (OTA) update for ADT-1 Developer Kit. OTA updates will appear over the next few days.

Similar to our previous release of the preview, we are also providing updated system image downloads for Nexus 5 & Nexus 7 (2013) devices to help with your testing as well. These images support the Android 5.0 SDK, but only have the minimal apps pre-installed in order to enable developer testing:

  • Nexus 5 (GSM/LTE) “hammerhead” Device System Image
  • Nexus 7 (2013) - (Wifi) “razor” Device System Image

For the developer preview versions, there will not be an over the air (OTA) update. You will need to wipe and reflash your developer device to use the latest developer preview versions. If you want to receive the official consumer OTA update in November and any other official updates, you will have to have a factory image on your Nexus device.

Validate your apps with the Android 5.0 SDK

With the consumer availability of Android 5.0 and the Nexus 6, Nexus 9, and Nexus Player right around the corner, here are a few things you should do to prepare:

  1. Get the emulator system images through the SDK Manager or download the Nexus device system images.
  2. Recompile your apps against Android 5.0 SDK, especially if you used any preview APIs. Note: APIs have changed between the preview SDK and the final SDK.
  3. Validate that your current Android apps run on the new API 21 level with ART enabled. And if you use the NDK for your C/C++ Android apps, validate against the 64-bit emulator. ART is enabled by default on API 21 & new Android devices with Android 5.0.

Once you validate your current app, explore the new APIs and features for Android 5.0.

Migrate Your Existing App to Material Design

Android 5.0 Lollipop introduces Material Design, which enables your apps to adopt a bold, colorful, and flexible design, while remaining true to a small set of key principles that guide user interaction across multiple screens and devices.

After making sure your current apps work with Android 5.0, now is the time to enable the Material theme in your app with the AppCompat support library. For quick tips & recommendations for making your app shine with Material Design, check out our Material Design guidelines and tablet optimization tips. For those of you new to Material Design, check out our Getting Started guide.

Get your apps ready for Google Play!

Starting today, you can publish your apps that are targeting Android 5.0 Lollipop to Google Play. In your app manifest, update android:targetSdkVersion to "21", test your app, and upload it to the Google Play Developer Console.

Starting November 3rd, Nexus 9 will be the first device available to consumers that will run Android 5.0. Therefore, it is a great time to publish on Google Play, once you've updated and tested your app. Even if your apps target earlier versions of Android, take a few moments to test them on the Android 5.0 system images, and publish any updates needed in advance of the Android 5.0 rollout.

Stay tuned for more details on the Nexus 6 and Nexus 9 devices, and how to make sure your apps look their best on them.

Next up, Android TV!

We also announced the first consumer Android TV device, Nexus Player. It’s a streaming media player for movies, music and videos, and also a first-of-its-kind Android gaming device. Users can play games on their HDTVs with a gamepad, then keep playing on their phones while they’re on the road. The device is also Google Cast-enabled, so users can cast your app from their phones or tablets to their TV.

If you’re developing for Android TV, watch for more information on November 3rd about how to distribute your apps to Android TV users through the Google Play Developer Console. You can start getting your app ready by making sure it meets all of the TV Quality Guidelines.

Get started with Android 5.0 Lollipop platform

If you haven’t had a chance to take a look at this new version of Android yet, download the SDK and get started today. You can learn more about what’s new in the Android 5.0 platform highlights and get all the details on new APIs and changed behaviors in the API Overview. You can also check out the latest DevBytes videos to learn more about Android 5.0 features.

Enjoy this new release of Android!

Join the discussion on

+Android Developers
Categories: Programming

Google Play Services 6.1

Wed, 10/08/2014 - 19:05
gps

Google Play services 6.1 is now rolled out to devices worldwide, bringing you the newest features from Google to help you optimize your apps. You can get started developing today by downloading the Google Play services SDK from the Android SDK Manager.

Google Play services 6.1 adds Enhanced Ecommerce analytics support from Google Tag Manager and offers new improvements to the Google Drive Android API. With the latest release, we’re also including a refresh of the Google Fit developer preview, so that you can test your fitness apps on any Android device.

Analytics

Launched in Google Play services 5.0, Enhanced Ecommerce is an analytics extension designed to provide richer insights into pre-purchase shopping behavior and into product performance. It’s a great way to gain visibility into the full customer journey, helping you understand how different user acquisition campaigns are performing at a granular level. By including support for Enhanced Ecommerce in Google Tag Manager with the latest release of Google Play services, we are supercharging your ability to regularly update and manage tags on mobile apps more easily, so that you can consistently measure product impressions, shopping funnel events, and more.

Drive

To make it easier to use Drive, we added enhancements to the Google Drive Android API. With the new Completion Events feature, you can see when actions are committed to the server and improve the response time to conflicts. Material design elements have been incorporated into the File Picker UI, along with the addition of Recent and Starred views. A new setParents() method enables you to organize files and folders, while the previous Contents class has been replaced with a simpler DriveContents class.

Learn more about how to use these new features in this DevBytes video.

Google Fit

Initially introduced in August, the Google Fit Developer Preview has been refreshed to enable you to test your new fitness apps on any Android device. We expect to make additional changes to the APIs, so please check back with us on new developments.

Get Started

To get started developing, download the latest Google Play services SDK from the Android SDK Manager. For details on the new APIs, take a look at the New Features documentation. For setup information, see Set Up Google Play Services SDK.

To learn more about Google Play services and the APIs available to you through it, visit the Google Services section on the Android Developers site.

We hope you enjoy this release of Google Play services!




Join the discussion on
+Android Developers


Categories: Programming

Updated Cross-Platform Tools in Google Play Game Services

Tue, 10/07/2014 - 22:51

By Ben Frenkel, Google Play Games team

Game services UIs are now updated for material design, across all of the SDKs.

Game developers, we've updated some of our popular developer tools to give you a consistent set of game services across platforms, a refreshed UI based on material design, and new tools to give you better visibility into what users are doing in your games.

Let’s take a look at the new features.

Real-time Multiplayer in the Play Games cross-platform C++ SDK

To make it easier to build cross-platform games, we’ve added Real-Time Multiplayer (RTMP) to the latest Google Play Games C++ SDK. The addition of RTMP brings the C++ SDK to feature parity with the Play services SDK on Android and the Play Games iOS SDK. Learn more »

Material Design refresh across Android, cross-platform C++, and iOS SDKs

We’ve incorporated material design into the user-interface of the latest Play Games services SDKs for Android, cross-platform C++, and iOS. This gives you a bold, colorful design that’s consistent across all of your games, for all of your users. Learn more »

New quests features and completion statistics

Quests are a popular way to increase player engagement by adding fresh content without updating your game. We’ve added some new features to quests to make them easier to implement and manage.

First, we’ve simplified quests implementations by providing out-of-the-box toasts for “quest accepted” and “quest completed” events. You can invoke these toasts from your game with just a single call, on any platform. This removes the need to create your own custom toasts, though you are still free to do so.

You also have more insight into how your quests are performing through new in-line quest stats in the Developer Console. With these stats, you can better monitor how many people are completing their quests, so you can adjust the criteria to make them easier to achieve, if needed. Learn more »

Last, we’ve eliminated the 24-hour lead-time requirement for publishing and allowing repeating quests to have the same name. You now have the freedom to publish quests whenever you want with whatever name you want.

New quest stats let you see how many users are completing their quests.

Multiplayer game statistics

Now when you add multiplayer support through Google Play game services, you get multiplayer stats for free, without having to implement a custom logging solution. You can simply visit the Developer Console to see how players are using your multiplayer integration and look at trends in overall usage. The new stats are available as tabs under the Engagement section. Learn more »

Multiplayer stats let you see trends in how players are using your app's multiplayer integration.

New game services insights and alerts

We’re continuing to expand the types of alerts we offer the Developer Console to let you know about more types of issues that might be affecting your users' gameplay experiences. You’ll now get an alert when you have a broken implementation of real-time and turn-based multiplayer, and we’ll also notify you if your Achievements and Leaderboard implementations use too many duplicate images. Learn more »

Get Started

You can get started with all of these new features right away. Visit the Google Play game services developer site to download the updated SDKs. For migration details on the Game Services SDK for iOS, see the release notes. You can take a look at the new stats and alerts by visiting the Google Play Developer Console.

Join the discussion on

+Android Developers
Categories: Programming

Tips for Error Handling with Android Wear APIs

Sat, 10/04/2014 - 04:54

By +Wayne Piekarski, Developer Advocate, Android Wear

For developers using the Android Wear APIs in Google Play services, it is important to correctly handle all the error conditions that can occur on legacy phones or when users do not have a wearable device. This post describes the best practice in handling error conditions with the GoogleApiClient connect() method. If you do not implement this correctly, your existing application functionality may fail for non-wearable users.

There are two ways that the connect() method can return ConnectionResult.API_UNAVAILABLE for wearable support with Google Play services:

  • When requesting Wearable.API on any device running Android 4.2 (API level 17) or earlier
  • When requesting Wearable.API when no Android Wear companion application or device is available

Google Play services provides a wide range of useful features such as integration with Google Drive, Wallet, Google+, and Google Play games services (just to name a few!). During initialization, the application uses GoogleApiClient.Builder() to make calls to addApi() to request the features that are necessary. The connect() method is then called to establish a connection to the Google Play services library, and it can return error codes if any API is not available.

If you request multiple APIs from a single GoogleApiClient, such as Drive and Wear, and the Wear support returns API_UNAVAILABLE, then the Drive request will also fail. Since Wear support is not guaranteed to be available on all devices, you should make sure to use a separate client for this request.

The best practice for developers is to implement two separate GoogleApiClient connections:

  • One connection for Android Wear support, and
  • A separate connection for all of the other APIs you need

This will ensure that the functionality of your app will remain for all users, whether or not there is wearable support available on their devices, as well as on older legacy devices.

It's important that you implement this best practice immediately, because your current users may be affected if not handled correctly in your app.

Join the discussion on

+Android Developers
Categories: Programming

Allthecooks on Android Wear

Wed, 09/24/2014 - 21:56

By Hoi Lam, Developer Advocate, Android Wear

The best cooking companion since the apron?

Android Wear is designed for serving up useful information at just the right time and in the right place. A neat example of this is Allthecooks Recipes. It gives you the right recipe, right when you need it.

This app is a great illustration of the four creative visions for Android Wear:

  1. Launched automatically
  2. Glanceable
  3. Suggest and demand
  4. Zero or low interaction

Allthecooks also shows what developers can do by combining both the power of the mobile device and the convenience of Android Wear.

Pick the best tool for the job

One particularly well-designed aspect of Allthecooks is their approach to the multi-device experience. Allthecooks lets the user search and browse the different recipes on their Android phone or tablet. When the user is ready, there is a clearly labelled blue action link to send the recipe to the watch.

The integration is natural. Using the on-screen keyboard and the larger screen real estate, Allthecooks is using the best screen to browse through the recipes. On the wearables side, the recipe is synchronised by using the DataApi and is launched automatically, fulfilling one of the key creative visions for Android Wear.

The end result? The mobile / Wear integration is seamless.

Thoughtful navigation

Once the recipe has been sent to the Android Wear device, Allthecooks splits the steps into easily glanceable pages. At the end of that list of steps, it allows the user to jump back to the beginning with a clearly marked button.

This means if you would like to browse through the steps before starting to cook, you can effortlessly get to the beginning again without swiping through all the pages. This is a great example of two other points in the vision: glanceable and zero or low interaction.

A great (cooking) assistant

One of the key ingredients of great cooking is timing, and Allthecooks is always on hand to do all the inputs for you when you are ready to start the clock. A simple tap on the blue “1” and Allthecooks will automatically set the timer to one hour. It is a gentle suggestion that Allthecooks can set the timer for you if you want.

Alternatively, if you want to use your egg timer, why not? It is a small detail but it really demonstrates the last and final element of Android Wear’s vision of suggest and demand. It is an ever ready assistant when the user wants it. At the same time, it is respectful and does not force the user to go down a route that the user does not want.

It’s about the details

Great design is about being user-centric and paying attention to details. Allthecooks could have just shrunk their mobile app for wear. Instead the Allthecooks team put a lot of thoughts into the design and leveraged all four points of the Android Wear creative vision. The end result is that the user can get the best experience out of both their Android mobile device and their Android Wear device. So developers, what will you be cooking next on Android Wear?

For more inspiring Android Wear user experiences, check out the Android Wear collection on Google Play!


Join the discussion on
+Android Developers


Categories: Programming

Conference Data Sync and GCM in the Google I/O App

Tue, 09/23/2014 - 18:44
By Bruno Oliveira, tech lead of the 2014 Google I/O mobile app

Keeping data in sync with the cloud is an important part of many applications, and the Google I/O App is no exception. To do this, we leverage the standard Android mechanism for this purpose: a Sync Adapter. Using a Sync Adapter has many benefits over using a more rudimentary mechanism such as setting up recurring alarms, because the system automatically handles the scheduling of Sync Adapters to optimize battery life.

We store the data in a local SQLite database. However, rather than having the whole application access that database directly, the application employs another standard Android mechanism to control and organize access to that data. This structure is, naturally, a Content Provider. Only the content provider's implementation has direct access to the SQLite database. All other parts of the app can only access data through the Content Resolver. This allows for a very flexible decoupling between the representation of the data in the database and the more abstract view of that data that is used throughout the app.

The I/O app maintains with two main kinds of data: conference data (sessions, speakers, rooms, etc) and user data (the user's personalized schedule). Conference data is kept up to date with a one-way sync from a set of JSON files stored in Google Cloud Storage, whereas user data goes through a two-way sync with a file stored in the user's Google Drive AppData folder.

Downloading Conference Data Efficiently

For a conference like Google I/O, conference data can be somewhat large. It consists of information about all the sessions, rooms, speakers, map locations, social hashtags, video library items and others. Downloading the whole data set repeatedly would be wasteful both in terms of battery and bandwidth, so we adopt a strategy to minimize the amount of data we download and process.

This strategy is separating the data into several different JSON files, and having them be referenced by a central master JSON file called the manifest file. The URL of the manifest file is the only URL that is hard-coded into the app (it is defined by the MANIFEST_URL constant in Config.java). Note that the I/O app uses Google Cloud Storage to store and serve these files, but any robust hosting service accessible via HTTP can be used for the same purpose.

The first part of the sync process is checking if the manifest file was changed since the app last downloaded it, and processing it only if it's newer. This logic is implemented by the fetchConfenceDataIfNewer method in RemoteConferenceDataFetcher.

public class RemoteConferenceDataFetcher {
    // (...)
    public String[] fetchConferenceDataIfNewer(String refTimestamp) throws IOException {
        BasicHttpClient httpClient = new BasicHttpClient();
        httpClient.setRequestLogger(mQuietLogger);
        // (...)

        // Only download if data is newer than refTimestamp
        if (!TextUtils.isEmpty(refTimestamp) && TimeUtils
            .isValidFormatForIfModifiedSinceHeader(refTimestamp)) {
                httpClient.addHeader("If-Modified-Since", refTimestamp);
            }
        }

        HttpResponse response = httpClient.get(mManifestUrl, null);
        int status = response.getStatus();
        if (status == HttpURLConnection.HTTP_OK) {
            // Data modified since we last checked -- process it!
        } else if (status == HttpURLConnection.HTTP_NOT_MODIFIED) {
            // data on the server is not newer than our data - no work to do!
            return null;
        } else {
            // (handle error)
        }
    }
    // (...)
}

Notice that we submit the HTTP If-Modified-Since header with our request, so that if the manifest hasn't changed since we last checked it, we will get an HTTP response code of HTTP_NOT_MODIFIED rather than HTTP_OK, we will react by skipping the download and parsing process. This means that unless the manifest has changed since we last saw it, the sync process is very economical: it consists only of a single HTTP request and a short response.

The manifest file's format is straightforward: it consists of references to other JSON files that contain the relevant pieces of the conference data:

{
  "format": "iosched-json-v1",
  "data_files": [
    "past_io_videolibrary_v5.json",
    "experts_v11.json",
    "hashtags_v8.json",
    "blocks_v10.json",
    "map_v11.json",
    "keynote_v10.json",
    "partners_v2.json",
    "session_data_v2.681.json"
  ]
}

The sync process then proceeds to process each of the listed data files in order. This part is also implemented to be as economical as possible: if we detect that we already have a cached version of a specific data file, we skip it entirely and use our local cache instead. This task is done by the processManifest method.

Then, each JSON file is parsed and the entities present in each one are accumulated in memory. At the end of this process, the data is written to the Content Provider.

Issuing Content Provider Operations Efficiently

The conference data sync needs to be efficient not only in the amount of data it downloads, but also in the amount of operations it performs on the database. This must be done as economically as possible, so this step is also optimized: instead of overwriting the whole database with the new data, the Sync Adapter attempts to preserve the existing entities and only update the ones that have changed. In our tests, this optimization step reduced the total sync time from 16 seconds to around 2 seconds on our test devices.

In order to accomplish this important third layer of optimization, the application needs to know, given an entity in memory and its version in the Content Provider, whether or not we need to issue content provider operations to update that entity. Comparing the entity in memory to the entity in the database field by field is one option, but is cumbersome and slow, since it would require us to read every field. Instead, we add a field to each entity called the import hashcode. The import hashcode is a weak hash value generated from its data. For example, here is how the import hashcode for a speaker is computed:

public class Speaker {
    public String id;
    public String publicPlusId;
    public String bio;
    public String name;
    public String company;
    public String plusoneUrl;
    public String thumbnailUrl;

    public String getImportHashcode() {
        StringBuilder sb = new StringBuilder();
        sb.append("id").append(id == null ? "" : id)
                .append("publicPlusId")
                .append(publicPlusId == null ? "" : publicPlusId)
                .append("bio")
                .append(bio == null ? "" : bio)
                .append("name")
                .append(name == null ? "" : name)
                .append("company")
                .append(company== null ? "" : company)
                .append("plusoneUrl")
                .append(plusoneUrl == null ? "" : plusoneUrl)
                .append("thumbnailUrl")
                .append(thumbnailUrl == null ? "" : thumbnailUrl);
        String result = sb.toString();
        return String.format(Locale.US, "%08x%08x", 
            result.hashCode(), result.length());
    }
}

Every time an entity is updated in the database, its import hashcode is saved with it as a database column. Later, when we have a candidate for an updated version of that entity, all we need to do is compute the import hashcode of the candidate and compare it to the import hashcode of the entity in the database. If they differ, then we issue Content Provider operations to update the entity in the database. If they are the same, we skip that entity. This incremental update logic can be seen, for example, in the makeContentProviderOperations method of the SpeakersHandler class:

public class SpeakersHandler extends JSONHandler {
    private HashMap mSpeakers = new HashMap();

    // (...)
    @Override
    public void makeContentProviderOperations(ArrayList list) {
        // (...)
        int updatedSpeakers = 0;
        for (Speaker speaker : mSpeakers.values()) {
            String hashCode = speaker.getImportHashcode();
            speakersToKeep.add(speaker.id);

            if (!isIncrementalUpdate || !speakerHashcodes.containsKey(speaker.id) ||
                    !speakerHashcodes.get(speaker.id).equals(hashCode)) {
                // speaker is new/updated, so issue content provider operations
                ++updatedSpeakers;
                boolean isNew = !isIncrementalUpdate || 
                    !speakerHashcodes.containsKey(speaker.id);
                buildSpeaker(isNew, speaker, list);
            }
        }

        // delete obsolete speakers
        int deletedSpeakers = 0;
        if (isIncrementalUpdate) {
            for (String speakerId : speakerHashcodes.keySet()) {
                if (!speakersToKeep.contains(speakerId)) {
                    buildDeleteOperation(speakerId, list);
                    ++deletedSpeakers;
                }
            }
        }
    }
}

The buildSpeaker and buildDeleteOperation methods (omitted here for brevity) simply build the Content Provider operations necessary to, respectively, insert/update a speaker or delete a speaker from the Content Provider. Notice that this approach means we only issue Content Provider operations to update a speaker if the import hashcode has changed. We also deal with obsolete speakers, that is, speakers that were in the database but were not referenced by the incoming data, and we issue delete operations for those speakers.

Making Sync Robust

The sync adapter in the I/O app is responsible for several tasks, amongst which are the remote conference data sync, the user schedule sync and also the user feedback sync. Failures can happen in any of them because of network conditions and other factors. However, a failure in one of the tasks should not impact the execution of the other tasks. This is why we structure the sync process as a series of independent tasks, each protected by a try/catch block, as can be seen in the performSync method of the SyncHelper class:

// remote sync consists of these operations, which we try one by one (and
// tolerate individual failures on each)
final int OP_REMOTE_SYNC = 0;
final int OP_USER_SCHEDULE_SYNC = 1;
final int OP_USER_FEEDBACK_SYNC = 2;

int[] opsToPerform = userDataOnly ?
        new int[] { OP_USER_SCHEDULE_SYNC } :
        new int[] { OP_REMOTE_SYNC, OP_USER_SCHEDULE_SYNC, OP_USER_FEEDBACK_SYNC};

for (int op : opsToPerform) {
    try {
        switch (op) {
            case OP_REMOTE_SYNC:
                dataChanged |= doRemoteSync();
                break;
            case OP_USER_SCHEDULE_SYNC:
                dataChanged |= doUserScheduleSync(account.name);
                break;
            case OP_USER_FEEDBACK_SYNC:
                doUserFeedbackSync();
                break;
        }
    } catch (AuthException ex) {
        // (... handle auth error...)
    } catch (Throwable throwable) {
        // (... handle other error...)

        // Let system know an exception happened:
        if (syncResult != null && syncResult.stats != null) {
            ++syncResult.stats.numIoExceptions;
        }
    }
}

When one particular part of the sync process fails, we let the system know about it by increasing syncResult.stats.numIoExceptions. This will cause the system to retry the sync at a later time, using exponential backoff.

When Should We Sync? Enter GCM.

It's very important for users to be able to get updates about conference data in a timely manner, especially during (and in the few days leading up to) Google I/O. A naïve way to solve this problem is simply making the app poll the server repeatedly for updates. Naturally, this causes problems with bandwidth and battery consumption.

To solve this problem in a more elegant way, we use GCM (Google Cloud Messaging). Whenever there is an update to the data on the server side, the server sends a GCM message to all registered devices. Upon receipt of this GCM message, the device performs a sync to download the new conference data. The GCMIntentService class handles the incoming GCM messages:

Update (23 September 2014): Since this blog post was first published, the GCMBaseIntentService class has been deprecated. Please use the GoogleCloudMessaging API instead.

public class GCMIntentService extends GCMBaseIntentService {
    private static final String TAG = makeLogTag("GCM");

    private static final Map MESSAGE_RECEIVERS;
    static {
        // Known messages and their GCM message receivers
        Map  receivers = new HashMap();
        receivers.put("test", new TestCommand());
        receivers.put("announcement", new AnnouncementCommand());
        receivers.put("sync_schedule", new SyncCommand());
        receivers.put("sync_user", new SyncUserCommand());
        receivers.put("notification", new NotificationCommand());
        MESSAGE_RECEIVERS = Collections.unmodifiableMap(receivers);
    }

    // (...)

    @Override
    protected void onMessage(Context context, Intent intent) {
        String action = intent.getStringExtra("action");
        String extraData = intent.getStringExtra("extraData");
        LOGD(TAG, "Got GCM message, action=" + action + ", extraData=" + extraData);

        if (action == null) {
            LOGE(TAG, "Message received without command action");
            return;
        }

        action = action.toLowerCase();
        GCMCommand command = MESSAGE_RECEIVERS.get(action);
        if (command == null) {
            LOGE(TAG, "Unknown command received: " + action);
        } else {
            command.execute(this, action, extraData);
        }

    }
    // (...)
}

Notice that the onMessage method delivers the message to the appropriate handler depending on the GCM message's "action" field. If the action field is "sync_schedule", the application delivers the message to an instance of the SyncCommand class, which causes a sync to happen. Incidentally, notice that the implementation of the SyncCommand class allows the GCM message to specify a jitter parameter, which causes it to trigger a sync not immediately but at a random time in the future within the jitter interval. This spreads out the syncs evenly over a period of time rather than forcing all clients to sync simultaneously, and thus prevents a sudden peak in requests on the server side.

Syncing User Data

The I/O app allows the user to build their own personalized schedule by choosing which sessions they are interested in attending. This data must be shared across the user's Android devices, and also between the I/O website and Android. This means this data has to be stored in the cloud, in the user's Google account. We chose to use the Google Drive AppData folder for this task.

User data is synced to Google Drive by the doUserScheduleSync method of the SyncHelper class. If you dive into the source code, you will notice that this method essentially accesses the Google Drive AppData folder through the Google Drive HTTP API, then reconciles the set of sessions in the data with the set of sessions starred by the user on the device, and issues the necessary modifications to the cloud if there are locally updated sessions.

This means that if the user selects one session on their Android device and then selects another session on the I/O website, the result should be that both the Android device and the I/O website will show that both sessions are in the user's schedule.

Also, whenever the user adds or removes a session on the I/O website, the data on all their Android devices should be updated, and vice versa. To accomplish that, the I/O website sends our GCM server a notification every time the user makes a change to their schedule; the GCM server, in turn, sends a GCM message to all the devices owned by that user in order to cause them to sync their user data. The same mechanism works across the user's devices as well: when one device updates the data, it issues a GCM message to all other devices.

Conclusion

Serving fresh data is a key component of many Android apps. This article showed how the I/O app deals with the challenges of keeping the data up-to-date while minimizing network traffic and database changes, and also keeping this data in sync across different platforms and devices through the use of Google Cloud Storage, Google Drive and Google Cloud Messaging.

Categories: Programming

Messaging on Android Wear

Wed, 09/17/2014 - 18:45

By Timothy Jordan, Developer Advocate

Sending messages on Android Wear feels as easy as it was to pass notes back in school. Remember when your friends always felt nearby? That feeling is why I love staying in touch with friends and family using my wearable.

Your messaging app likely already works on Android Wear. With just a few more lines of code you can unlock simple but powerful features that let your users communicate even more effortlessly.

Message notifications for free

If your Android app uses notifications to let the user know about new messages, these will work automatically on their wearable. That is, when you build notifications with the NotificationCompat.Builder class, the system takes care of displaying them properly, whether they appear on a handheld or wearable. Also, an "Open on phone" action will be added so it's easy for the user to reply via the app on their handheld.

Google+ Hangouts message.

Reply like a champ

Messages on Wear get really exciting when you can reply directly from the watch with your voice. In addition to being super convenient, this always gives me a Dick Tracy thrill… but maybe that's just me. =]

To add this functionality, it's as simple as adding an action to the notification via WearableExtender that includes a RemoteInput to your notification. After the user replies, you'll just grab their voice input as a string from the RemoteInput included in the Intent. You can even include text responses the user can easily select from a list by passing an array of them to the setChoices method of the RemoteInput. More details and code can be found here.

WhatsApp message with the reply by voice action.

See who is texting

Messages are more meaningful when you are connected to the sender. That's why we recommend you include the photo of the sender as the background of the notification. As soon as the user taps into the message, they also see who it's from, which will make it matter more (or maybe that other thing, depending on who it is).

You should add a photo with a resolution of at least 400x400, but we recommend 640x400. With the larger size, the background will be given parallax scrolling. If the background is to be included in the apk, place it in the res/drawable-nodpi directory. Then call setBackground() on your WearableExtender and add it to your notification. More details and code can be found here.

Path Talk message with a clear picture of the sender.

Custom actions

Basic notifications with reply by voice and a good background image are the most important parts to get done right away. But why stop there? It's easy to extend the unique parts of your service to the wearable. A simple first step is adding in a custom action the way Omlet does. These are just actions defined with the WearableExtender that raise an intent on the handheld.

Omlet includes two extra actions with every message: Like and Check-In. Check-In sends along the user's current location.

Custom Layouts

Custom interaction on the wearable, like the following example from TextMe, is straightforward to implement. They have what appears to be a simple notification with an action that allows the user to select an emoticon. However, to show this emoticon picker, they are actually issuing a notification from the wearable. The round trip looks something like this:

  1. The handheld gets a new message, issues a notification setLocalOnly(True), and sends a message to the wearable using the Data Layer API
  2. The wearable receives that message using the WearableListenerService and issues a custom notification with a PendingIntent to launch an activity when the user views the notification
  3. That activity has a custom layout defined with the Wearable UI Library
  4. Once the user selects an emoticon, the wearable sends a message back to the handheld
  5. The handheld receives that message and sends it along to the server

Custom layouts are documented in more depth here.

TextMe allows users to reply with a quick emoticon.

Next steps

Make your messaging service awesome by providing rich functionality on the user's wearable. It's easy to get started and easy to go further. It all starts at developer.android.com/wear.


Join the discussion on
+Android Developers


Categories: Programming

Google Play Services 5.0

Tue, 09/16/2014 - 22:45
gps

Google Play services 5.0 is now rolled out to devices worldwide, and it includes a number of features you can use to improve your apps. This release introduces Android wearable services APIs, Dynamic Security Provider and App Indexing, whilst also including updates to the Google Play game services, Cast, Drive, Wallet, Analytics, and Mobile Ads.

Android wearable services

Google Play services 5.0 introduces a set of APIs that make it easier to communicate with your apps running on Android wearables. The APIs provide an automatically synchronized, persistent data store and a low-latency messaging interface that let you sync data, exchange control messages, and transfer assets.

Dynamic security provider

Provides an API that apps can use to easily install a dynamic security provider. The dynamic security provider includes a replacement for the platform's secure networking APIs, which can be updated frequently for rapid delivery of security patches. The current version includes fixes for recent issues identified in OpenSSL.

Google Play game services

Quests are a new set of APIs to run time-based goals for players, and reward them without needing to update the game. To do this, you can send game activity data to the Quests service whenever a player successfully wins a level, kills an alien, or saves a rare black sheep, for example. This tells Quests what’s going on in the game, and you can use that game activity to create new Quests. By running Quests on a regular basis, you can create an unlimited number of new player experiences to drive re-engagement and retention.

Saved games lets you store a player's game progress to the cloud for use across many screen, using a new saved game snapshot API. Along with game progress, you can store a cover image, description and time-played. Players never play level 1 again when they have their progress stored with Google, and they can see where they left off when you attach a cover image and description. Adding cover images and descriptions provides additional context on the player’s progress and helps drive re-engagement through the Play Games app.

App Indexing API

The App Indexing API provides a way for you to notify Google about deep links in your native mobile applications and drive additional user engagement. Integrating with the App Indexing API allows the Google Search app to serve up your app’s history to users as instant Search suggestions, providing fast and easy access to inner pages in your app. The deep links reported using the App Indexing API are also used by Google to index your app’s content and surface them as deep links to Google search result.

Google Cast

The Google Cast SDK now includes media tracks that introduce closed caption support for Chromecast.

Drive

The Google Drive API adds the ability to sort query results, create folders offline, and select any mime type in the file picker by default.

Wallet

Wallet objects from Google take physical objects (like loyalty cards, offers) from your wallet and store them in the cloud. In this release, Wallet adds "Save to Wallet" button support for offers. When a user clicks "Save to Wallet" the offer gets saved and shows up in the user's Google Wallet app. Geo-fenced in-store notifications prompt the user to show and scan digital cards at point-of-sale, driving higher redemption. This also frees the user from having to carry around offers and loyalty cards.

Users can also now use their Google Wallet Balance to pay for Instant Buy transactions by providing split tender support. With split tender, if your Wallet Balance is not sufficient, the payment is split between your Wallet Balance and a credit/debit card in your Google Wallet.

Analytics

Enhanced Ecommerce provides visibility into the full customer journey, adding the ability to measure product impressions, product clicks, viewing product details, adding a product to a shopping cart, initiating the checkout process, internal promotions, transactions, and refunds. Together they help users gain deeper insights into the performance of their business, including how far users progress through the shopping funnel and where they are abandoning in the purchase process. Enhanced Ecommerce also allows users to analyze the effectiveness of their marketing and merchandising efforts, including the impact of internal promotions, coupons, and affiliate marketing programs.

Mobile Ads

Google Mobile Ads are a great way to monetise your apps and you now have access to better in-app purchase ads. We've now added a default implementation for consumable purchases using the Google Play In-app Billing service.

And that’s another release of Google Play services. The updated Google Play services SDK is now available through the Android SDK manager. For details on the APIs, please see New Features in Google Play services 5.0.




Join the discussion on
+Android Developers


Categories: Programming

Android One: Bringing Your Apps to the Next Five Billion

Tue, 09/16/2014 - 18:35
Posted by Rich Hyndman, Developer Advocate

With the launch of Android One, more people across the world will have access to high-quality and affordable smartphones, packed with plenty of processing power and running the latest version of Android. These devices are available now in India and soon in Indonesia, the Philippines, and South Asia, so now is a good time to make sure your apps are ready for these new markets. This post highlights a few areas to consider.

These days, we often talk about smooth, 60fps transitions and keeping apps jank-free, and rightly so — performance is a critical metric for app quality. But in the user experience hierarchy of needs, an app should first and foremost do its job reliably and consistently.

If your app has search functionality, will user requests time out entirely? Do you think it is more important that a result is returned in a timely manner, or that the result is returned at all? If you're trying to build a robust app to reach the next five billion, it might be less about returning a result immediately, and more about returning a result at all. To address this challenge, why not include an option to users to “notify me with the results” when a search query is running on a slow network? Your app can then take as long as it needs to successfully retrieve the data in the background and show a notification when complete. The difference in user experience between an app that times out on a slower network and one that caters to user-specific needs will be very impactful for driving mobile app adoption.

There are also ways to test app performance without flying around the globe. The Android Emulator has network speed and network delay emulation settings, which can become an integral part of your testing strategy. If you’re testing on physical hardware, try turning off WiFi and switching the network to 2G only; how well does your app perform? Do search pages load? Does data refresh? These issues can often be fixed with relatively minor changes to your app logic or by leveraging a SyncAdapter. Check out our blog post on sync in the Google I/O app for more ideas.

Another key area for you to be aware of is app memory utilization. As part of the KitKat launch, we added new tools to the SDK for analyzing memory use and new APIs like isLowRamDevice(). We also just added a Memory Monitor to Android Studio 0.8.10 (currently in Canary). Much of this is documented in our Best Practices for Performance guide.

Moving forward, the Android L release has a strong focus on battery usage and analysis. Project Volta introduces new tools, such as Battery Historian and new APIs like JobScheduler, that can really help optimize battery use of your app.

By ensuring your app works well on slower networks, uses minimal memory, minimizes battery usage and doesn’t have a larger-than-necessary APK, you will help the next five billion discover, use and love your app.

Categories: Programming

Update on Android Wear Paid Apps

Mon, 09/08/2014 - 22:02

Update (8 September 2014): All of the issues in the post below have now been resolved in Android Studio 0.8.3 onwards, released on 21 July 2014. The gradle wearApp rule, and the packaging documentation, were updated to use res/raw. The instructions on this blog post remain correct and you can continue to use manual packaging if you want. You can upload Android Wear paid apps to the Google Play using the standard release wearApp release mechanism.

We have a workaround to enable paid apps (and other apps that use Google Play's forward-lock mechanism) on Android Wear. The assets/ directory of those apps, which contains the wearable APK, cannot be extracted or read by the wearable installer. The workaround is to place the wearable APK in the res/raw directory instead.

As per the documentation, there are two ways to package your wearable app: use the “wearApp” Gradle rule to package your wearable app or manually package the wearable app. For paid apps, the workaround is to manually package your apps with the following two changes, and you cannot use the “wearApp” Gradle rule. To manually package the wearable APK into res/raw, do the following:

  1. Copy the signed wearable app into your handheld project's res/raw directory and rename it to wearable_app.apk, it will be referred to as wearable_app.
  2. Create a res/xml/wearable_app_desc.xml file that contains the version and path information of the wearable app:
    <wearableApp package="wearable app package name">
        <versionCode>1</versionCode>
        <versionName>1.0</versionName>
        <rawPathResId>wearable_app</rawPathResId>
    </wearableApp>

    The package, versionCode, and versionName are the same as values specified in the wearable app's AndroidManifest.xml file. The rawPathResId is the static variable name of the resource. If the filename of your resource is wearable_app.apk, the static variable name would be wearable_app.

  3. Add a <meta-data> tag to your handheld app's <application> tag to reference the wearable_app_desc.xml file.
    <meta-data android:name="com.google.android.wearable.beta.app"
               android:resource="@xml/wearable_app_desc"/>
  4. Build and sign the handheld app.

We will be updating the “wearApp” Gradle rule in a future update to the Android SDK build tools to support APK embedding into res/raw. In the meantime, for paid apps you will need to follow the manual steps outlined above. We will be also be updating the documentation to reflect the above workaround. We're working to make this easier for you in the future, and we apologize for the inconvenience.


Join the discussion on
+Android Developers


Categories: Programming

The Beautiful Design Summer 2014 Collection on Google Play

Tue, 09/02/2014 - 16:10
Posted by Marco Paglia, Android Design Team

It’s that time again! Last summer, we published the first Beautiful Design collection on Google Play, and updated it in the winter with a fresh set of beautifully crafted apps.

Since then, developers have been hard at work updating their existing apps with new design ideas, and many new apps targeted to phones and tablets have launched on Google Play sporting exquisite detail in their UIs. Some apps are even starting to incorporate elements from material design, which is great to see. We’re on the lookout for even more material design concepts applied across the Google Play ecosystem!

Today, we're refreshing the Beautiful Design collection with our latest favorite specimens of delightful design from Google Play. As a reminder, the goal of this collection is to highlight beautiful apps with masterfully crafted design details such as beautiful presentation of photos, crisp and meaningful layout and typography, and delightful yet intuitive gestures and transitions.

The newly updated Beautiful Design Summer 2014 collection includes:

Flight Track 5, whose gorgeously detailed flight info, full of maps and interactive charts, stylishly keeps you in the know.

Oyster, a book-reading app whose clean, focused reading experience and delightful discovery makes it a joy to take your library with you, wherever you go.

Gogobot, an app whose bright colors and big images make exploring your next city delightful and fun.

Lumosity, Vivino, FIFA, Duolingo, SeriesGuide, Spotify, Runtastic, Yahoo News Digest… each with delightful design details.

Airbnb, a veteran of the collection from this past winter, remains as they continue to finesse their app.

If you’re an Android designer or developer, make sure to play with some of these apps to get a sense for the types of design details that can separate good apps from great ones. And remember to review the material design spec for ideas on how to design your next beautiful Android app!.


Join the discussion on

+Android Developers
Categories: Programming

Powerful New Messaging Features with GCM

Mon, 08/25/2014 - 18:51

By Subir Jhanb, Google Cloud Messaging team

Developers from all segments are increasingly relying on Google Cloud Messaging (GCM) to handle their messaging needs and make sure that their apps stay battery-friendly. GCM has been experiencing incredible momentum, with more than 100,000 apps registered, 700,000 QPS, and 300% QPS growth over the past year.

At Google I/O we announced the general availability of several GCM capabilities, including the GCM Cloud Connection Server, User Notifications, and a new API called Delivery Receipt. This post highlights the new features and how you can use them in your apps. You can watch these and other GCM announcements at our I/O presentation.

Two-way XMPP messaging with Cloud Connection Server

XMPP-based Cloud Connection Server (CCS) provides a persistent, asynchronous, bidirectional connection to Google servers. You can use the connection to send and receive messages between your server and your users' GCM-connected devices. Apps can now send upstream messages using CCS, without needing to manage network connections. This helps keep battery and data usage to a minimum. You can establish up to 100 XMPP connections and have up to 100 outstanding messages per connection. CCS is available for both Android and Chrome.

User notifications managed across multiple devices

Nowadays users have multiple devices and hence receive notifications multiple times. This can reduce notifications from being a useful feature to being an annoyance. Thankfully, the GCM User Notifications API provides a convenient way to reach all devices for a user and help you synchronise notifications including dismissals - when the user dismisses a notification on one device, the notification disappears automatically from all the other devices. User Notifications is available on both HTTP and XMPP.

Insight into message status through delivery receipts

When sending messages to a device, a common request from developers is to get more insight on the state of the message and to know if it was delivered. This is now available using CCS with the new Delivery Receipt API. A receipt is sent as soon as the message is sent to the endpoint, and you can also use upstream for app level delivery receipt.

How to get started

If you’re already using GCM, you can take advantage of these new features right away. If you haven't used GCM yet, you’ll be surprised at how easy it is to set up — get started today! And remember, GCM is completely free no matter how big your messaging needs are.

To learn more about GCM and its new features — CCS, user notifications, and Delivery Receipt — take a look at the I/O Bytes video below and read our developer documentation.


Join the discussion on
+Android Developers


Categories: Programming