<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Google Data &#187; Tim Bray</title>
	<atom:link href="/author/tim-bray/feed/" rel="self" type="application/rss+xml" />
	<link>https://googledata.org</link>
	<description>Everything Google: News, Products, Services, Content, Culture</description>
	<lastBuildDate>Thu, 19 Mar 2015 22:49:02 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.7.5</generator>
	<item>
		<title>Google Play services and OAuth Identity Tools</title>
		<link>https://googledata.org/google-android/google-play-services-and-oauth-identity-tools/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=google-play-services-and-oauth-identity-tools</link>
		<comments>https://googledata.org/google-android/google-play-services-and-oauth-identity-tools/#comments</comments>
		<pubDate>Wed, 26 Sep 2012 17:43:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=3725743061fcf9daf5c1d666410e3407</guid>
		<description><![CDATA[Posted by Tim Bray
The rollout of Google Play services to all Android 2.2+ devices worldwide is now complete, and all of those devices now have new tools for working with OAuth 2.0 tokens.  This is an example of the kind of agility in rolling out new p...]]></description>
				<content:encoded><![CDATA[<em>Posted by <a href="https://plus.google.com/107606703558161507946/posts">Tim Bray</a></em><br />
<p>The rollout of Google Play services to all Android 2.2+ devices worldwide is now complete, and all of those devices now have new tools for working with OAuth 2.0 tokens.  This is an example of the kind of agility in rolling out new platform capabilities that Google Play services provides.</p><h3>Why OAuth 2.0 Matters</h3><p>The Internet already has too many usernames and passwords, and they don’t scale.  Furthermore, your Android device has a strong notion of who you are.  In this situation, the industry consensus is that OAuth 2.0 is a good choice for the job, offering the promise of strong security minus passwords.</p><p>Google Play services make OAuth 2.0 authorization available to Android apps that want to access Google APIs, with a good user experience and security. </p><p>Typically, when you want your Android app to use a Google account to access something, you have to pick which account on the device to use, then you have to generate an OAuth 2.0 token, then you have to use it in your HTTP-based dialogue with the resource provider.</p><p>These tasks are largely automated for you if you’re using a recent release of the <a href="http://code.google.com/p/google-api-java-client/">Google APIs Client Library for Java</a>; the discussion here applies if you want to access the machinery directly, for example in sending your own HTTP GETs and POSTs to a RESTful interface.</p><h3>Preparation</h3><p>Google Play services has just started rolling out, and even after the rollout is complete, will only be available on compatible Android devices running 2.2 or later.  This is the vast majority, but there will be devices out there where it’s not available.  It is also possible for a user to choose to disable the software.</p><p>For these reasons, before you can start making calls, you have to verify that Google Play services is installed.  To do this, call <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/common/GooglePlayServicesUtil#isGooglePlayServicesAvailable(android.content.Context)">isGooglePlayServicesAvailable()</a>.  The result codes, and how to deal with them, are documented in the <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/common/ConnectionResult">ConnectionResult</a> class.</p><h3>Choosing an Account</h3><p>This is not, and has never been, rocket science; there are many examples online that retrieve accounts from Android’s AccountManager and display some sort of pick list. The problem is that they all have their own look and feel, and for something like this, which touches on security, that’s a problem; the user has the right to expect consistency from the system.</p><p>Now you can use the handy  <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/common/AccountPicker">AccountPicker.newChooseAccountIntent()</a> method to give you an Intent; feed it to startActivityForResult() and you’ll launch a nice standardized user experience that will return you an account (if the user feels like providing one).</p><p>Two things to note: When you’re talking to these APIs, they require a Google account (AccountManager can handle multiple flavors), so specify <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/auth/GoogleAuthUtil#GOOGLE_ACCOUNT_TYPE">GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE</a> argument as the value for the <code>allowableAccountTypes</code> argument.  Second, you don’t need an android.accounts.Account object, you just use the email-address string (available in account.name) that uniquely identifies it.</p><h3>Getting a Token</h3><p>There’s really only one method call you need to use, <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/autonlyh/GoogleAuthUtil#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">GoogleAuthUtil.getToken()</a>.  It takes three arguments: a Context, an email address, and another string argument called scope.  Every information resource that is willing to talk OAuth 2.0 needs to publish which scope (or scopes) it uses. For example, to access the Google+ API, the scope is <code>oauth2:https://www.googleapis.com/auth/plus.me</code>. You can provide multiple space-separated scopes in one call and get a token that provides access to all of them.  Code like this might be typical:</p><pre><code>  private final static String G_PLUS_SCOPE = 
      "oauth2:https://www.googleapis.com/auth/plus.me";
  private final static String USERINFO_SCOPE =   
      "https://www.googleapis.com/auth/userinfo.profile";
  private final static String SCOPES = G_PLUS_SCOPE + " " + USERINFO_SCOPE;</code></pre><p>In an ideal world, getToken() would be synchronous, but three things keep it from being that simple:</p><ol><li><p>The first time an app asks for a token to access some resource, the system will need to interact with the user to make sure they’re OK with that.</p></li>
<li><p>Any time you ask for a token, the system may well have a network conversation with the identity back-end services.</p></li>
<li><p>The infrastructure that handles these requests may be heavily loaded and not able to get you your token right away. Rather than keeping you waiting, or just failing, it may ask you to go away and come back a little later.</p></li>
</ol><p>The first consequence is obvious; you absolutely can’t call getToken() on the UI thread, since it’s subject to unpredictable delays.  </p><p>When you call it, the following things can happen:</p><ul><li><p>It returns a token. That means that everything went fine, the back-end thinks the authorization was successful, and you should be able to proceed and use the token.</p></li>
<li><p>It throws a <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/auth/UserRecoverableAuthException">UserRecoverableAuthException</a>, which means that you need to interact with the user, most likely to ask for their approval on using their account for this purpose. The exception has a getIntent() method, whose return value you can feed to startActivityForResult() to take care of that. Of course, you’ll need to be watching for the OK in the onActivityResult() method.</p></li>
<li><p>It throws an IOException, which means that the authorization infrastructure is stressed, or there was a (not terribly uncommon on mobile devices) networking error.  You shouldn’t give up instantly, because a repeat call might work.  On the other hand, if you go back instantly and pester the server again, results are unlikely to be good. So you need to wait a bit; best practice would be the classic exponential-backoff pattern.</p></li>
<li><p>It throws a <a href="https://developers.google.com/android/google-play-services/reference/com/google/android/gms/auth/GoogleAuthException">GoogleAuthException</a>, which means that authorization just isn’t going to happen, and you need to let your user down politely. This can happen if an invalid scope was requested, or the account for the email address doesn’t actually exist on the device.</p></li>
</ul><p>Here’s some sample code:</p><pre><code>       try {
            // if this returns, the OAuth framework thinks the token should be usable 
            String token = GoogleAuthUtil.getToken(this, mRequest.email(),  
                               mRequest.scope());
            response = doGet(token, this);

        } catch (UserRecoverableAuthException userAuthEx) {
            // This means that the app hasn't been authorized by the user for access
            // to the scope, so we're going to have to fire off the (provided) Intent
            // to arrange for that. But we only want to do this once. Multiple
            // attempts probably mean the user said no.
            if (!mSecondTry) {
                startActivityForResult(userAuthEx.getIntent(), REQUEST_CODE);
                response = null;
            } else {
                response = new Response(-1, null, "Multiple approval attempts");
            }

        }  catch (IOException ioEx) {
            // Something is stressed out; the auth servers are by definition 
            //  high-traffic and you can't count on 100% success. But it would be 
            //  bad to retry instantly, so back off
            if (backoff.shouldRetry()) {
                backoff.backoff();
                response = authenticateAndGo(backoff);
            } else {
                response = 
                    new Response(-1, null, "No response from authorization server.");
            }

        }  catch (GoogleAuthException fatalAuthEx)  {
            Log.d(TAG, "Fatal Authorization Exception");
            response = new Response(-1, null, "Fatal authorization exception: " + 
                               fatalAuthEx.getLocalizedMessage());
        }</code></pre><p>This is from a <a href="http://code.google.com/p/authorized-activity/">sample library</a> I’ve posted on code.google.com with an AuthorizedActivity class that implements this. We think that some of this authorization behavior is going to be app-specific, so it’s not clear that this exact AuthorizedActivity recipe is going to work for everyone; but it’s Apache2-licensed, so feel free to use any pieces that work for you.  It’s set up as a library project, and there’s also a small sample app called G+ Snowflake that uses it to return some statistics about your Google+ posts; the app is in the <a href="https://play.google.com/store/apps/details?id=com.textuality.gpstats">Google Play Store</a> and its <a href="http://code.google.com/p/g-plus-snowflake/">source is online</a> too.</p><h3>Registering Your App</h3><p>Most services that do OAuth 2.0 authorization want you to register your app, and Google’s are no exception. You need to visit the <a href="https://code.google.com/apis/console/%20">Google APIs Console</a>, create a project, pick the APIs you want to access off the Services menu, and then hit the API Access tab to do the registration.  It’ll want you to enter your package name; the value of the package attribute of the <code>manifest</code> element in your AndroidManifest.xml. </p><p>Also, it’ll want the SHA1 signature of the certificate you used to sign your app.  Anyone who’s published apps to Google Play Apps knows about keystores and signing. But before you get there, you’ll be working with your debug-version apps, which are signed with a certificate living in ~/.android/debug.keystore (password: “android”).  Fortunately, your computer probably already has a program called “keytool” installed; you can use this to get the signature. For your debug version, a correct incantation is:</p><pre class="no-pretty-print">keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -v -list</pre><p>This will print out the SHA1 signature in a nicely labeled easy-to-cut-and-paste form.</p><p>This may feel a little klunky, but it’s worth it, because some magic is happening.  When your app is registered and you generate a token and send it to a service provider, the provider can check with Google, which will confirm that yes, it issued that token, and give the package name of the app it was issued to.  Those of you who who’ve done this sort of thing previously will be wondering about Client IDs and API Keys, but with this mechanism you don’t need them.</p><h3>Using Your Token</h3><p>Suppose you’ve registered your app and called GoogleAuthUtil.getToken() and received a token.  For the purposes of this discussion, let’s suppose that it’s “MissassaugaParnassus42”.  Then all you need to do is, when you send off an HTTP request to your service provider, include an HTTP header like so:</p><pre class="no-pretty-print">Authorization: Bearer MissassaugaParnassus42</pre><p>Then your HTTP GETs and POSTs should Just Work.  You should call GoogleAuthUtil.getToken() to get a token before each set of GETs or POSTs; it’s smart about caching things appropriately, and also about dealing with token expiry and refresh. </p><p>Once again, as I said at the top, if you’re happy using the <a href="http://code.google.com/p/google-api-java-client/">Google APIs Client Library for Java</a>, it’ll take care of all the client-side stuff; you’ll still need to do the developer console app registration.</p><p>Otherwise, there’s a little bit of coding investment here, but the payoff is pretty big: Secure, authenticated, authorized, service access with a good user experience.</p><a href="https://plus.google.com/108967384991768947849/posts/eZaNYTZbc2d" style="text-decoration: none; color: #333;"><br />
<div style="display: inline-block; line-height: 0;float:right;"><div style="float:left;"><span style="font: 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 11px;">Join the discussion on</span><br />
<span style="font: bold 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 7px;">+Android Developers</span><br />
</div><div style="float: right;"><img src="https://ssl.gstatic.com/images/icons/gplus-32.png" width="32" height="32" style="border: 0;"/><br />
</div></div></a>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/google-play-services-and-oauth-identity-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Replying to User Reviews on Google Play</title>
		<link>https://googledata.org/google-android/replying-to-user-reviews-on-google-play/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=replying-to-user-reviews-on-google-play</link>
		<comments>https://googledata.org/google-android/replying-to-user-reviews-on-google-play/#comments</comments>
		<pubDate>Thu, 21 Jun 2012 17:45:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=b3667781fe5391eaaf893b71019c0f58</guid>
		<description><![CDATA[[This post is by Trevor Johns from the Android team&#160;&#8212;&#160;Tim Bray]User reviews on Google Play are great for helping people discover quality apps and give feedback to developers and other potential app users. But what about when developers ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://plus.google.com/u/0/112423705617084925086/posts">Trevor Johns</a> from the Android team&nbsp;&mdash;&nbsp;Tim Bray]</i></p><p>User reviews on Google Play are great for helping people discover quality apps and give feedback to developers and other potential app users. But what about when developers want to give feedback to their users? Sometimes a user just needs a helping hand, or perhaps a new feature has been added and the developer wants to share the good news.</p><a href="http://1.bp.blogspot.com/-NntfSQNXe-s/T9jKXEb6QVI/AAAAAAAABbQ/WLn9mQHQBxc/s1600/reply_s.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 336px;" src="http://1.bp.blogspot.com/-NntfSQNXe-s/T9jKXEb6QVI/AAAAAAAABbQ/WLn9mQHQBxc/s400/reply_s.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5753571021642416466" /></a><!--<a href="http://1.bp.blogspot.com/-hNSVsrWB71U/T9jKAIeqEYI/AAAAAAAABbE/T8PGsjSxSvI/s1600/reply.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 335px;" src="http://1.bp.blogspot.com/-hNSVsrWB71U/T9jKAIeqEYI/AAAAAAAABbE/T8PGsjSxSvI/s400/reply.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5753570627590689154" /></a>--><p>That’s why we’re adding the ability for Google Play developers to respond to reviews from the Google Play Android Developer Console. Developers can gather additional information, provide guidance, and — perhaps most importantly — let users know when their feature requests have been implemented.</p><p>We’ll also notify the user who wrote the review via email that the developer has responded. Users can then contact the developer directly if additional followup is needed or update their review.</p><p>We’re releasing this feature today to those with a <a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=1295940">Top Developer badge</a>  <span style="white-space:nowrap;">(<img src="https://ssl.gstatic.com/android/market_images/badges/topdev_ann.png"/>)</span>. And based on feedback from users and developers, we will offer it to additional Google Play developers in the future.</p><p>Conversations are meant to be two-sided, and facilitating discussion between developers and users will ultimately yield better apps, to the benefit of everyone.</p>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/replying-to-user-reviews-on-google-play/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Helping you build beautiful, powerful, successful apps</title>
		<link>https://googledata.org/google-android/helping-you-build-beautiful-powerful-successful-apps/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=helping-you-build-beautiful-powerful-successful-apps</link>
		<comments>https://googledata.org/google-android/helping-you-build-beautiful-powerful-successful-apps/#comments</comments>
		<pubDate>Thu, 21 Jun 2012 17:19:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=be6ab1da44a01031b9d43f610b8932bb</guid>
		<description><![CDATA[[This post is by Billy Rutledge, Director of Developer Relations for Android.&#160;&#8212;&#160;Tim Bray]Just in time for Google I/O next week, the Android Developers site is stepping into a new look that is streamlined, simplified, and refocused. A de...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-gc6WzbMPquI/T-NOSznHV_I/AAAAAAAABdk/Z6T1NIpMnvY/s1600/dac-logo.png" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em"><img itemprop="image" border="0" height="67" width="320" src="http://4.bp.blogspot.com/-gc6WzbMPquI/T-NOSznHV_I/AAAAAAAABdk/Z6T1NIpMnvY/s320/dac-logo.png" /></a><p><i>[This post is by <a href="https://plus.google.com/115982658362240279544/posts">Billy Rutledge</a>, Director of Developer Relations for Android.&nbsp;&mdash;&nbsp;Tim Bray]</i></p><p><span itemprop="description">Just in time for Google I/O next week, the <a href="http://developer.android.com">Android Developers site</a> is stepping into a new look that is streamlined, simplified, and refocused.</span> A developer’s tasks fall into three baskets: Designing, developing, and distributing. We're trying to make developer.android.com's organization reflect this reality, shepherding you through the app development life cycle, from start to finish. </p><h3>Design</h3><p>Earlier this year, we launched <a href="http://developer.android.com/design"><i>Android Design</i></a>, an online style guide which lays out the principles, building blocks, and patterns for excellence in Android user interfaces. It seems to be working; every day, we see more and more beautiful apps arriving in Google Play. At I/O, we’ll continue to talk design, kicking off with <a href="https://developers.google.com/events/io/sessions/gooio2012/112/">Android Design for Success</a>, led by Matias Duarte.</p><h3>Develop</h3><p>An Android app should be fast, powerful and useful. With <a href="http://developer.android.com/training">Android Training</a>, one of the many parts of the Develop section that we continue to build out, we lay out best practices in a variety of framework topics to help you achieve those goals. If you’re at I/O and you’re interested in Android tools, be sure to start off your show with <a href="https://developers.google.com/events/io/sessions/gooio2012/104/">What’s new in Android Developers’ Tools</a>.</p><h3>Distribute</h3><p>The most important piece of the piece of the puzzle is about getting your app in front of millions and millions of Android users on Google Play. That’s why we added a section on distributing your app — a peek into the world of publishing and promoting your app. Chris Yerga on the Play team will be kicking off our how-to sessions on distributing your with  <a href="https://developers.google.com/events/io/sessions/gooio2012/123/">Android apps in Google Play</a>.</p><p>This is just a small sample of the Android sessions at Google I/O, many of which will be live-streamed so you can follow along even if you can’t make it out to San Francisco. In the meantime, we hope you find the new Android Developer site much more useful as you build great apps.</p><a href="https://plus.google.com/108967384991768947849/posts/Xpf8DZGPfis" style="text-decoration: none; color: #333;"><br />
<div style="display: inline-block; line-height: 0;float:right;"><div style="float:left;"><span style="font: 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 11px;">Join the discussion on</span><br />
<span style="font: bold 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 7px;">+Android Developers</span><br />
</div><div style="float: right;"><img src="https://ssl.gstatic.com/images/icons/gplus-32.png" width="32" height="32" style="border: 0;"/><br />
</div></div></a>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/helping-you-build-beautiful-powerful-successful-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Using DialogFragments</title>
		<link>https://googledata.org/google-android/using-dialogfragments/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-dialogfragments</link>
		<comments>https://googledata.org/google-android/using-dialogfragments/#comments</comments>
		<pubDate>Sun, 03 Jun 2012 19:06:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=85ed995fe4a561b43e5d51b90385cf57</guid>
		<description><![CDATA[[This post is by David Chandler, Android Developer Advocate&#160;&#8212;&#160;Tim Bray]Honeycomb introduced Fragments to support reusing portions of UI and logic across multiple activities in an app. In parallel, the showDialog / dismissDialog methods ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="http://turbomanage.com/">David Chandler</a>, Android Developer Advocate&nbsp;&mdash;&nbsp;Tim Bray]</i></p><p>Honeycomb introduced Fragments to support reusing portions of UI and logic across multiple activities in an app. In parallel, the showDialog / dismissDialog methods in Activity are being deprecated <a href="http://android-developers.blogspot.com/2011/02/android-30-fragments-api.html">in favor of DialogFragments</a>.</p><p><span itemprop="description"><br />
In this post, I’ll show how to use DialogFragments with the <a href="http://developer.android.com/reference/android/support/v4/app/DialogFragment.html">v4 support library</a> (for backward compatibility on pre-Honeycomb devices) to show a simple edit dialog and return a result to the calling Activity using an interface.</span> For design guidelines around Dialogs, see the <a href="http://developer.android.com/design/building-blocks/dialogs.html"><cite>Android Design</cite></a> site.</p><h3>The Layout</h3><p>Here’s the layout for the dialog in a file named <code>fragment_edit_name.xml</code>.</p><pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/edit_name"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_gravity="center" android:orientation="vertical"  >

    &lt;TextView
        android:id="@+id/lbl_your_name" android:text="Your name" 
        android:layout_width="wrap_content" android:layout_height="wrap_content" />
      
    &lt;EditText
        android:id="@+id/txt_your_name"
        android:layout_width="match_parent"  android:layout_height="wrap_content" 
        android:inputType=”text”
        android:imeOptions="actionDone" />
&lt;/LinearLayout></code></pre><p>Note the use of two optional attributes. In conjunction with <code>android:inputType=”text”</code>, <code>android:imeOptions=”actionDone”</code> configures the soft keyboard to show a Done key in place of the Enter key.</p><h3>The Dialog Code</h3><p>The dialog extends <a href="http://developer.android.com/reference/android/app/DialogFragment.html">DialogFragment</a>, and since we want backward compatibility, we’ll import it from the v4 support library. (To add the support library to an Eclipse project, right-click on the project and choose Android Tools | Add Support Library...). </p><pre><code>import android.support.v4.app.DialogFragment;
// ...

public class EditNameDialog extends DialogFragment {

    private EditText mEditText;

    public EditNameDialog() {
        // Empty constructor required for DialogFragment
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_edit_name, container);
        mEditText = (EditText) view.findViewById(R.id.txt_your_name);
        getDialog().setTitle("Hello");

        return view;
    }
}</code></pre><p>The dialog extends DialogFragment and includes the required empty constructor. Fragments implement the <code>onCreateView()</code> method to actually load the view using the provided LayoutInflater.</p><h3>Showing the Dialog</h3><p>Now we need some code in our Activity to show the dialog. Here is a simple example that immediately shows the EditNameDialog to enter the user’s name. On completion, it shows a Toast with the entered text.</p><pre><code>import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
// ...

public class FragmentDialogDemo extends FragmentActivity implements EditNameDialogListener {

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

    private void showEditDialog() {
        FragmentManager fm = getSupportFragmentManager();
        EditNameDialog editNameDialog = new EditNameDialog();
        editNameDialog.show(fm, "fragment_edit_name");
    }

    @Override
    public void onFinishEditDialog(String inputText) {
        Toast.makeText(this, "Hi, " + inputText, Toast.LENGTH_SHORT).show();
    }
}</code></pre><p>There are a few things to notice here. First, because we’re using the support library for backward compatibility with the Fragment API, our Activity extends FragmentActivity from the support library. Because we’re using the support library, we call <code>getSupportFragmentManager()</code> instead of <code>getFragmentManager()</code>.</p><p>After loading the initial view, the activity immediately shows the EditNameDialog by calling its show() method. This allows the DialogFragment to ensure that what is happening with the Dialog and Fragment states remains consistent. By default, the back button will dismiss the dialog without any additional code.</p><h3>Using the Dialog</h3><p>Next, let’s enhance EditNameDialog so it can return a result string to the Activity.</p><pre><code>import android.support.v4.app.DialogFragment;
// ...
public class EditNameDialog extends DialogFragment implements OnEditorActionListener {

    public interface EditNameDialogListener {
        void onFinishEditDialog(String inputText);
    }

    private EditText mEditText;

    public EditNameDialog() {
        // Empty constructor required for DialogFragment
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_edit_name, container);
        mEditText = (EditText) view.findViewById(R.id.txt_your_name);
        getDialog().setTitle("Hello");

        // Show soft keyboard automatically
        mEditText.requestFocus();
        getDialog().getWindow().setSoftInputMode(
                LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        mEditText.setOnEditorActionListener(this);

        return view;
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (EditorInfo.IME_ACTION_DONE == actionId) {
            // Return input text to activity
            EditNameDialogListener activity = (EditNameDialogListener) getActivity();
            activity.onFinishEditDialog(mEditText.getText().toString());
            this.dismiss();
            return true;
        }
        return false;
    }
}</code></pre><p>For user convenience, we programmatically focus on the EditText with <code>mEditText.requestFocus()</code>. Alternatively, we could have used the <code>&lt;requestFocus/></code> tag in the layout XML to do this; however, in some cases it’s preferable to request focus programmatically. For example, an OnFocusChangeListener added in the Fragment’s <code>onCreateView()</code> method won’t get called if you request focus in the layout XML.</p><p>If the user focuses on an EditText, the soft keyboard will automatically appear. In order to force this to happen with our programmatic focus, we call <code>getDialog().getWindow().setSoftInputMode()</code>. Note that many Window operations you might have done previously in a Dialog can still be done in a DialogFragment, but you have to call <code>getDialog().getWindow()</code> instead of just <code>getWindow()</code>. The resulting dialog is shown on both a handset and tablet (not to scale):</p><a href="http://1.bp.blogspot.com/-6qyjPxTuzv0/T6lde-Oq_fI/AAAAAAAABXc/zle7OFEGP44/s1600/fddns%2Bcopy.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 203px;" src="http://1.bp.blogspot.com/-6qyjPxTuzv0/T6lde-Oq_fI/AAAAAAAABXc/zle7OFEGP44/s400/fddns%2Bcopy.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5740221986742402546" /></a><p>The <code>onEditorAction()</code> method handles the callback when the user presses the Done key. It gets invoked because we’ve set an OnEditorActionListener on the EditText. It calls back to the Activity to send the entered text. To do this, EditNameDialog declares an interface EditNameDialogListener that is implemented by the Activity. This enables the dialog to be reused by many Activities. To invoke the callback method <code>onFinishEditDialog()</code>, it obtains a reference to the Activity which launched the dialog by calling getActivity(), which all Fragments provide, and then casts it to the interface type. In <a href="http://en.wikipedia.org/wiki/Model–view–controller">MVC</a> architecture, this is a common pattern for allowing a view to communicate with a controller.</p><p>We can dismiss the dialog one of two ways. Here we are calling dismiss() within the Dialog class itself. It could also be called from the Activity like the show() method.</p><p>Hopefully this sheds some more light on Fragments as they relate to Dialogs. You can find the sample code in this blog post <a href="http://code.google.com/p/dialogfragmentdemo/">on Google Code</a>.</p><p>References for learning more about Fragments:</p><ul><li><p><a href="http://developer.android.com/guide/topics/fundamentals/fragments.html">Fragments Dev Guide</a></p></li>
<li><p><a href="http://developer.android.com/training/basics/fragments/index.html">“Basic Training” on Fragments</a></p></li>
<li><p><a href="http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html">Updating Applications for On-screen Input Methods</a></p></li>
<li><p><a href="http://developer.android.com/reference/android/widget/TextView.OnEditorActionListener.html">OnEditorActionListener</a></p></li>
<li><p><a href="http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html">EditorInfo and IME options</a></p></li>
</ul>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/using-dialogfragments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android C2DM — Client Login key expiration</title>
		<link>https://googledata.org/google-android/android-c2dm-client-login-key-expiration/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-c2dm-client-login-key-expiration</link>
		<comments>https://googledata.org/google-android/android-c2dm-client-login-key-expiration/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 16:44:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=52c3a45266427ff16f1e16ae54461919</guid>
		<description><![CDATA[[This post is by Francesco Nerieri, engineering team lead for C2DM&#160;&#8212;&#160;Tim Bray]In the upcoming weeks, some of the older Client Login authentication keys will expire. If you generated the token you’re currently using to authenticate wit...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://plus.google.com/104524825852741167674/posts">Francesco Nerieri</a>, engineering team lead for C2DM&nbsp;&mdash;&nbsp;Tim Bray]</i></p><p>In the upcoming weeks, some of the older Client Login authentication keys will expire. If you generated the token you’re currently using to authenticate with the C2DM servers before October 2011, it will stop working.  </p><p>If the response from the C2DM servers contains an <code>Update-Client-Auth</code> header, you’ll need to replace the current token with the one included in the header.</p><pre><code>  // Check for updated token header
  String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
  if (updatedAuthToken != null &amp;&amp; !authToken.equals(updatedAuthToken)) {
    log.info("Got updated auth token from datamessaging servers: " +
        updatedAuthToken);
    serverConfig.updateToken(updatedAuthToken);
  }</code></pre><p>We suggest that you start using the Update-Client-Auth response header to update tokens regularly, as keys will expire periodically from now on.  For example, have a look at  the Chrome to Phone service hosted on code.google.com; <a href="http://code.google.com/p/chrometophone/source/browse/trunk/appengine/c2dm/com/google/android/c2dm/server/C2DMessaging.java">this code</a> takes care of authenticating via Client Login and then sending a message:</p><p>Alternatively, you can manually generate a new Client Login token now and replace the one currently in use.  ClientLogin can be used with any application that can make an HTTPS POST request. The POST request should be structured as a form post with the default encoding application/x-www-form-urlencoded, like this:</p><pre class="no-pretty-print">POST /accounts/ClientLogin HTTP/1.0
Content-type: application/x-www-form-urlencoded

accountType=GOOGLE&amp;Email=johndoe@gmail.com&amp;Passwd=north23AZ&amp;service=ac2dm</pre><p>If the POST succeeds, the response contains the authorization token, labeled "Auth", which is your new token.  You could even do this from the command line:</p><pre class="no-pretty-print">curl -d \
  "accountType=HOSTED_OR_GOOGLE&amp;Email=johndoe@gmail.com&amp;Passwd=north23AZ&amp;service=ac2dm" \
  https://www.google.com/accounts/ClientLogin | \
  grep Auth</pre><p>If your request fails or if you are prompted for captchas, please read <a href="https://developers.google.com/accounts/docs/AuthForInstalledApps">ClientLogin for Installed Applications</a>.  And of course, if you updated your code to use the Update-Client-Auth header <em>after</em> the keys had expired, then you will first need to manually generate a new token.  </p><p>Have fun with C2DM!</p>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-c2dm-client-login-key-expiration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accessibility: Are You Serving All Your Users?</title>
		<link>https://googledata.org/google-android/accessibility-are-you-serving-all-your-users/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=accessibility-are-you-serving-all-your-users</link>
		<comments>https://googledata.org/google-android/accessibility-are-you-serving-all-your-users/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 17:35:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=5fb69376e8950de76ab712680bcb65b1</guid>
		<description><![CDATA[[This post is by Joe Fernandez,  a technical writer for developer.android.com who cares about accessibility and usability.&#160;—&#160;Tim&#160;Bray.]We recently published some new resources to help developers make their Android applications more acc...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://plus.google.com/103507786235300238642/posts">Joe Fernandez</a>,  a technical writer for <a href="http://developer.android.com/">developer.android.com</a> who cares about accessibility and usability.&nbsp;—&nbsp;Tim&nbsp;Bray.]</i></p><p>We recently published some new resources to help developers make their Android applications more accessible:</p><ul><li><p><a href="http://developer.android.com/guide/topics/ui/accessibility/index.html">Accessibility Developer Guide</a></p></li>
<li><p><a href="http://developer.android.com/training/accessibility/index.html">Implementing Accessibility Training</a></p></li>
</ul><p>“But,” you may be thinking, “What is accessibility, exactly? Why should I make it a priority? How do I do it? And most importantly, how do I spell it?” All good questions. Let’s hit some of the key points.</p><p><span itemprop="description"><br />
Accessibility is about making sure that Android users who have limited vision or other physical impairments can use your application just as well as all those folks in line at the supermarket checking email on their phones. </span>It’s also about the Mom over in the produce section whose kids are driving her to distraction, and really needs to see that critical notification your application is trying to deliver. It’s also about you, in the future; Is your eyesight getting better over time? How about that hand-eye coordination?</p><p>When it comes down to it, making an application accessible is about having a deep commitment to usability, getting the details right and delighting your users. It also means stepping into new territory and getting a different perspective on your application. Try it out: Open up an application you developed (or your all-time favorite app), then close your eyes and try to complete a task. No peeking! A little challenging, right? </p><h3>How Android Enables Accessibility</h3><p>One of main ways that Android enables accessibility is by allowing users to hear spoken feedback that announces the content of user interface components as they interact with applications. This spoken feedback is provided by an accessibility service called <a href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a>, which is available for free on Google Play and has become a standard component of recent Android releases.</p><p>Now <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#test-audibles">enable TalkBack</a>, and try that eyes-closed experiment again. Being able to hear your application’s interface probably makes this experiment a little easier, but it’s still challenging. This type of interaction is how many folks with limited vision use their Android devices every day. The spoken feedback works because all the user interface components provided by the Android framework are built so they can provide descriptions of themselves to accessibility services like TalkBack. </p><p>Another key element of accessibility on Android devices is the ability to use alternative navigation. Many users prefer directional controllers such as D-pads, trackballs or keyboard arrows because it allows them to make discrete, predictable movements through a user interface. You can try out directional control with your apps using the virtual keyboard in the <a href="http://developer.android.com/guide/developing/devices/emulator.html">Android emulator</a> or by installing and enabling the <a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">Eyes-Free Keyboard</a> on your device. Android enables this type of navigation by default, but you, as a developer, may need to take a few steps to make sure users can effectively navigate your app this way.</p><h3>How to Make Your Application Accessible</h3><p>It would be great to be able to give you a standard recipe for accessibility, but the truth of the matter is that the right answer depends on the design and functionality of your application. Here are some key steps for ensuring that your application is accessible:</p><ol><li><p><b>Task flows:</b> Design well-defined, clear task flows with minimal navigation steps, especially for major user tasks, and make sure those tasks are navigable via focus controls (see item 4).</p></li>
<p>
<li><b>Action target size:</b> Make sure buttons and selectable areas are of sufficient size for users to easily touch them, especially for critical actions. How big? We recommend that touch targets be <a href="http://developer.android.com/design/style/metrics-grids.html#48dp-rhythm">48dp</a> (roughly 9mm) or larger.</li>
</p><li><p><b>Label user interface controls:</b> <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#label-ui">Label user interface components</a> that do not have visible text, especially <a href="http://developer.android.com/reference/android/widget/ImageButton.html">ImageButton</a>, <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a>, and <a href="http://developer.android.com/reference/android/widget/EditText.html">EditText</a> components. Use the <a href="http://developer.android.com/reference/android/view/View.html#attr_android:contentDescription">android:contentDescription</a> XML layout attribute or <a href="http://developer.android.com/reference/android/view/View.html#attr_android:contentDescription">setContentDescription()</a> to provide this information for accessibility services. </p></li>
<li><p><b>Enable focus-based navigation:</b> Make sure <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#focus-nav">users can navigate</a> your screen layouts using hardware-based or software directional controls (D-pads, trackballs and keyboards). In a few cases, you may need to make UI components <a href="http://developer.android.com/reference/android/view/View.html#attr_android:focusable">focusable</a> or change the <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#focus-order">focus order</a> to be more logical.</p></li>
<li><p><b>Use framework-provided controls:</b> Use Android's built-in user interface controls whenever possible, as these components provide accessibility support by default.</p></li>
<li><p><b>Custom view controls:</b> If you build <a href="http://developer.android.com/guide/topics/ui/custom-components.html%20">custom interface controls</a> for your application, <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#custom-views">implement accessibility interfaces</a> for your custom views and provide text labels for the controls.</p></li>
<li><p><b>Test:</b> Checking off the items on this list doesn’t guarantee your app is accessible. <a href="http://developer.android.com/guide/topics/ui/accessibility/apps.html#test">Test accessibility</a> by attempting to navigate your application using directional controls, and also try eyes free navigation with the TalkBack service enabled.</p></li>
</ol><p>Here’s an example of implementing some basic accessibility features for an ImageButton inside an XML layout:</p><pre><code>&lt;ImageButton
    android:id="@+id/add_note_button"
    android:src="@drawable/add_note_image"
    android:contentDescription="@string/add_note_description"/></code></pre><p>Notice that we’ve added a content description that accessibility services can use to provide an audible explanation of the button. Users can navigate to this button and activate it with directional controls, because ImageButton objects are focusable by default (so you don’t have to include the <code>android:focusable="true"</code> attribute).</p><p>The good news is that, in most cases, implementing accessibility isn’t about radically restructuring your application, but rather working through the subtle details of accessibility. Making sure your application is accessible is an opportunity to look at your app from a different perspective, improve the overall quality of your app and ensure that all your users have a great experience.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-9037887593434390057?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/accessibility-are-you-serving-all-your-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Faster Emulator with Better Hardware Support</title>
		<link>https://googledata.org/google-android/a-faster-emulator-with-better-hardware-support/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-faster-emulator-with-better-hardware-support</link>
		<comments>https://googledata.org/google-android/a-faster-emulator-with-better-hardware-support/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 18:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=8575668e1f563e54b5deed9369d8e1d6</guid>
		<description><![CDATA[[This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. — Tim Bray.]The Android emulator is a key tool for Android developers in building and testing their apps. As the power and diversity of Android devices has grown quickly...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. — Tim Bray.]</i></p><p>The Android emulator is a key tool for Android developers in building and testing their apps. As the power and diversity of Android devices has grown quickly,  it’s been hard for the emulator keep pace. </p><p>Today we’re thrilled to announce several significant improvements to the emulator, including a dramatic performance upgrade and support for a broader range of hardware features, notably sensors and multi-finger input.</p><h3>Added GPU Support</h3><p>The system image we’re shipping today has built-in GPU support (Android 4.0.3 r2).  With Android’s growing reliance on using the GPU to improve performance, the difference is significant.  In the video below,   the emulator is still interpreting ARM instructions; the performance boost is the effect of putting the GPU to work.</p><iframe width="420" height="315" src="http://www.youtube.com/embed/T--vFtyZvc4" frameborder="0" allowfullscreen=""></iframe><p>
As a bonus, since we’re now supporting OpenGL ES 2.0, your OpenGL games can now run inside the emulator. </p><p>Please note that there are a lot of GPUs out there, and we haven’t tested all of them for this beta release, so let us know if you have <a href="http://code.google.com/p/android/issues/entry?template=Tools%20GPU%20bug%20report">feedback</a> or encounter issues. </p><h3>More Hardware Feature Emulation</h3><p>The hardware features of mobile devices are a significant part of what makes them a unique platform for development, so we’re also pleased to announce that in addition to the camera support we added last year, it’s now possible to use a tethered Android device to supply inputs for sensors and multi-touch input.</p><p>We’re working on providing emulator support for more hardware features including Bluetooth and NFC.</p><h3>Improved CPU Performance</h3><p>We’ve also improved the CPU performance of the Android emulator.  Hardware floating point operation has been available for system images since Ice Cream Sandwich (Android 4.0), allowing CPU operations to be emulated roughly twice as quickly.</p><p>Last week’s r17 developer tools release included x86 system images and host drivers (available through the SDK Manager), allowing the emulator to access the host CPU natively and offer significantly faster execution.</p><p>This video shows a CPU-bound application on two emulators running the same system image, one with virtualization, one without.</p><iframe width="420" height="315" src="http://www.youtube.com/embed/1gnQX_izOrk" frameborder="0" allowfullscreen=""></iframe><h3>Building a modern emulator</h3><p>Because the Android platform allows deep interaction between applications, and with system components, we need to provide an emulator with a complete system image.  Our emulator virtualizes a complete device: hardware, kernel, low-level system libraries, and app framework.</p><p>Of course, the system being emulated typically has an ARM CPU; historically, we’d been emulating those instructions in software, and that worked OK until the advent of tablet support with additional animations and complexity in Android 3.0.</p><p>The missing pieces were the completion of Android x86 support, and the GPU support in last week’s release of SDK Tools r17.  This works by funneling the OpenGL ES 2.0 instructions from the emulator to the host OS, converted to standard OpenGL 2.0, and running natively on the host GPU.</p><h3>Conclusion</h3><p>The Android ecosystem has a lot of devices in many different form factors. Developers need a good way of testing these apps without having to own everything out there and a fast, rich Android emulator is immensely helpful.</p><p>We hope that these new improvements will make the emulator a more useful tool in your development and testing, and look forward to improving it further for you.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8363285670263533337?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/a-faster-emulator-with-better-hardware-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>The Gmail Public Labels API</title>
		<link>https://googledata.org/google-android/the-gmail-public-labels-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-gmail-public-labels-api</link>
		<comments>https://googledata.org/google-android/the-gmail-public-labels-api/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 05:43:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=6680aa0123fdb43ec25e0d278a6ef6e9</guid>
		<description><![CDATA[[This post is by Nadav Aharony, a product manager on the Android team&#160;&#8212;&#160;Tim Bray]We’re rolling out new developer features for the Gmail Android app:  It now includes a public ContentProvider that you can use to retrieve label data. Yo...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Nadav Aharony, a product manager on the Android team&nbsp;&mdash;&nbsp;Tim Bray]</i></p><p>We’re rolling out new developer features for the Gmail Android app:  It now includes a public ContentProvider that you can use to retrieve label data. You can use this to access up-to-date unread counts for specific accounts’ inboxes and labels. </p><p>To use the API, the Gmail app needs to be at version 2.3.6 or higher on Froyo or Gingerbread; 4.0.5 or higher on Honeycomb and ICS. Before using it, be sure you first check the Gmail app version; we’ve provided a handy  <code>GmailContract.canReadLabels(Context)</code> method to help with this. Your app will need the <code>com.google.android.gm.permission.READ_CONTENT_PROVIDER</code> permission.</p><h3>Finding the Gmail accounts set up on the device</h3><p>The Labels API needs a valid Gmail account to build a query for per-label information.  Assuming the <a href="http://developer.android.com/reference/android/Manifest.permission.html#GET_ACCOUNTS">GET_ACCOUNTS</a> permission, the <a href="http://developer.android.com/reference/android/accounts/AccountManager.html">AccountManager</a> can be used to fetch this information:</p><pre><code>// Get the account list, and pick the first one
final String ACCOUNT_TYPE_GOOGLE = "com.google";
final String[] FEATURES_MAIL = {
        "service_mail"
};
AccountManager.get(this).getAccountsByTypeAndFeatures(ACCOUNT_TYPE_GOOGLE, FEATURES_MAIL,
        new AccountManagerCallback() {
            @Override
            public void run(AccountManagerFuture future) {
                Account[] accounts = null;
                try {
                    accounts = future.getResult();
                    if (accounts != null &amp;&amp; accounts.length > 0) {
                        String selectedAccount = accounts[0].name;
                        queryLabels(selectedAccount);
                    }

                } catch (OperationCanceledException oce) {
                    // TODO: handle exception
                } catch (IOException ioe) {
                    // TODO: handle exception
                } catch (AuthenticatorException ae) {
                    // TODO: handle exception
                }
            }
        }, null /* handler */);</code></pre><h3>Getting and accessing existing labels</h3><p>Once you’ve got the email account, you can get a <a href="http://developer.android.com/guide/topics/providers/content-provider-basics.html">ContentProvider</a> URI to query against. We've provided a simple support class called <a href="https://developers.google.com/gmail/android/com/google/android/gm/contentprovider/GmailContract">GmailContract.java</a> for constructing the URI and defining the columns and relevant constants. </p><p>You can access any label, predefined or user-defined. The predefined labels include (you have to use symbolic constants rather than these strings, see below): </p><ul><li><p>Priority Inbox</p></li><li><p>Starred</p></li><li><p>Chats</p></li><li><p>Sent</p></li><li><p>Drafts</p></li><li><p>All mail</p></li><li><p>Spam</p></li><li><p>Trash</p></li></ul><p>To obtain a Cursor with information for all labels in an account, your app can either query this URI directly or use a <a href="http://developer.android.com/reference/android/content/CursorLoader.html">CursorLoader</a>. Here’s an example:</p><pre><code>Cursor c = 
    getContentResolver().query(GmailContract.Labels.getLabelsUri(selectedAccount), 
        null, null, null, null);</code></pre><p>You can query and watch for changes on a single label by storing the URI value in the <code>GmailContract.Labels.URI</code> column from the cursor data.</p><p>The <code>NAME</code> value for pre-defined labels can vary by locale, so don’t use <code>GmailContract.Labels.NAME</code>. Instead, identify pre-defined labels like Inbox, Sent or Drafts using the String value in the <code>GmailContract.Labels.CANONICAL_NAME</code> column. Here’s an example:</p><pre><code>// loop through the cursor and find the Inbox
if (c != null) {
    final String inboxCanonicalName = GmailContract.Labels.LabelCanonicalName.CANONICAL_NAME_INBOX;
    final int canonicalNameIndex = c.getColumnIndexOrThrow(GmailContract.Labels.CANONICAL_NAME);
    while (c.moveToNext()) {
        if (inboxCanonicalName.equals(c.getString(canonicalNameIndex))) {
            // this row corresponds to the Inbox
        }
    }
}</code></pre><p>If you choose to use a <a href="http://developer.android.com/reference/android/content/CursorLoader.html">CursorLoader</a>, it will keep the label counts up to date as they change over time.</p><h3>Sample App</h3><p>You can find a sample app that makes use of the new API <a href="https://developers.google.com/gmail/android/android-gmail-api-sample.tar.gz">here</a>. The app provides a basic readout of label and message-count information.</p><p>People care about their incoming mail; we’re looking forward to seeing what you do with access to this information.  We’re also open to suggestions as to how to improve and extend this new API.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8804233573658324945?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/the-gmail-public-labels-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making the Android Developer Console work for your whole team</title>
		<link>https://googledata.org/google-android/making-the-android-developer-console-work-for-your-whole-team/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=making-the-android-developer-console-work-for-your-whole-team</link>
		<comments>https://googledata.org/google-android/making-the-android-developer-console-work-for-your-whole-team/#comments</comments>
		<pubDate>Thu, 29 Mar 2012 17:20:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=20c45f2f6e7ca0a3c496b1c6f981422b</guid>
		<description><![CDATA[[This post is by Ellie Powers, a product manager on the Google Play team. — Tim Bray]As your apps have gotten more successful, more people have joined your team. Today, we’re making it easier to work together on analyzing and managing your publis...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-Hzf1VF82_FE/T3OXjzFfijI/AAAAAAAABQM/GbKa2aE5m9o/s1600/mum2.png"><img style="border: 5px solid #ddd;float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 191px;" src="http://4.bp.blogspot.com/-Hzf1VF82_FE/T3OXjzFfijI/AAAAAAAABQM/GbKa2aE5m9o/s400/mum2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5725086192582494770" /></a><p><i>[This post is by <a href="https://plus.google.com/100189531984607939401/posts">Ellie Powers</a>, a product manager on the Google Play team. — Tim Bray]</i></p>As your apps have gotten more successful, more people have joined your team. Today, we’re making it easier to work together on analyzing and managing your published Android apps. Sharing passwords is <a href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=2543765">generally a bad idea</a>; so as of now, there’s no need to do that for the Android Developer Console — everyone can use his or her own Google account.<br />
<br />
The account that you use today to sign into the Android Developer Console will become the <em>account owner</em>; only the account owner can manage access to the Console. The account owner can email an invitation to anyone; when they accept it, they’ll need to use a Google account to sign in.<br />
<br />
Different people in your team do different jobs, so when you invite someone to your Android Developer Console, you’ll be able to specify what access they need. Today, you can limit access per-user to financial reports. In the future, we’ll give you more fine-grained control over access to the Console.  For details, see <a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=2528691">Account owner and user access</a>.<br />
<br />
We hope this helps your team collaborate more easily. If you have any issues, feel free to get in touch via the <a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=136601">Developer Help Center</a>. <br />
<a href="https://plus.google.com/108967384991768947849/posts/6VWzZeupVSJ" style="text-decoration: none; color: #333;"><br />
<div style="display: inline-block; line-height: 0;float:right;"><div style="float:left;"><span style="font: 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 11px;">Join the discussion on</span><br />
<span style="font: bold 13px/16px arial,sans-serif; margin-right: 4px; margin-top: 7px;">+Android Developers</span><br />
</div><div style="float: right;"><img src="https://ssl.gstatic.com/images/icons/gplus-32.png" width="32" height="32" style="border: 0;"/><br />
</div></div></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3726073550611530071?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/making-the-android-developer-console-work-for-your-whole-team/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Unifying Key Store Access in ICS</title>
		<link>https://googledata.org/google-android/unifying-key-store-access-in-ics/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=unifying-key-store-access-in-ics</link>
		<comments>https://googledata.org/google-android/unifying-key-store-access-in-ics/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 16:15:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=1e27ee58c879dd1a2d3906fe56acefad</guid>
		<description><![CDATA[[This post is a group effort by Tony Chan, Fred Chung, Brian Carlstrom, and Kenny Root. — Tim Bray]
Android 4.0 (ICS) comes with a number of enhancements that make it easier for people to bring their personal Android devices to work.   In this pos...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is a group effort by Tony Chan, Fred Chung, Brian Carlstrom, and Kenny Root. — Tim Bray]</i></p><p><span itemprop="description"><br />
Android 4.0 (ICS) comes with <a href="https://plus.google.com/u/0/116015738121164122619/posts/XCiRMwEEVuy">a number of enhancements</a> that make it easier for people to bring their personal Android devices to work.   In this post, we’re going to have a look at the key store functionality.</span></p><p>Back in Android 1.6 (Donut), a system key store was added for use by VPN.  Although this was later expanded to support WiFi authentication, applications weren’t able to access it.</p><p>In the past, it was common practice for apps to maintain their own key store if they needed to authenticate a secure SSL web server, or authenticate the user to a server via a client certificate.  While this works, it can present manageability issues in an enterprise environment where multiple certificates may be shared across a number of apps such as Email and Browser.</p><h3>New in ICS: KeyChain </h3><p>To bridge the gap in ICS, there’s a new API named <a href="http://developer.android.com/reference/android/security/KeyChain.html">KeyChain</a> that regulates application access to the system key store and allows users to grant application access to the credentials stored there.  Additionally, this API enables applications to initiate installation of credentials from X.509 certificates and PKCS#12 key stores.</p><a href="http://2.bp.blogspot.com/-f7QriOX9amI/T16HXPqp6-I/AAAAAAAABNY/1pt9zD49uFI/s1600/extract_cert_1.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 225px; height: 400px;" src="http://2.bp.blogspot.com/-f7QriOX9amI/T16HXPqp6-I/AAAAAAAABNY/1pt9zD49uFI/s400/extract_cert_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5719157410219289570" /></a><p>The KeyChain API is rather simple.  To install a key store or a certificate, you retrieve an install intent, supply the raw bytes of the credentials, and use the intent to launch a system installation dialog.  If it’s a keystore, as in the example below, you’ll need provide the data in <a href="http://en.wikipedia.org/wiki/PKCS12">PKCS#12</a> format, and the user will have to know the PKCS#12 password.</p><pre><code>  byte[] keystore = . . (read from a PKCS#12 keystore)

  Intent installIntent = KeyChain.createInstallIntent();
  installIntent.putExtra(KeyChain.EXTRA_PKCS12, keystore);
  startActivityForResult(installIntent, INSTALL_KEYSTORE_CODE);</code></pre><p>The install intent launches a system dialog that prompts the user to enter the password for the keystore.  </p><p>This can also be used for installing organizational CA certificates which will then be trusted by all applications to authenticate to non-public servers with certificates issued by the same CA.</p><p>In ICS, Android no longer requires a separate password to protect the system credential storage.  Rather, it uses the screen lock password for this purpose, and the <a href="http://developer.android.com/guide/topics/admin/device-admin.html">Android Device Administration API</a> can be used for central policy enforcement. This means, for example, that the screen lock password can’t be removed as long as the secured credentials remain on the device.</p><h3>Accessing System Key Store Credentials</h3><p>Once the system key store is configured, the KeyChain API offers functions such as requesting a client certificate for authenticating with an SSL server.  The first time an application requests access, the user is prompted with a list of available certificates and can select one to grant access to that certificate to the application.  If the user chooses to allow access to a certificate, a string alias name for the certificate is returned to the application.  The application can then use the alias to access the certificate in the future without further user involvement.</p><p>The code below illustrates how an application can prompt the user to select a credential alias and grant access to the application.  KeyChain will remember this selection such that the same application can save the credential alias selection and have access to the same certificate in future.  For example, the Email application for ICS has implemented this feature in its Server Settings screen.</p><pre><code>  KeyChain.choosePrivateKeyAlias(this,
    new KeyChainAliasCallback() {

        public void alias(String alias) {
            // Credential alias selected.  Remember the alias selection for future use.
            if (alias != null) saveAlias(alias);
        }
    },
    new String[] {"RSA", "DSA"}, // List of acceptable key types. null for any
    null,                        // issuer, null for any
    "internal.example.com",      // host name of server requesting the cert, null if unavailable
    443,                         // port of server requesting the cert, -1 if unavailable
    null);                       // alias to preselect, null if unavailable</code></pre><a href="http://4.bp.blogspot.com/-z5bVnwKbMNk/T193IeaZ1gI/AAAAAAAABNw/c8snqQ3q05M/s1600/choose_cert_2.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 225px; height: 400px;" src="http://4.bp.blogspot.com/-z5bVnwKbMNk/T193IeaZ1gI/AAAAAAAABNw/c8snqQ3q05M/s400/choose_cert_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5719421039270286850" /></a><p>Once an application has been granted access to the certificate, it can access the private key through the <a href="http://developer.android.com/reference/android/security/KeyChain.html#getPrivateKey(android.content.Context,%20java.lang.String)">getPrivateKey()</a> method.  It is worth noting that as with any <a href="http://developer.android.com/reference/java/security/PrivateKey.html">PrivateKey</a> objects, the application should not make assumptions about the encoding.  For example, on some implementations the PrivateKey object may just be an opaque representation of a key stored in a hardware key store.</p><p>Here’s a sample code snippet that demonstrates the use of private key retrieved from the key store for signing:</p><pre><code>    PrivateKey privateKey = KeyChain.getPrivateKey(context, savedAlias);
    if (privateKey != null) {
        ...
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        ...
    }</code></pre><p>A common use of the private key is for SSL client authentication.  This can be implemented by using an <a href="http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html">HttpsURLConnection</a> with a custom <a href="http://developer.android.com/reference/javax/net/ssl/X509KeyManager.html">X509KeyManager</a> that returns the PrivateKey retrieved from the KeyChain API.  The open source Email application for ICS uses KeyChain with an <a href="http://developer.android.com/reference/javax/net/ssl/X509ExtendedKeyManager.html">X509ExtendedKeyManager</a>.  To learn more, have a look at the source code (in SSLUtils.java).</p><p>This API provides a unified way to access the system key store credentials.  If your application uses client certificates (take note: enterprise email client or web browser developers) you should definitely look into the KeyChain API for your next update!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4475335699969734409?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/unifying-key-store-access-in-ics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Apps Break the 50MB Barrier</title>
		<link>https://googledata.org/google-android/android-apps-break-the-50mb-barrier/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-apps-break-the-50mb-barrier</link>
		<comments>https://googledata.org/google-android/android-apps-break-the-50mb-barrier/#comments</comments>
		<pubDate>Tue, 06 Mar 2012 01:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=912ee0b7c730107a3e89ccf3c28ff878</guid>
		<description><![CDATA[Android applications have historically been limited to a maximum size of 50MB. This works for most apps, and smaller is usually better — every megabyte you add makes it harder for your users to download and get started. However, some types of apps,...]]></description>
				<content:encoded><![CDATA[<p>Android applications have historically been limited to a maximum size of 50MB. This works for most apps, and smaller is usually better — every megabyte you add makes it harder for your users to download and get started. However, some types of apps, like high-quality 3D interactive games, require more local resources.</p><p>So today, we’re expanding the Android app size limit to 4GB.</p><p>The size of your APK file will still be limited to 50MB to ensure secure on-device storage, but you can now attach expansion files to your APK.</p><ul><li><p>Each app can have two expansion files, each one up to 2GB, in whatever format you choose.</p></li><li><p>Android Market will host the files to save you the hassle and cost of file serving.</p></li><li><p>Users will see the total size of your app and all of the downloads before they install/purchase.</p></li></ul><p>On most newer devices, when users download your app from Android Market, the expansion files will be downloaded automatically, and the refund period won’t start  until the expansion files are downloaded. On older devices, your app will download the expansion files the first time it runs, via a downloader library which we’ve provided below.</p><p>While you can use the two expansion files any way you wish, we recommend that one serve as the initial download and be rarely if ever updated; the second can be smaller and serve as a “patch carrier,” getting versioned with each major release.</p><h3>Helpful Resources</h3><p>In order to make expansion file downloading as easy as possible for developers, we're providing sample code and libraries in the <a href="http://developer.android.com/sdk/adding-components.html">Android SDK Manager</a>.</p><ul><li><p>In the Google Market Licensing package, an updated License Verification Library (LVL). This minor update mostly adds the ability to obtain expansion file details from the licensing server.</p></li><li><p>From the Google Market APK Expansion package, the downloader service example.  <a href="http://developer.android.com/sdk/adding-components.html#InstallingComponents">The library</a> makes it relatively simple to implement a downloader service in your application that follows many of our best practices, including resuming downloads and displaying a progress notification.</p></li></ul><p>Because many developers may not be used to working with one or two large files for all of their secondary content, the example code also includes support for using a Zip file as the secondary file. The Zip example implements a reasonable patching strategy that allows for the main expansion file to “patch” the APK and the patch file to “patch” both the APK and the main expansion file by searching for asset files in all three places, in the order patch->main->APK. </p><h3>Expansion File Basics</h3><p>Expansion files have a specific naming convention and are located in a specific place for each app.  As expansion files are uploaded to the publisher site, they are assigned a version code based upon the version of the APK that they are associated with.  The naming convention and location are as follows:</p><blockquote><p>Location: <code>&lt;shared-storage>/Android/obb/&lt;package-name>/</code><br/>Filename: <code>[main|patch].&lt;expansion-version>.&lt;package-name>.obb</code><br/>Example: <code>/sdcard/Android/obb/com.example.myapp/main.5.com.example.myapp.obb</code></p></blockquote><p>Expansion files are stored in shared storage. Unlike APK files, they can be read by any application.</p><h3>Downloading and Using the Expansion Files</h3><p>When the primary activity for the app is created, it should check to make sure the expansion files are available.  The downloader library provides helper functions (for example the “Helpers” class in the code below) to make this easy.</p><pre><code>boolean expansionFilesDelivered() {
    // get filename where main == true and version == 3
    String fileName = Helpers.getExpansionAPKFileName(this, true, 3);
    // does the file exist with FILE_SIZE?
    if (!Helpers.doesFileExist(this, fileName, FILE_SIZE, false)) {
        return false;
    }
    return true;
}</code></pre><a href="http://1.bp.blogspot.com/-FoijusoKkCY/T1Tzxm_QJvI/AAAAAAAABNA/7qLq48ZwgdI/s1600/APKExpansion.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 372px; height: 400px;" src="http://1.bp.blogspot.com/-FoijusoKkCY/T1Tzxm_QJvI/AAAAAAAABNA/7qLq48ZwgdI/s400/APKExpansion.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5716461860644988658" /></a><p>If the file does not exist, fire up the downloader service with <code>DownloaderClientMarshaller.startDownloadServiceIfRequired()</code>. The downloader will perform an LVL check against the server.  This check will deliver the names of the files, file sizes, and the file URLs.</p><p>Once that check has been completed, it will begin downloading the files.  You don’t have to use our download solution, but you might want to because we:</p><ul><li><p>Include a notification UI that provides progress and estimated completion time in layouts customized for ICS and pre-ICS devices</p></li><li><p>Resume large files safely</p></li><li><p>Handle redirection with appropriate limits</p></li><li><p>Run in the background as a service</p></li><li><p>Pause and resume downloads when WiFi is not available</p></li></ul><p>Enjoy! We can’t wait to see what kinds of things developers do with this! For more information about how to use expansion files with your app, read the <a href="http://developer.android.com/guide/market/expansion-files.html%20">APK Expansion Files</a> developer guide.</p><p><i>[This post wasn’t actually written by anyone, but bashed out by a posse of engineering and product-management people. Heavy bashers included Dan Galpin, Ilya Firman, Andy Stadler, Michael Siliski, and Ellie Powers.]</i></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2573571652292551746?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-apps-break-the-50mb-barrier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Design V2: Now with stencils</title>
		<link>https://googledata.org/google-android/android-design-v2-now-with-stencils/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-design-v2-now-with-stencils</link>
		<comments>https://googledata.org/google-android/android-design-v2-now-with-stencils/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 22:05:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=3526ec5cb311bde017c4b276d4386fbd</guid>
		<description><![CDATA[[This post is by Android designer Alex Faaborg, on behalf of the entire User Experience team. —Tim Bray]When we initially released Android Design, by far the number one request we received was for us to release stencils as well.  The fine folks on t...]]></description>
				<content:encoded><![CDATA[<img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px; " src="http://1.bp.blogspot.com/-wjQccEThR14/T05phaDTH7I/AAAAAAAABLk/zIOLXcxUG5Q/s400/faaborg.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5714620999829495730" /><p><i>[This post is by Android designer <a href="https://plus.google.com/102905316931749515082/posts">Alex Faaborg</a>, on behalf of the entire User Experience team. —Tim Bray]</i></p><p>When we initially released <a href="http://developer.android.com/design/index.html"><i>Android Design</i></a>, by far the number one request we received was for us to release stencils as well.  <span itemprop="description">The fine folks on the Android User Experience team are pleased today to release some official Android Design stencils for your mockup-creating pleasure. </span> </p><a href="http://4.bp.blogspot.com/-gkhwmjszXQ4/T05qjoQROKI/AAAAAAAABLw/oMSw2FzdFb8/s1600/stencilCrop.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://4.bp.blogspot.com/-gkhwmjszXQ4/T05qjoQROKI/AAAAAAAABLw/oMSw2FzdFb8/s320/stencilCrop.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5714622137513359522" /></a><p>With these stencils you can now drag and drop your way to beautifully designed Ice Cream Sandwich (Android 4.0) applications, with grace and ease. The stencils feature the rich typography, colors, interactive controls, and icons found throughout Ice Cream Sandwich, along with some phone and tablet outlines to frame your meticulously crafted creations. </p><p>Currently we have stencils available for those venerable interactive design powerhouses Adobe® Fireworks®, and Omni® OmniGraffle® and we may expand to other applications® in the future.  The source files for the various icons and controls are also available, created in Adobe® Photoshop®, and Adobe® Illustrator®. <a href="http://developer.android.com/design/downloads">Here are the downloads</a>.  </p><p>We’ll be updating these stencils over time so, as always, please send in your feedback!</p><p>Happy mockup making,<br />
— Your friendly Android Design Droids</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5432342374374599349?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-design-v2-now-with-stencils/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Share With Intents</title>
		<link>https://googledata.org/google-android/share-with-intents/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=share-with-intents</link>
		<comments>https://googledata.org/google-android/share-with-intents/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 15:20:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=960b35638cd278259def1250f7b9317e</guid>
		<description><![CDATA[[This post is by Alexander Lucas, an Android Developer Advocate bent on saving the world 5 minutes. —Tim Bray][Please join the discussion on Google+.]Intents are awesome. They are my favorite feature of Android development.  They make all sorts of s...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/TQf98KOwFtI/AAAAAAAAAPU/GAn3Efe53UM/s1600/alexlucas.png"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand; height: 120px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/TQf98KOwFtI/AAAAAAAAAPU/GAn3Efe53UM/s400/alexlucas.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5550684275737630418" /></a><p><i>[This post is by Alexander Lucas, an Android Developer Advocate bent on saving the world 5 minutes. —Tim Bray]</i></p><p><i>[Please join <a href="https://plus.google.com/108967384991768947849/posts/ExqhqWWqSP9">the discussion on Google+</a>.]</i></p><p>Intents are awesome. They are my favorite feature of Android development.  They make all sorts of stuff easier.  Want to scan a barcode?  In the olden platforms, if you were lucky, this involved time and effort finding and comparing barcode-scanning libraries that handled as much as possible of camera interaction, image processing, an internal database of barcode formats, and UI cues to the user of what was going on.  If you weren’t lucky, it was a few months of research &amp; haphazard coding to figure out how to do that yourself.</p><p>On Android, it’s a declaration to the system that you would like to scan a barcode.</p><pre><code>public void scanSomething() {
    // I need things done!  Do I have any volunteers?
    Intent intent = new Intent("com.google.zxing.client.android.SCAN");

    // This flag clears the called app from the activity stack, so users arrive in the expected
    // place next time this application is restarted.
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

    intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
    startActivityForResult(intent, 0);
}
...
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == 0) {
        if (resultCode == RESULT_OK) {
            //  The Intents Fairy has delivered us some data!
            String contents = intent.getStringExtra("SCAN_RESULT");
            String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
            // Handle successful scan
        } else if (resultCode == RESULT_CANCELED) {
            // Handle cancel
        }
    }
}</code></pre><p>See that?  That’s <em>nothing</em>.  That’s 5 minutes of coding, 3 of which were just to look up the name of the result you wanted to pull.  And that was made possible because the Barcode Scanner application is designed to be able to scan barcodes for whatever other applications may need it.</p><p>More important, our app is completely decoupled from the BarcodeScanner app.  There’s no integration- in fact, neither application is checking to verify that the other exists.  If the user preferred, they could remove “Barcode Scanner” and replace it with a competing app.  As long as that app supported the same intent, functionality would remain the same.  This decoupling is important.  It’s the easy way.  It’s the <a href="http://en.wikipedia.org/wiki/Larry_Wall#Virtues_of_a_programmer">lazy</a> way.  It’s the Android way.</p><h3>Sharing Data Using Intents</h3><p>One of the most inherently useful Android intents is the Share intent.  You can let the user share data to any service they want, <em>without writing the sharing code yourself</em>, simply by creating a share intent.</p><pre><code>Intent intent=new Intent(android.content.Intent.ACTION_SEND);
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

// Add data to the intent, the receiving app will decide what to do with it.
intent.putExtra(Intent.EXTRA_SUBJECT, “Some Subject Line”);
intent.putExtra(Intent.EXTRA_TEXT, “Body of the message, woot!”);</code></pre><p>... and starting it with a <a href="http://developer.android.com/reference/android/content/Intent.html#createChooser(android.content.Intent,%20java.lang.CharSequence)">chooser</a>:</p><pre><code>startActivity(Intent.createChooser(intent, “How do you want to share?”));</code></pre><p>With these 5 lines of code, you get to bypass authenticating, credential storage/management, web API interaction via http posts, all sorts of things. Where by “bypass”, I mean “have something else take care of.”  Like the barcode scanning intent, all you really had to do was declare that you have something you’d like to share, and let the user choose from a list of takers.  You’re not limited to sending text, either.  Here’s how you’d create an intent to share an image:</p><pre><code>private Intent createShareIntent() {
    ...
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    shareIntent.setType("image/*");

    // For a file in shared storage.  For data in private storage, use a ContentProvider.
    Uri uri = Uri.fromFile(getFileStreamPath(pathToImage));
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    return shareIntent;
}  </code></pre><p>Note that just by using <a href="http://developer.android.com/reference/android/content/Intent.html#setType(java.lang.String)">setType()</a> to set a MIME type, you’ve filtered down the list of apps to those that will know what to do with an image file.</p><h3>Intents over Integration</h3><p>Think about this for a second.  By making the simple assumption that any user of any service (Task Manager, Social Network, Photo sharing site) already has some app on their phone that can share to that service, you can leverage the code that they’ve already written.  This has several awesome implications:</p><ul><li><p><i>Less UI</i> — You don’t have to clog up your UI with customized, clickable badges of services you support.  Just add a “share” button.  It’s okay, we’ve made sure all your users know what it does [insert smiley here].</p></li><li><p><i>Leveraged UI</i> — You can bet that every high-quality web service out there has spent serious time on the UI of their Android app’s “share” activity.  Don’t reinvent the wheel!  Just grab a couple and go for a ride.</p></li><li><p>Filtered for the user — If I don’t have a Foo-posting app on my phone, there’s a good chance I don’t care about posting to Foo.  Now I won’t see Foo icons everywhere that are useless to me.</p></li><li><p><i>Client App Ecosystem</i> — Much like an email client, anyone can write a client for any service.  Users will use the ones they want, uninstall the ones they don’t.  Your app supports them all.</p></li><li><p><i>Forward Compatible with new services</i> — If some swanky new service springs up out of nowhere with an Android Application, as long as that application knows how to receive the share intent, you already support it.  You don’t spend time in meetings discussing whether or not to wedge support for the new service into your impending Next Release(tm), you don’t burn engineering resources on implementing support as fast as possible, you don’t even upload a new version of anything to Android Market.  Above all, you don’t do any of that again next week, when another new service launches and the whole process threatens to repeat itself.  You just hang back and let your users download an application that makes yours even more useful.</p></li></ul><h3>Avoid One-Off Integrations</h3><p>For each pro of the Intent approach, integrating support to post to these services one-at-a-time has a corresponding con.</p><ul><li><p><i>Bad for UI</i> — If your photo-sharing app has a Foo icon, what you might not immediately understand is that while you’re trying to tell the user “We post to Foo!” what you’re really saying is “We don’t post to Bar, Baz, or let you send the photo over email, sms, or bluetooth.  If we did, there would be icons.  In fact, we probably axed those features because of the space the icons would take on our home screen.  Oh, and we’ll probably use some weird custom UI and make you authenticate through a browser, instead of the Foo client you already have installed.”  I’m not going to name names, but a lot of you are guilty of this.  It’s time to stop.  (I mean it.  Stop.)</p></li><li><p>Potentially wasted effort — Let’s say you chose one service, and integrated it into your UI <em>perfectly</em>.  Through weeks of back-and-forth with Foo’s staff, you’ve got the API and authentication mechanisms down pat, the flow is seamless, everything’s great.  Only problem is that you just wasted all that effort, because none of your user-base particularly cares for Foo.  Ouch!</p></li><li><p><i>Not forward compatible for existing services</i> — Any breaking changes in the API are your responsibility to fix, quickly, and that fix won’t be active until your users download a newer version of your app.</p></li><li><p><i>Won’t detect new services</i> — This one really hurts.  If a brand new service Baz comes out, and you’ve actually got the engineering cycles to burn, you need to get the SDK, work out the bugs, develop a sharing UI, have an artist draw up your own “edgy” (ugh) but legally distinct version of the app’s logo so you can plaster it on your home screen, work out all the bugs, and launch.</p></li></ul><p>You will be judged harshly by your users.  And deservedly so.</p><h3>Ice Cream Sandwich makes it even easier</h3><p>With the release of ICS, a useful tool for sharing called <a href="http://developer.android.com/reference/android/widget/ShareActionProvider.html">ShareActionProvider</a> was added to the framework, making the sharing of data across Android applications even easier.  ShareActionProviders let you populate lists of custom views representing ACTION_SEND targets, facilitating (for instance) adding a “share” menu to the ActionBar, and connecting it to whatever data the user might want to send.</p><p>Doing so is pretty easy.  Configure the menu items in your Activity’s onCreateOptionsMenu method, like so:</p><pre><code>@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Get the menu item.
    MenuItem menuItem = menu.findItem(R.id.menu_share);
    // Get the provider and hold onto it to set/change the share intent.
    mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();

    // Attach an intent to this ShareActionProvider.  You can update this at any time,
    // like when the user selects a new piece of data they might like to share.
    mShareActionProvider.setShareIntent(yourCreateShareIntentMethod());

    // This line chooses a custom shared history xml file. Omit the line if using
    // the default share history file is desired.
    mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
      . . .
}</code></pre><p>Note that you can specify a history file, which will adapt the ordering of share targets based on past user choices.  One shared history file can be used throughout an application, or different history files can be used within the same application, if you want to use a separate history based on what kind of data the user wants to share.  In the above example, a custom history file is used.  If you wish to use the default history for the application, you can omit that line entirely.  </p><p>This will help optimize for an important feature of the ShareActionProvider:  The user’s most common ways to share float to the top of the drop-down, with the least used ones disappearing below the fold of the “See More” button.  The most commonly selected app will even become a shortcut right next to the dropdown, for easy one-click access!</p><a href="http://2.bp.blogspot.com/-mVQddiSMz0I/TzL2y2Ny5uI/AAAAAAAABKo/ikNPtWiPu4w/s1600/Screenshot_2012-02-08-14-01-21.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 180px; height: 320px;" src="http://2.bp.blogspot.com/-mVQddiSMz0I/TzL2y2Ny5uI/AAAAAAAABKo/ikNPtWiPu4w/s320/Screenshot_2012-02-08-14-01-21.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5706895031239108322" /></a><p>You’ll also need to define a custom menu item in XML.  Here’s an example from the <a href="http://developer.android.com/guide/topics/ui/actionbar.html#ShareActionProvider">ActionBar Dev Guide</a>.</p><pre><code>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android">
    &lt;item android:id="@+id/menu_share"
          android:title="@string/share"
          android:showAsAction="ifRoom"
          android:actionProviderClass="android.widget.ShareActionProvider" />
&lt;/menu></code></pre><p>And with that, you can have an easy sharing dropdown that will look like the screenshot here. Note that you get the nice standard three-dots-two-lines “Share” glyph for free.</p><h3>Remember: Smart and Easy</h3><p>The share intent is the preferred method of sharing throughout the Android ecosystem. It’s how you share images from Gallery, links from the browser, and apps from Android Market. Intents are the easiest path to writing flexible applications that can participate in a rapidly expanding ecosystem, but they’re also the smart path to writing applications that will stay relevant to your users, letting them share their data to any service they want, no matter how often their preferences change over time.   So take a step back and stop worrying about if your user wants to tweet, digg, post, email, im, mms, bluetooth, NFC, foo, bar or baz something.  Just remember that they want to share it.  Android can take it from there.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-552000352514140667?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/share-with-intents/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Security Update</title>
		<link>https://googledata.org/uncategorized/android-security-update/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-security-update</link>
		<comments>https://googledata.org/uncategorized/android-security-update/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 20:31:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=7054141b2a6a02d064d39efa376fb0b3</guid>
		<description><![CDATA[Recently, there’s been a lot of news coverage of malware in the mobile space.  Over on our Mobile blog, Hiroshi Lockheimer, VP of Android engineering, has posted Android and Security.  We think most Android developers will find it interesting reading.]]></description>
				<content:encoded><![CDATA[<p>Recently, there’s been a lot of news coverage of malware in the mobile space.  Over on our Mobile blog, Hiroshi Lockheimer, VP of Android engineering, has posted <a href="http://googlemobile.blogspot.com/2012/02/android-and-security.html">Android and Security</a>.  We think most Android developers will find it interesting reading.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6876646662488307059?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/android-security-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Social APIs in Android ICS</title>
		<link>https://googledata.org/google-android/new-social-apis-in-android-ics/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-social-apis-in-android-ics</link>
		<comments>https://googledata.org/google-android/new-social-apis-in-android-ics/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 16:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=eda05ee18f67838ad19343f8b84c2aab</guid>
		<description><![CDATA[[This post is by Daniel Lehmann, Tech Lead on the Android Apps team.&#160;&#8212;&#160;Tim&#160;Bray][We’re trying something new; There’s a post over on Google+ where we’ll host a discussion of this article.  Daniel Lehmann has agreed to drop by ...]]></description>
				<content:encoded><![CDATA[<a href="http://3.bp.blogspot.com/-wevmqYoGX4k/TyoUmDOuBHI/AAAAAAAABJ8/QB7Rf5ccSmc/s1600/_MG_6086.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand; height: 100px;" src="http://3.bp.blogspot.com/-wevmqYoGX4k/TyoUmDOuBHI/AAAAAAAABJ8/QB7Rf5ccSmc/s200/_MG_6086.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5704394521952781426" /></a><p><i>[This post is by <a href="https://plus.google.com/u/0/107954099379890493913/posts">Daniel Lehmann</a>, Tech Lead on the Android Apps team.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p><i>[We’re trying something new; There’s a <a href="https://plus.google.com/108967384991768947849/108967384991768947849/posts/URQQYg9cyii">post over on Google+</a> where we’ll host a discussion of this article.  Daniel Lehmann has agreed to drop by and participate. Come on over and join in!]</i><p>With Android Ice Cream Sandwich, we set out to build software that supports emotional connections between humans and the devices they carry. We wanted to build the most personal device that the user has ever owned.</p><p>The first ingredient in our recipe is to show users the people that they care about most in a magazine-like way. High-resolution photos replace simple lists of text.</p><a href="http://1.bp.blogspot.com/-1LN_CVbvm7Y/Tymru-Sq1II/AAAAAAAABI0/9JIBbvjjoNA/s1600/image00.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 225px;" src="http://1.bp.blogspot.com/-1LN_CVbvm7Y/Tymru-Sq1II/AAAAAAAABI0/9JIBbvjjoNA/s400/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704279226525078658" /></a><p>The second ingredient is to more prominently visualize their friends’ activities. We show updates from multiple sources wherever a contact is displayed, without the need to open each social networking app individually.</p><p>Android is an open platform, and in Ice Cream Sandwich we provide a rich new API to allow any social networking application to integrate with the system. This post explains how apps like Google+ use these APIs, and how other social networks can do the same.</p><h3>A few basics</h3><p>Since Eclair (Android 2.0),  the system has been able to join contacts from different sources. Android can notice if you are connected to the same person and different networks, and join those into aggregate contacts.</p><a href="http://3.bp.blogspot.com/-FZaYd2fySUM/TymsgSSySgI/AAAAAAAABJM/hV1J_QvvNSA/s1600/Joining.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 355px;" src="http://3.bp.blogspot.com/-FZaYd2fySUM/TymsgSSySgI/AAAAAAAABJM/hV1J_QvvNSA/s400/Joining.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704280073707866626" /></a><p>Essential terms to understand throughout the remainder of this post are:</p><ul><li><p><a href="http://developer.android.com/reference/android/provider/ContactsContract.RawContacts.html"><i>RawContact</i></a> is a contact as it exists in one source, for example a friend in Skype.</p></li><li><p><i>Data</i> rows exists for each piece of information that the raw contact contains (name, phone number, email address, etc.).</p></li><li><p>A <i>Contact</i> joins multiple raw contacts into one aggregate. This is what the user perceives as a real contact in the People and Phone apps.</p></li><li><p>A <i>sync adapter</i> synchronizes its raw contacts with its cloud source. It can be bundled with a Market application (examples: Skype, Twitter, Google+).</p></li></ul><p>While users deal with contacts, sync adapters work with their raw contact rows. They own the data inside a raw contact, but by design it is left up to Android to properly join raw contact rows with others.</p><p>Contacts sync adapters have a special xml file that describes their content, which is documented in the Android SDK. In the following paragraphs, we’ll assume this file is named contacts.xml.</p><p>The Android SDK also contains the application SampleSyncAdapter (and its source code) that implements everything mentioned in here in an easy to understand way.</p><h3>High resolution photos</h3><p>In Android versions prior to Honeycomb (3.0), contact photos used to be 96x96. Starting with ICS, they now have a thumbnail (which is the 96x96 version) and a display photo. The display photo’s maximum size can vary from device to device (On Galaxy Nexus and Nexus S, it is currently configured to be 256x256, but expect this to vary with future devices). The size as configured can be queried like this:</p><pre><code>private static int getPhotoPickSize(Context context) {
  // Note that this URI is safe to call on the UI thread.
  Cursor c = context.getContentResolver().query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
      new String[]{ DisplayPhoto.DISPLAY_MAX_DIM }, null, null, null);
  try {
    c.moveToFirst();
    return c.getInt(0);
  } finally {
    c.close();
  }
}</code></pre><p>This value is useful if you need to query the picture from the server (as you can specify the right size for the download). If you already have a high resolution picture, there is no need for any resizing on your side; if it is too big, the contacts provider will downsample it automatically.</p><p>Up until now, pictures were written using a <a href="http://developer.android.com/reference/android/content/ContentValues.html">ContentValues</a> object, just like all the other data rows of the raw contact. While this approach is still supported, it might fail when used with bigger pictures, as there is a size limit when sending ContentValues across process boundaries. The prefered way now is to use an <a href="http://developer.android.com/reference/android/content/res/AssetFileDescriptor.html">AssetFileDescriptor</a> and write them using a FileOutputStream instead:</p><pre><code>private static void saveBitmapToRawContact(Context context, long rawContactId, byte[] photo) throws IOException {
    Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
    Uri outputFileUri =
        Uri.withAppendedPath(rawContactUri, RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
    AssetFileDescriptor descriptor = context.getContentResolver().openAssetFileDescriptor(
        outputFileUri, "rw");
    FileOutputStream stream = descriptor.createOutputStream();
    try {
      stream.write(photo);
    } finally {
      stream.close();
      descriptor.close();
    }
}</code></pre><p>For best results, store uncompressed square photos and let the contacts provider take care of compressing the photo. It will create both a thumbnail and a display photo as necessary.</p><p>This API is available on API version 14+. For older versions, we recommend to fallback to the old method using ContentValues and assuming a constant size of 96x96.</p><h3>Update streams</h3><p>The API for update streams is the biggest new addition for contacts in Ice Cream Sandwich. Sync adapters can now enrich their contact data by providing a social stream that includes text and photos.</p><a href="http://3.bp.blogspot.com/-dxfZhChtRd0/Tyms1JTH7wI/AAAAAAAABJY/H621VFXCJE4/s1600/Hier.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand; height: 150px;" src="http://3.bp.blogspot.com/-dxfZhChtRd0/Tyms1JTH7wI/AAAAAAAABJY/H621VFXCJE4/s320/Hier.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704280432070618882" /></a><p>This API is intended to provide an entry point into your social app to increase user engagement. We chose to only surface the most recent few stream items, as we believe that your social app will always be the best way to interact with posts on your network.</p><a href="http://1.bp.blogspot.com/-jXC4b6gTcxE/Tymt2TUwPKI/AAAAAAAABJk/I9dqeYnFjcM/s1600/image01.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 180px; height: 320px;" src="http://1.bp.blogspot.com/-jXC4b6gTcxE/Tymt2TUwPKI/AAAAAAAABJk/I9dqeYnFjcM/s320/image01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704281551453306018" /></a><p><a href="http://developer.android.com/reference/android/provider/ContactsContract.Contacts.StreamItems.html">StreamItems</a> rows are associated with a raw contact row. They contain the newest updates of that raw contact, along with text, time stamp and comments. They can also have pictures, which are stored in <a href="http://developer.android.com/reference/android/provider/ContactsContract.StreamItems.StreamItemPhotos.html">StreamItemPhotos</a>. The number of stream items per raw contact has a limit, which on the current Nexus devices is set to 5, but expect this number to change with future devices. The limit can be queried like this:</p><pre><code>private static int getStreamItemLimit(Context context) {
  // Note that this URI is safe to call on the UI thread.
  Cursor c = context.getContentResolver().query(StreamItems.CONTENT_LIMIT_URI,
      new String[]{ StreamItems.MAX_ITEMS }, null, null, null);
  try {
    c.moveToFirst();
    return c.getInt(0);
  } finally {
    c.close();
  }
}</code></pre><p>When displayed in the People app, stream items from all participating raw contacts will be intermixed and shown chronologically.</p><p>The following function shows how to add a stream item to an existing raw contact:</p><pre><code>private static void addContactStreamItem(Context context, long rawContactId, String text,
    String comments, long timestamp, String accountName, String accountType){
  ContentValues values = new ContentValues();
  values.put(StreamItems.RAW_CONTACT_ID, rawContactId);
  values.put(StreamItems.TEXT, "Breakfasted at Tiffanys");
  values.put(StreamItems.TIMESTAMP, timestamp);
  values.put(StreamItems.COMMENTS, comments);
  values.put(StreamItems.ACCOUNT_NAME, accountName);
  values.put(StreamItems.ACCOUNT_TYPE, accountType);
  context.getContentResolver().insert(StreamItems.CONTENT_URI, values);
}</code></pre><p>You can also specify an action that should be executed when a stream item or one of its photos is tapped. To achieve this, specify the receiving Activities in your contacts.xml using the tags <code>viewStreamItemActivity</code> and <code>viewStreamItemPhotoActivity</code>:</p><pre><code>&lt;ContactsAccountType
  xmlns:android="http://schemas.android.com/apk/res/android"
  viewStreamItemActivity="com.example.activities.ViewStreamItemActivity”
  viewStreamItemPhotoActivity="com.example.activities.ViewStreamItemPhotoActivity">
  &lt;!-- Description of your data types -->
&lt;/ContactsAccountType></code></pre><p>Update streams are available on API version 15+ and are intended to replace the StatusUpdate API. For previous versions, we recommend that you fall back to the StatusUpdates API, which only shows a single text item and no pictures.</p><h3>“Me” profile</h3><p>Ice Cream Sandwich is the first version of Android that supports the “Me” contact, which is prominently shown at the top of the list of the new People app. This simplifies use-cases that used to be a multi-tap process in previous versions — for example, sharing personal contact data with another person or “navigating home” in a navigation app. Also it allows applications to directly address the user by name and show their photo.</p><p>The “Me” profile is protected by the new permissions <code>READ_PROFILE</code> and <code>WRITE_PROFILE</code>. The new functionality is powerful; <code>READ_PROFILE</code> lets developers access users’ personally identifying information.  Please make sure to inform the user on why you require this permission.</p><p>The entry point to the new API is <a href="http://developer.android.com/reference/android/provider/ContactsContract.Profile.html">ContactsContract.Profile</a> and is available on API version 14+.</p><h2>Add connection</h2><p>Previously, connecting with users on a social network involved opening the respective social networking app, searching for the person and then connecting (“Friend”, “Follow” etc.). Ice Cream Sandwich has a much slicker approach: When looking at an existing contact in the People application, the user can decide to add this person to another network as well. For example, the user might want to follow a person on Google+ that they already have as a contact in Gmail.</p><a href="http://1.bp.blogspot.com/-IsWg8KGPrGs/TymuwS08A4I/AAAAAAAABJw/K-iaBsUYM00/s1600/image00.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 180px; height: 320px;" src="http://1.bp.blogspot.com/-IsWg8KGPrGs/TymuwS08A4I/AAAAAAAABJw/K-iaBsUYM00/s320/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704282547752272770" /></a><p>Once the user taps one of the “Add connection” commands, the app is launched and can look for the person using the information that is already in the contact. Search criteria are up to the app, but good candidates are name, email address or phone number.</p><p>To specify your “Add connection” menu item, use the attributes <code>inviteContactActivity</code> and <code>inviteContactActionLabel</code> in your contacts.xml:</p><pre><code>&lt;ContactsAccountType
  xmlns:android="http://schemas.android.com/apk/res/android"
  inviteContactActivity="com.example.activities.InviteContactActivity"
  inviteContactActionLabel="@string/invite_action_label">
  &lt;!-- Description of your data types -->
&lt;/ContactsAccountType></code></pre><p>Be sure to use the same verb as you typically use for adding connections, so that in combination with your app icon the user understands which application is about to be launched.</p><p>The “Add connection” functionality is available on API version 14+.</p><h3>Contact-view notification</h3><p>High-resolution pictures need a lot of space, and social streams quickly become outdated. It is therefore not a good idea to keep the whole contacts database completely in sync with the social network. A well-written sync adapter should take importance of contacts into account; as an example, starred contacts are shown with big pictures, so high-resolution pictures are more important. Your network might also have its own metrics that can help to identify important contacts.</p><p>For all other contacts, you can register to receive a notification which is sent by the People app to all sync adapters that contribute to a contact whenever the contact’s detail page is opened. At that point, you can provide additional information. As an example, when the Google+ sync adapter receives this notification, it pulls in the high-resolution photo and most recent social stream posts for that user and writes them to the contacts provider. This can be achieved by adding the <code>viewContactNotifyService</code> attribute to contacts.xml:</p><pre><code>&lt;ContactsAccountType
  xmlns:android="http://schemas.android.com/apk/res/android"
  viewContactNotifyService="com.example.notifier.NotifierService">
  &lt;!-- Description of your data types -->
&lt;/ContactsAccountType></code></pre><p>When this Intent is launched, its <code>data</code> field will point to the URI of the raw contact that was opened.</p><p>These notifications are available with API version 14+.</p><h3>Summary</h3><p>With Ice Cream Sandwich, we improved key areas around high resolution photos and update streams, and simplified the creation of new connections.</p><p>Everything outlined in here is done using open APIs that can be implemented by any network that wants to participate. We’re excited to see how developers take advantage of these new features!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2262704684721792677?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/new-social-apis-in-android-ics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Developers on Google+</title>
		<link>https://googledata.org/google-android/android-developers-on-google/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-developers-on-google</link>
		<comments>https://googledata.org/google-android/android-developers-on-google/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 18:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=43dfe140d92c972c70ef31b475cbccca</guid>
		<description><![CDATA[[This post is by Reto Meier, Android Developer Relations Tech Lead.&#160;&#8212;&#160;Tim&#160;Bray]I’ve been fortunate enough to be involved with Android since the 0.9 preview SDK was released to developers back in 2007. A lot has changed since then...]]></description>
				<content:encoded><![CDATA[<a href="http://1.bp.blogspot.com/-mh0HQ8xUFhU/TybSV8Wd-4I/AAAAAAAABH4/5qdXX_PyYVw/s1600/RUNE4063.jpg"><img style="border: 5px solid #ddd;float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://1.bp.blogspot.com/-mh0HQ8xUFhU/TybSV8Wd-4I/AAAAAAAABH4/5qdXX_PyYVw/s200/RUNE4063.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5703477252530764674" /></a><p><i>[This post is by <a href="https://plus.google.com/111169963967137030210/posts">Reto Meier</a>, Android Developer Relations Tech Lead.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>I’ve been fortunate enough to be involved with Android since the 0.9 preview SDK was released to developers back in 2007. A lot has changed since then, but one thing that hasn’t is the rapid pace at which new tools, resources, and information have become available for us Android developers. Just look at the last few months. </p><p>In December <a href="http://developer.android.com/training">Android Training</a> launched, with its first set of classes designed to demonstrate the best practices behind building great Android Apps.</p><p>Earlier this month, the <a href="http://developer.android.com/design"><cite>Android design</cite></a> site went live — offering a place to learn about the principles, building blocks, and patterns you need to make good design decisions when creating your Android app interfaces.</p><a href="http://2.bp.blogspot.com/-nyTsKF68CBA/TybSlNRJq3I/AAAAAAAABIE/W230SOsvqzU/s1600/AndroidDev-2.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://2.bp.blogspot.com/-nyTsKF68CBA/TybSlNRJq3I/AAAAAAAABIE/W230SOsvqzU/s400/AndroidDev-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5703477514769902450" /></a><p>We’ve got a lot more planned in the coming year, so to help you keep abreast of all the latest Android developer news we’re launching the <a href="https://plus.google.com/108967384991768947849/">+Android Developers</a> page on Google+!</p><p>One of my favourite things about Google+ is the quality of conversation around posts, so <a href="https://plus.google.com/108967384991768947849/">+Android Developers</a> will focus on being a place for the people behind the Android developer experience, and Android developers all around the world, to meet and discuss the latest in Android app development.</p><p>We’ll be posting development tips, discussing updates to the SDK and developer tools, highlighting new Android training classes, and posting video and pics from Android developer events around the world.</p><p>We’ll also be using Google+ Hangouts to help us all interact even more closely. Starting with weekly broadcast office-hours on Hangouts On Air to answer Android development questions. These will happen every Wednesday at 2pm Pacific Time (10pm UTS) in Mountain View—expect to see these hangouts in more time zones as our teams in London, Sydney, and Tokyo get involved. Each hangout will be <a href="http://www.youtube.com/playlist?list=PL7383D9AADA6E6D55">recorded for YouTube</a>, so if you can’t join us live you won’t miss out.</p><p>It turns out that hangouts are a lot of fun, so we’ll be doing more of these that feature interviews with Google engineers and 3rd party Android app developers willing to share their tips and experiences.</p><p>We’re looking forward to interacting with you even more closely, so add us to your circles, join the conversation by commenting on posts, and join the hangouts. We can't wait to hear what you have to say.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8753602663961406489?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-developers-on-google/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Say Goodbye to the Menu Button</title>
		<link>https://googledata.org/google-android/say-goodbye-to-the-menu-button/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=say-goodbye-to-the-menu-button</link>
		<comments>https://googledata.org/google-android/say-goodbye-to-the-menu-button/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 20:10:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=caedc15f0c02908274695c508ed9db19</guid>
		<description><![CDATA[[This post is by Scott Main, lead tech writer for developer.android.com.&#160;&#8212;&#160;Tim&#160;Bray]Before Android 3.0 (Honeycomb), all Android-powered devices included a dedicated Menu button. As a developer, you could use the Menu button to disp...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-iuj3Ow47b_k/TyG1PTXTodI/AAAAAAAABGo/Z5kHmVtOUF0/s1600/RUNE4057.jpg"><img style="border: 5px solid #ddd; float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 164px;" src="http://4.bp.blogspot.com/-iuj3Ow47b_k/TyG1PTXTodI/AAAAAAAABGo/Z5kHmVtOUF0/s200/RUNE4057.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5702037877728453074" /></a><p><i>[This post is by Scott Main, lead tech writer for <a href="http://developer.android.com">developer.android.com</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Before Android 3.0 (Honeycomb), all Android-powered devices included a dedicated Menu button. As a developer, you could use the Menu button to display whatever options were relevant to the user, often using the activity’s built-in options menu. Honeycomb removed the reliance on physical buttons, and introduced the <a href="http://developer.android.com/reference/android/app/ActionBar.html">ActionBar</a> class as the standard solution to make actions from the user options immediately visible and quick to invoke. In order to provide the most intuitive and consistent user experience in your apps, you should migrate your designs away from using the Menu button and toward using the action bar. This isn’t a new concept — the action bar pattern has been around on Android even before Honeycomb — but as Ice Cream Sandwich rolls out to more devices, it’s important that you begin to migrate your designs to the action bar in order to promote a consistent Android user experience.</p><p>You might worry that it’s too much work to begin using the action bar, because you need to support versions of Android older than Honeycomb. However, it’s quite simple for most apps because you can continue to support the Menu button on pre-Honeycomb devices, but also provide the action bar on newer devices with only a few lines of code changes.</p><a href="http://1.bp.blogspot.com/-KIyVJ4DBLdw/TyGbNsLn4hI/AAAAAAAABFs/xgLPIAaEP6I/s1600/image01.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 230px; height: 400px;" src="http://1.bp.blogspot.com/-KIyVJ4DBLdw/TyGbNsLn4hI/AAAAAAAABFs/xgLPIAaEP6I/s400/image01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702009262728274450" /></a><p>If I had to put this whole post into one sentence, it’d be: Set <a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"><code>targetSdkVersion</code></a> to 14 and, if you use the options menu, surface a few actions in the action bar with <code>showAsAction="ifRoom"</code>.</p><h3>Don’t call it a menu</h3><p>Not only should your apps stop relying on the hardware Menu button, but you should stop thinking about your activities using a “menu button” at all. Your activities should provide buttons for important user actions directly in the action bar (or elsewhere on screen). Those that can’t fit in the action bar end up in the <i>action overflow</i>.</p><p>In the screenshot here, you can see an action button for Search and the action overflow on the right side of the action bar.</p><p>Even if your app is built to support versions of Android older than 3.0 (in which apps traditionally use the options menu panel to display user options/actions), when it runs on Android 3.0 and beyond, there’s no Menu button. The button that appears in the system/navigation bar represents the action overflow for legacy apps, which reveals actions and user options that have “overflowed off the screen.” </p><p>This might seem like splitting hairs over terminology, but the name <i>action overflow</i> promotes a different way of thinking. Instead of thinking about a menu that serves as a catch-all for various user options, you should think more about which user options you want to display on the screen as actions. Those that don't need to be on the screen can overflow off the screen. Users can reveal the overflow and other options by touching an overflow button that appears alongside the on-screen action buttons.</p><h3>Action overflow button for legacy apps</h3><p>If you’ve already developed an app to support Android 2.3 and lower, then you might have noticed that when it runs on a device without a hardware Menu button (such as a Honeycomb tablet or Galaxy Nexus), the system adds the action overflow button beside the system navigation. </p><a href="http://1.bp.blogspot.com/-u-3KNfy5n9M/TyG235X2rGI/AAAAAAAABHM/g_qGEXBdJW8/s1600/image00.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 49px;" src="http://1.bp.blogspot.com/-u-3KNfy5n9M/TyG235X2rGI/AAAAAAAABHM/g_qGEXBdJW8/s400/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702039674637692002" /></a><!--<a href="http://3.bp.blogspot.com/-OEFZwRHwsFA/TyGbZ_-MsnI/AAAAAAAABF4/rq9uuGlQm8Q/s1600/image00.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 49px;" src="http://3.bp.blogspot.com/-OEFZwRHwsFA/TyGbZ_-MsnI/AAAAAAAABF4/rq9uuGlQm8Q/s400/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702009474199106162" /></a>--><p>This is a compatibility behavior for legacy apps designed to ensure that apps built to expect a Menu button remain functional. However, this button doesn’t provide an ideal user experience. In fact, in apps that don’t use an options menu anyway, this action overflow button does nothing and creates user confusion. So you should update your legacy apps to remove the action overflow from the navigation bar when running on Android 3.0+ and begin using the action bar if necessary. You can do so all while remaining backward compatible with the devices your apps currently support.</p><p>If your app runs on a device without a dedicated Menu button, the system decides whether to add the action overflow to the navigation bar based on which API levels you declare to support in the <a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk></code></a> manifest element. The logic boils down to:</p><ul><li><p>If you set either <code>minSdkVersion</code> or <code>targetSdkVersion</code> to 11 or higher, the system <em>will not</em> add the legacy overflow button. </p></li><li><p>Otherwise, the system <em>will</em> add the legacy overflow button when running on Android 3.0 or higher.</p></li><li><p>The only exception is that if you set <code>minSdkVersion</code> to 10 or lower, set <code>targetSdkVersion</code> to 11, 12, or 13, and you do not use <a href="http://developer.android.com/reference/android/app/ActionBar.html%20">ActionBar</a>, the system <em>will</em> add the legacy overflow button when running your app <em>on a handset</em> with Android 4.0 or higher. </p></li></ul><p>That exception might be a bit confusing, but it’s based on the belief that if you designed your app to support pre-Honeycomb handsets and Honeycomb tablets, it probably expects handset devices to include a Menu button (but it supports tablets that don’t have one).</p><p>So, to ensure that the overflow action button never appears beside the system navigation, you should set the <code>targetSdkVersion</code> to 14. (You can leave <code>minSdkVersion</code> at something much lower to continue supporting older devices.)</p><h3>Migrating to the action bar</h3><p>If you have activities that use the options menu (they implement <a href="http://developer.android.com/reference/android/app/Activity.html#onCreateOptionsMenu(android.view.Menu)">onCreateOptionsMenu()</a>), then once the legacy overflow button disappears from the system/navigation bar (because you’ve set <code>targetSdkVersion</code> to 14), you need to provide an alternative means for the user to access the activity’s actions and other options. Fortunately, the system provides such a means by default: the action bar.</p><p>Add <code>showAsAction="ifRoom"</code> to the <code>&lt;item></code> elements representing the activity’s most important actions to show them in the action bar when space is available. For help deciding how to prioritize which actions should appear in the action bar, see <cite>Android Design’s</cite> <a href="http://developer.android.com/design/patterns/actionbar.html">Action Bar guide</a>.</p><a href="http://1.bp.blogspot.com/-sUzHJNpXDkw/TyGwS1y-asI/AAAAAAAABGc/5_dEJ8DfhCA/s1600/icon_samples.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 315px; height: 60px;" src="http://1.bp.blogspot.com/-sUzHJNpXDkw/TyGwS1y-asI/AAAAAAAABGc/5_dEJ8DfhCA/s400/icon_samples.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702032440952777410" /></a><p>To further provide a consistent user experience in the action bar, we suggest that you use action icons designed by the Android UX Team where appropriate. The available icons support common user actions such as Refresh, Delete, Attach, Star, Share and more, and are designed for the light and dark Holo themes; they’re available on the <cite>Android Design</cite>   <a href="http://developer.android.com/design/downloads/index.html">downloads page</a>.</p><p>If these icons don’t accommodate your needs and you need to create your own, you should follow the <a href="http://developer.android.com/design/style/iconography.html">Iconography design guide</a>.</p><h3>Removing the action bar</h3><p>If you don’t need the action bar, you can remove it from your entire app or from individual activities. This is appropriate for apps that never used the options menu or for apps in which the action bar doesn’t meet design needs (such as games). You can remove the action bar using a theme such as <code>Theme.Holo.NoActionBar</code> or <code>Theme.DeviceDefault.NoActionBar</code>.</p><p>In order to use such a theme and remain backward compatible, you can use Android’s resource system to define different themes for different platform versions, as described by Adam Powell’s post, <a href="http://android-developers.blogspot.com/2012/01/holo-everywhere.html">Holo Everywhere</a>. All you need is your own theme, which you define to inherit different platform themes depending on the current platform version.</p><p>For example, here’s how you can declare a custom theme for your application:</p><pre><code>&lt;application android:theme="@style/NoActionBar"></code></pre><p>Or you can instead declare the theme for individual <code>&lt;activity></code> elements.</p><p>For pre-Honeycomb devices, include the following theme in <code>res/values/themes.xml</code> that inherits the standard platform theme:</p><pre><code>&lt;resources>
    &lt;style name="NoActionBar" parent="@android:style/Theme">
        &lt;!-- Inherits the default theme for pre-HC (no action bar) -->
    &lt;/style>
&lt;/resources></code></pre><p>For Honeycomb and beyond, include the following theme in <code>res/values-v11/themes.xml</code> that inherits a <code>NoActionBar</code> theme:</p><pre><code>&lt;resources>
    &lt;style name="NoActionBar" parent="@android:style/Theme.Holo.NoActionBar">
        &lt;!-- Inherits the Holo theme with no action bar; no other styles needed. -->
    &lt;/style>
&lt;/resources></code></pre><p>At runtime, the system applies the appropriate version of the <code>NoActionBar</code> theme based on the system’s API version.</p><h3>Summary</h3><ul><li><p>Android no longer requires a dedicated Menu button, some devices don’t have one, and you should migrate away from using it. </p></li><li><p>Set <a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"><code>targetSdkVersion</code></a> to 14, then test your app on Android 4.0. </p></li><li><p>Add <code>showAsAction="ifRoom"</code> to menu items you’d like to surface in the action bar.</p></li><p><li>If the ActionBar doesn’t work for your app, you can remove it with <code>Theme.Holo.NoActionBar</code> or <code>Theme.DeviceDefault.NoActionBar</code>.</li></p></ul><p>For information about how you should design your action bar, see <cite>Android Design’s</cite> <a href="http://developer.android.com/design/patterns/actionbar.html">Action Bar guide</a>. More information about implementing the action bar is also available in the <a href="http://developer.android.com/guide/topics/ui/actionbar.html">Action Bar developer guide</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7750059148144062785?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/say-goodbye-to-the-menu-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Southern-hemisphere Developer Labs</title>
		<link>https://googledata.org/uncategorized/southern-hemisphere-developer-labs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=southern-hemisphere-developer-labs</link>
		<comments>https://googledata.org/uncategorized/southern-hemisphere-developer-labs/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 23:37:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=924ca6a290e8f5af14e2d7b1b45a393e</guid>
		<description><![CDATA[We’ve just scheduled Android Developer Labs for Melbourne (January 31), Sydney (February 3), and Auckland (February 8).  The material is not introductory; it’s aimed at people with existing apps who want to make them better in the era of Ice Cream ...]]></description>
				<content:encoded><![CDATA[<p>We’ve just scheduled Android Developer Labs for Melbourne (January 31), Sydney (February 3), and Auckland (February 8).  The material is not introductory; it’s aimed at people with existing apps who want to make them better in the era of Ice Cream Sandwich and tablets.  You’ll want to show up with the SDK installed, and a couple of devices.</p><p>If this describes you, drop by the <a href="https://sites.google.com/site/androiddeveloperlabs/">ADL page</a> and sign up.  You should hurry, because these are not large-scale events and there are more qualified people than there are seats.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2318375095485779407?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/southern-hemisphere-developer-labs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing the Android Design site</title>
		<link>https://googledata.org/google-android/introducing-the-android-design-site/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducing-the-android-design-site</link>
		<comments>https://googledata.org/google-android/introducing-the-android-design-site/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 21:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=aa64d2d6ae95bfcc31c7f4e98f2d2700</guid>
		<description><![CDATA[[This post is by Christian Robertson,  who  leads the Android visual design group. He is also the designer of the Roboto font family.&#160;—Tim Bray]Ice Cream Sandwich (Android 4.0) is our biggest redesign yet&#160;—&#160;both for users and develop...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-mvxnJ_jo-Do/Tw3RY2z9a5I/AAAAAAAABCU/aOnMTHkF7MI/s1600/sg.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 291px;" src="http://4.bp.blogspot.com/-mvxnJ_jo-Do/Tw3RY2z9a5I/AAAAAAAABCU/aOnMTHkF7MI/s320/sg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5696439328654060434" /></a><p><i>[This post is by <a href="https://plus.google.com/110879635926653430880/posts">Christian Robertson</a>,  who  leads the Android visual design group. He is also the designer of the Roboto font family.&nbsp;—Tim Bray]</i></p><p>Ice Cream Sandwich (Android 4.0) is our biggest redesign yet&nbsp;—&nbsp;both for users and developers. We’ve enhanced the UI framework with new interactions and styles that will let you create Android apps that are simpler and more beautiful than ever before.</p><p>To help you in that mission, we’re introducing <a href="http://developer.android.com/design/"><cite>Android Design</cite></a>: the place to learn about principles, building blocks, and patterns for creating world-class Android user interfaces. Whether you’re a UI professional or a developer playing that role, these docs show you how to make good design decisions, big and small.</p><p>The Android User Experience Team is committed to helping you design amazing apps that people love, and this is just the beginning. In the coming months, we’ll expand <cite>Android Design</cite> with more in-depth content. And watch this blog for a series of posts about design, and invitations to Google+ hangouts on the topics you care about most.</p><p>So head on over to <a href="http://developer.android.com/design/"><cite>Android Design</cite></a>, and make something amazing!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5428686436183648102?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/introducing-the-android-design-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Levels in Renderscript</title>
		<link>https://googledata.org/uncategorized/levels-in-renderscript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=levels-in-renderscript</link>
		<comments>https://googledata.org/uncategorized/levels-in-renderscript/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 21:43:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=0b15215c6f704eb1f0c9b2998a1a4bfb</guid>
		<description><![CDATA[[This post is by R. Jason Sams, an Android Framework engineer who specializes in graphics, performance tuning, and software architecture.&#160;—Tim Bray]For ICS, Renderscript (RS) has been updated with several new features to simplify adding compute ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://plus.google.com/113680924389579925739/posts">R. Jason Sams</a>, an Android Framework engineer who specializes in graphics, performance tuning, and software architecture.&nbsp;—Tim Bray]</i></p><a href="http://1.bp.blogspot.com/-1AN0Pp29JF8/Twy_hmUcPhI/AAAAAAAABBk/e9VKCVmrytY/s1600/jsams.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 201px;" src="http://1.bp.blogspot.com/-1AN0Pp29JF8/Twy_hmUcPhI/AAAAAAAABBk/e9VKCVmrytY/s320/jsams.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5696138212659707410" /></a><p>For ICS, Renderscript (RS) has been updated with several new features to simplify adding compute acceleration to your application.  RS is interesting for compute acceleration when you have large buffers of data on which you need to do significant processing.  In this example we will look at applying a levels/saturation operation on a bitmap.</p><p>In this case, saturation is implemented by multiplying every pixel by a color matrix Levels are typically implemented with several operations.  </p><ol><li><p>Input levels are adjusted.</p></li><li><p>Gamma correction.</p></li><li><p>Output levels are adjusted.</p></li><li><p>Clamp to the valid range.</p></li></ol><p>A simple implementation of this might look like:</p><pre><code>for (int i=0; i &lt; mInPixels.length; i++) {
    float r = (float)(mInPixels[i] &amp; 0xff);
    float g = (float)((mInPixels[i] >> 8) &amp; 0xff);
    float b = (float)((mInPixels[i] >> 16) &amp; 0xff);

    float tr = r * m[0] + g * m[3] + b * m[6];
    float tg = r * m[1] + g * m[4] + b * m[7];
    float tb = r * m[2] + g * m[5] + b * m[8];
    r = tr;
    g = tg;
    b = tb;

    if (r &lt; 0.f) r = 0.f;
    if (r > 255.f) r = 255.f;
    if (g &lt; 0.f) g = 0.f;
    if (g > 255.f) g = 255.f;
    if (b &lt; 0.f) b = 0.f;
    if (b > 255.f) b = 255.f;

    r = (r - mInBlack) * mOverInWMinInB;
    g = (g - mInBlack) * mOverInWMinInB;
    b = (b - mInBlack) * mOverInWMinInB;

    if (mGamma != 1.0f) {
        r = (float)java.lang.Math.pow(r, mGamma);
        g = (float)java.lang.Math.pow(g, mGamma);
        b = (float)java.lang.Math.pow(b, mGamma);
    }

    r = (r * mOutWMinOutB) + mOutBlack;
    g = (g * mOutWMinOutB) + mOutBlack;
    b = (b * mOutWMinOutB) + mOutBlack;

    if (r &lt; 0.f) r = 0.f;
    if (r > 255.f) r = 255.f;
    if (g &lt; 0.f) g = 0.f;
    if (g > 255.f) g = 255.f;
    if (b &lt; 0.f) b = 0.f;
    if (b > 255.f) b = 255.f;

    mOutPixels[i] = ((int)r) + (((int)g) &lt;&lt; 8) + (((int)b) &lt;&lt; 16)
                    + (mInPixels[i] &amp; 0xff000000);
}</code></pre><p>This code assumes a bitmap has been loaded and transferred to an integer array for processing.  Assuming the bitmaps are already loaded, this is simple.</p><pre><code>        mInPixels = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
        mOutPixels = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
        mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
                            mBitmapIn.getWidth(), mBitmapIn.getHeight());</code></pre><p>Once the data is processed with the loop, putting it back into the bitmap to draw is simple.</p><pre><code>        mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
                             mBitmapOut.getWidth(), mBitmapOut.getHeight());</code></pre><p>The full code of the application is around 232 lines when you include code to compute the constants for the filter kernel, manage the controls, and display the image.  On the devices I have laying around this takes about 140-180ms to process an 800x423 image.</p><a href="http://2.bp.blogspot.com/-6jVhUd2Tyk4/TwzHq8NEgtI/AAAAAAAABBw/1kLwL4oY2Xw/s1600/city2.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; " src="http://2.bp.blogspot.com/-6jVhUd2Tyk4/TwzHq8NEgtI/AAAAAAAABBw/1kLwL4oY2Xw/s400/city2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5696147169246216914" /></a><p>What if that is not fast enough?  </p><p>Porting the kernel of this image processing to RS (available at <a href="http://code.google.com/p/android-renderscript-samples/source/browse/Levels">android-renderscript-samples</a>) is quite simple.  The pixel processing kernel above, reimplemented for RS looks like:</p><pre><code>void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
    float3 pixel = convert_float4(in[0]).rgb;
    pixel = rsMatrixMultiply(&amp;colorMat, pixel);
    pixel = clamp(pixel, 0.f, 255.f);
    pixel = (pixel - inBlack) * overInWMinInB;
    if (gamma != 1.0f)
        pixel = pow(pixel, (float3)gamma);
    pixel = pixel * outWMinOutB + outBlack;
    pixel = clamp(pixel, 0.f, 255.f);
    out->xyz = convert_uchar3(pixel);
}</code></pre><p>It takes far fewer lines of code because of the built-in support for vectors of floats, matrix operations, and format conversions.  Also note that there is no loop present.</p><p>The setup code is slightly more complex because you also need to load the script.</p><pre><code>        mRS = RenderScript.create(this);
        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
                                                          Allocation.MipmapControl.MIPMAP_NONE,
                                                          Allocation.USAGE_SCRIPT);
        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
                                                           Allocation.MipmapControl.MIPMAP_NONE,
                                                           Allocation.USAGE_SCRIPT);
        mScript = new ScriptC_levels(mRS, getResources(), R.raw.levels);</code></pre><p>This code creates the RS context.  It then uses this context to create two memory allocations to hold the RS copy of the bitmap data.  Last, it loads the script to process the data.</p><p>Also in the source there are a few small blocks of code to copy the computed constants to the script when they change.  Because we reflect the globals from the script this is easy.</p><pre><code>        mScript.set_inBlack(mInBlack);
        mScript.set_outBlack(mOutBlack);
        mScript.set_inWMinInB(mInWMinInB);
        mScript.set_outWMinOutB(mOutWMinOutB);
        mScript.set_overInWMinInB(mOverInWMinInB);</code></pre><p>Earlier we noted that there was no loop to process all the pixels.  The RS code that processes the bitmap data and copies the result back looks like this:</p><pre><code>        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
        mOutPixelsAllocation.copyTo(mBitmapOut);</code></pre><p>The first line takes the script and processes the input allocation and places the result in the output allocation.  It does this by calling the natively compiled version of the script above once for each pixel in the allocation.  However, unlike the dalvik implementation, the primitives will automatically launch extra threads to do the work.  This, combined with the performance of native code can produce large performance gains.  I’ll show the results with and without the gamma function working because it adds a lot of cost.</p><h4>800x423 image</h4><table><tr><th>Device</th><th>Dalvik</th><th>RS</th><th>Gain</th></tr><tr><th>Xoom</th><td>174ms</td><td>39ms</td><td>4.5x</td></tr><tr><th>Galaxy Nexus</th><td>139ms</td><td>30ms</td><td>4.6x</td></tr><tr><th>Tegra 30 device</th><td>136ms</td><td>19ms</td><td>7.2x</td></tr></table><h4>800x423 image with gamma correction</h4><table><tr><th>Device</th><th>Dalvik</th><th>RS</th><th>Gain</th></tr><tr><th>Xoom</th><td>994ms</td><td>259ms</td><td>3.8x</td></tr><tr><th>Galaxy Nexus</th><td>787ms</td><td>213ms</td><td>3.7x</td></tr><tr><th>Tegra 30 device</th><td>783ms</td><td>104ms</td><td>7.5x</td></tr></table><p>These large gains represent a large return on the simple coding investment shown above.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5058038089639562398?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/levels-in-renderscript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Holo Everywhere</title>
		<link>https://googledata.org/uncategorized/holo-everywhere/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=holo-everywhere</link>
		<comments>https://googledata.org/uncategorized/holo-everywhere/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 21:35:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=2ca25e29edd2716ae7f3c73c6f705786</guid>
		<description><![CDATA[[This post is by Adam Powell, an Android Framework engineer who cares about style. —Tim Bray]Android 4.0 showcases the Holo theme family, further refined since its debut in Android 3.0. But as most developers know, a new system theme for some Android...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://plus.google.com/107708120842840792570/posts">Adam Powell</a>, an Android Framework engineer who cares about style. —Tim Bray]</i></p><p>Android 4.0 showcases the Holo theme family, further refined since its debut in Android 3.0. But as most developers know, a new system theme for some Android devices isn’t a new or uncommon event. For developers new system themes mean more design targets for their apps. Using system themes means developers can take advantage of a user’s existing expectations and it can save a lot of production time, but only if an app designer can reliably predict the results. Before Android 4.0 the variance in system themes from device to device could make it difficult to design an app with a single predictable look and feel. We set out to improve this situation for the developer community in Ice Cream Sandwich and beyond.</p><div style="float:left; margin: 5px 20px 10px 0;"><img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://3.bp.blogspot.com/-Ih4mfw7ugas/TwNnpaoc79I/AAAAAAAABAE/BmBauVfE7OA/s400/Screenshot_2011-11-17-22-19-53.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693508315147726802" /><p style="text-align: center;">Theme.Holo</p></div><p>If you’re not already familiar with Android’s style and theme system, you should read <a href="http://developer.android.com/guide/topics/ui/themes.html">Styles and Themes</a> before continuing.</p><h3>Compatibility Standard</h3><p>In Android 4.0, Holo is different. We’ve made the inclusion of the unmodified Holo theme family a compatibility requirement for devices running Android 4.0 and forward. If the device has Android Market it will have the Holo themes as they were originally designed.</p><p>This standardization goes for all of the public Holo widget styles as well. The Widget.Holo styles will be stable from device to device, safe for use as parent styles for incremental customizations within your app.</p><p>The Holo theme family in Android 4.0 consists of the themes Theme.Holo, Theme.Holo.Light, and Theme.Holo.Light.DarkActionBar. Examples of these themes in action are shown in the screenshots lining this post.</p><p>To use a Holo theme, explicitly request one from your manifest on your activity or application element, e.g. <code>android:theme="@android:style/Theme.Holo"</code>. Your app will be displayed using the unmodified theme on all compatible Android 4.0 devices. The Holo themes may also be used as stable parent themes for app-level theme customizations.</p><h3>What about device themes?</h3><p>We have no desire to restrict manufacturers from building their own themed experience across their devices. In fact we’ve gone further to make this even easier. In Android 4.0’s API (level 14) we’ve added a new public theme family to complement the Holo family introduced in Android 3.0: DeviceDefault. DeviceDefault themes are aliases for the device’s native look and feel. The DeviceDefault theme family and widget style family offer ways for developers to target the device’s native theme with all customizations intact.</p><div style="float:right;margin: 5px 0 10px 20px;"><img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://1.bp.blogspot.com/-Mi2BW-8T8eY/TwNpdVemR_I/AAAAAAAABAc/-oOTaZ5M4_A/s400/Screenshot_2011-11-17-22-23-18.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693510306629044210" /><p style="text-align: center;">Theme.Holo.Light</p></div><p> Formally separating these theme families will also make future merges easier for manufacturers updating to a new platform version, helping more devices update more quickly. Google’s Nexus devices alias DeviceDefault to the unmodified Holo themes.</p><h3>Making use of your chosen theme</h3><p>We’ve added a number of theme attributes to report common metrics and color palette info to apps that want to fit in with a theme. These include highlight colors, default padding and margins for common UI elements such as list items, and more. Apps that wish to integrate with their chosen theme (both Holo and DeviceDefault included) can refer to these theme attributes as in the examples below:</p><p>Sample button with system-supplied touch highlight:</p><pre><code>&lt;ImageButton android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/button_icon"
    android:background="?android:attr/selectableItemBackground" /></code></pre><p>Sample widget with a custom pressedHighlightColor attribute, value retrieved from the system theme:</p><pre><code>&lt;MyWidget android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    myapp:pressedHighlightColor="?android:attr/colorPressedHighlight" /></code></pre><p>Sample list item layout using system-supplied metrics and text appearance:</p><pre><code>&lt;LinearLayout android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
    android:paddingRight="?android:attr/listPreferredItemPaddingRight">
    &lt;TextView android:id="@+id/text"
        android:textAppearance="?android:attr/textAppearanceListItem" />
    &lt;!-- Other views here -->
&lt;/LinearLayout></code></pre><div style="float:left; margin: 5px 20px 10px 0;"><img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://1.bp.blogspot.com/-99NqKnTQ2Ew/TwNp6O1LBVI/AAAAAAAABAo/TIQZ27oOhd4/s400/Screenshot_2011-11-17-22-24-28.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693510803060884818"  /><p style="text-align: center;">Theme.Holo.Light.DarkActionBar<br/>(Available in API level 14 and above)</p></div><h3>Defaults for Older Apps</h3><p>If an app does not explicitly request a theme in its manifest, Android 4.0 will determine the default theme based on the app’s targetSdkVersion to maintain the app’s original expectations: For values less than 11, <code>@android:style/Theme</code>; between 11 and 13 <code>@android:style/Theme.Holo</code>; and for 14 and higher <code>@android:style/Theme.DeviceDefault</code>.</p><h3>Using Holo while supporting Android 2.x</h3><p>Most Android developers will still want to support 2.x devices for a while as updates and new devices continue to roll out. This doesn’t stop you from taking advantage of newer themes on devices that support them though. Using Android’s resource system you can define themes for your app that are selected automatically based on the platform version of the device it’s running on.</p><p><em>Theme.Holo and Theme.Holo.Light have been available since API level 11, but Theme.Holo.Light.DarkActionBar is new in API level 14.</em></p><p>res/values/themes.xml:</p><pre><code>&lt;resources>
    &lt;style name="MyTheme" parent="<b>@android:style/Theme</b>">
        &lt;!-- Any customizations for your app running on pre-3.0 devices here -->
    &lt;/style>
&lt;/resources></code></pre><p>res/values-v11/themes.xml:</p><pre><code>&lt;resources>
    &lt;style name="MyTheme" parent="<b>@android:style/Theme.Holo</b>">
        &lt;!-- Any customizations for your app running on devices with Theme.Holo here -->
    &lt;/style>
&lt;/resources></code></pre><p>Finally, in AndroidManifest.xml:</p><pre><code>&lt;!-- [...] -->
    &lt;application android:name="MyApplication"
            android:label="@string/application_label"
            android:icon="@drawable/app_icon"
            android:hardwareAccelerated="true"
            android:theme="@style/MyTheme">
&lt;!-- [...] --></code></pre><p>You can go as far with this idea as you like, up to and including defining your own theme attributes with different values across configurations for use in your other resources. To learn more about Android’s resource system, see <a href="http://developer.android.com/guide/topics/resources/index.html">Application Resources</a>.</p><h3>Final Thoughts</h3><p>Android apps running on 4.0 and forward can use the Holo themes and be assured that their look and feel will not change when running on a device with a custom skin. Apps that wish to use the device’s default styling can do so using the DeviceDefault themes that are now in the public API. These changes let you spend more time on your design and less time worrying about what will be different from one device to another. Finally, Android’s resource system allows you to support features from the latest platform version while offering graceful fallback on older devices.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8646760043976821672?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/holo-everywhere/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Watch out for XmlPullParser.nextText()</title>
		<link>https://googledata.org/uncategorized/watch-out-for-xmlpullparser-nexttext/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=watch-out-for-xmlpullparser-nexttext</link>
		<comments>https://googledata.org/uncategorized/watch-out-for-xmlpullparser-nexttext/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 18:55:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=4101548d3416ff67745f14620f3d0fc8</guid>
		<description><![CDATA[[This post is by Jesse Wilson from the Dalvik team. —Tim Bray]Using XmlPullParser is an efficient and maintainable way to parse XML on Android. Historically Android has had two implementations of this interface:KXmlParser, via XmlPullParserFactory.ne...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s1600/jessehawaii.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px; height: 149px;" src="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s200/jessehawaii.jpg" border="0" alt="Jesse Wilson" id="BLOGGER_PHOTO_ID_5657543353414584562" /></a><p><i>[This post is by <a href="http://www.publicobject.com/">Jesse Wilson</a> from the Dalvik team. —Tim Bray]</i></p><p>Using <a href="http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html">XmlPullParser</a> is an efficient and maintainable way to parse XML on Android. Historically Android has had two implementations of this interface:</p><ul><li><p>KXmlParser, via <a href="http://developer.android.com/reference/org/xmlpull/v1/XmlPullParserFactory.html#newPullParser()">XmlPullParserFactory.newPullParser()</a>.</p></li><li><p>ExpatPullParser, via <a href="http://developer.android.com/reference/android/util/Xml.html#newPullParser()">Xml.newPullParser()</a>.</p></li></ul><p>The implementation from <code>Xml.newPullParser()</code> had a bug where calls to <code>nextText()</code> didn’t always advance to the <code>END_TAG</code> as the documentation promised it would. As a consequence, some apps may be working around the bug with extra calls to <code>next()</code> or <code>nextTag()</code>:</p><pre><code>    public void parseXml(Reader reader)
            throws XmlPullParserException, IOException {
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(reader);

        parser.nextTag();
        parser.require(XmlPullParser.START_TAG, null, "menu");
        while (parser.nextTag() == XmlPullParser.START_TAG) {
            parser.require(XmlPullParser.START_TAG, null, "item");
            String itemText = parser.nextText();
            <b>parser.nextTag(); // this call shouldn’t be necessary!</b>
            parser.require(XmlPullParser.END_TAG, null, "item");
            System.out.println("menu option: " + itemText);
        }
        parser.require(XmlPullParser.END_TAG, null, "menu");
    }

    public static void main(String[] args) throws Exception {
        new Menu().parseXml(new StringReader("&lt;?xml version='1.0'?>"
                + "&lt;menu>"
                + "  &lt;item>Waffles&lt;/item>"
                + "  &lt;item>Coffee&lt;/item>"
                + "&lt;/menu>"));
    }</code></pre><p>In Ice Cream Sandwich we changed <code>Xml.newPullParser()</code> to return a KxmlParser and deleted our ExpatPullParser class. This fixes the <code>nextTag()</code> bug. Unfortunately, apps that currently work around the bug may crash under Ice Cream Sandwich:</p><pre><code>org.xmlpull.v1.XmlPullParserException: expected: END_TAG {null}item (position:START_TAG &lt;item>@1:37 in java.io.StringReader@40442fa8) 
     at org.kxml2.io.KXmlParser.require(KXmlParser.java:2046)
     at com.publicobject.waffles.Menu.parseXml(Menu.java:25)
 at com.publicobject.waffles.Menu.main(Menu.java:32)</code></pre><p>The fix is to call <code>nextTag()</code> after a call to <code>nextText()</code> only if the current position is not an <code>END_TAG</code>:</p><pre><code>  while (parser.nextTag() == XmlPullParser.START_TAG) {
      parser.require(XmlPullParser.START_TAG, null, "item");
      String itemText = parser.nextText();
      if (parser.getEventType() != XmlPullParser.END_TAG) {
          parser.nextTag();
      }
      parser.require(XmlPullParser.END_TAG, null, "item");
      System.out.println("menu option: " + itemText);
  }</code></pre><p>The code above will parse XML correctly on all releases. If your application uses <code>nextText()</code> extensively, use this helper method in place of calls to <code>nextText()</code>:</p><pre><code>  private String safeNextText(XmlPullParser parser)
          throws XmlPullParserException, IOException {
      String result = parser.nextText();
      if (parser.getEventType() != XmlPullParser.END_TAG) {
          parser.nextTag();
      }
      return result;
  }</code></pre><p>Moving to a single XmlPullParser simplifies maintenance and allows us to spend more energy on improving system performance.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7567337483684147968?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/watch-out-for-xmlpullparser-nexttext/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Introducing Android Training</title>
		<link>https://googledata.org/uncategorized/introducing-android-training/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducing-android-training</link>
		<comments>https://googledata.org/uncategorized/introducing-android-training/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 04:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=dd2b101971b41bb1ea82c3b138606c17</guid>
		<description><![CDATA[[This post is by Reto Meier, Android Developer Relations Tech Lead.&#160;&#8212;&#160;Tim&#160;Bray]Today I’m thrilled to announce the beta launch of Android Training — a collection of classes that we hope will help you to build better Android ap...]]></description>
				<content:encoded><![CDATA[<a href="http://2.bp.blogspot.com/-65ZTcnMYW9c/TurVOon7PrI/AAAAAAAAA_s/07tBb3zCktI/s1600/new+prof.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://2.bp.blogspot.com/-65ZTcnMYW9c/TurVOon7PrI/AAAAAAAAA_s/07tBb3zCktI/s400/new+prof.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686591926908436146" /></a><p><i>[This post is by <a href="https://plus.google.com/111169963967137030210/posts">Reto Meier</a>, Android Developer Relations Tech Lead.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Today I’m thrilled to announce the beta launch of <a href="https://developer.android.com/training/">Android Training</a> — a collection of classes that we hope will help you to build better Android apps. </p><p>From <a href="https://developer.android.com/training/design-navigation/">designing effective navigation</a>, to <a href="https://developer.android.com/training/managing-audio/">managing audio playback</a>, to <a href="https://developer.android.com/training/monitoring-device-state/">optimizing battery life</a>, these classes are designed to demonstrate best practices for solving common Android development problems.</p><p>Each class explains the steps required to solve a problem, or implement a feature, with plenty of code snippets and sample code for you to use within your own apps. </p><p>We’re starting small and this is just the beginning for Android Training. Over the coming months we will be increasing the number of classes available, as well as introducing over-arching courses and sample apps to further help your development experience.</p><p>Helping developers build great apps is what the Android Developer Relations team is all about, so we’re excited to see how you use these classes to make your apps even better.</p><p>We’d love to know what you think of these classes, and what classes you’d like to see next.<!-- Let us know over at Google+ [Link to Android Google+ page].--></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3511095358900350369?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/introducing-android-training/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>More Android Games that Play Nice</title>
		<link>https://googledata.org/google-android/more-android-games-that-play-nice/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=more-android-games-that-play-nice</link>
		<comments>https://googledata.org/google-android/more-android-games-that-play-nice/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 22:36:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=274ec46d505ca2266160a7bf35bd4cd2</guid>
		<description><![CDATA[[This post is by Dan Galpin, who lives the Android Games lifestyle every day.&#160;&#8212;&#160;Tim&#160;Bray]Making a game on Android is easy. Making a great game for a mobile, multitasking, often multi-core, multi-purpose system like Android is trick...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-fixaHjPgkZo/Tukog-1pbjI/AAAAAAAAA_Q/iqVq-CVMxac/s1600/dan.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 185px; height: 228px;" src="http://4.bp.blogspot.com/-fixaHjPgkZo/Tukog-1pbjI/AAAAAAAAA_Q/iqVq-CVMxac/s400/dan.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686120551620898354" /></a><p><i>[This post is by <a href="https://plus.google.com/105593270217665985575/posts">Dan Galpin</a>, who lives the Android Games lifestyle every day.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Making a game on Android is easy. Making a great game for a mobile, multitasking, often multi-core, multi-purpose system like Android is trickier. Even the best developers frequently make mistakes in the way they interact with the Android system and with other applications — mistakes that don’t affect the quality of gameplay, but which affect the quality of the user’s experience in other ways.</p><p>A truly great Android game knows how to play nice: how to fit seamlessly into the system of apps, services, and UI features that run on Android devices. In this multi-part series of posts, Android Developer Relations engineers who specialize in games explain what it takes to make your game play nice.</p><h3>II: Navigation and Lifecycle</h3><p>Android users get used to using the back key.  We expect the volume keys to work in some intuitive fashion.  We expect that the home key behaves in a manner consistent with the <a href="http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html">Android navigation paradigm</a>.  Sometimes we even expect the menu key to do something.</p><h3>1. Problem: There’s no place like [Home]</h3><p>I’m playing [insert favorite game here] and I accidentally hit the [Home] key or the [Back] key. This is probably happening because I’m furiously using the touchscreen to actually play the game.  Whether I’ve been cutting ropes, controlling aircraft, cleaving fruit, or flinging birds, I’m almost certainly angry if I’ve suddenly lost all of my game progress.</p><h4>What went wrong?</h4><p>Lots of developers assume that pressing the Home key exits a game.  Perhaps this is because on some mobile devices the Home key is a somewhat-difficult-to-press physical button. Depending on the device and Android release, it might be a physical, capacitive, or soft button. This means that it is relatively easy to hit accidentally.  Having progress lost by such an event as an incoming call is even worse.</p><h4>How to avoid Angry Users</h4><ol><li><p>Save as much about the status of the game into the Bundle in <a href="http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">onSaveInstanceState()</a> as you can. This helper function will get called whenever your application receives an <a href="http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)">onPause()</a> callback.  Note that you can save byte arrays into that bundle, so it can easily be used for raw data.</p></li><li><p>If your game takes lots of native system resources, consider dumping large textures (or all textures and geometry) during onPause() or onStop().  (<a href="http://android-developers.blogspot.com/2011/12/a">GLSurfaceView</a> will do this automatically unless you <a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.html#setPreserveEGLContextOnPause(boolean)">tell it not to</a> — at least you can tell it not to do so starting in API level 11).  This will help your title continue to reside in memory, which will typically speed task-switching back to your game for very large titles that might otherwise be swapped out of memory, but may slow things down for smaller titles that can more efficiently multitask if they don’t bother to do this.</p></li><li><p>When your game resumes, restore the state from the bundle in <a href="http://developer.android.com/reference/android/app/Activity.html#onRestoreInstanceState(android.os.Bundle)">onRestoreInstanceState()</a>. If there is any sort of time-consuming loading that has to be done, make sure that you notify the user of what is happening to give them the best possible experience.</p></li><p><li>Test thoroughly!</li></p></ol><h4>2. Problem: [Back] I say!</h4><p>I’m in the middle of playing a game and I hit the back key.  One of several bad things can happen here:</p><ol><li><p>The game exits immediately, losing all state and leading to Angry User Syndrome.  (see Problem 1).</p></li><li><p>The game does nothing.</p></li></ol><h4>What went wrong?</h4><p>We already know what is wrong with scenario 1.  It’s essentially a data loss scenario, and it’s worse than <a href="http://www.youtube.com/watch?v=Tjl9tg9smgc">pigs stealing your eggs</a>.  What is wrong with scenario 2?</p><p>The [Back] key is an essential part of the Android navigation paradigm.  If the back key doesn’t return to the previous screen in the activity stack (or in the game hierarchy) there better be a very good reason, such as an active document with no capability to save a draft.</p><h4>What to do about it</h4><p>If the user is in the middle of gameplay It is customary to display some sort of dialog asking the user if they intended the action:</p><p>“Are you sure you wish to exit now?  <a href="http://www.youtube.com/watch?v=1JpdW-D6c14">That monster looks hungry</a>.”</p><p>In an extreme action game, you might also wish to do something similar to what <a href="http://code.google.com/p/replicaisland/">Replica Island</a> (RI) did.  RI assumed that any [Back] keypress that happened within 200ms of another touch event was invalid in order to make it a bit more challenging to accidentally press the key.</p><p>At the Main Menu of the game, you can decide whether it makes sense to prompt the user or not.  If your game has very long load times, you might want to prompt the user.</p><h3>3.  Problem: Quiet [Down]!</h3><p>There’s nothing worse than wanting to settle down for a good session of [insert favorite game here] in some sort of public place with your volume turned up.  Suddenly everyone has learned that you <a href="http://youtu.be/8XJUYmwBlZA">prefer pummelling produce</a> to predicting present progressions and that’s practically profane in your profession.</p><h4>What went wrong?</h4><p>By default, volume keys in most Android devices will control the ringer volume, and your application must pass the volume keys through to the super class so this continues to work.</p><h4>What to do about it</h4><p>In order to make these keys control the music volume (which is the channel that your game will be using), you need to call <a href="http://developer.android.com/reference/android/app/Activity.html#setVolumeControlStream(int)">setVolumeControlStream(AudioManager.STREAM_MUSIC)</a>.  As stated previously, all you need to do is pass these keys through to the framework and you’ll get control of the audio in the standard and proper way.  Do it as early as possible so a user can start changing the volume far before you begin playing anything.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2298285560651431866?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/more-android-games-that-play-nice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Add Voice Typing To Your IME</title>
		<link>https://googledata.org/uncategorized/add-voice-typing-to-your-ime/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=add-voice-typing-to-your-ime</link>
		<comments>https://googledata.org/uncategorized/add-voice-typing-to-your-ime/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 21:40:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=bad839302c87700e4c8abca258fba9a1</guid>
		<description><![CDATA[[This post is by Luca Zanolin, an Android engineer who works on voice typing.&#160;&#8212;&#160;Tim&#160;Bray]A new feature available in Android 4.0 is voice typing: the difference for users is that the recognition results appear in the text box while ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Luca Zanolin, an Android engineer who works on voice typing.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>A new feature available in Android 4.0 is voice typing: the difference for users is that the recognition results appear in the text box while they are still speaking. If you are an IME developer, you can easily integrate with voice typing. </p><p>To simplify the integration, if you download <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/voiceimeutils.jar">this</a> library and modify your IME as described below, everything will work smoothly on any device with Android 2.2 or later. On 4.0+, users will get voice typing, and earlier versions will use standard voice recognition; the difference is illustrated below.</p><a href="http://4.bp.blogspot.com/-HXI0a-ADssM/TuZvhNAPSsI/AAAAAAAAA-c/bh9t_h2L_x0/s1600/voice-modes.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 333px;" src="http://4.bp.blogspot.com/-HXI0a-ADssM/TuZvhNAPSsI/AAAAAAAAA-c/bh9t_h2L_x0/s400/voice-modes.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5685354195818859202" /></a><p>To see how to integrate voice typing you can take a look at this <a href="https://code.google.com/p/google-voice-typing-integration/source/browse/#git/VoiceImeDemo">sample IME</a>. The IME is really simple and contains only one button: a microphone. By pressing the microphone, the user triggers voice recognition.</p><p>Here are the steps that you need to follow to integrate voice recognition into your IME.</p><h3>Download the library</h3><p>Download <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/voiceimeutils.jar">this library</a> and add it to your IME APK.</p><h3>Create the voice recognition trigger</h3><p>The library contains the <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html">VoiceRecognitionTrigger</a> helper class. Create an instance of it inside the <a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onCreate()">InputMethodService#onCreate</a> method in your IME.</p><pre><code>public void onCreate() {
    super.onCreate();
    ...
    mVoiceRecognitionTrigger = new VoiceRecognitionTrigger(this);
}</code></pre><h3>Add the microphone icon to your IME</h3><p>You need to modify the UI of your IME, add a microphone icon, and register an OnClickListener to trigger voice recognition. You can find the assets inside the sample IME. The microphone icon should be displayed only if voice recognition is installed; use <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html">VoiceRecognitionTrigger#isInstalled()</a>.</p><pre><code>public View onCreateInputView() {
  LayoutInflater inflater = (LayoutInflater) getSystemService(
      Service.LAYOUT_INFLATER_SERVICE);
  mView = inflater.inflate(R.layout.ime, null);
  ...
  mButton = (ImageButton) mView.findViewById(R.id.mic_button);
  if (mVoiceRecognitionTrigger.isInstalled()) {
    mButton.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        mVoiceRecognitionTrigger.startVoiceRecognition();
      }
    });
    mButton.setVisibility(View.VISIBLE);
  } else {
    mButton.setVisibility(View.GONE);
  }
  return mView;
}</code></pre><p>If your IME supports multiple languages, you can specify in which language recognition should be done as a parameter of <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/com/google/android/voiceime/VoiceRecognitionTrigger.html#startVoiceRecognition(java.lang.String)">startVoiceRecognition()</a>.</p><h3>Notify the trigger when your IME starts</h3><p>When your IME starts, you need to notify the trigger, so it can insert into the text view any pending recognition results.</p><pre><code>@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
  super.onStartInputView(info, restarting);
  if (mVoiceRecognitionTrigger != null) {
    mVoiceRecognitionTrigger.onStartInputView();
  }
}</code></pre><h3>Modify your AndroidManifest</h3><p>In order to start a voice recognition through the Intent API, the library uses a service and an activity, and you need to add them into your manifest.</p><pre><code>&lt;manifest ... >
  &lt;application ...>
    ...
    &lt;service android:name="com.google.android.voiceime.ServiceHelper" />
    &lt;activity
        android:name="com.google.android.voiceime.ActivityHelper"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:excludeFromRecents="true"
        android:windowSoftInputMode="stateAlwaysHidden"
        android:finishOnTaskLaunch="true"
        android:configChanges="keyboard|keyboardHidden|navigation
                               |orientation"/>
  &lt;/application>
&lt;/manifest></code></pre><h3>Update the microphone icon dynamically (optional)</h3><p>This step is optional, but you should implement it if possible as it will improve the user experience. Voice recognition requires network access, and if there is no network, your IME should notify the user that voice recognition is currently disabled. To achieve this, you need to register the <a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html">VoiceRecognitionTrigger.Listener</a> and enable/disable the microphone accordingly. </p><p>The listener is registered in <a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onCreate()">InputMethodService#onCreate</a>, and you have to unregister it in <a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onDestroy()">InputMethodService#onDestroy</a>, otherwise you will leak the listener.</p><pre><code>@Override
public void onCreate() {
  super.onCreate();
  ... 
  mVoiceRecognitionTrigger = new VoiceRecognitionTrigger(this);
  mVoiceRecognitionTrigger.register(new VoiceRecognitionTrigger.Listener() {
    @Override
    public void onVoiceImeEnabledStatusChange() {
      updateVoiceImeStatus();
    }
  });
}

...
@Override
public void onDestroy() {
  ...
  if (mVoiceRecognitionTrigger != null) {
    mVoiceRecognitionTrigger.unregister(this);
  }
  super.onDestroy();
}

private void updateVoiceImeStatus() {
  if (mVoiceRecognitionTrigger.isInstalled()) {
    mButton.setVisibility(View.VISIBLE);
    if (mVoiceRecognitionTrigger.isEnabled()) {
      mButton.setEnabled(true);
    } else {
      mButton.setEnabled(false);
    }
  } else {
    mButton.setVisibility(View.GONE);
  }
  mView.invalidate();
}</code></pre><p>And add this permission into your manifest:</p><pre><code>&lt;manifest ... >
  ...
  &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  ...
&lt;/manifest></code></pre><h3>That&rsquo;s all there is to it</h3><p>Voice recognition makes it easy for users to do more with their Android devices, so we appreciate your support in adding it to your IMEs.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1436820868716344333?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/add-voice-typing-to-your-ime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Making Android Games that Play Nice</title>
		<link>https://googledata.org/google-android/making-android-games-that-play-nice/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=making-android-games-that-play-nice</link>
		<comments>https://googledata.org/google-android/making-android-games-that-play-nice/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 14:45:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=4079a7ae399e38879d1235fc310eae9e</guid>
		<description><![CDATA[[This post is by Ian Ni-Lewis,  a Developer Advocate who devotes most of his time to making Android games more awesome.&#160;&#8212;&#160;Tim&#160;Bray]Making a game on Android is easy. Making a great game for a mobile, multitasking, often multi-core, ...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-WZ2VRtoH_lA/TsryB8owaYI/AAAAAAAAA-E/OLtnJm8dE2w/s1600/ian2.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 198px; height: 241px;" src="http://4.bp.blogspot.com/-WZ2VRtoH_lA/TsryB8owaYI/AAAAAAAAA-E/OLtnJm8dE2w/s400/ian2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5677616395524794754" /></a><p><i>[This post is by <a href="https://plus.google.com/109486821799932251955/posts">Ian Ni-Lewis</a>,  a Developer Advocate who devotes most of his time to making Android games more awesome.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Making a game on Android is easy. Making a <em>great</em> game for a mobile, multitasking, often multi-core, multi-purpose system like Android is trickier. Even the best developers frequently make mistakes in the way they interact with the Android system and with other applications — mistakes that don’t affect the quality of gameplay, but which affect the quality of the user’s experience in other ways. </p><p>A truly great Android game knows how to play nice: how to fit seamlessly into the system of apps, services, and UI features that run on Android devices. In this multi-part series of posts, Android Developer Relations engineers who specialize in games explain what it takes to make your game play nice.</p><h3>I: The Audio Lifecycle (or, why is there music coming from my pants?)</h3><p>One of the most awesome things about Android is that it can do so much stuff in the background. But when apps aren’t careful about their background behaviors, it can get annoying. Take my own personal pet peeve: game audio that doesn’t know when to quit.</p><h3>The problem </h3><p>I’m on the bus to work, passing the time with a great Android game. I’m completely entranced by whatever combination of birds, ropes, and ninjas is popular this week. Suddenly I panic: I’ve almost missed my stop! I leap up, quickly locking my phone as I shove it into a pocket. </p><p>I arrive breathless at my first meeting of the day. The boss, perhaps sensing my vulnerability, asks me a tough question. Not tough enough to stump me, though — I’ve got the answer to that right here on my Android phone! I whip out my phone and press the unlock button... and the room dissolves in laughter as a certain well-known game ditty blares out from the device.</p><p>The initial embarrassment is bad enough, but what’s this? I can’t even mute the thing! The phone is showing the lock screen and the volume buttons are inactive. My stress level is climbing and it takes me three tries to successfully type in my unlock code. Finally I get the thing unlocked, jam my finger on the home button and breathe a sigh of relief as the music stops. But the damage is done — my boss is glowering and for the rest of the week my co-workers make video game noises whenever they pass my desk.</p><h3>What went wrong? </h3><p>It’s a common mistake: the developer of the game assumed that if the game received an <a href="http://developer.android.com/reference/android/app/Activity.html#onResume()">onResume()</a> message, it was safe to resume audio. The problem is that onResume() doesn’t necessarily mean your app is visible — only that it’s active. In the case of a locked phone, onResume() is sent as soon as the screen turns on, even though the phone’s display is on the lock screen and the volume buttons aren’t enabled. </p><p>Fixing this is trickier than it sounds. Some games wait for <a href="http://developer.android.com/reference/android/app/Activity.html#onWindowFocusChanged(boolean)">onWindowFocusChanged()</a> instead of onResume(), which works pretty well on Gingerbread. But on Honeycomb and higher, onWindowFocusChanged() is sent when certain foreground windows — like, ironically, the volume control display window — take focus. The result is that when the user changes the volume, all of the sound is muted. Not the developer’s original intent!</p><p>Waiting for onResume() <em>and</em> onFocusChanged() seems like a possible fix, and it works pretty well in a large number of cases. But even this approach has its Achilles’ heel. If the device falls asleep on its own, or if the user locks the phone and then immediately unlocks it, your app may not receive any focus changed messages at all. </p><h3>What to do about it</h3><p>Here’s the easy two-step way to avoid user embarrassment:</p><ol><li><p>Pause the game (and all sound effects) whenever you receive an <a href="http://developer.android.com/reference/android/app/Activity.html#onPause()">onPause()</a> message. When gameplay is interrupted — whether because the phone is locked, or the user received a call, or for some other reason — the game should be paused.</p></li><li><p>After the game is paused, require user input to continue. The biggest mistake most game developers make is to automatically restart gameplay and audio as soon as the user returns to the game. This isn’t just a question of solving the “music over lock screen” issue. Users like to come back to a paused game. It’s no fun to switch back to a game, only to realize you’re about to die because gameplay has resumed before you expected it. </p></li></ol><p>Some game designers don’t like the idea of pausing the background music when the game is paused. If you absolutely must resume music as soon as your game regains focus, then you should do the following:</p><ol><li><p>Pause playback when you receive onPause().</p></li><li><p>When you receive onResume():</p><ol><li><p>If you have previously received an onFocusChanged(false) message, wait for an onFocusChanged(true) message to arrive before resuming playback.</p></li><li><p>If you have <em>not</em> previously received an onFocusChanged(false) message, then resume audio immediately.</p></li></ol></li><li><p>Test thoroughly! </p></li></ol><p>Fixing audio embarrassments is almost always a quick and easy process. Take the time to do it right, and your users will thank you.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1665572372970222288?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/making-android-games-that-play-nice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>New Layout Widgets: Space and GridLayout</title>
		<link>https://googledata.org/google-android/new-layout-widgets-space-and-gridlayout/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-layout-widgets-space-and-gridlayout</link>
		<comments>https://googledata.org/google-android/new-layout-widgets-space-and-gridlayout/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 23:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=96e117a7ef738b5d5ed61dbc30178b96</guid>
		<description><![CDATA[[This post is by Philip Milne, who is part of the Android framework team.&#160;&#8212;&#160;Tim&#160;Bray]Ice Cream Sandwich (ICS) sports two new widgets that have been designed to support the richer user interfaces made possible by larger displays: Sp...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="http://blog.enigmosaurus.net/">Philip Milne</a>, who is part of the Android framework team.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Ice Cream Sandwich (ICS) sports two new widgets that have been designed to support the richer user interfaces made possible by larger displays: <a href="http://developer.android.com/reference/android/widget/Space.html">Space</a> and <a href="http://developer.android.com/reference/android/widget/GridLayout.html">GridLayout</a>.</p><p>The most commonly used class for layout in Android is <a href="http://developer.android.com/reference/android/widget/LinearLayout.html">LinearLayout</a>, which allows its children to be aligned in the usual ways: along either the horizontal or vertical axes. It’s often possible to take a complicated layout and break it down into a set of nested linear layouts and, provided this nesting doesn’t get too deep, this is still a good choice for many simple layouts. </p><p>A number of posts and articles (e.g. <a href="http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html">Android Layout Tricks #1</a>, <a href="http://www.androidguys.com/2009/04/24/flattening-the-stack/">Flattening The Stack</a>) have highlighted drawbacks of nested layouts; which fall into three basic categories: </p><ul><li><p>Inability to control alignment along both axes simultaneously</p></li><li><p>Performance problems in hierarchies that are too deep</p></li><li><p>Unsuitability for design tools that support free-form editing </p></li></ul><p>A simple example of the first problem is the following form: </p><a href="http://2.bp.blogspot.com/-v5fdrXd7GNA/TrxWJ35If7I/AAAAAAAAA5Y/4wofsXZwmKs/s1600/milne-1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://2.bp.blogspot.com/-v5fdrXd7GNA/TrxWJ35If7I/AAAAAAAAA5Y/4wofsXZwmKs/s400/milne-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504358202376114" /></a><p>As the font and the text of the “Email address” label change, we want the label to remain aligned with the <em>baseline</em> of the component to its right, and aligned with the <em>right</em> edge of the label below it. It’s not possible to do this with nested LinearLayouts because the label needs to be aligned with other components both horizontally and vertically. </p><p>These problems aren’t new to Android, or UI toolkits in general, but we’ve used them to drive our work in enriching platform support for flatter hierarchies. </p><h3>GridLayout </h3><p>To provide better support for layouts like these we have added a new layout to the Android framework: GridLayout, which can be used to solve the above problems by dividing the container’s real estate into rows and columns: </p><a href="http://2.bp.blogspot.com/-ceJ2DjokqHE/TrxWTnrN6yI/AAAAAAAAA5k/1qCEdOM-mqc/s1600/milne-2.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://2.bp.blogspot.com/-ceJ2DjokqHE/TrxWTnrN6yI/AAAAAAAAA5k/1qCEdOM-mqc/s400/milne-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504525647735586" /></a><p>Now the “Email address” label can belong both to a <em>row</em> that is <em>baseline</em>-aligned, and a <em>column</em> that is <em>right</em>-aligned. </p><p>GridLayout uses a grid of infinitely-thin lines to separate its drawing area into: <em>rows</em>, <em>columns</em>, and <em>cells</em>. It supports both row and column <em>spanning</em>, which together allow a widget to occupy a rectangular range of cells that are next to each other. We’ll use the words <em>row</em>, <em>column</em>, and <em>cell</em> in the text below as shorthand for <em>row group</em>, <em>column group</em> and <em>cell group</em> respectively, where groups have one or more contiguous elements.  </p><h4>Similarities with LinearLayout</h4><p>Wherever possible, GridLayout uses the same conventions as LinearLayout for all its XML API — so it should be easy to start using GridLayout if you’ve already used LinearLayout. In fact, the APIs are so similar that changing a tag name from LinearLayout to GridLayout in an XML file that uses LinearLayout will often produce a similar UI without requiring any other changes. When it doesn’t, you’ll still generally end up with a good starting point for a two-dimensional layout. </p><h3>Getting Started</h3><p>Two examples in the samples area of the Android 4.0 SDK show typical use of the programmatic and XML APIs respectively:  </p><ul><li><p><a href="http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/GridLayout0.html">samples/ApiDemos/src/com/example/android/apis/view/GridLayout0.java</a></p></li><li><p><a href="http://developer.android.com/resources/samples/ApiDemos/res/layout/grid_layout_1.xml">samples/ApiDemos/res/layout/grid_layout_1.xml</a></p></li></ul><p>[Both examples produce the same UI.] </p><p>Here’s a slightly simpler version of the above XML layout. </p><pre><code>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;GridLayout
        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:useDefaultMargins="true"
        android:alignmentMode="alignBounds"
        android:columnOrderPreserved="false"

        android:columnCount="4"
        >

    &lt;TextView
            android:text="Email setup"
            android:textSize="32dip"

            android:layout_columnSpan="4"
            android:layout_gravity="center_horizontal"
            />

    &lt;TextView
            android:text="You can configure email in just a few steps:"
            android:textSize="16dip"

            android:layout_columnSpan="4"
            android:layout_gravity="left"
            />

    &lt;TextView
            android:text="Email address:"

            android:layout_gravity="right"
            />

    &lt;EditText
            android:ems="10"
            />

    &lt;TextView
            android:text="Password:"

            android:layout_column="0"
            android:layout_gravity="right"
            />

    &lt;EditText
            android:ems="8"
            />

    &lt;Space
            android:layout_row="4"
            android:layout_column="0"
            android:layout_columnSpan="3"
            android:layout_gravity="fill"
            />

    &lt;Button
            android:text="Next"

            android:layout_row="5"
            android:layout_column="3"
            />
&lt;/GridLayout></code></pre><p>The first difference you’ll notice in these examples is the absence of the WRAP_CONTENT and MATCH_PARENT constants that normally adorn Android layout resources. You don’t normally need to use these with GridLayout, for reasons that are described in the API doc for <a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html">GridLayout.LayoutParams</a>. </p><h4>Row and Column Indices</h4><p>The second thing you may notice in the XML resources is that widgets don’t always explicitly define which cells they are to be placed in. Each widget’s layout parameters have row and column indices that together define where the widget should be placed but when either or both of these values are not specified, GridLayout supplies default values rather than throwing an exception. </p><h4>Automatic Index Allocation</h4><p>As children are added to a GridLayout, it maintains a cursor position and a “high-water mark” that it uses to place widgets in cells that don’t yet have anything in them. </p><a href="http://4.bp.blogspot.com/-nQwSciBv9fw/TrxWZ_T6YRI/AAAAAAAAA5w/mZW4egdPJv4/s1600/milne-3.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-nQwSciBv9fw/TrxWZ_T6YRI/AAAAAAAAA5w/mZW4egdPJv4/s400/milne-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504635071652114" /></a><p>When GridLayout’s <a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:orientation">orientation</a> property is <code>horizontal</code> and a <a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:columnCount">columnCoun</a>t has been set (to 8 in this example) the high-water mark (shown above in <span style="color: red;">red</span>) is maintained as a separate height value for each column. When indices need to be created, GridLayout first determines the size of the cell group (by looking at the <a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html#attr_android:layout_rowSpan">rowSpan</a> and <a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html#attr_android:layout_columnSpan">columnSpan</a> parameters of the new widget) and then, starting at the cursor, goes through the available locations from: left to right, top to bottom, so as to find the row and column indices of the first location that’s free. </p><p>When GridLayout’s orientation is <code>vertical</code>, all of the same principles apply, except that the roles of the horizontal and vertical axes are exchanged. </p><p>If you want multiple views to be placed in the same cell, you have to define the indices explicitly, as the default allocation procedure above is designed to place widgets in separate cells. </p><h3>Sizes, Margins and Alignment/Gravity </h3><p>In GridLayout, specifying sizes and margins is done just as with a LinearLayout. Alignment/gravity also works just like gravity in LinearLayout and uses the same constants: <a href="http://developer.android.com/reference/android/view/Gravity.html#LEFT">left</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#TOP">top</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#RIGHT">right</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#BOTTOM">bottom</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER_HORIZONTAL">center_horizontal</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER_VERTICAL">center_vertical</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER">center</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#FILL_HORIZONTAL">fill_horizontal</a>, <a href="http://developer.android.com/reference/android/view/Gravity.html#FILL_VERTICAL">fill_vertical</a> and <a href="http://developer.android.com/reference/android/view/Gravity.html#FILL">fill</a>. </p><h3>Flexibility</h3><p>Unlike most grids in other toolkits, GridLayout does not associate data with rows or columns. Instead, everything to do with alignment and flexibility is associated with the components themselves. GridLayout departs from the norm here to provide a more general system that allows subtle relationships between ancestors in deeply nested layouts to be accommodated in a single layout configuration. </p><p>The flexibility of columns is inferred from the gravity of the components inside the column. If every component defines a gravity, the column is taken as flexible, otherwise the column is considered inflexible. Full details are in GridLayout’s <a href="http://developer.android.com/reference/android/widget/GridLayout.html">API docs</a>. </p><h3>Emulating Features from other Layouts</h3><p>GridLayout does not incorporate all of the features of every layout in the Android platform but it has a rich enough feature set that idiomatic use of other layouts can normally be emulated from inside a single GridLayout. </p><p>Although <a href="http://developer.android.com/reference/android/widget/LinearLayout.html">LinearLayout</a> can be considered a special case of a GridLayout, for the degenerate case when a set of views are aligned in a single row or column, LinearLayout is the better choice when this is all that is required as it clarifies the purpose of the container and may have some (relatively small) performance advantages. </p><p><a href="http://developer.android.com/reference/android/widget/TableLayout.html">TableLayout</a> configurations are normally straightforward to accommodate, as GridLayout supports both row and column spanning. <a href="http://developer.android.com/reference/android/widget/TableRow.html">TableRows</a> can be removed, as they are not required by GridLayout. For the same UI, a GridLayout will generally be faster and take less memory than than a TableLayout. </p><p>Simple <a href="http://developer.android.com/reference/android/widget/RelativeLayout.html">RelativeLayout</a> configurations can be written as grids simply by grouping the views that are related to each other into rows and columns. Unlike conventional grids, GridLayout uses a constraints solver to do the heavy lifting of the layout operation. By using GridLayout’s  <a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:rowOrderPreserved">rowOrderPreserved</a> and <a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:columnOrderPreserved">columnOrderPreserved</a> properties it’s possible to free GridLayout from the confines of traditional grid systems and support the majority of RelativeLayout configurations — even ones that require grid lines to pass over each other as children change size.  </p><p>Simple <a href="http://developer.android.com/reference/android/widget/FrameLayout.html">FrameLayout</a> configurations can be accommodated within the cells of a GridLayout because a single cell can contain multiple views. To switch between two views, place them both in the same cell and use the visibility constant <a href="http://developer.android.com/reference/android/view/View.html#GONE">GONE</a> to switch from one to the other from code. As with the LinearLayout case above, if all you need is the functionality described above, FrameLayout is the better choice and may have some small performance advantages. </p><p>One key feature that GridLayout lacks is the ability to distribute excess space between rows or columns in specified proportions — a feature that LinearLayout provides by supporting the principle of <a href="http://developer.android.com/reference/android/widget/LinearLayout.LayoutParams.html#attr_android:layout_weight">weight</a>. This omission and possible ways around it are discussed in GridLayout’s API docs. </p><h3>The Phases of the Layout Operation</h3><p>It’s useful to distinguish the allocation phase for cell indices discussed above from the layout operation itself. Normally the phase that allocates indices happens once, if at all, when a UI is initialized. The index-allocation phase only applies when indices have been left unspecified, and is responsible for ensuring that all views have a defined set of cells in which they are to be placed at layout time. </p><p>The layout operation happens after this and is recalculated each time a view changes size. GridLayout measures the size of each child during the layout operation so it can calcuate the heights and widths of the rows and columns in the grid. The layout phase completes by using gravity to place each of the components in its cell. </p><p>Although index allocation normally only happens once, GridLayout is technically a dynamic layout, meaning that if you change its orientation property or add or remove children after components have been laid out, GridLayout will repeat the above procedure to reallocate indices in a way that is right for the new configuration. </p><p>From a performance standpoint, it is worth knowing that the GridLayout implementation has been optimized for the common case, when initialization happens once and layout happens frequently. As a result, the initialization step sets up internal data structures so that the layout operation can complete quickly and without allocating memory. Put another way, changes either to GridLayout’s orientation or the number of children it has are much more expensive than an ordinary layout operation. </p><h3>Conclusion</h3><p>GridLayout’s feature set incorporates much of the functionality of the Android framework’s existing general-purpose layouts: LinearLayout, FrameLayout, TableLayout and RelativeLayout. As such, it provides a way to replace many deeply nested view hierarchies with a single highly optimized layout implementation. </p><p>If you are starting a UI from scratch and are not familiar with Android layouts, use a GridLayout — it supports most of the features of the other layouts and has a simpler and more general API than either TableLayout or RelativeLayout. </p><p>We anticipate that the combination of FrameLayout, LinearLayout and GridLayout together will provide a feature set that’s rich enough to allow most layout problems to be solved without writing layout code by hand. It’s worth spending some time deciding which of these layouts is right for the top of your tree; a good choice will minimize the need for intermediate containers and result in a user interface that is faster and uses less memory. </p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8379178536336854115?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/new-layout-widgets-space-and-gridlayout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>More Android Developer Labs in Asia</title>
		<link>https://googledata.org/google-android/more-android-developer-labs-in-asia/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=more-android-developer-labs-in-asia</link>
		<comments>https://googledata.org/google-android/more-android-developer-labs-in-asia/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 18:36:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=a80ac25a6875ff3be33d211dfbcd2731</guid>
		<description><![CDATA[A couple of months ago, we kicked off a series of Android Developer Labs in Asia, North America and Europe.  To wrap up the 2011 series, we now have opened registration for 2 more locations in Asia.Taipei — December 2, 2011Hong Kong — December 6, 2...]]></description>
				<content:encoded><![CDATA[<p>A couple of months ago, we kicked off a series of Android Developer Labs in <a href="http://android-developers.blogspot.com/2011/08/android-developer-labs-2011.html">Asia, North America and Europe</a>.  To wrap up the 2011 series, we now have <a href="https://sites.google.com/site/androiddevlabs2011/apac-android-developer-lab">opened registration</a> for 2 more locations in Asia.</p><ul><li><p>Taipei — December 2, 2011</p></li><li><p>Hong Kong — December 6, 2011</p></li></ul><p>Remember, this ADL series isn’t another set of introduction-to-Android sessions, nor any other kind of general overview. It's specifically aimed at optimizing Android apps for tablets, in particular creating high-quality tablet apps with an emphasis on polish and user experience.</p><p>Registration is a two-step process. Anyone can register, but we can only accommodate a relatively small number of attendees from among the registrants, based on whether they already have an Android app with the potential to be a top-tier tablet app in terms of quality, fit, and finish. The goal is to bring your app to the ADL, and leave equipped to make it into one that makes Android tablet users smile.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6428902022448054162?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/more-android-developer-labs-in-asia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JNI Local Reference Changes in ICS</title>
		<link>https://googledata.org/google-android/jni-local-reference-changes-in-ics/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jni-local-reference-changes-in-ics</link>
		<comments>https://googledata.org/google-android/jni-local-reference-changes-in-ics/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 14:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=508006bafb6e4e8fbbfbabc233a189e4</guid>
		<description><![CDATA[[This post is by Elliott Hughes, a Software Engineer on the Dalvik team.&#160;&#8212;&#160;Tim&#160;Bray]If you don’t write native code that uses JNI, you can stop reading now. If you do write native code that uses JNI, you really need to read this.W...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Elliott Hughes, a Software Engineer on the Dalvik team.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>If you don’t write native code that uses JNI, you can stop reading now. If you do write native code that uses JNI, you really need to read this.</p><h3>What’s changing, and why?</h3><p>Every developer wants a good <a href="http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)">garbage collector</a>. The best garbage collectors move objects around. This lets them offer very cheap allocation and bulk deallocation, avoids heap fragmentation, and may improve locality. Moving objects around is a problem if you’ve handed out pointers to them to native code. JNI uses types such as <code>jobject</code> to solve this problem: rather than handing out direct pointers, you’re given an opaque handle that can be traded in for a pointer when necessary. By using handles, when the garbage collector moves an object, it just has to update the handle table to point to the object’s new location. This means that native code won’t be left holding dangling pointers every time the garbage collector runs.</p><p>In previous releases of Android, we didn’t use indirect handles; we used direct pointers. This didn’t seem like a problem as long as we didn’t have a garbage collector that moves objects, but it let you write buggy code that still seemed to work. In Ice Cream Sandwich, even though we haven't yet implemented such a garbage collector, we've moved to indirect references so you can start detecting bugs in your native code.</p><p>Ice Cream Sandwich features a JNI bug compatibility mode so that as long as your AndroidManifest.xml’s targetSdkVersion is less than Ice Cream Sandwich, your code is exempt. But as soon as you update your targetSdkVersion, your code needs to be correct.</p><p><a href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">CheckJNI</a> has been updated to detect and report these errors, and in Ice Cream Sandwich, CheckJNI is on by default if <code>debuggable="true"</code> in your manifest.</p><h3>A quick primer on JNI references</h3><p>In JNI, there are several kinds of reference. The two most important kinds are local references and global references. Any given <code>jobject</code> can be either local or global. (There are weak globals too, but they have a separate type, <code>jweak</code>, and aren’t interesting here.)</p><p>The global/local distinction affects both lifetime and scope. A global is usable from any thread, using that thread’s <code>JNIEnv*</code>, and is valid until an explicit call to <code>DeleteGlobalRef()</code>. A local is only usable from the thread it was originally handed to, and is valid until either an explicit call to <code>DeleteLocalRef()</code> or, more commonly, until you return from your native method. When a native method returns, all local references are automatically deleted.</p><p>In the old system, where local references were direct pointers, local references were never really invalidated. That meant you could use a local reference indefinitely, even if you’d explicitly called <code>DeleteLocalRef()</code> on it, or implicitly deleted it with <code>PopLocalFrame()</code>!</p><p>Although any given <code>JNIEnv*</code> is only valid for use on one thread, because Android never had any per-thread state in a <code>JNIEnv*</code>, it used to be possible to get away with using a <code>JNIEnv*</code> on the wrong thread. Now there’s a per-thread local reference table, it’s vital that you only use a <code>JNIEnv*</code> on the right thread.</p><p>Those are the bugs that ICS will detect. I’ll go through a few common cases to illustrate these problems, how to spot them, and how to fix them. It’s important that you do fix them, because it’s likely that future Android releases will utilize moving collectors. It will not be possible to offer a bug-compatibility mode indefinitely.</p><h3>Common JNI reference bugs</h3><h4>Bug: Forgetting to call <code>NewGlobalRef()</code> when stashing a <code>jobject</code> in a native peer</h4><p>If you have a native peer (a long-lived native object corresponding to a Java object, usually created when the Java object is created and destroyed when the Java object’s finalizer runs), you must not stash a <code>jobject</code> in that native object, because it won’t be valid next time you try to use it. (Similar is true of <code>JNIEnv*</code>s. They <em>might</em> be valid if the next native call happens on the same thread, but they won’t be valid otherwise.)</p><pre><code> class MyPeer {
 public:
   MyPeer(jstring s) {
     str_ = s; // Error: stashing a reference without ensuring it’s global.
   }
   jstring str_;
 };

 static jlong MyClass_newPeer(JNIEnv* env, jclass) {
   jstring local_ref = env->NewStringUTF("hello, world!");
   MyPeer* peer = new MyPeer(local_ref);
   return static_cast&lt;jlong>(reinterpret_cast&lt;uintptr_t>(peer));
   <span style="color: red;">// Error: local_ref is no longer valid when we return, but we've stored it in 'peer'.</span>
 }

 static void MyClass_printString(JNIEnv* env, jclass, jlong peerAddress) {
   MyPeer* peer = reinterpret_cast&lt;MyPeer*>(static_cast&lt;uintptr_t>(peerAddress));
   // Error: peer->str_ is invalid!
   ScopedUtfChars s(env, peer->str_);
   std::cout &lt;&lt; s.c_str() &lt;&lt; std::endl;
 }</code></pre><p>The fix for this is to only store JNI global references. Because there’s never any automatic cleanup of JNI global references, it’s critically important that you clean them up yourself. This is made slightly awkward by the fact that your destructor won’t have a <code>JNIEnv*</code>. The easiest fix is usually to have an explicit ‘destroy‘ function for your native peer, called from the Java peer’s finalizer:</p><pre><code> class MyPeer {
 public:
   MyPeer(JNIEnv* env, jstring s) {
     this->s = env->NewGlobalRef(s);
   }
   ~MyPeer() {
     assert(s == NULL);
   }
   void destroy(JNIEnv* env) {
     env->DeleteGlobalRef(s);
     s = NULL;
   }
   jstring s;
 };</code></pre><p>You should always have matching calls to <code>NewGlobalRef()</code>/<code>DeleteGlobalRef()</code>. CheckJNI will catch global reference leaks, but the limit is quite high (2000 by default), so watch out.</p><p>If you do have this class of error in your code, the crash will look something like this:</p><pre><code>    JNI ERROR (app bug): accessed stale local reference 0x5900021 (index 8 in a table of size 8)
    JNI WARNING: jstring is an invalid local reference (0x5900021)
                 in LMyClass;.printString:(J)V (GetStringUTFChars)
    "main" prio=5 tid=1 RUNNABLE
      | group="main" sCount=0 dsCount=0 obj=0xf5e96410 self=0x8215888
      | sysTid=11044 nice=0 sched=0/0 cgrp=[n/a] handle=-152574256
      | schedstat=( 156038824 600810 47 ) utm=14 stm=2 core=0
      at MyClass.printString(Native Method)
      at MyClass.main(MyClass.java:13)</code></pre><p>If you’re using another thread’s <code>JNIEnv*</code>, the crash will look something like this:</p><pre><code> JNI WARNING: threadid=8 using env from threadid=1
                 in LMyClass;.printString:(J)V (GetStringUTFChars)
    "Thread-10" prio=5 tid=8 NATIVE
      | group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
      | sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
      | schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8
      at MyClass.printString(Native Method)
      at MyClass$1.run(MyClass.java:15)</code></pre><h4>Bug: Mistakenly assuming <code>FindClass()</code> returns global references</h4><p><code>FindClass()</code> returns local references. Many people assume otherwise. In a system without class unloading (like Android), you can treat jfieldID and jmethodID as if they were global. (They’re not actually references, but in a system with class unloading there are similar lifetime issues.) But jclass is a reference, and <code>FindClass()</code> returns local references. A common bug pattern is “static jclass”. Unless you’re manually turning your local references into global references, your code is broken. Here’s what correct code should look like:</p><pre><code> static jclass gMyClass;
 static jclass gSomeClass;

 static void MyClass_nativeInit(JNIEnv* env, jclass myClass) {
   // ‘myClass’ (and any other non-primitive arguments) are only local references.
   gMyClass = env->NewGlobalRef(myClass);

   // FindClass only returns local references.
   jclass someClass = env->FindClass("SomeClass");
   if (someClass == NULL) {
     return; // FindClass already threw an exception such as NoClassDefFoundError.
   }
   gSomeClass = env->NewGlobalRef(someClass);
 }</code></pre><p>If you do have this class of error in your code, the crash will look something like this:</p><pre><code>    JNI ERROR (app bug): attempt to use stale local reference 0x4200001d (should be 0x4210001d)
    JNI WARNING: 0x4200001d is not a valid JNI reference
                 in LMyClass;.useStashedClass:()V (IsSameObject)</code></pre><h4>Bug: Calling <code>DeleteLocalRef()</code> and continuing to use the deleted reference</h4><p>It shouldn’t need to be said that it’s illegal to continue to use a reference after calling <code>DeleteLocalRef()</code> on it, but because it used to work, so you may have made this mistake and not realized. The usual pattern seems to be where native code has a long-running loop, and developers try to clean up every single local reference as they go to avoid hitting the local reference limit, but they accidentally also delete the reference they want to use as a return value!</p><p>The fix is trivial: don’t call <code>DeleteLocalRef()</code> on a reference you’re going to use (where “use” includes “return”).</p><h4>Bug: Calling <code>PopLocalFrame()</code> and continuing to use a popped reference</h4><p>This is a more subtle variant of the previous bug. The <code>PushLocalFrame()</code> and <code>PopLocalFrame()</code> calls let you bulk-delete local references. When you call <code>PopLocalFrame()</code>, you pass in the one reference from the frame that you’d like to keep (typically for use as a return value), or NULL. In the past, you’d get away with incorrect code like the following:</p><pre><code> static jobjectArray MyClass_returnArray(JNIEnv* env, jclass) {
   env->PushLocalFrame(256);
   jobjectArray array = env->NewObjectArray(128, gMyClass, NULL);
   for (int i = 0; i &lt; 128; ++i) {
       env->SetObjectArrayElement(array, i, newMyClass(i));
   }
   env->PopLocalFrame(NULL); <span style="color: red;">// Error: should pass 'array'.</span>
   return array; <span style="color: red;">// Error: array is no longer valid.</span>
 }</code></pre><p>The fix is generally to pass the reference to <code>PopLocalFrame()</code>. Note in the above example that you don’t need to keep references to the individual array elements; as long as the GC knows about the array itself, it’ll take care of the elements (and any objects they point to in turn) itself.</p><p>If you do have this class of error in your code, the crash will look something like this:</p><pre><code>  JNI ERROR (app bug): accessed stale local reference 0x2d00025 (index 9 in a table of size 8)
    JNI WARNING: invalid reference returned from native code
                 in LMyClass;.returnArray:()[Ljava/lang/Object;</code></pre><h3>Wrapping up</h3><p>Yes, we asking for a bit more attention to detail in your JNI coding, which is extra work.  But we think that you’ll come out ahead on the deal as we roll in better and more sophisticated memory management code.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4948819655425709769?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/jni-local-reference-changes-in-ics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android 4.0 Graphics and Animations</title>
		<link>https://googledata.org/google-android/android-4-0-graphics-and-animations/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-4-0-graphics-and-animations</link>
		<comments>https://googledata.org/google-android/android-4-0-graphics-and-animations/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 14:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=ee7c53fd8255ebb957b349a12066f79e</guid>
		<description><![CDATA[[This post is by Romain Guy and Chet Haase, Android engineers who have been known to collaborate on the subject of graphics, UIs, and animation. You can read more from them on their blogs at curious-creature.org and graphics-geek.blogspot.com.&#160;&#038;md...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Romain Guy and Chet Haase, Android engineers who have been known to <a href="http://filthyrichclients.org">collaborate</a> on the subject of graphics, UIs, and animation. You can read more from them on their blogs at <a href="http://curious-creature.org">curious-creature.org</a> and <a href="http://graphics-geek.blogspot.com">graphics-geek.blogspot.com</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Earlier this year, <a href="http://android-developers.blogspot.com/2011/03/android-30-hardware-acceleration.html%20">Android 3.0 launched</a> with a new 2D rendering pipeline designed to support hardware acceleration on tablets. With this new pipeline, all drawing operations performed by the UI toolkit are carried out using the GPU.</p><p>You’ll be happy to hear that Android 4.0, Ice Cream Sandwich, brings an improved version of the hardware-accelerated 2D rendering pipeline to phones, starting with <a href="http://www.google.com/nexus">Galaxy Nexus</a>.</p><h3>Enabling hardware acceleration</h3><p>In Android 4.0 (API level 14), hardware acceleration, for the first time, is on by default for all applications. For applications at lower API levels, you can turn it on by adding <code>android:hardwareAccelerated="true"</code> to the <code>&lt;application></code> tag in your AndroidManifest.xml.</p><p>To learn more about the hardware accelerated 2D rendering pipeline visit the official <a href="http://developer.android.com/guide/topics/graphics/hardware-accel.html">Android developer guide</a>. This guide explains how to control hardware acceleration at various levels, offers several performance tips and tricks and describes in details the new drawing model.</p><p>I also encourage you to watch the <a href="http://www.youtube.com/watch?v=v9S5EO7CLjo">Android Hardware Accelerated Rendering</a> talk that we gave at Google I/O 2011.</p><h3>Introducing TextureView</h3><p>Applications that need to display OpenGL or video content rely today on a special type of UI element called <a href="http://developer.android.com/reference/android/view/SurfaceView.html">SurfaceView</a>. This widget works by creating a new window placed behind your application’s window. It then punches a hole through your application’s window to reveal the new window. While this approach is very efficient, since the content of the new window can be refreshed without redrawing the application’s window, it suffers from several important limitations.</p><p>Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView. SurfaceView also cannot interact properly with some features of the UI toolkit such as fading edges or <code>View.setAlpha()</code>.</p><p>To solve these problems, Android 4.0 introduces a new widget called <a href="http://developer.android.com/reference/android/view/TextureView.html">TextureView</a> that relies on the hardware accelerated 2D rendering pipeline and <a href="http://developer.android.com/reference/android/graphics/SurfaceTexture.html">SurfaceTexture</a>. TextureView offers the same capabilities as SurfaceView but, unlike SurfaceView, behaves as a regular view. You can for instance use a TextureView to display an OpenGL scene or a video stream. The TextureView itself can be animated, scrolled, etc.</p><p>The following piece of code creates a TextureView to display the video preview from the default camera. The TextureView itself is rotated 45 degrees and semi-transparent.</p><pre><code>public class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
    private Camera mCamera;
    private TextureView mTextureView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);

        setContentView(mTextureView);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mCamera = Camera.open();

        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
                previewSize.width, previewSize.height, Gravity.CENTER));

        try {
            mCamera.setPreviewTexture(surface);
        } catch (IOException t) {
        }

        mCamera.startPreview();
        
        mTextureView.setAlpha(0.5f);
        mTextureView.setRotation(45.0f);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Ignored, the Camera does all the work for us
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mCamera.stopPreview();
        mCamera.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Called whenever a new frame is available and displayed in the TextureView
    }
}</code></pre><p>A TextureView can just as easily be used to embed an OpenGL scene in your application. As of Android 4.0, <a href="http://developer.android.com/reference/javax/microedition/khronos/egl/EGL10.html#eglCreateWindowSurface(javax.microedition.khronos.egl.EGLDisplay,%20javax.microedition.khronos.egl.EGLConfig,%20java.lang.Object,%20int%5B%5D)">eglCreateWindowSurface()</a> can be used to render into a SurfaceTexture object.</p><h3>Animation</h3><p>There were minor improvements in Android 4.0 to some of the new animation facilities that were added in the 3.x releases.</p><p>First, if you're new to the new android.animation package and classes added in 3.0 and 3.1, you might want to read <a href="http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.html">Animation in Honeycomb</a> and <a href="http://graphics-geek.blogspot.com/2011/06/introducing-viewpropertyanimator.html">Introducing ViewPropertyAnimator</a>. These articles discuss the new APIs added in 3.0 that make animation in Android easier, more powerful, and more flexible. The Android 4.0 improvements discussed below are small additions to these core facilities.</p><h3>Properties</h3><p>One of the constraints of the Java programming language is the lack of “properties”. There is no way to refer generically to a field or a setter/getter of an object. As long as you know what kind of object you have, this is not a problem, because you then know the set of fields and methods that you can call. But if someone passes you some subclass of Object and you'd like to get or set some value  “foo” on it, you're out of luck. You can use reflection or JNI to get access to the foo field/methods, but there is no way to refer directly to a field or a method unless you know the instance type of the object that has that field/method on it.</p><p>This is a constraint that the new animation system works within. Its whole job, you might say, is to get and set values on generic objects that it's been told about. If someone wants to animate the alpha property on a View, they tell the system the target object and the name of that field (“alpha”), and the animation system uses JNI to figure out which method(s) act on a field of that name. Basically, it looks for <code>setAlpha()</code> and, sometimes, <code>getAlpha()</code> methods. Then when an animation frame occurs, it calculates the new value and passes it into the setter method that it found.</p><p>This seems like a lot of work for what it does, but there's really no way around it. Unless the animation system were specific to View objects, there's no way that it could know that the target object has appropriate setter/getter methods. And even if it did, there's still no way for callers that construct the animations to tell the animator about the property named  “alpha”; there are no function handles like there are in other languages, and there's no way to reference a public field either. (I'm ignoring Reflection here, which has Method and Field objects, because this approach requires much more overhead and processing than the simple function/field references of other languages).</p><p>If only there were a way to refer to these properties and to get/set them on generic objects...</p><p>Now there is. There is a new Property object in the android.util package that does exactly this. This class offers a <code>set()</code> and a <code>get()</code> method. So if someone hands you a Property object, you can safely call the <code>set()</code> and <code>get()</code> methods without knowing anything about the target object and it will do the job. Moreover, it will do it much more efficiently than the current JNI or reflection approaches because it can, depending on the implementation of it, set a field or call a method on the target object directly. For example, the new ALPHA property on View calls setAlpha() on the View object.</p><p>The Property class is a generic utility that can be used anywhere, not just in animations. But it's animations that benefit enormously from it, in their ability to handle properties in a type-safe and efficient manner.</p><p>For example prior to Android 4.0, you might construct a fade-out animation on some object myView like this:</p><pre><code>ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 0);</code></pre><p>In Android 4.0, you can use the new ALPHA object on View to construct a Property-based animator instead:</p><pre><code>ObjectAnimator anim = ObjectAnimator.ofFloat(myView, View.ALPHA, 0);</code></pre><h3>ViewPropertyAnimator Additions</h3><p>There were minor API additions to the ViewPropertyAnimator class (introduced in Android 3.1) which make this class more flexible and powerful:</p><ul><li><p><code>cancel()</code>: You can now cancel() a running ViewPropertyAnimator.</p></li><li><p><code>setStartDelay()</code>: You can now set a startDelay on the ViewPropertyAnimator, just like the startDelay of the other Animator classes.</p></li><li><p><code>start()</code>: ViewPropertyAnimators start automatically, but they do so on the next animation frame handled. This allows them to collect several requests and bundle them together, which is much more efficient and makes it easier to synchronize multiple animations together. However, if you just want to run a single animation, or want to make sure it starts immediately, at the time of construction, you can call <code>start()</code> to avoid that intervening delay.</p></li></ul><h3>LayoutTransition</h3><p>LayoutTransition (introduced in Android 3.0) continues to provide functionality that makes some kinds of animations easier, specifically when adding, removing, hiding, and showing views. For example, either this snippet in a layout file:</p><pre><code>&lt;LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:id="@+id/container"></code></pre><p>Or this code added at runtime:</p><pre><code> container.setLayoutTransition(new LayoutTransition());</code></pre><p>will result in a container that animates the visibility of its children views. So when a view is added to the container, the other children will animate out of the way and then the new one will fade in. Similarly, removing a child from the container will fade it out and then animate the other children around to their final places and sizes.</p><p>You can customize the animations and timing behavior of a LayoutTransition object, but the code above allows a very easy way to get reasonable default animation behavior.</p><p>One of the constraints in the pre-4.0 version of the class was that it did not account for changes in the bounds of the parent hierarchy. So, for example, if a LinearLayout with horizontal orientation has a layout_width of wrap_content and you want to run a transition that removes an item from that layout, then you might notice the parent snapping to the end size and clipping its children instead of animating all of them into their new positions. The new approach (enabled by default, but disabled by a call to <code>setAnimateParentHierarchy(false))</code> also animates the layout bounds and scrolling values of the parent layout and its parents, all the way up the view hierarchy. This allows LayoutTransition to account for all layout-related changes due to that view being added or removed from its transitioning container.</p><h3>Conclusion</h3><p>The Android 3.0 release saw huge improvements in the visual capabilities of the platform, as we started enabling hardware acceleration and providing new, more flexible animation capabilities. Android 4.0 continues this trend as we continue to work hard on improving the performance, features, and usability of the Android APIs. We’re not done yet, but the enhancements in this release should help you create more exciting Android experiences and applications.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8414461099127805380?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-4-0-graphics-and-animations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Android WebDriver</title>
		<link>https://googledata.org/google-android/introducing-android-webdriver/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducing-android-webdriver</link>
		<comments>https://googledata.org/google-android/introducing-android-webdriver/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 19:46:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=d78a16aaacfc99df1284d570dd29c69d</guid>
		<description><![CDATA[[This post is by Dounia Berrada, an engineer on the EngTools team.&#160;&#8212;&#160;Tim&#160;Bray]Selenium WebDriver is a browser automation tool which provides a lightweight and elegant way for testing web apps. Selenium WebDriver is now available as...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-1xbHAI0ZXm8/Tqhm98ZSBgI/AAAAAAAAAt0/P0yGyM_ZIys/s1600/dounia.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 213px; height: 320px;" src="http://4.bp.blogspot.com/-1xbHAI0ZXm8/Tqhm98ZSBgI/AAAAAAAAAt0/P0yGyM_ZIys/s320/dounia.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5667893345415988738" /></a><p><i>[This post is by Dounia Berrada, an engineer on the EngTools team.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Selenium WebDriver is a browser automation tool which provides a lightweight and elegant way for testing web apps. Selenium WebDriver is now available as an SDK extra in the Android SDK, and supports 2.3 (Gingerbread) and onwards!</p><p>Whether or not your site is optimized for mobile browsers, you can be sure that users will be accessing it from their phones and tablets. WebDriver makes it easy to write automated tests that ensure your site works correctly when viewed from the Android browser. We’ll walk you through some basics about WebDriver and look at it in action.</p><h3>WebDriver Basics</h3><p>WebDriver tests are end-to-end tests that exercise the web application just like a real user would. WebDriver models user interactions with a web page such as finger flicks, finger scrolls and long presses. It can rotate the display and interact with HTML5 features such as local storage, session storage and the application cache. Those tests run as part of an <a href="http://developer.android.com/guide/topics/testing/testing_android.html">Android tests project</a> and are based on Junit. They can be <a href="http://developer.android.com/resources/tutorials/testing/helloandroid_test.html">launched from Eclipse</a> or the command line. WebDriver tests can be wired with a continuous integration system and can run on phone and tablet emulators or real devices. Once the test starts, WebDriver opens a WebView configured like the Android browser and runs the tests against it. </p><p>WebDriver is an Android SDK extra and can be installed following <a href="http://code.google.com/p/selenium/wiki/AndroidDriver?ts=1318649352&amp;updated=AndroidDriver#Using_the_Android_Test_Framework">these instructions</a>. Once you’ve done that you’ll be ready to write tests! There is a comprehensive WebDriver <a href="http://seleniumhq.org/docs/03_webdriver.html">user guide</a> on the Selenium site, but let’s start with a basic example using <a href="http://www.google.com/">www.google.com</a> to give you a taste of what’s possible.</p><h3>Getting Started</h3><p>First, create an Android project containing an empty activity with no layout.</p><pre><code>public class SimpleAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}</code></pre><p>Then create the Android test project that will contain the tests. WebDriver will create the WebView and set the layout automatically in the main Activity.</p><p>Let’s write a test that opens the Google home page on Android and issues a query for “weather in San Francisco”. The test will verify that Google returns search results, and that the first result returned is giving the weather in San Francisco.</p><pre><code>public class SimpleGoogleTest extends ActivityInstrumentationTestCase2&lt;SimpleAppActivity> {

    public void testGoogleShouldWork() {
      // Create a WebDriver instance with the activity in which we want the test to run
      WebDriver driver = new AndroidDriver(getActivity());
      // Let’s open a web page
      driver.get("http://www.google.com");

      // Lookup for the search box by its name
      WebElement searchBox = driver.findElement(By.name("q"));

      // Enter a search query and submit
      searchBox.sendKeys("weather in san francisco");
      searchBox.submit();

      // Making sure that Google shows 11 results
      WebElement resultSection = driver.findElement(By.id("ires"));
      List&lt;WebElement> searchResults = resultSection.findElements(By.tagName("li"));
      assertEquals(11, searchResults.size());

      // Let’s ensure that the first result shown is the weather widget
      WebElement weatherWidget = searchResults.get(0);
      assertTrue(weatherWidget.getText().contains("Weather for San Francisco, CA"));
    }
}</code></pre><p>Now let’s see our test in action! WebDriver will create a WebView with the same configuration as the Android browser in the main UI thread, i.e. the activity thread. The activity will display the WebView on the screen, allowing you to see your web application as the test code is executing. </p><h3>Interaction Testing</h3><p>We’ve mentioned that WebDriver supports creating advanced gestures to interact with the device. Let’s use WebDriver to throw an image across the screen by flicking horizontally, and ensure that the next image in the gallery is displayed.</p><pre><code>WebElement toFlick = driver.findElement(By.id("image"));
// 400 pixels left at normal speed
Action flick = getBuilder(driver).flick(toFlick, 0, -400, FlickAction.SPEED_NORMAL)
        .build();
flick.perform();
WebElement secondImage = driver.findElement(“secondImage”);
assertTrue(secondImage.isDisplayed());</code></pre><p>Now, let’s rotate the screen and ensure that the image displayed on screen is resized.</p><pre><code>assertEquals(landscapeSize, secondImage.getSize())
((Rotatable) driver).rotate(ScreenOrientation.PORTRAIT);
assertEquals(portraitSize, secondImage.getSize());</code></pre><p>What if your test reveals a bug? You can easily take a screenshot for help in future debugging: </p><pre><code>File tempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);</code></pre><h3>Find Out More</h3><p>If this has whetted your appetite and you’d like to know more, go ahead and install the Android WebDriver, take a look at the documentation on the <a href="http://code.google.com/p/selenium/wiki/AndroidDriver">Selenium project’s wiki</a>, or just <a href="http://selenium.googlecode.com/svn/trunk/docs/api/java/index.html">browse the javadocs</a>. For questions and feedback not only of the Android WebDriver but also its desktop brethren, please join <a href="http://groups.google.com/group/webdriver/">webdriver@googlegroups.com</a>. For announcements keep an eye on <a href="http://seleniumhq.wordpress.com/">http://seleniumhq.wordpress.com/</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6569655635880991626?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/introducing-android-webdriver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>New Public APIs in ICS</title>
		<link>https://googledata.org/google-android/new-public-apis-in-ics/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-public-apis-in-ics</link>
		<comments>https://googledata.org/google-android/new-public-apis-in-ics/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 17:20:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=4c7803bb2cc6cdd9ce66c8cc337fa985</guid>
		<description><![CDATA[Since Android is open-source, anyone can look at the code and see how it works inside.  If you do this, you’ll notice that most but not all of the APIs are publicly documented.If they’re publicly documented, they’re part of what we consider the A...]]></description>
				<content:encoded><![CDATA[<p>Since Android is open-source, anyone can look at the code and see how it works inside.  If you do this, you’ll notice that most but not all of the APIs are <a href="http://developer.android.com/">publicly documented</a>.</p><p>If they’re publicly documented, they’re part of what we consider the Android Application Framework.  This means their tests appear in the <a href="http://source.android.com/compatibility/cts-intro.html">Compatibility Test Suite (CTS)</a> so that our hardware partners have to prove that the APIs work, and that we promise to try very hard not to change them and thus break your code.</p><p>In almost every case, there’s only one reason for leaving APIs undocumented: We’re not sure that what we have now is the best solution, and we think we might have to improve it, and we’re not prepared to make those commitments to testing and preservation.</p><p>We’re not claiming that they’re “Private”  or “Secret”&nbsp;&mdash;&nbsp;How could they be, when anyone in the world can discover them?  We’re also not claiming they’re forbidden: If you use them, your code will compile and probably run.  And in fact we know of quite a few apps out there whose developers have used undocumented APIs, often to good effect.  It’s hard to get too upset about this in cases where there’s a useful API that we haven’t gotten around to stabilizing.</p><p>But the developers who use those APIs have to be prepared to deal with the situation that arises when we move them from the undocumented outside into the Android Application Framework.  Fortunately, this is reasonably straightforward.  Also we take a close look at Android Market, using our in-house analytics tools, to get a feel for the impact when we know one of these changes is coming.</p><p>There are a few such changes coming up in the Android 4.0 &ldquo;Ice Cream Sandwich&rdquo; (ICS) release of Android.  We wanted to take the opportunity to combine these words on undocumented APIs with some specifics about the changes.</p><h3>Calendars</h3><p>Let’s start with the good news: As of ICS, the Android Framework will include a fully-worked-out <a href="http://developer.android.com/reference/android/provider/CalendarContract.html">set of APIs</a> for accessing Calendar data.  You can guess the bad news: Quite a few developers have built apps (including many good ones) using the undocumented Calendar APIs, some using fairly low-level access to the calendar database.  Unfortunately, these integrations were unsupported, and prone to breakage by platform updates or OEM customization of calendar features.</p><p>We want to see lots of good calendar apps and extensions that work reliably across Android devices, and aren't broken by platform updates. So we decided to create a clean API, including a comprehensive set of Intents, to manage calendar data in ICS. Now anyone can code against these new APIs and know that Android is committed to supporting them, and that partners have to support these APIs as part of CTS. </p><p>Once the new APIs arrive, you’re going to have to update your apps before they’ll run correctly on ICS while still working on older releases.  There are a variety of techniques for doing that, many of which have been featured on this blog, including <a href="http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html">reflection</a> and <a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">lazy loading</a>.  Recently, we introduced <a href="http://android-developers.blogspot.com/2011/07/multiple-apk-support-in-android-market.html">Multiple-APK support</a>, which could also be used to help with this sort of transition.</p><h3>Text To Speech</h3><p>Android has never really had a text-to-speech API at the Framework level, but there was unofficial access at the C++ level.  With ICS, we will have a fully-thought-through <a href="http://developer.android.com/reference/android/speech/tts/TextToSpeech.html">application-level API</a> running on Dalvik, so you can access it with ordinary Java-language application code.  </p><p>The old C++ API will no longer be supported, but we’ll have a compatibility layer that you can use to bridge from it to the new API.  We think it should be easy to update for ICS with very little work.</p><h3>Doing the Right Thing</h3><p>We recognize that this means some work for developers affected by these changes, but we’re confident that Android programs in general, and both Calendar and TTS apps in particular, will come out ahead.  And we also think that most developers know that when they use undocumented APIs, they’re making a commitment to doing the right thing when those APIs change.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1775949760892875753?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/new-public-apis-in-ics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Market Featured-Image Guidelines</title>
		<link>https://googledata.org/google-android/android-market-featured-image-guidelines/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-market-featured-image-guidelines</link>
		<comments>https://googledata.org/google-android/android-market-featured-image-guidelines/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 15:38:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=1567770be4848d6a4e572c3f3f03f082</guid>
		<description><![CDATA[[This post is by Natascha Bock, a Product Marketing Manager on Android.&#160;&#8212;&#160;Tim&#160;Bray]With the latest Android Market update, our editorial team can use your 1024 x 500 “Featured Image” to promote your app on tablets, phones, and t...]]></description>
				<content:encoded><![CDATA[<a href="http://3.bp.blogspot.com/-3TWKMFw919Q/ToymcLyETfI/AAAAAAAAAtE/YkZ9y7DTTrI/s1600/NataschaBock254.jpg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 174px;" src="http://3.bp.blogspot.com/-3TWKMFw919Q/ToymcLyETfI/AAAAAAAAAtE/YkZ9y7DTTrI/s200/NataschaBock254.jpg" border="0" id="BLOGGER_PHOTO_ID_5660081834827206130" /></a><p><i>[This post is by Natascha Bock, a Product Marketing Manager on Android.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>With the latest <a href="http://android-developers.blogspot.com/2011/07/new-android-market-for-phones.html">Android Market update</a>, our editorial team can use your 1024 x 500 “Featured Image” to promote your app on tablets, phones, and the Web.  The image can be used on the home page on all versions of Android Market (Web, tablet and phone), on your product page in the Web and tablet versions, and on current and future top-level Android Market pages on phones.</p><p>Creating a Featured Image that will do a great job of highlighting your app requires special design consideration.  </p><h3>Not Really Optional</h3><p>While many promotional assets are listed as “optional” for the publishing site, we strongly recommend treating them as required.  To start with, a Featured Image is required if your app is to be featured anywhere within Android Market.  They’re a good idea anyhow; they enhance your product page, making your game or app more attractive to end-users (and more likely to be considered for featuring by our editorial team).</p><p>There’s nothing optional about the size, either; it has to be 1024 x 500 pixels.</p><h3>Do’s and Dont’s</h3><p>Your graphic is not an ad, it’s a teaser.  It’s a place for bold, creative promotional images.</p><p>Vivid background colors work best.  Black and white are problems because those are the backgrounds used by the mobile-device and Web versions of Android Market.</p><p>Limit Text to your app name and maybe a few additional descriptive words. Anything else will be unreadable on phones, anyhow.</p><table frame="void" rules="none"  style="div.nbp {margin: 0px 40px 0 40px;}  table {text-align: center;}"><tr valign="top" align="left"><td><img src="http://1.bp.blogspot.com/-z3zf4G4XASw/ToojUEM07TI/AAAAAAAAAr8/uxwgC51i08w/s1600/unicorn_good_small.jpg"/></td><td><img src="http://4.bp.blogspot.com/-fdWjRen-4Ms/ToojgJanoxI/AAAAAAAAAsE/bzHaOdzXj10/s400/unicorn_bad_small.jpg"/></td></tr><tr valign="bottom" align="left"><td><div class="nbp"><b>Do:</b> Make the graphic fun<br/>and enticing.</div></td><td><div class="nbp"><b>Don't:</b> Create a text-heavy<br/> advertising-style graphic.</div></td></tr><tr valign="bottom" align="left"><td><div class="nbp"><b>Do:</b> Use colors that stand out on<br/>black or white backgrounds.</div></td><td><div class="nbp"><b>Don't:</b> Let the graphic fade into<br/>the background.</div></td></tr><tr valign="bottom" align="left"><td><div class="nbp"><b>Do:</b> Promote your brand prominently.</div></td><td><div class="nbp"><b>Don't:</b> Overload the graphic with details.</div></td></tr></table><h3>Scaling</h3><p>Your image has to be designed to scale; it will need to look good both in a full-size Web browser and on a little handset.  You can rely on the aspect ratio being constant, but not the size. Here’s a tip: Try resizing your image down to 1 inch in width. If it still looks good and conveys your brand message, you have a winner.  </p><p>On the Web:</p><img src="http://3.bp.blogspot.com/-mW6qBQ8Bszs/ToyX1nZOjOI/AAAAAAAAAsM/P0HJ3moNgWU/s1600/unicorn_good_large.jpg" border="0" id="BLOGGER_PHOTO_ID_5660065779061525730" /><p><br/>On a tablet:</p><img  src="http://4.bp.blogspot.com/-e29k-os_U0Q/ToyYBd-QMRI/AAAAAAAAAsU/IH7ztHjBm2E/s400/unicorn_good_medium.jpg" border="0" id="BLOGGER_PHOTO_ID_5660065982690898194" />
<p><br/>On a big phone:</p><img  src="http://2.bp.blogspot.com/-gjBc_e77uDc/ToyYLp0FzYI/AAAAAAAAAsc/d26iOEY80HM/s400/unicorn_good_small.jpg" border="0" id="BLOGGER_PHOTO_ID_5660066157668191618" />
<p><br/>On a small phone:</p><img src="http://1.bp.blogspot.com/-tLNR7MzNdEc/ToyYS1d3l1I/AAAAAAAAAsk/MUoJ6v5VPWQ/s400/unicorn_good_extrasmall.jpg" border="0" id="BLOGGER_PHOTO_ID_5660066281055295314" /><h3>More Dont’s</h3><ul><li><p>Device imagery is tempting, but becomes dated fast, and may be inappropriate if your user’s device looks entirely different.</p></li>  <li><p>In-app screenshots are inappropriate because your product page already includes a place for these.  </p></li><li><p>Just using your app icon is a failure of imagination.  You have more room; put it to good use!</p></li></ul><h3>Consider the Context</h3><p>Given the size of the form factor, the phone is the most challenging channel for your image.  Below we have both the “good” and “bad” sample images in that context:</p><a href="http://2.bp.blogspot.com/-a5pXADMla6w/ToyoF-681iI/AAAAAAAAAtM/YpLR3wrik94/s1600/Market_home_home_mock2.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://2.bp.blogspot.com/-a5pXADMla6w/ToyoF-681iI/AAAAAAAAAtM/YpLR3wrik94/s400/Market_home_home_mock2.jpg" border="0" id="BLOGGER_PHOTO_ID_5660083652440938018" /></a><h3>Don’t Forget</h3><p>A 1024 x 500 Featured Image is <em>required</em> for feature placement consideration. Don't miss out on the opportunity!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-687446965502713273?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-market-featured-image-guidelines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android’s HTTP Clients</title>
		<link>https://googledata.org/google-android/android%e2%80%99s-http-clients/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android%25e2%2580%2599s-http-clients</link>
		<comments>https://googledata.org/google-android/android%e2%80%99s-http-clients/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 16:17:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=e298d7c344e5f005ea8e48df67d9ffa5</guid>
		<description><![CDATA[[This post is by Jesse Wilson from the Dalvik team. —Tim Bray]Most network-connected Android apps will use HTTP to send and receive data. Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. Both support HTTPS, streaming uploa...]]></description>
				<content:encoded><![CDATA[<a href="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s1600/jessehawaii.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 199px;" src="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s200/jessehawaii.jpg" border="0" alt="Jesse Wilson" id="BLOGGER_PHOTO_ID_5657543353414584562" /></a><p><i>[This post is by <a href="http://www.publicobject.com/">Jesse Wilson</a> from the Dalvik team. —Tim Bray]</i></p><p>Most network-connected Android apps will use HTTP to send and receive data. Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. Both support HTTPS, streaming uploads and downloads, configurable timeouts, IPv6 and connection pooling.</p><h3>Apache HTTP Client</h3><p><a href="http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html%20">DefaultHttpClient</a> and its sibling <a href="http://developer.android.com/reference/android/net/http/AndroidHttpClient.html">AndroidHttpClient</a> are extensible HTTP clients suitable for web browsers. They have large and flexible APIs. Their implementation is stable and they have few bugs. </p><p>But the large size of this API makes it difficult for us to improve it without breaking compatibility. The Android team is not actively working on Apache HTTP Client.</p><h3>HttpURLConnection</h3><p><a href="http://developer.android.com/reference/java/net/HttpURLConnection.html">HttpURLConnection</a> is a general-purpose, lightweight HTTP client suitable for most applications. This class has humble beginnings, but its focused API has made it easy for us to improve steadily.</p><p>Prior to Froyo, HttpURLConnection had some frustrating bugs. In particular, calling <code>close()</code> on a readable InputStream could <a href="http://code.google.com/p/android/issues/detail?id=2939">poison the connection pool</a>. Work around this by disabling connection pooling:</p><pre><code>private void disableConnectionReuseIfNecessary() {
    // HTTP connection reuse which was buggy pre-froyo
    if (Integer.parseInt(Build.VERSION.SDK) &lt; Build.VERSION_CODES.FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}</code></pre><p>In Gingerbread, we added transparent response compression. HttpURLConnection will automatically add this header to outgoing requests, and handle the corresponding response:</p><p><code>Accept-Encoding: gzip</code></p><p>Take advantage of this by configuring your Web server to compress responses for clients that can support it. If response compression is problematic, the <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html">class documentation</a> shows how to disable it.</p><p>Since HTTP’s <code>Content-Length</code> header returns the compressed size, it is an error to use <a href="http://developer.android.com/reference/java/net/URLConnection.html#getContentLength()%20">getContentLength()</a> to size buffers for the uncompressed data. Instead, read bytes from the response until <a href="http://developer.android.com/reference/java/io/InputStream.html#read(byte%5B%5D)">InputStream.read()</a> returns -1.</p><p>We also made several improvements to HTTPS in Gingerbread. <a href="http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html">HttpsURLConnection</a> attempts to connect with <a href="http://en.wikipedia.org/wiki/Server_Name_Indication">Server Name Indication</a> (SNI) which allows multiple HTTPS hosts to share an IP address. It also enables compression and session tickets. Should the connection fail, it is automatically retried without these features. This makes HttpsURLConnection efficient when connecting to up-to-date servers, without breaking compatibility with older ones.</p><p>In Ice Cream Sandwich, we are adding a response cache. With the cache installed, HTTP requests will be satisfied in one of three ways:</p><ul><li><p>Fully cached responses are served directly from local storage. Because no network connection needs to be made such responses are available immediately. </p></li><li><p>Conditionally cached responses must have their freshness validated by the webserver. The client sends a request like “Give me /foo.png if it changed since yesterday” and the server replies with either the updated content or a <code>304&nbsp;Not&nbsp;Modified</code> status. If the content is unchanged it will not be downloaded!</p></li><li><p>Uncached responses are served from the web. These responses will get stored in the response cache for later.</p></li></ul><p>Use reflection to enable HTTP response caching on devices that support it. This sample code will turn on the response cache on Ice Cream Sandwich without affecting earlier releases:</p><pre><code>private void enableHttpResponseCache() {
    try {
        long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
        File httpCacheDir = new File(getCacheDir(), "http");
        Class.forName("android.net.http.HttpResponseCache")
            .getMethod("install", File.class, long.class)
            .invoke(null, httpCacheDir, httpCacheSize);
    } catch (Exception httpResponseCacheNotAvailable) {
    }
}</code></pre><p>You should also configure your Web server to set cache headers on its HTTP responses.</p><h3>Which client is best?</h3><p>Apache HTTP client has fewer bugs on Eclair and Froyo. It is the best choice for these releases.</p><p>For Gingerbread and better, HttpURLConnection is the best choice. Its simple API and small size makes it great fit for Android. Transparent compression and response caching reduce network use, improve speed and save battery. New applications should use <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html">HttpURLConnection</a>; it is where we will be spending our energy going forward.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2415412611315413372?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android%e2%80%99s-http-clients/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Euro Android Developer Labs</title>
		<link>https://googledata.org/google-android/euro-android-developer-labs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=euro-android-developer-labs</link>
		<comments>https://googledata.org/google-android/euro-android-developer-labs/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 16:26:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=ef2d732a4aa70adf1e2942ffe66c7148</guid>
		<description><![CDATA[This series started last month, and now registration is open for the European leg:Berlin&#160;&#8212;&#160;September 28 and 29.London&#160;&#8212;&#160;October 3 and 5.Paris&#160;&#8212;&#160;October 27 and 28.Remember, this ADL series isn’t another ...]]></description>
				<content:encoded><![CDATA[<p>This series <a href="http://android-developers.blogspot.com/2011/08/android-developer-labs-2011.html">started last month</a>, and now <a href="https://sites.google.com/site/androiddevlabs2011/index">registration is open</a> for the European leg:</p><ul><li><p>Berlin&nbsp;&mdash;&nbsp;September 28 and 29.</p></li><li><p>London&nbsp;&mdash;&nbsp;October 3 and 5.</p></li><li><p>Paris&nbsp;&mdash;&nbsp;October 27 and 28.</p></li></ul><p>Remember, this ADL series isn’t another set of introduction-to-Android sessions, nor any other kind of general overview. It's specifically aimed at optimizing Android apps for tablets, in particular creating high-quality tablet apps with an emphasis on polish and user-experience.</p><p>Registration is a two-step process. Anyone can register, but we can only accommodate a relatively small number of attendees from among the registrants, based on whether they already have an Android app with the potential to be a top-tier tablet app in terms of quality, fit, and finish. The goal is to bring your app to the ADL, and leave equipped to make it into one that makes Android tablet users smile.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1934213262974721775?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/euro-android-developer-labs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preparing for Handsets</title>
		<link>https://googledata.org/google-android/preparing-for-handsets/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=preparing-for-handsets</link>
		<comments>https://googledata.org/google-android/preparing-for-handsets/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 16:26:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=1103f1f0803fb71821f97d4152e54d6b</guid>
		<description><![CDATA[[This post is by Scott Main, lead tech writer for developer.android.com.&#160;&#8212;&#160;Tim&#160;Bray]Early this year, Honeycomb (Android 3.0) launched for tablets. Although Honeycomb remains tablets-only, the upcoming Ice Cream Sandwich (ICS) relea...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-ICF_-w7Of4o/Thsttq7Hr9I/AAAAAAAAAh8/UECE2TIepTs/s1600/scott.png"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 185px; height: 228px;" src="http://3.bp.blogspot.com/-ICF_-w7Of4o/Thsttq7Hr9I/AAAAAAAAAh8/UECE2TIepTs/s400/scott.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5628142421969186770" /></a><p><i>[This post is by Scott Main, lead tech writer for <a href="http://developer.android.com">developer.android.com</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Early this year, Honeycomb (Android 3.0) launched for tablets. Although Honeycomb remains tablets-only, the upcoming Ice Cream Sandwich (ICS) release will support big screens, small screens, and everything in between. This is the way Android will stay from now on: the same version runs on all screen sizes.</p><p>Some Honeycomb apps assume that they’ll run only on a large screen, and have baked that into their designs. This assumption is currently true, but will become false with the arrival of ICS, because Android apps are forward-compatible&nbsp;&mdash;&nbsp;an app developed for Honeycomb is compatible with a device running ICS, which could be a tablet, a phone, or something else.</p><p>So, if you’ve developed a tablet app on Honeycomb, it’s important that your app do one of two things: prevent installation on smaller screens or (preferably) support smaller screens with the same APK.</p><h3>Making your Honeycomb app for tablets only</h3><p>If you don’t want your app to be used on handsets (perhaps it truly makes sense only on a large screen) or you need more time to update it, add the following <a href="http://developer.android.com/guide/topics/manifest/supports-screens-element.html"><code>&lt;supports-screens></code></a> declaration to your manifest:</p><pre><code>&lt;manifest ... >
    &lt;supports-screens android:smallScreens="false"
                      android:normalScreens="false"
                      android:largeScreens="false"
                      android:xlargeScreens="true"
                      android:requiresSmallestWidthDp="600" />
    &lt;application ... >
        ...
    &lt;/application>
&lt;/manifest></code></pre><p>This describes your app’s screen-size support in two different ways:</p><ul><li><p>It declares that the app does not support the screen size buckets “small”, “normal”, and “large”, which are traditionally not tablets</p></li><li><p>It declares that the app requires a screen size with a minimum usable area that is at least 600dp wide</p></li></ul><p>The first technique is for devices that are running Android 3.1 or older, because those devices declare their size based on generalized screen size buckets. The <a href="http://developer.android.com/guide/topics/manifest/supports-screens-element.html#requiresSmallest">requiresSmallestWidthDp</a> attribute is for devices running Android 3.2 and newer, which added the capability for apps to  specify their size requirements based on a minimum number of density-independent pixels.  In this example, the app declares a minimum width requirement of 600dp, which generally implies a 7”-or-greater screen. </p><p>Your size choice might be different, of course, based on how well your design works on different screen sizes; for example, if your design works well only on screens that are 9” or larger, you might require a minimum width of 720dp.</p><p>The catch is that you must compile your application against Android 3.2 or higher in order to use the <code>requiresSmallestWidthDp</code> attribute. Older versions don’t understand this attribute and will raise a compile-time error. The safest thing to do is develop your app against the platform that matches the API level you’ve set for <a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#min">minSdkVersion</a>. When you’re making final preparations to build your release candidate, change the build target to Android 3.2 and add the <code>requiresSmallestWidthDp</code> attribute. Android versions older than 3.2 simply ignore that XML attribute, so there’s no risk of a runtime failure.</p><p>For more information about why the “smallest width” screen size is important for supporting different screen sizes, read <a href="http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html">New Tools for Managing Screen Sizes</a> (really; it’s got lots of things you need to know).</p><h3>Making your Honeycomb app work on handsets</h3><p>On the other hand, if you want to distribute your app to devices of all sizes, we recommend that you update your existing Honeycomb app to work on smaller screens as well, rather than publishing multiple APKs. </p><p>Optimizing for handsets can be tricky if your designs currently use all of a large screen to deliver  content. It’s worth the effort, though, because Ice Cream Sandwich brings the Honeycomb APIs to handsets and you’ll significantly increase the user-base for your app. Using a single APK for all devices also simplifies your updating and publishing process and makes it easier for users to identify your app.</p><p>Here are two guidelines to help make your Honeycomb tablet app work well on handsets:</p><ul><li><p>Build your design around Fragments that you can reuse in different combinations, in single-pane layouts on handsets and multi-pane layouts on tablets</p></li><li><p>Be conservative with your Action Bar design so the system can adjust its layout based on the screen size</p></li></ul><h4>Creating single-pane and multi-pane layouts</h4><p>The most effective way to optimize your app for both handsets and tablets is to combine fragments in different ways to create “single-pane” layouts for handsets and “multi-pane” layouts for tablets. There are two approaches to doing this:</p><ul><li><p>For any screen in which your tablet version displays multiple fragments, use the same activity for handsets, but show only one fragment at a time&nbsp;&mdash;&nbsp;swapping the fragments within the activity when necessary. </p></li><li><p>Use separate activities to host each fragment on a handset. For example, when the tablet UI uses two fragments in an activity, use the same activity for handsets, but supply an alternative layout that includes just one fragment. When you need to switch fragments (such as when the user selects an item), start another activity that hosts the other fragment.</p></li></ul><p>The approach you choose depends on your app design and personal preferences. The first option (single activity) requires that you dynamically add each fragment to the activity at runtime---rather than declare the fragments in your activity’s layout file&nbsp;&mdash;&nbsp;because you cannot remove a fragment from an activity if it’s been declared in the XML layout. You might also need to update the action bar each time the fragments change, depending on what actions or navigation modes are provided for the fragment. In some cases, these factors might not matter to your app, so using one activity and swapping fragments will work well. Other times, however, using just one activity and dynamically swapping fragments can make your code more complicated, because you must manage all the fragment combinations in the activity’s code rather than leveraging alternative layout files.</p><p>I’m going to talk about the second option in more detail. It might be a little more up-front work, because each fragment must work well across separate activities, but it usually pays off. It means that you can use alternative layout files that define different fragment combinations, keep fragment code modular, simplify action bar management, and let the system handle all the back stack work.</p><p>The following figure demonstrates how an application with two fragments can be arranged for both handsets and tablets when using separate activities for the handset design:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-5tx-S4aRB70/Tnd2n4Ih4gI/AAAAAAAAArU/kqujPLvcgUk/s1600/fragments.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 228px;" src="http://2.bp.blogspot.com/-5tx-S4aRB70/Tnd2n4Ih4gI/AAAAAAAAArU/kqujPLvcgUk/s400/fragments.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5654118284642083330" /></a><p>In this app, Activity A is the “main activity” and uses different layouts to display either one or two fragments at a time, depending on the size of the screen. When on a handset-sized screen, the layout contains only Fragment A (the list view); when on a tablet-sized screen, the layout contains both Fragment A and Fragment B. </p><p>Here’s <code>res/layout/main.xml</code> for handsets:</p><pre><code>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    &lt;fragment class="<b>com.example.android.TitlesFragment</b>"
              android:id="@+id/list_frag"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>
&lt;/FrameLayout></code></pre><p>And <code>res/layout-large/main.xml</code> for tablets:</p><pre><code>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/frags">
  &lt;fragment class="<b>com.example.android.TitlesFragment</b>"
            android:id="@+id/list_frag"
            android:layout_width="@dimen/titles_size"
            android:layout_height="match_parent"/>
  &lt;fragment class="<b>com.example.android.DetailsFragment</b>"
            android:id="@+id/details_frag"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
&lt;/LinearLayout></code></pre><p>How the application responds when a user selects an item from the list depends on whether Fragment B is available in the layout. If Fragment B is there,  Activity A notifies Fragment B to update itself. If Fragment B is not in the layout, Activity A starts Activity B (which hosts Fragment B).</p><p>To implement this pattern for your application, it's important that you develop your fragments to be highly compartmentalized. Specifically, you should follow two general guidelines:</p><ul><li><p>Do not manipulate one fragment directly from another.</p></li><li><p>Keep all code that concerns content in a fragment inside that fragment, rather than putting it in the host activity’s code.</p></li></ul><p>To avoid directly calling one fragment from another, declare a callback interface in each fragment class that it can use to deliver events to its host activity, which implements the callback interface. When the activity receives a callback due to an event (such as the user selecting a list item), it acts appropriately based on the current fragment configuration.</p><p>For example, Activity A from above handles item selections like this:</p><pre><code>/** This is a callback that the list fragment (Fragment A) calls
    when a list item is selected */
public void onItemSelected(int position) {
  DisplayFragment fragB = (DisplayFragment) getFragmentManager()
                              .findFragmentById(R.id.display_frag);
  if (fragB == null) {
      // DisplayFragment (Fragment B) is not in the layout, 
      // start DisplayActivity (Activity B)
      // and pass it the info about the selected item
      Intent intent = new Intent(this, DisplayActivity.class);
      intent.putExtra("position", position);
      startActivity(intent);
  } else {
      // DisplayFragment (Fragment B) is in the layout, tell it to update
      fragB.updateContent(position);
  }
}</code></pre><p>When <code>DisplayActivity</code> (Activity B) starts, it reads the data delivered by the Intent and passes it to the <code>DisplayFragment</code> (Fragment B).</p><p>If Fragment B needs to deliver a result back to Fragment A, then the process works similarly with a callback interface between Fragment B and Activity B. That is, Activity B implements a callback interface defined by Fragment B. When Activity B gets the callback, it sets the result for the activity and finishes itself. Activity A then receives the result and delivers it to Fragment A.</p><p>For a complete demonstration of this technique for creating different fragment combinations for different tablets and handsets, look at the code for this updated version of the <a href="http://developer.android.com/resources/samples/HoneycombGallery/index.html">Honeycomb Gallery sample</a>.</p><h3>Making the Action Bar work on handsets</h3><p>As long as you’ve been using the framework’s implementation of <a href="http://developer.android.com/reference/android/app/ActionBar.html">ActionBar</a> for your tablet app (rather than building your own), the conversion from tablets to handsets should be painless. The Android system will do the work for you; all you need to do is ensure that your action bar design is flexible. Here are some important tips:</p><ul><li><p>When setting a menu item to be an action item, <em>avoid using the “always” value</em>. Use “ifRoom” for action items you’d like to add to the action bar. Now, you might need “always” when an action view does not have an alternative action for the overflow menu or when a menu item added by a fragment is low in the menu order and it must jump into the action bar at all times. But you should not use “always” more than once or twice.</p></li><li><p>When possible, <em>provide icons for all action items</em> and declare <code>showAsAction="ifRoom|withText"</code>. This way, if there’s not enough room for the text, but there is enough for the icon, then just the icon may be used.</p></li><li><p><em>Avoid using custom navigation modes in the action bar</em>. Use the built-in tab and drop-down navigation modes&nbsp;&mdash;&nbsp;they’re designed to be flexible and adapt to different screen sizes. For example, when the width is too narrow for both tabs and other action items, the tabs appear below the action bar. If your app requires a custom navigation mode in the action bar, thoroughly test it on smaller screens when Ice Cream Sandwich becomes available and make any adjustments necessary for a narrow action bar.</p></li></ul><p>For example, the mock ups below demonstrates how the system might adapt an app’s action bar based on the available screen space. On the handset, only two action items fit, so the remaining menu items appear in the traditional menu and the tabs appear in a separate row. On the tablet, more action items can fit in the action bar and so do the tabs.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-OxiegwhkSI8/Tnd20i8UFgI/AAAAAAAAArc/ZKeG4WPeeMA/s1600/actionbar-phone-tablet.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 205px;" src="http://4.bp.blogspot.com/-OxiegwhkSI8/Tnd20i8UFgI/AAAAAAAAArc/ZKeG4WPeeMA/s400/actionbar-phone-tablet.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5654118502292002306" /></a><h3>Some other tips</h3><ul><li><p>When working with a <a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a>, consider how you might provide more or less information in each list item based on the available space. That is, you can create alternative layouts to be used by the items in your list adapter such that a large screen might display more detail for each item.</p></li><li><p>Create <a href="http://developer.android.com/guide/topics/resources/more-resources.html%20">alternative resource files</a> for values such as integers, dimensions, and even booleans. Using size qualifiers for these resources, you can easily apply different layout sizes, font sizes, or enable/disable features based on the current screen size.</p></li></ul><h3>Testing your handset support</h3><p>At this point you might be wondering, “How do I test my layout for smaller screens without a handset that runs Honeycomb?” Well, until Ice Cream Sandwich is available for the SDK, you technically can’t. So don’t publish your changes until you’re able to test on a device or emulator running ICS. </p><p>However, you can begin some early testing of your alternative layouts with a little trick: instead of using the “large” configuration qualifier for the tablet layouts, use the “land” qualifier (that is, instead of <code>res/layout-large/main.xml</code>, use <code>res/layout-land/main.xml</code>). This way, a Honeycomb tablet (or emulator) in landscape orientation uses your tablet design and the same device in portrait orientation uses your handset design. Just be certain to switch back to using the size qualifiers once you’re able to test on ICS.</p><h3>Conclusion</h3><p>Ice Cream Sandwich is coming, and with it, handsets will be able to install apps built on Honeycomb. We haven’t released the ICS SDK just yet, but you can start preparing your Honeycomb apps by thinking about how they should work on smaller screens.</p><p>So if you have a Honeycomb tablet app out there (and by that, I mean an app with <code>minSdkVersion="11"</code> or higher), you should make sure it’s available only on large screen devices for now. We hope that you’ll then follow our advice here and optimize your tablet app to support smaller screens, using the same APK for both tablets and handsets.</p><p>If your app supports API levels lower than 11, then there’s probably nothing you need to do right now, because your app is already running on handset devices. When the ICS SDK does arrive, though, it’ll still be important that you verify your app’s performance on the new platform. </p><p>Stay tuned to the blog for more information about ICS as it nears release.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2402592046885452873?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/preparing-for-handsets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Thinking Like a Web Designer</title>
		<link>https://googledata.org/google-android/thinking-like-a-web-designer/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=thinking-like-a-web-designer</link>
		<comments>https://googledata.org/google-android/thinking-like-a-web-designer/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 16:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=13f4e2fd4847a3a6e578a8573da3aef4</guid>
		<description><![CDATA[[This post is by Roman Nurik, who is passionate about icons, with input from me and a bunch of the Framework engineers. —Tim Bray]The number of people working on mobile apps, and specifically Android, is growing fast. Since modern mobile software-dev...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GTM_W5mVPTU/TMB-JMl-xsI/AAAAAAAAANM/kWr3jmU5aO0/s1600/Roman.jpg"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 305px;" src="http://1.bp.blogspot.com/_GTM_W5mVPTU/TMB-JMl-xsI/AAAAAAAAANM/kWr3jmU5aO0/s320/Roman.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5530559038875420354" /></a><p><i>[This post is by <a href="http://twitter.com/romannurik">Roman Nurik</a>, who is passionate about icons, with input from me and a bunch of the Framework engineers. —Tim Bray]</i></p><p>The number of people working on mobile apps, and specifically Android, is growing fast. Since modern mobile software-development is a relatively new profession, the community is growing by sucking in experts from related domains, one being web design and development.</p><p>It turns out that familiarity with web UI development, particularly using modern HTML5 techniques, can be a great primer for Android UI development. The Android framework and SDK have many analogues to tools and techniques in the Web repertoire of HTML, CSS, and JavaScript.</p><p>In this blog post, we’ll walk through a few web development features and look for matches in the world of Android UI development.</p><h3>Device resolutions and physical sizes</h3><p>One of the most important aspects of both Android UI design and web design is support for multiple screen resolutions and physical sizes. Just as your web app needs to work on any physical display and inside any size browser window, your native app needs to run on a variety of form factors, ranging from 2.5” phones to 10” tablets to (possibly) 50” TVs.</p><p>Let’s look at some ways in which CSS and Android allow for flexible and adaptive layouts.</p><h4>Providing custom layouts for different resolutions</h4><p><a href="http://www.w3.org/TR/css3-mediaqueries/">CSS3 media queries</a> allow developers to include additional stylesheets to target different viewport and screen configurations. For example, developers can provide additional style rules or override existing styles for mobile devices. Although the markup (layout hierarchy) remains the same, CSS3 has several sophisticated techniques for completely transforming the placement of elements with different stylesheets.</p><p>Android has long offered a similar mechanism in resource directory qualifiers. This extends to many different types of resources (layouts, images or ‘drawables’, styles, dimensions, etc). Thus you can customize the view hierarchy as well as styling depending on device form factor, A base set of layouts for handsets can be extended for tablets by placing additional layouts in <code>res/layout-xlarge</code> or <code>res/layout-sw600dp</code> (smallest width 600 density-independent pixels) directories. Note that the <a href="http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html">latter syntax</a> requires Android 3.2 or later.</p><p>Below is a CSS3 example of how one could hide a ‘left pane’ on smaller devices and show it on screens at least 600 pixels wide:</p><pre><code>#leftPane {
  display: none;
}

@media screen and (min-device-width:600px) {
  #leftPane {
    display: block;
  }
}</code></pre><p>The same could be accomplished on Android using multiple layout directories:</p><p><i>res/layout/foo.xml</i>:</p><pre><code>&lt;FrameLayout>
  &lt;!-- a single pane -->
  &lt;View android:id="main_pane">
&lt;/FrameLayout></code></pre><p><i>res/layout-sw600dp/foo.xml</i>:</p><pre><code>&lt;LinearLayout android:orientation="horizontal">
  &lt;!-- two panes -->
  &lt;View android:id="left_pane">
  &lt;View android:id="main_pane">
&lt;/LinearLayout></code></pre><p>As a side note, if you plan on creating multi-pane layouts, consider using <a href="http://developer.android.com/guide/topics/fundamentals/fragments.html">fragments</a>, which help break up your screens into modular chunks of both layout and code.</p><p>There are also other neat ways of using resource directory qualifiers. For example, you could create <code>values/dimens.xml</code> and <code>values-sw600dp/dimens.xml</code> files specifying different font sizes for body text, and reference those values in your layouts by setting <code>android:textSize="@dimen/my_body_text_size"</code>. The same could be done for margins, line spacing, or other dimensions to help manage whitespace on larger devices.</p><h4>‘Holy grail’ layouts</h4><p>Web developers have long dreamt of an easy way to build a <a href="http://www.alistapart.com/articles/holygrail/">‘holy grail’</a> 5-pane layout (header/footer + 3 vertical columns). There are a variety of pre-CSS3 tricks including <code>position:fixed</code>, <code>float:left</code>, negative margins, and so on, to build such layouts but CSS3 introduced the <a href="http://www.w3.org/TR/css3-flexbox/">flexible box</a> module, which simplifies this tremendously.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-dPXRqF4HobE/Tm9-a269N4I/AAAAAAAAAqM/lm8autOD2FU/s1600/webhead-HolyGrail.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 327px;" src="http://2.bp.blogspot.com/-dPXRqF4HobE/Tm9-a269N4I/AAAAAAAAAqM/lm8autOD2FU/s400/webhead-HolyGrail.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5651875057257756546" /></a><p style="text-align:center">Figure: An archetypal “holy grail” layout</p><p>It turns out that grail is pretty holy for Android tablet apps, too, and in particular for tablets held sideways in landscape mode.  A good approach involves the use of LinearLayout, one of the simplest and most popular of the Android layouts.</p><p>LinearLayout has this neat way to stretch its children to fit the remaining space, or to distribute available space to certain children, using the <code>android:layout_weight</code> attribute. If a LinearLayout has two children with a fixed size, and another child with a nonzero <code>layout_weight</code>, that other child view will stretch to fill the remaining available space. For more on layout_weight and other ways to make layouts more efficient (like switching from nested LinearLayouts to RelativeLayout), check out <a href="http://developer.android.com/resources/articles/layout-tricks-efficiency.html">Layout Tricks: Creating Efficient Layouts</a>.</p><p>Let’s take a look at some example code for implementing such a ‘holy grail’ layout on Android and on the web:</p><pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    &lt;!-- top pane -->
    &lt;View android:id="@+id/top_pane"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

    &lt;LinearLayout android:id="@+id/middle_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        &lt;!-- left pane -->
        &lt;View id="@+id/left_pane"
            android:layout_width="300dp"
            android:layout_height="match_parent" />

        &lt;!-- center pane -->
        &lt;View id="@+id/center_pane"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        &lt;!-- right pane -->
        &lt;View id="@+id/right_pane"
            android:layout_width="300dp"
            android:layout_height="match_parent" />

    &lt;/LinearLayout>

    &lt;!-- bottom pane -->
    &lt;View android:id="@+id/bottom_pane"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

&lt;/LinearLayout></code></pre><p><b>Note:</b> Android tablet apps in landscape will generally show an <a href="http://developer.android.com/guide/topics/ui/actionbar.html">action bar</a> as the top pane and will usually have neither a right nor bottom pane. Also note that the action bar layout is automatically provided by the framework as of Android 3.0, and thus you don’t need to worry about positioning it.</p><p>And here’s an example implementation using the CSS3 flexible box model; notice the similarities:</p><pre><code>&lt;style>
  html, body { margin: 0; height: 100%; }

  #container {
    height: 100%;
    display: -webkit-box; /* like LinearLayout */
    display:    -moz-box;
    -webkit-box-orient: vertical; /* like android:orientation */
       -moz-box-orient: vertical;
  }

  #top, #bottom { height: 50px; }

  #middle {
    -webkit-box-flex: 1; /* like android:layout_weight */
       -moz-box-flex: 1;
    display: -webkit-box;
    -webkit-box-orient: horizontal;
       -moz-box-orient: horizontal;
  }

  #left, #right { width: 300px; }

  #center {
    -webkit-box-flex: 1;
       -moz-box-flex: 1;
  }
&lt;/style>

&lt;div id="container">
  &lt;div id="top">&lt;/div>
  &lt;div id="middle">
    &lt;div id="left">&lt;/div>
    &lt;div id="center">&lt;/div>
    &lt;div id="right">&lt;/div>
  &lt;/div>
  &lt;div id="bottom">&lt;/div>
&lt;/div></code></pre><h4>Layered content</h4><p>In CSS, with <code>position:absolute</code>, you can overlay your UI elements. On Android, you can use FrameLayout to achieve this. The child views in a frame layout are laid out on top of each other, with optional <code>layout_gravity</code> attributes indicating alignment with the parent frame layout.</p><p>Below is a contrived example of a FrameLayout with three children.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-swOQH-PxIuo/Tm9-rnioTfI/AAAAAAAAAqU/1aqDlSyjkQw/s1600/webhead-Frame1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 322px;" src="http://4.bp.blogspot.com/-swOQH-PxIuo/Tm9-rnioTfI/AAAAAAAAAqU/1aqDlSyjkQw/s400/webhead-Frame1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5651875345186967026" /></a><p style="text-align:center">Figure: Example FrameLayout with three children (2 with top-left and 1 bottom-right alignment)</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-rhw8-whtMKY/Tm9-9OM3ayI/AAAAAAAAAqc/8Efa6J7zs7Q/s1600/webhead-Frame2.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 210px;" src="http://1.bp.blogspot.com/-rhw8-whtMKY/Tm9-9OM3ayI/AAAAAAAAAqc/8Efa6J7zs7Q/s400/webhead-Frame2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5651875647622441762" /></a><p style="text-align:center">Figure: Isometric view of the example FrameLayout and its children.</p><p>The code for this example is as follows:</p><pre><code>&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="200dp">

    &lt;!-- bottom-most child, with bottom-right alignment -->
    &lt;View android:layout_gravity="bottom|right"
        android:layout_width="100dp"
        android:layout_height="150dp" />

    &lt;!-- middle child, with top-left alignment -->
    &lt;View android:layout_gravity="top|left"
        android:layout_width="200dp"
        android:layout_height="175dp" />

    &lt;!-- top-most child, with top-left alignment →
    &lt;!-- also stretched to fill vertically -->
    &lt;View android:layout_gravity="top|left"
        android:layout_width="100dp"
        android:layout_height="match_parent" />

&lt;/FrameLayout></code></pre><h4>Scrollable content</h4><p>HTML, by default, flows in reading order and scrolls vertically.   When content extends beyond the bottom of the browser, scrollbars automatically appear. Content panes can also be made individually scrollable using overflow:scroll or overflow:auto. </p><p>Android screen content isn’t scrollable by default.  However, many content Views such as ListView and EditText offer scrolling, and any layout can be made scrollable by wrapping it in a ScrollView or HorizontalScrollView.</p><p>It’s also possible to add custom scrolling to views by using methods like <a href="http://developer.android.com/reference/android/view/View.html#scrollTo(int,%20int)">View.scrollTo</a> and helpers like <a href="http://developer.android.com/reference/android/widget/Scroller.html">Scroller</a> in response to touch events. And for horizontal, snap-to-page-bounds scrolling, one can use the excellent <a href="http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html">new ViewPager class</a> in the support library.</p><p>Below is an example of a ScrollView containing a single TextView child and the code needed to implement something like this.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-OHAF5PuAScQ/Tm9_HyGl97I/AAAAAAAAAqk/IDWo6QXjg6A/s1600/webhead-Scroll.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 395px;" src="http://2.bp.blogspot.com/-OHAF5PuAScQ/Tm9_HyGl97I/AAAAAAAAAqk/IDWo6QXjg6A/s400/webhead-Scroll.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5651875829058500530" /></a><p style="text-align:center">Figure: A TextView inside a ScrollView, scrolled about half way.</p><pre><code>
&lt;ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    &lt;!-- the scrollable content -->
    &lt;TextView android:layout_gravity="bottom|right"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="32dp"
        android:textSize="48sp"
        android:text="The\nquick\nbrown\nfox\njumps\nover..." />

&lt;/ScrollView></code></pre><h4>Custom layouts</h4><p>Sometimes the positioning and layout behaviors you can achieve with CSS aren’t enough to achieve your desired layout. In those cases, developers fall back on JavaScript coupled with absolute positioning to place and size elements as needed.</p><p>Programmatically defined layouts are also possible on Android. In fact, they’re sometimes the most elegant and/or performant way of implementing a unique or otherwise tricky layout. Not happy with nesting LinearLayouts for implementing a 2x3 grid of navigation icons? Just extend ViewGroup and implement your own layout logic! (see an example DashboardLayout <a href="http://code.google.com/p/iosched/source/browse/android/src/com/google/android/apps/iosched/ui/widget/DashboardLayout.java">here</a>). All the built-in layouts such as LinearLayout, FrameLayout, and RelativeLayout are implemented this way, so there generally aren’t the same performance implications with custom layouts as there are with scripted layout on the web.</p><h3>Device densities</h3><p>Web designers have long dealt with the reality that display densities vary, and that there wasn’t much they could do about it. This meant that for a long time web page graphics and UI elements had different physical sizes across different displays. Your 100px wide logo could be 1” wide on a desktop monitor or ¾” on a netbook. This was mostly OK, given that (a) pointing devices such as mice offered generally good precision in interacting with such elements and (b) browsers allowed visually-impaired users to zoom pages arbitrarily.</p><p>However, on touch-enabled mobile devices, designers really need to begin thinking about physical screen size, rather than resolution in pixels. A 100px wide button on a 120dpi (low density) device is ~0.9” wide while on a 320dpi (extra-high density) screen it’s only ~0.3” wide. You need to avoid the fat-finger problem, where a crowded space of small touch targets coupled with an imprecise pointing tool (your finger) leads to accidental touches. The Android framework tries really hard to take your layout and scale elements up or down as necessary to work around device-density differences and get a usable result on a wide range of them.  This includes the browser, which scales a 160px <code>&lt;img></code> at 100% browser zoom up to 240px on a 240dpi screen, such that its physical width is always 1”.</p><p>Developers can achieve finer-grained control over this browser scaling by providing custom stylesheets and images for different densities, using CSS3 media query filters such as <code>-webkit-max-device-pixel-ratio</code> and <code>&lt;meta></code> viewport arguments such as <code>target-densitydpi=device-dpi</code>. For an in-depth discussion on how to tame this mobile browser behavior see this blog post: <a href="http://designbycode.tumblr.com/post/1127120282/pixel-perfect-android-web-ui">Pixel-perfect Android web UIs</a>.</p><p>For native Android apps, developers can use resource directory qualifiers to provide different images per density (such as drawable-hdpi and drawable-mdpi). In addition, Android offers a special dimension unit called ‘density independent pixels’ (dp) which can (and should!) be used in layout definitions to offset the density factors and create UI elements that have consistent physical sizes across screens with different densities. </p><h3>Features you don’t have out of the box</h3><p>There are a few features that web designers and developers rely on that aren’t currently available in the Android UI toolkit.</p><p>Developers can defer to user-driven browser zooming and two-dimensional panning for content that is too small or too large for its viewport, respectively. Android doesn’t currently provide an out-of-the-box mechanism for two-dimensional layout zooming and panning, but with some extra legwork using existing APIs, these interactions are possible. However, zooming and panning an entire UI is not a good experience on mobile, and is generally more appropriate for individual content views such as lists, photos, and maps.</p><p>Additionally, vector graphics (generally implemented with SVG) are gaining in popularity on the Web for a number of reasons: the need for resolution independence, accessibility and ‘indexability’ for text-heavy graphics, tooling for programmatic graphic generation, etc. Although you can’t currently drop an SVG into an Android app and have the framework render it for you, Android’s version of WebKit supports SVG as of Android 3.0. As an alternative, you can use the very robust <a href="http://developer.android.com/reference/android/graphics/Canvas.html">Canvas</a> drawing methods, similar to HTML5’s canvas APIs, to render vector graphics. There are also community projects such as <a href="http://code.google.com/p/svg-android">svg-android</a> that support rendering a subset of the SVG spec.</p><h3>Conclusion</h3><p>Web developers have a number of different tools for frontend layout and styling at their disposal, and there are analogues for almost all of these in the world of Android UI engineering. If you’re wondering about analogues to other web- or CSS-isms, start a conversation out there in the Android community; you&rsquo;ll find you&rsquo;re not alone.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6785431911844538016?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/thinking-like-a-web-designer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Horizontal View Swiping with ViewPager</title>
		<link>https://googledata.org/google-android/horizontal-view-swiping-with-viewpager/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=horizontal-view-swiping-with-viewpager</link>
		<comments>https://googledata.org/google-android/horizontal-view-swiping-with-viewpager/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 18:15:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=bf09192f7c5c64e494aa869f306799c9</guid>
		<description><![CDATA[[This post is by Rich &#8220;geekyouup&#8221; Hyndman, inspired by the fact that life just got that little bit easier&#160;&#8212;&#160;Tim&#160;Bray]Whether you have just started out in Android app development or are a veteran of the craft, it probabl...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-MSpH3X8YbbY/TlPvIhr-RTI/AAAAAAAAAp8/vgTjMrbnB0U/s1600/avatar.jpeg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 120px; height: 120px;" src="http://2.bp.blogspot.com/-MSpH3X8YbbY/TlPvIhr-RTI/AAAAAAAAAp8/vgTjMrbnB0U/s200/avatar.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5644117687786161458" /></a><p><i>[This post is by <a href="http://geekyouup.com/+">Rich &ldquo;geekyouup&rdquo; Hyndman</a>, inspired by the fact that life just got that little bit easier&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Whether you have just started out in Android app development or are a veteran of the craft, it probably won’t be too long before you’ll need to implement horizontally scrolling sets of views. Many existing Android apps already use this UI pattern, such as the new Android Market, Google Docs and Google+. ViewPager standardizes the implementation.</p><p>ViewPager was released as part of the <a href="http://developer.android.com/sdk/compatibility-library.html">Compatibility Package</a> revision 3 and works with Android 1.6 upwards. After following <a href="http://developer.android.com/sdk/compatibility-library.html">the instructions</a> to obtain the package you can right-click on your Android project in Eclipse, choose ‘Android Tools’ and ‘Add Compatibility Library’, making the new classes available.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-T0ubrNZd4ro/TlOx2EZGnXI/AAAAAAAAAp0/p7PQWuJc8Ns/s1600/MarketSwipe.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 214px;" src="http://4.bp.blogspot.com/-T0ubrNZd4ro/TlOx2EZGnXI/AAAAAAAAAp0/p7PQWuJc8Ns/s400/MarketSwipe.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5644050300475448690" /></a><p>ViewPager is a <a href="http://developer.android.com/reference/android/view/ViewGroup.html">ViewGroup</a> and works in a similar manner to AdapterViews (like ListView and Gallery) so it shouldn’t feel too foreign. Note that if you use ViewPager in an xml layout, be sure to use the full class reference, e.g.</p><pre><code> &lt;android.support.v4.view.ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        … /></code></pre><p>ViewPagers source their views from PagerAdapters which give you have full control over the reuse and recycling of the views. A PagerAdapter implementation called FragmentPagerAdapter is provided to facilitate the use of Fragments in a ViewPager; This is immensely powerful and as simple as implementing getCount() and getItem(). There is a sample called <a href="http://developer.android.com/resources/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.html">Fragment Pager Support</a> provided in the <a href="http://developer.android.com/resources/samples/Support4Demos/src/com/example/android/supportv4/app/index.html">Support Demos</a> to illustrate this.</p><pre><code>    public static class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public Fragment getItem(int position) {
            return ArrayListFragment.newInstance(position);
        }
    }</code></pre><p>FragmentPagerAdapter will detach each fragment as you swipe through the list, but keep them in memory so they can simply be reattached when the user swipes back. If you have a larger number of Fragments, the FragmentStatePagerAdapter is worth considering as it will remove them, with the downside being they need to be rebuilt as the user swipes back to them. So, if you have fewer, more complex fragments the FragmentPagerAdapter makes sense, but consider FragmentStatePagerAdapter for larger sets.</p><p>On the more simplistic side I recently wrote a ViewPager/PagerAdapter <a href="http://code.google.com/p/viewpagerexample/">example</a> that serves up simple TextViews. One thing to note is that if you are implementing your own PagerAdapter it is up to you, the developer, to add and remove your views to and from the ViewGroup. To facilitate this the ViewPager is passed into the PagerAdapter methods instantiateItem() and destroyItem().</p><pre><code>    @Override
    public Object instantiateItem(View collection, int position) {
        View v = layoutInflater.inflate(...);
        ...
        ((ViewPager) collection).addView(v,0);
        return tv;
    }

    @Override
    public void destroyItem(View collection, int position, Object view) {
        ((ViewPager) collection).removeView((TextView) view);
    }</code></pre><p>The source code for ViewPager is also included and available in &lt;android-sdk>/extras/android/compatibility/v4/src. It is worth checking as you can generate the reference documentation from it using Javadoc. In the reference docs / source you’ll find other useful methods, for example setOnPageChangeListener(), which enables your application to track which View is currently visible.</p><p>If you are launching an app onto Android Market that uses ViewPager then please ping me <a href="http://geekyouup.com/+">on Google+</a> or <a href="http://twitter.com/geekyouup">Twitter</a>, I’d love to see how widely it is being used and the innovative scenarios in which it appears.</p>
<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7390374903254543557?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/horizontal-view-swiping-with-viewpager/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Preview of Google TV Add-on for the Android SDK</title>
		<link>https://googledata.org/uncategorized/preview-of-google-tv-add-on-for-the-android-sdk/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=preview-of-google-tv-add-on-for-the-android-sdk</link>
		<comments>https://googledata.org/uncategorized/preview-of-google-tv-add-on-for-the-android-sdk/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 21:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=7e3126b640c24c0af78dd8af26b974e5</guid>
		<description><![CDATA[[This post is by Ambarish Kenghe, who’s a Product Manager for Google TV — Tim Bray]At Google I/O, we announced that Android Market is coming to Google TV. Today, we’re announcing a preview of the Google TV Add-on for the Android SDK. With the upc...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Ambarish Kenghe, who’s a Product Manager for Google TV — Tim Bray]</i></p><a href="http://4.bp.blogspot.com/-PHLQLnnUUVk/TlKKcQyyCQI/AAAAAAAAAGY/bOBD8YJOXOo/s1600/ak.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="border: 5px solid #ddd;float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 174px; height: 228px;" src="http://4.bp.blogspot.com/-PHLQLnnUUVk/TlKKcQyyCQI/AAAAAAAAAGY/bOBD8YJOXOo/s400/ak.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5643725501197584642" /></a>At <a href="http://googletv.blogspot.com/2011/05/google-tv-at-io-2011.html">Google I/O</a>, we announced that Android Market is coming to Google TV. Today, we’re announcing a preview of the <a href="http://code.google.com/tv/android/docs/gtv_addon.html">Google TV Add-on</a> for the <a href="http://developer.android.com/sdk/index.html">Android SDK</a>. With the upcoming OS update to Honeycomb, Google TV devices will be Android compatible. That means developers can build great new Android apps for TV, optimize existing mobile or tablet apps for TV, and distribute those apps through Android Market.
<p>While the add-on does not contain all features of Google TV, it enables developers to emulate Google TV and build apps using standard Android SDK tools. It also provides new <a href="http://code.google.com/tv/android/docs/gtv_provider.html">APIs for TV interaction</a>, such as TV channel line-up. Google TV emulation is currently supported on <a href="http://code.google.com/tv/android/docs/gtv_emulator.html#SystemRequirements">Linux with KVM</a> only, and we are working on support for other operating systems. We’re very happy that through KVM we’ve been able to create a fast Android emulator for TV.</p><p>Depending on the design and use case, an existing Android app may work well on Google TV as is, or it may require fixes. With the add-on you can test your apps to determine if they would be a good fit for TV and whether any tweaks are required. We are also publishing <a href="http://code.google.com/tv/android/docs/gtv_android_patterns.html">UI guidelines</a> to help you with topics like optimizing for D-pad navigation, presenting information for 10-foot viewing, designing apps that work well across devices, etc. The guidelines include information on how certain UI elements on Google TV differ from other Android devices.</p><p>As with other devices, apps that require features not supported on Google TV <a href="http://developer.android.com/guide/appendix/market-filters.html">won’t appear in Android Market</a> on Google TV. For example, Google TV-based devices do not have a touchscreen; hence apps which require touchscreen will not appear. Conversely, if the manifest says touchscreen is not required, the app will appear. Please follow <a href="http://code.google.com/tv/android/docs/gtv_android_features.html">our guidelines</a> carefully.</p><p>These are still early days for Google TV, and this release is another step in providing developer tools for the big screen. While the number of apps available on TV will initially be small, we expect that through this early release of the add-on you'll be able to bring optimized TV apps into the ecosystem more quickly. To start doing this, download the <a href="http://code.google.com/tv/android/docs/gtv_addon.html#Install">Google TV add-on</a> today. Also, please continue to reach out to us on the <a href="http://code.google.com/tv/android/community.html">Google TV Android Developer Community forum</a>. We look forward to your contributions!</p>
<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6099733541811853946?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/uncategorized/preview-of-google-tv-add-on-for-the-android-sdk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Developer Labs 2011</title>
		<link>https://googledata.org/google-android/android-developer-labs-2011/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-developer-labs-2011</link>
		<comments>https://googledata.org/google-android/android-developer-labs-2011/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 23:43:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=2fe19afefe22176e23bc72e085dea06c</guid>
		<description><![CDATA[We in Android Developer Relations have been cooking up a rather special set of Android Developer Labs (ADLs) for the second half of 2011, and we’re ready to start the ball rolling.Here’s the schedule. These are one-day events, so in Seattle and New...]]></description>
				<content:encoded><![CDATA[<p>We in Android Developer Relations have been cooking up a rather special set of Android Developer Labs (ADLs) for the second half of 2011, and we’re ready to start the ball rolling.</p><p>Here’s the schedule. These are one-day events, so in Seattle and New York we’re running it twice for two audiences.</p><ul><li><p><a href="https://sites.google.com/site/androiddeveloperlabsindia2011/">Bangalore &mdash; August 2</a> (happening today)</p></li><li><p><a href="https://sites.google.com/site/androiddevlabs2011/home">Seattle &mdash; August 15 and 16</a> </p></li><li><p><a href="https://sites.google.com/site/androiddevlabs2011/nyc">New York &mdash; August  23 and 24</a> </p></li><li><p><a href="https://sites.google.com/site/androiddevlabs2011/losangeles">Los Angeles &mdash; September  2</a></p></li></ul><p>This ADL series isn’t another set of introduction-to-Android sessions, nor any other kind of general overview.  It's specifically aimed at optimizing Android apps for tablets, in particular creating high-quality tablet apps with an emphasis on polish and user-experience. </p><p>Registration is a two-step process.  Anyone can register, but we can only accommodate a relatively small number of attendees from among the registrants, based on whether they already have an Android app with the potential to be a top-tier tablet app in terms of quality, fit, and finish. The goal is to bring your app to the ADL, and leave equipped to make it into one that makes Android tablet users smile.</p><p>Do you think you qualify?  Sign up and show us!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1843024197726855477?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-developer-labs-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Class Loading in Dalvik</title>
		<link>https://googledata.org/google-android/custom-class-loading-in-dalvik/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=custom-class-loading-in-dalvik</link>
		<comments>https://googledata.org/google-android/custom-class-loading-in-dalvik/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 15:35:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=a1a920872809ce2dd980b0b443c2e223</guid>
		<description><![CDATA[[This post is by Fred Chung,  who&#8217;s an Android Developer Advocate&#160;&#8212;&#160;Tim&#160;Bray]The Dalvik VM provides facilities for developers to perform custom class loading.  Instead of loading Dalvik executable (“dex”) files from the d...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-0Jihpe-acmw/TjGDqxyvX7I/AAAAAAAAApc/i6i1UB6BBG8/s1600/fchung.png"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 249px; height: 320px;" src="http://2.bp.blogspot.com/-0Jihpe-acmw/TjGDqxyvX7I/AAAAAAAAApc/i6i1UB6BBG8/s320/fchung.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5634429379761102770" /></a><p><i>[This post is by <a href="https://plus.google.com/112600205125796554588/">Fred Chung</a>,  who&rsquo;s an Android Developer Advocate&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>The Dalvik VM provides facilities for developers to perform custom class loading.  Instead of loading Dalvik executable (“dex”) files from the default location, an application can load them from alternative locations such as internal storage or over the network.  </p><p>This technique is not for every application; In fact, most do just fine without it.  However, there are situations where custom class loading can come in handy.  Here are a couple of scenarios:</p><ul><li><p>Big apps can contain more than 64K method references, which is the maximum number of supported in a dex file.  To get around this limitation, developers can partition part of the program into multiple secondary dex files, and load them at runtime.</p></li><li><p>Frameworks can be designed to make their execution logic extensible by dynamic code loading at runtime.</p></li></ul><p>We have created a <a href="http://code.google.com/p/android-custom-class-loading-sample/">sample app</a> to demonstrate the partitioning of dex files and runtime class loading.   (Note that for reasons discussed below, the app cannot be built with the  ADT Eclipse plug-in.  Instead, use the included Ant build script.  See Readme.txt for detail.)  </p><p>The app has a simple Activity that invokes a library component to display a Toast.  The Activity and its resources are kept in the default dex, whereas the library code is stored in a secondary dex bundled in the APK.  This requires a modified build process, which is shown below in detail.  </p><p>Before the library method can be invoked, the app has to first explicitly load the secondary dex file.  Let’s take a look at the relevant moving parts.</p><h3>Code Organization</h3><p>The application consists of 3 classes.</p><ul><li><p><code>com.example.dex.MainActivity</code>: UI component from which the library is invoked</p></li><li><p><code>com.example.dex.LibraryInterface</code>: Interface definition for the library</p></li><li><p><code>com.example.dex.lib.LibraryProvider</code>: Implementation of the library</p></li></ul><p>The library is packaged in a secondary dex, while the rest of the classes are included in the default (primary) dex file.  The “Build process” section below illustrates how to accomplish this.  Of course, the packaging decision is dependent on the particular scenario a developer is dealing with.</p><h3>Class loading and method invocation</h3><p>The secondary dex file, containing <code>LibraryProvider</code>, is stored as an application asset.  First, it has to be copied to a storage location whose path can be supplied to the class loader.  The sample app uses the app’s private internal storage area for this purpose.  (Technically, external storage would also work, but one has to consider the security implications of keeping application binaries there.) </p><p>Below is a snippet from <code>MainActivity</code> where standard file I/O is used to accomplish the copying.</p><pre><code>  // Before the secondary dex file can be processed by the DexClassLoader,
  // it has to be first copied from asset resource to a storage location.
  File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE),
          SECONDARY_DEX_NAME);
  ...
  BufferedInputStream bis = null;
  OutputStream dexWriter = null;

  static final int BUF_SIZE = 8 * 1024;
  try {
      bis = new BufferedInputStream(getAssets().open(SECONDARY_DEX_NAME));
      dexWriter = new BufferedOutputStream(
          new FileOutputStream(dexInternalStoragePath));
      byte[] buf = new byte[BUF_SIZE];
      int len;
      while((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
          dexWriter.write(buf, 0, len);
      }
      dexWriter.close();
      bis.close();
      
  } catch (. . .) {...}</code></pre><p>Next, a <a href="http://developer.android.com/reference/dalvik/system/DexClassLoader.html">DexClassLoader</a> is instantiated to load the library from the extracted secondary dex file.   There are a couple of ways to invoke methods on classes loaded in this manner.  In this sample, the class instance is cast to an interface through which the method is called directly.  </p><p>Another approach is to invoke methods using the reflection API.  The advantage of using reflection is that it doesn’t require the secondary dex file to implement any particular interfaces.  However, one should be aware that reflection is verbose and slow.</p><pre><code>  // Internal storage where the DexClassLoader writes the optimized dex file to
  final File optimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);

  DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
                                         optimizedDexOutputPath.getAbsolutePath(),
                                         null,
                                         getClassLoader());
  Class libProviderClazz = null;
  try {
      // Load the library.
      libProviderClazz =
          cl.loadClass("com.example.dex.lib.LibraryProvider");
      // Cast the return object to the library interface so that the
      // caller can directly invoke methods in the interface.
      // Alternatively, the caller can invoke methods through reflection,
      // which is more verbose. 
      LibraryInterface lib = (LibraryInterface) libProviderClazz.newInstance();
      lib.showAwesomeToast(this, "hello");
  } catch (Exception e) { ... }</code></pre><h3>Build Process</h3><p>In order to churn out two separate dex files, we need to tweak the standard build process.  To do the trick, we simply modify the “-dex” target in the project’s Ant <a href="http://code.google.com/p/android-custom-class-loading-sample/source/browse/trunk/android-custom-class-loading-sample/build.xml">build.xml</a>.</p><p>The modified “-dex” target performs the following operations:</p><ol><li><p>Create two staging directories to store .class files to be converted to the default dex and the secondary dex.</p></li><li><p>Selectively copy .class files from PROJECT_ROOT/bin/classes to the two staging directories.  </p><pre><code>      &lt;!-- Primary dex to include everything but the concrete library
                 implementation. -->
            &lt;copy todir="${out.classes.absolute.dir}.1" >
                &lt;fileset dir="${out.classes.absolute.dir}" >
                        &lt;exclude name="com/example/dex/lib/**" />
                &lt;/fileset>
            &lt;/copy>
            &lt;!-- Secondary dex to include the concrete library implementation. -->
            &lt;copy todir="${out.classes.absolute.dir}.2" >
                &lt;fileset dir="${out.classes.absolute.dir}" >
                        &lt;include name="com/example/dex/lib/**" />
                &lt;/fileset>
            &lt;/copy>     </code></pre></li><li><p>Convert .class files from the two staging directories into two separate dex files.</p></li><li><p>Add the secondary dex file to a jar file, which is the expected input format for the <code>DexClassLoader</code>.  Lastly, store the jar file in the “assets” directory of the project.</p><pre><code>    &lt;!-- Package the output in the assets directory of the apk. -->
            &lt;jar destfile="${asset.absolute.dir}/secondary_dex.jar"
                   basedir="${out.absolute.dir}/secondary_dex_dir"
                   includes="classes.dex" /></code></pre></li></ol><p>To kick-off the build, you execute <code>ant debug</code> (or <code>release</code>) from the project root directory.</p><p>That’s it!  In the right situations, dynamic class loading can be quite useful.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-694692997105002017?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/custom-class-loading-in-dalvik/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>New Tools For Managing Screen Sizes</title>
		<link>https://googledata.org/google-android/new-tools-for-managing-screen-sizes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-tools-for-managing-screen-sizes</link>
		<comments>https://googledata.org/google-android/new-tools-for-managing-screen-sizes/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 17:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=eb72a08f2df634a0276eff096f6dcffa</guid>
		<description><![CDATA[[This post is by Dianne Hackborn and a supporting cast of thousands; Dianne&#8217;s fingerprints can be found all over the Android Application Framework&#160;&#8212;&#160;Tim&#160;Bray]Android 3.2 includes new tools for supporting devices with a wide r...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Dianne Hackborn and a supporting cast of thousands; Dianne&rsquo;s fingerprints can be found all over the Android Application Framework&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s1600/IMG_0089.jpg"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 262px; height: 400px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s400/IMG_0089.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5465289764591543458" /></a><p><a href="http://android-developers.blogspot.com/2011/07/android-32-platform-and-updated-sdk.html">Android 3.2</a> includes new tools for supporting devices with a wide range of screen sizes.  One important result is better support for a new size of screen; what is typically called a “7-inch” tablet.  This release  also offers several new APIs to simplify developers’ work in adjusting to different screen sizes.</p><p>This a long post.  We start by discussing the why and how of Android “dp” arithmetic, and the finer points of the screen-size buckets.  If you know all that stuff, you can skip down to “Introducing Numeric Selectors” to read about what’s new. We also provide our recommendations for how you can do layout selection in apps targeted at Android 3.2 and higher in a way that should allow you to support the maximum number of device geometries with the minimum amount of effort.</p><p>Of course, the official write-up on <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple Screens</a> is also required reading for people working in this space.</p><h3>Understanding Screen Densities and the “dp”</h3><p>Resolution is the actual number of pixels available in the display, density is how many pixels appear within a constant area of the display, and size is the amount of physical space available for displaying your interface.  These are interrelated: increase the resolution and density together, and size stays about the same.  This is why the 320x480 screen on a G1 and 480x800 screen on a Droid are both the same screen size: the 480x800 screen has more pixels, but it is also higher density.</p><p>To remove the size/density calculations from the picture, the Android framework works wherever possible in terms of "dp" units, which are corrected for density.  In medium-density ("mdpi") screens, which correspond to the original Android phones, physical pixels are identical to dp's; the devices&rsquo; dimensions are 320x480 in either scale.  A more recent phone might have physical-pixel dimensions of 480x800 but be a high-density device.  The conversion factor from hdpi to mdpi in this case is 1.5, so for a developer's purposes, the device is 320x533 in dp's.</p><h3>Screen-size Buckets</h3><p>Android has included support for three screen-size “buckets” since 1.6, based on these “dp” units: “normal”  is currently the most popular device format (originally 320x480, more recently higher-density 480x800); “small” is for smaller screens, and “large” is for “substantially larger” screens.  Devices that fall in the “large” bucket include the Dell Streak and original 7” Samsung Galaxy Tab.  Android 2.3 introduced a new bucket size “xlarge”, in preparation for the approximately-10” tablets (such as the Motorola Xoom) that Android 3.0 was designed to support. </p><p>The definitions are:</p><ul><li><p>xlarge screens are at least 960dp x 720dp.</p></li><li><p>large screens are at least 640dp x 480dp.</p></li><li><p>normal screens are at least 470dp x 320dp.</p></li><li><p>small screens are at least 426dp x 320dp.  (Android does not currently support screens smaller than this.)</p></li></ul><p>Here are some more examples of how this works with real screens:</p><ul><li><p>A QVGA screen is 320x240 ldpi.  Converting to mdpi (a 4/3 scaling factor) gives us 426dp x 320dp; this matches the minimum size above for the small screen bucket.</p></li><li><p>The Xoom is a typical 10” tablet with a 1280x800 mdpi screen.  This places it into the xlarge screen bucket.</p></li><li><p>The Dell Streak is a 800x480 mdpi screen.  This places it into the bottom of the large size bucket.</p></li><li><p>A typical 7” tablet has a 1024x600 mdpi screen.  This also counts as a large screen.</p></li><li><p>The original Samsung Galaxy Tab is an interesting case.  Physically it is a 1024x600 7” screen and thus classified as “large”.  However the device configures its screen as hdpi, which means after applying the appropriate ⅔ scaling factor the actual space on the screen is 682dp x 400dp.  This actually moves it out of the “large” bucket and into a “normal” screen size.  The Tab actually reports that it is “large”; this was a mistake in the framework’s computation of the size for that device that we made.  Today no devices should ship like this.</p></li></ul><h3>Issues With Buckets</h3><p>Based on developers’ experience so far, we’re not convinced that this limited set of screen-size buckets gives developers everything they need in adapting to the increasing variety of Android-device shapes and sizes.  The primary problem is that the borders between the buckets may not always correspond to either devices available to consumers or to the particular needs of apps.</p><p>The “normal” and “xlarge” screen sizes should be fairly straightforward as a target: “normal” screens generally require single panes of information that the user moves between, while “xlarge” screens can comfortably hold multi-pane UIs (even in portrait orientation, with some tightening of the space).</p><p>The “small” screen size is really an artifact of the original Android devices having 320x480 screens.  240x320 screens have a shorter aspect ratio, and applications that don’t take this into account can break on them.  These days it is good practice to test user interfaces on a small screen to ensure there are no serious problems.</p><p>The “large” screen size has been challenging for developers&nbsp;&mdash;&nbsp;you will notice that it encompases everything from the Dell Streak to the original Galaxy Tab to 7" tablets in general. Different applications may also reasonably want to take different approaches to these two devices; it is also quite reasonable to want to have different behavior for landscape vs. portrait large devices because landscape has plenty of space for a multi-pane UI, while portrait may not.</p><h3>Introducing Numeric Selectors</h3><p>Android 3.2 introduces a new approach to screen sizes, with the goal of making developers' lives easier. We have defined a set of numbers describing device screen sizes, which you can use to select resources or otherwise adjust your UI.  We believe that using these will not only reduce developers’ workloads, but future-proof their apps significantly.</p><p>The numbers describing the screen size are all in “dp” units (remember that your layout dimensions should also be in dp units so that the system can adjust for screen density).  They are:</p><ul><li><p><b>width dp</b>: the current width available for application layout in “dp” units; changes when the screen switches orientation between landscape and portrait.</p></li><li><p><b>height dp</b>: the current height available for application layout in “dp” units; also changes when the screen switches orientation.</p></li><li><p><b>smallest width dp</b>: the smallest width available for application layout in “dp” units; this is the smallest width dp that you will ever encounter in any rotation of the display.</p></li></ul><p>Of these, <b>smallest width dp</b> is the most important.  It replaces the old screen-size buckets with a continuous range of numbers giving the effective size.  This number is based on width because that is fairly universally the driving factor in designing a layout.  A UI will often scroll vertically, but have fairly hard constraints on the minimum space it needs horizontally; the available width is also the key factor in determining whether to use a phone-style one-pane layout or tablet-style multi-pane layout.</p><p>Typical numbers for screen width dp are:</p><ul><li><p>320: a phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).</p></li><li><p>480: a tweener tablet like the Streak (480x800 mdpi).</p></li><li><p>600: a 7” tablet (600x1024).</p></li><li><p>720: a 10” tablet (720x1280, 800x1280, etc).</p></li></ul><h3>Using the New Selectors</h3><p>When you are designing your UI, the main thing you probably care about is where you switch between a phone-style UI and a tablet-style multi-pane UI.  The exact point of this switch will depend on your particular design&nbsp;&mdash;&nbsp;maybe you need a full 720dp width for your tablet layout, maybe 600dp is enough, or 480dp, or even some other number between those.  Either pick a width and design to it; or after doing your design, find the smallest width it supports.</p><p>Now you can select your layout resources for phones vs. tablets using the number you want.  For example, if 600dp is the smallest width for your tablet UI, you can do this:</p><pre><code>res/layout/main_activity.xml           # For phones
res/layout-sw600dp/main_activity.xml   # For tablets</code></pre><p>For the rare case where you want to further customize your UI, for example for 7” vs. 10” tablets, you can define additional smallest widths:</p><pre><code>res/layout/main_activity.xml           # For phones
res/layout-sw600dp/main_activity.xml   # For 7” tablets
res/layout-sw720dp/main_activity.xml   # For 10” tablets</code></pre><p>Android will pick the resource that is closest to the device’s “smallest width,” without being larger; so for a hypothetical 700dp x 1200dp tablet, it would pick layout-sw600dp.</p><p>If you want to get fancier, you can make a layout that can change when the user switches orientation to the one that best fits in the current available width.  This can be of particular use for 7” tablets, where a multi-pane layout is a very tight fit in portrait::</p><pre><code>res/layout/main_activity.xml          # Single-pane
res/layout-w600dp/main_activity.xml   # Multi-pane when enough width</code></pre><p>Or the previous three-layout example could use this to switch to the full UI whenever there is enough width:</p><pre><code>res/layout/main_activity.xml                 # For phones
res/layout-sw600dp/main_activity.xml         # Tablets
res/layout-sw600dp-w720dp/main_activity.xml  # Large width</code></pre><p>In the setup above, we will always use the phone layout for devices whose smallest width is less than 600dp; for devices whose smallest width is at least 600dp, we will switch between the tablet and large width layouts depending on the current available width.</p><p>You can also mix in other resource qualifiers:</p><pre><code>res/layout/main_activity.xml                 # For phones
res/layout-sw600dp/main_activity.xml         # Tablets
res/layout-sw600dp-port/main_activity.xml    # Tablets when portrait</code></pre><h3>Selector Precedence</h3><p>While it is safest to specify multiple configurations like this to avoid potential ambiguity, you can also take advantage of some subtleties of resource matching.  For example, the order that resource qualifiers must be specified in the directory name (documented in <a href="http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources">Providing Resources</a>) is also the order of their “importance.”  Earlier ones are more important than later ones.  You can take advantage of this to, for example, easily have a landscape orientation specialization for your default layout:</p><pre><code>res/layout/main_activity.xml                 # For phones
res/layout-land/main_activity.xml            # For phones when landscape
res/layout-sw600dp/main_activity.xml         # Tablets</code></pre><p>In this case when running on a tablet that is using landscape orientation, the last layout will be used because the “swNNNdp” qualifier is a better match than “port”.</p><h3>Combinations and Versions</h3><p>One final thing we need to address is specifying layouts that work on both Android 3.2 and up as well as previous versions of the platform.</p><p>Previous versions of the platform will ignore any resources using the new resource qualifiers.  This, then, is one approach that will work:</p><pre><code>res/layout/main_activity.xml           # For phones
res/layout-xlarge/main_activity.xml    # For pre-3.2 tablets
res/layout-sw600dp/main_activity.xml   # For 3.2 and up tablets</code></pre><p>This does require, however, that you have two copies of your tablet layout.  One way to avoid this is by defining the tablet layout once as a distinct resource, and then making new versions of the original layout resource that point to it.  So the layout resources we would have are:</p><pre><code>res/layout/main_activity.xml           # For phones
res/layout/main_activity_tablet.xml    # For tablets</code></pre><p>To have the original layout point to the tablet version, you put <code>&lt;item></code> specifications in the appropriate values directories.  That is these two files:</p><pre><code>res/values-xlarge/layout.xml
res/values-sw600dp/layout.xml</code></pre><p>Both would contain the following XML defining the desired resource:</p><pre><code>&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
    &lt;item type="layout" name="main_activty">
            @layout/main_activity_tablet
    &lt;/item>
&lt;/resources></code></pre><p>Of course, you can always simply select the resource to use in code.  That is, define two or more resources like “layout/main_activity” and “layout/main_activity_tablet,” and select the one to use in your code based on information in the Configuration object or elsewhere.  For example:</p><pre><code>public class MyActivity extends Activity {
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate();

        Configuration config = getResources().getConfiguration();
        if (config.smallestScreenWidthDp >= 600) {
            setContentView(R.layout.main_activity_tablet);
        } else {
            setContentView(R.layout.main_activity);
        }
    }
}</code></pre><h3>Conclusion</h3><p>We strongly recommend that developers start using the new layout selectors for apps targeted at Android release 3.2 or higher, as we will be doing for Google apps.  We think they will make your layout choices easier to express and manage.  </p><p>Furthermore, we can see a remarkably wide variety of Android-device form factors coming down the pipe.  This is a good thing, and will expand the market  for your work.  These new layout selectors are specifically designed to make it straightforward for you to make your apps run well in a future hardware ecosystem which is full of variety (and surprises).</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7898235252387825270?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/new-tools-for-managing-screen-sizes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Debugging Android JNI with CheckJNI</title>
		<link>https://googledata.org/google-android/debugging-android-jni-with-checkjni/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=debugging-android-jni-with-checkjni</link>
		<comments>https://googledata.org/google-android/debugging-android-jni-with-checkjni/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 17:32:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=d9b05ac2c0e2a4c05e9df834090cd084</guid>
		<description><![CDATA[[This post is by Elliott Hughes, a Software Engineer on the Dalvik team&#160;&#8212;&#160;Tim&#160;Bray]Although most Android apps run entirely on top of Dalvik, some use the Android NDK to include native code using JNI. Native code is harder to get ri...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Elliott Hughes, a Software Engineer on the Dalvik team&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Although most Android apps run entirely on top of Dalvik, some use the Android NDK to include native code using JNI. Native code is harder to get right than Dalvik code, and when you have a bug, it’s often a lot harder to find and fix it. Using JNI is inherently tricky (there’s precious little help from the type system, for example), and JNI functions provide almost no run-time checking. Bear in mind also that the developer console’s crash reporting doesn’t include native crashes, so you don’t even necessarily know how often your native code is crashing.</p><h3>What CheckJNI can do</h3><p>To help, there’s CheckJNI. It can catch a number of common errors, and the list is continually increasing. In Gingerbread, for example, CheckJNI can catch all of the following kinds of error:</p><ul><li><p>Arrays: attempting to allocate a negative-sized array.</p></li><li><p>Bad pointers: passing a bad jarray/jclass/jobject/jstring to a JNI call, or passing a NULL pointer to a JNI call with a non-nullable argument.</p></li><li><p>Class names: passing anything but the “java/lang/String” style of class name to a JNI call.</p></li><li><p>Critical calls: making a JNI call between a GetCritical and the corresponding ReleaseCritical.</p></li><li><p>Direct ByteBuffers: passing bad arguments to NewDirectByteBuffer.</p></li><li><p>Exceptions: making a JNI call while there’s an exception pending.</p></li><li><p>JNIEnv*s: using a JNIEnv* from the wrong thread.</p></li><li><p>jfieldIDs: using a NULL jfieldID, or using a jfieldID to set a field to a value of the wrong type (trying to assign a StringBuilder to a String field, say), or using a jfieldID for a static field to set an instance field or vice versa, or using a jfieldID from one class with instances of another class.</p></li><li><p>jmethodIDs: using the wrong kind of jmethodID when making a Call*Method JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).</p></li><li><p>References: using DeleteGlobalRef/DeleteLocalRef on the wrong kind of reference.</p></li><li><p>Release modes: passing a bad release mode to a release call (something other than 0, JNI_ABORT, or JNI_COMMIT).</p></li><li><p>Type safety: returning an incompatible type from your native method (returning a StringBuilder from a method declared to return a String, say).</p></li><li><p>UTF-8: passing an invalid <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> byte sequence to a JNI call.</p></li></ul><p>If you’ve written any amount of native code without CheckJNI, you’re probably already wishing you’d known about it. There’s a performance cost to using CheckJNI (which is why it isn’t on all the time for everybody), but it shouldn’t change the behavior in any other way.</p><h3>Enabling CheckJNI</h3><p>If you’re using the emulator, CheckJNI is on by default.  If you&rsquo;re working with an Android device, use the following adb command:</p><pre><code>adb shell setprop debug.checkjni 1</code></pre><p>This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Changing the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time each app starts:</p><pre><code>D Late-enabling CheckJNI</code></pre><p>If you don&rsquo;t see this, your app was probably already running; you just need to force stop it and start it again.</p><h3>Example</h3><p>Here’s the output you get if you return a byte array from a native method declared to return a String:</p><pre><code>W JNI WARNING: method declared to return 'Ljava/lang/String;' returned '[B'
W              failed in LJniTest;.exampleJniBug
I "main" prio=5 tid=1 RUNNABLE
I   | group="main" sCount=0 dsCount=0 obj=0x40246f60 self=0x10538
I   | sysTid=15295 nice=0 sched=0/0 cgrp=default handle=-2145061784
I   | schedstat=( 398335000 1493000 253 ) utm=25 stm=14 core=0
I   at JniTest.exampleJniBug(Native Method)
I   at JniTest.main(JniTest.java:11)
I   at dalvik.system.NativeStart.main(Native Method)
I 
E VM aborting</code></pre><p>Without CheckJNI, you’d just die via SIGSEGV, with none of this output to help you!</p><h3>New JNI documentation</h3><p>We’ve also recently added a page of <a href="http://developer.android.com/guide/practices/design/jni.html">JNI Tips</a> that explains some of the finer points of JNI. If you write native methods, even if CheckJNI isn’t rejecting your code, you should still read that page. It covers everything from correct usage of the JavaVM and JNIEnv types, how to work with native threads, local and global references, dealing with Java exceptions in native code, and much more, including answers to frequently-asked JNI questions.</p><h3>What CheckJNI can’t do</h3><p>There are still classes of error that CheckJNI can’t find. Most important amongst these are misuses of local references. CheckJNI can spot if you stash a JNIEnv* somewhere and then reuse it on the wrong thread, but it can’t detect you stashing a local reference (rather than a global reference) and then reusing it in a later native method call. Doing so is invalid, but currently mostly works (at the cost of making life hard for the GC), and we’re still working on getting CheckJNI to spot these mistakes.</p><p>We’re hoping to have more checking, including for local reference misuse, in a future release of Android. Start using CheckJNI now, though, and you’ll be able to take advantage of our new checks as they’re added.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2683173557318857484?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/debugging-android-jni-with-checkjni/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Mode for Apps on Large Screens</title>
		<link>https://googledata.org/google-android/new-mode-for-apps-on-large-screens/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-mode-for-apps-on-large-screens</link>
		<comments>https://googledata.org/google-android/new-mode-for-apps-on-large-screens/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 16:47:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=a178b69ce0b4a1b9c4f9c785527455e3</guid>
		<description><![CDATA[[This post is by Scott Main, lead tech writer for developer.android.com.&#160;&#8212;&#160;Tim&#160;Bray]Android tablets are becoming more popular, and we're pleased to note that the vast majority of apps resize to the larger screens just fine. To keep...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-ICF_-w7Of4o/Thsttq7Hr9I/AAAAAAAAAh8/UECE2TIepTs/s1600/scott.png"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 185px; height: 228px;" src="http://3.bp.blogspot.com/-ICF_-w7Of4o/Thsttq7Hr9I/AAAAAAAAAh8/UECE2TIepTs/s400/scott.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5628142421969186770" /></a><p><i>[This post is by Scott Main, lead tech writer for <a href="http://developer.android.com">developer.android.com</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Android tablets are becoming more popular, and we're pleased to note that the vast majority of apps resize to the larger screens just fine. To keep the few apps that don't resize well from frustrating users with awkward-looking apps on their tablets, a near-future release of Honeycomb is introducing a new screen compatibility mode to make these apps more usable on tablets. If your app is one of the many that do resize well, however, you should update your app as soon as possible to disable screen compatibility mode so that users experience your app the way you intend.</p><p>Beginning with the upcoming release, any app that does not target Android 3.0 (set either <code>android:minSdkVersion</code> or <code>android:targetSdkVersion</code> to “11”  or higher) or does not explicitly set <code>android:xlargeScreens="true"</code> in the <code>&lt;supports-screens></code> element will include a button in the system bar that, when touched, allows users to select between two viewing modes on large-screen devices.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-HY4vGH-SfJI/ThsvGKmWKOI/AAAAAAAAAiE/Gxb173A0kzE/s1600/compat-toggle.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 272px; height: 163px;" src="http://4.bp.blogspot.com/-HY4vGH-SfJI/ThsvGKmWKOI/AAAAAAAAAiE/Gxb173A0kzE/s400/compat-toggle.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5628143942300477666" /></a><p>“Stretch to fill screen” is normal layout resizing (using your app’s alternative resources for size and density) and “Zoom to fill screen” is the new screen compatibility mode.</p><p>When the user enables this new screen compatibility mode, the system no longer resizes your layout to fit the screen. Instead, it runs your app in an emulated normal/mdpi screen (approximately 320dp x 480dp) and scales that up to fill the screen---imagine viewing your app at the size of a phone screen then zooming in about 200%. The effect is that everything is bigger, but also more pixelated, because the system does not resize your layout or use your alternative resources for the current device (the system uses all resources for a normal/mdpi device). Here’s a comparison of what it looks like (screen compatibility mode enabled on the right):</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-_6VIHkFH3bU/ThsveqS49hI/AAAAAAAAAiM/dg7ZNWQqqqE/s1600/compat-compare.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 121px;" src="http://4.bp.blogspot.com/-_6VIHkFH3bU/ThsveqS49hI/AAAAAAAAAiM/dg7ZNWQqqqE/s400/compat-compare.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5628144363125667346" /></a><p>In cases where an app does not properly resize for larger screens, this screen compatibility mode can improve the app’s usability by emulating the app’s phone-style look, but zoomed in to fill the screen on a tablet.</p><p>However, most apps (even those that don’t specifically target Honeycomb) look just fine on tablets <em>without</em> screen compatibility mode, due to the use of alternative layouts for different screen sizes and the framework’s flexibility when resizing layouts. Unfortunately, if you haven’t said so in your manifest file, the system doesn’t know that your application properly supports large screens. Thus, if you’ve developed your app against any version lower than Android 3.0 and do not declare support for large screens in your manifest, the system is going to offer users the option to enable screen compatibility mode. </p><p>So, if your app is actually designed to resize for large screens, screen compatibility mode is probably an inferior user experience for your app and you should prevent users from using it. The easiest way to make sure that users cannot enable screen compatibility mode for your app is to declare support for xlarge screens in your manifest file’s <code>&lt;supports-screens></code> element. For example:</p><pre><code>&lt;manifest ... >
    &lt;supports-screens android:xlargeScreens="true" />
    ...
&lt;/manifest></code></pre><p>That’s it! No more screen compatibility mode.</p><p><b>Note</b>: If your app is specifically designed to support Android 3.0 and declares either <code>android:minSdkVersion</code> or <code>android:targetSdkVersion</code> with a value of “11” or greater, then your app is already in the clear and screen compatibility mode will not be offered to users, but adding this attribute certainly won’t hurt.</p><p>In conclusion, if your app has set the <code>android:minSdkVersion</code> and <code>android:targetSdkVersion</code> both with values <em>less</em> than “11” and you believe your app works well on large and xlarge screens (for example, you’ve tested on a Honeycomb tablet), you should make the above addition to your manifest file in order to disable the new screen compatibility mode.</p><p>If your app does <em>not</em> resize properly for large screens, then users might better enjoy your app using screen compatibility mode. However, please follow our guide to <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple Screens</a> so that you can also disable screen compatibility mode and provide a user experience that’s optimized for large-screen devices.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-415015198991209493?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/new-mode-for-apps-on-large-screens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>A Deep Dive Into Location</title>
		<link>https://googledata.org/google-android/a-deep-dive-into-location/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-deep-dive-into-location</link>
		<comments>https://googledata.org/google-android/a-deep-dive-into-location/#comments</comments>
		<pubDate>Thu, 23 Jun 2011 21:08:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=1dc12c23e5d0c9e4c53a84f10991b084</guid>
		<description><![CDATA[[This post is by Reto Meier, Tech Lead for Android Developer Relations, who wrote the book on Android App development.&#160;&#8212;&#160;Tim&#160;Bray]I'm a big fan of location-based apps, but not their seemingly-inevitable startup latency. Whether it'...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by <a href="https://twitter.com/retomeier">Reto Meier</a>, Tech Lead for Android Developer Relations, who <a href="http://www.amazon.com/gp/product/0470565527?tag=interventione-20">wrote the book</a> on Android App development.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-xpevUuRG5to/TgKBoB2GKWI/AAAAAAAAAdY/CBD2eimfS1c/s1600/reto.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 302px; height: 381px;" src="http://3.bp.blogspot.com/-xpevUuRG5to/TgKBoB2GKWI/AAAAAAAAAdY/CBD2eimfS1c/s400/reto.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5621197809601882466" /></a><p>I'm a big fan of location-based apps, but not their seemingly-inevitable startup latency. </p><p>Whether it's finding a place  to eat or searching for the nearest <a href="http://en.wikipedia.org/wiki/Barclays_Cycle_Hire">Boris Bike</a>, I find the delay while waiting for the GPS to get a fix, and then for the results list to populate, to be interminable. Once I’m in a venue and ready to get some tips, check-in, or review the food, I’m frequently thwarted by a lack of data connection.</p><p>Rather than shaking my fist at the sky, I’ve  written an open-source reference app that incorporates all of the tips, tricks, and cheats I know to reduce the time between opening an app and seeing an up-to-date list of nearby venues - as well as providing a reasonable level of offline support — all while keeping the impact on battery life to a minimum.</p><h3>Show Me the Code</h3><p>You can check-out the <a href="http://code.google.com/p/android-protips-location/%20">Android Protips for Location</a> open source project from Google Code. Don’t forget to read the <a href="http://code.google.com/p/android-protips-location/source/browse/trunk/Readme.txt">Readme.txt</a> for the steps required to make it compile and run successfully.</p><h3>What Does it Actually Do?</h3><p>It uses the <a href="http://code.google.com/apis/maps/documentation/places/">Google Places API</a> to implement the core functionality of apps that use location to provide a list of nearby points of interest, drill down into their details, and then check-in/rate/review them.</p><p>The code implements many of the best-practices I detailed in my Google I/O 2011 session, <a href="http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html">Android Protips: Advanced Topics for Expert Android Developers</a> (<a href="http://www.youtube.com/watch?v=twmuBbC_oB8">video</a>), including using Intents to receive location updates, using the Passive Location Provider, using and monitoring device state to vary refresh rates, toggling your manifest Receivers at runtime, and using the Cursor Loader. </p><p>The app targets Honeycomb but supports Android platforms from 1.6 and up. </p><p>Nothing would make me happier than for you to cut/copy/borrow / steal this code  to build better location-based apps. If you do, I’d love it if you <a href="http://www.twitter.com/retomeier">told me about it</a>!</p><h3>Now that you’ve got the code, let’s take a closer look at it</h3><p>My top priority was <em>freshness</em>: Minimize the latency between opening the app and being able to check in to a desired location, while still minimizing the impact of the app on battery life.</p><p>Related requirements:</p><ul><li><p>The current location has to be found as quickly as possible.</p></li><li><p>The list of venues should update when the location changes.</p></li><li><p>The list of nearby locations and their details must be available when we’re offline.</p></li><li><p>Check-ins must be possible while we’re offline.</p></li><li><p>Location data and other user data must be handled properly (see our <a href="http://android-developers.blogspot.com/2010/08/best-practices-for-handling-android.html">prior blog post on best practices</a>).</p></li></ul><h3>Freshness means never having to wait</h3><p>You can significantly reduce the latency for getting your first location fix by retrieving the last known location from the Location Manager each time the app is resumed. </p><p>In this snippet taken from the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLastLocationFinder.java">GingerbreadLastLocationFinder</a>, we iterate through each location provider on the device — including those that aren't currently available — to find the most timely and accurate last known location.</p><pre><code>List&lt;String> matchingProviders = locationManager.getAllProviders();
for (String provider: matchingProviders) {
  Location location = locationManager.getLastKnownLocation(provider);
  if (location != null) {
    float accuracy = location.getAccuracy();
    long time = location.getTime();
        
    if ((time > minTime &amp;&amp; accuracy &lt; bestAccuracy)) {
      bestResult = location;
      bestAccuracy = accuracy;
      bestTime = time;
    }
    else if (time &lt; minTime &amp;&amp; 
             bestAccuracy == Float.MAX_VALUE &amp;&amp; time > bestTime){
      bestResult = location;
      bestTime = time;
    }
  }
}</code></pre><p>If there is one or more locations available from within the allowed latency, we return the most accurate one. If not, we simply return the most recent result.</p><p>In the latter case (where it’s determined that the last location update isn't recent enough) this newest result is still returned, but we also request a single location update using that fastest location provider available.  </p><pre><code>if (locationListener != null &amp;&amp;
   (bestTime &lt; maxTime || bestAccuracy > maxDistance)) { 
  IntentFilter locIntentFilter = new IntentFilter(SINGLE_LOCATION_UPDATE_ACTION);
  context.registerReceiver(singleUpdateReceiver, locIntentFilter);      
  locationManager.requestSingleUpdate(criteria, singleUpatePI);
}</code></pre><p>Unfortunately we can’t specify “fastest” when using Criteria to choose a location provider, but in practice we know that coarser providers — particularly the network location provider — tend to return results faster than the more accurate options. In this case I’ve requested coarse accuracy and low power in order to select the Network Provider when it’s available.</p><p>Note also that this code snippet shows the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLastLocationFinder.java">GingerbreadLastLocationFinder</a> which uses the <code>requestSingleUpdate</code> method to receive a one-shot location update. This wasn’t available prior to Gingerbread - check out the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/LegacyLastLocationFinder.java">LegacyLastLocationFinder</a> to see how I have implemented the same functionality for devices running earlier platform versions.</p><p>The <code>singleUpdateReceiver</code> passes the received update back to the calling class through a registered Location Listener.</p><pre><code>protected BroadcastReceiver singleUpdateReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    context.unregisterReceiver(singleUpdateReceiver);
      
    String key = LocationManager.KEY_LOCATION_CHANGED;
    Location location = (Location)intent.getExtras().get(key);
      
    if (locationListener != null &amp;&amp; location != null)
      locationListener.onLocationChanged(location);
      
    locationManager.removeUpdates(singleUpatePI);
  }
};</code></pre><h3>Use Intents to receive location updates</h3><p>Having obtained the most accurate/timely estimate of our current location, we also want to receive location updates.</p><p>The <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/PlacesConstants.java">PlacesConstants</a> class includes a number of values that determine the frequency of location updates (and the associated server polling). Tweak them to ensure that updates occur exactly as often as required.</p><pre><code>// The default search radius when searching for places nearby.
public static int DEFAULT_RADIUS = 150;
// The maximum distance the user should travel between location updates. 
public static int MAX_DISTANCE = DEFAULT_RADIUS/2;
// The maximum time that should pass before the user gets a location update.
public static long MAX_TIME = AlarmManager.INTERVAL_FIFTEEN_MINUTES; </code></pre><p>The next step is to request the location updates from the Location Manager. In this snippet taken from the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLocationUpdateRequester.java">GingerbreadLocationUpdateRequester</a> we can pass the Criteria used to determine which Location Provider to request updates from directly into the <code>requestLocationUpdates</code> call.</p><pre><code>public void requestLocationUpdates(long minTime, long minDistance, 
  Criteria criteria, PendingIntent pendingIntent) {

  locationManager.requestLocationUpdates(minTime, minDistance, 
    criteria, pendingIntent);
}</code></pre><p>Note that we're passing in a Pending Intent rather than a Location Listener. </p><pre><code>Intent activeIntent = new Intent(this, LocationChangedReceiver.class);
locationListenerPendingIntent = 
  PendingIntent.getBroadcast(this, 0, activeIntent, PendingIntent.FLAG_UPDATE_CURRENT);</code></pre><p>I generally prefer this over using Location Listeners as it offers the flexibility of registering receivers in multiple Activities or Services, or directly in the manifest. </p><p>In this app, a new location means an updated list of nearby venues. This happens via a Service that makes a server query and updates the Content Provider that populates the place list.</p><p>Because the location change isn’t directly updating the UI, it makes sense to create and register the associated <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/LocationChangedReceiver.java">LocationChangedReceiver</a> in the manifest rather than the main Activity.</p><pre><code>&lt;receiver android:name=".receivers.LocationChangedReceiver"/></code></pre><p>The Location Changed Receiver extracts the location from each update and starts the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlacesUpdateService.java">PlaceUpdateService</a> to refresh the database of nearby locations.</p><pre><code>if (intent.hasExtra(locationKey)) {
  Location location = (Location)intent.getExtras().get(locationKey);
  Log.d(TAG, "Actively Updating place list");
  Intent updateServiceIntent = 
    new Intent(context, PlacesConstants.SUPPORTS_ECLAIR ? EclairPlacesUpdateService.class : PlacesUpdateService.class);
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_LOCATION, location);
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_RADIUS, PlacesConstants.DEFAULT_RADIUS);
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_FORCEREFRESH, true);

  context.startService(updateServiceIntent);
}</code></pre><h3>Monitor inactive providers for a better option</h3><p>The snippet from <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/UI/PlaceActivity.java">PlacesActivity</a> below shows how to monitor two important conditions:</p><ul><li><p>The Location Provider we are using being deactivated.</p></li><li><p>A better Location Provider becoming available.</p></li></ul><p>In either case, we simply re-run the process used to determine the best available provider and request location updates.</p><pre><code>// Register a receiver that listens for when the provider I'm using has been disabled. 
IntentFilter intentFilter = new IntentFilter(PlacesConstants.ACTIVE_LOCATION_UPDATE_PROVIDER_DISABLED);
registerReceiver(locProviderDisabledReceiver, intentFilter);

// Listen for a better provider becoming available.
String bestProvider = locationManager.getBestProvider(criteria, false);
String bestAvailableProvider = locationManager.getBestProvider(criteria, true);
if (bestProvider != null &amp;&amp; !bestProvider.equals(bestAvailableProvider))
  locationManager.requestLocationUpdates(bestProvider, 0, 0, 
    bestInactiveLocationProviderListener, getMainLooper());</code></pre><h3>Freshness means always being up to date. What if we could reduce startup latency to zero?</h3><p>You can start the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlacesUpdateService.java">PlacesUpdateService</a> in the background to refresh the list of nearby locations while your app is in the background. Done correctly, a relevant list of venues can be immediately available when you open the app.</p><p>Done poorly, your users will never find this out as you’ll have drained their battery too quickly.</p><p>Requesting location updates (particularly using the GPS) while your app isn’t in the foreground is poor practice, as it can significantly impact battery life. Instead, you can use the Passive Location Provider to receive location updates alongside other apps that have already requested them.</p><p>This extract from the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/FroyoLocationUpdateRequester.java">FroyoLocationUpdateRequester</a> enables passive updates on Froyo+ platforms.</p><pre><code>public void requestPassiveLocationUpdates(long minTime, long minDistance, PendingIntent pendingIntent) {
  locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
    PlacesConstants.MAX_TIME, PlacesConstants.MAX_DISTANCE, pendingIntent);    
}</code></pre><p>As a result receiving background location updates is effectively free! Unfortunately the battery cost of your server downloads aren’t, so you’ll still need to carefully balance how often you act on passive location updates with battery life.</p><p>You can achieve a similar effect in pre-Froyo devices using inexact repeating non-wake alarms as shown in the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/LegacyLocationUpdateRequester.java">LegacyLocationUpdateRequester</a>. </p><pre><code>public void requestPassiveLocationUpdates(long minTime, long minDistance, 
  PendingIntent pendingIntent) {

  alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,   
    System.currentTimeMillis()+PlacesConstants.MAX_TIME, 
    PlacesConstants.MAX_TIME, pendingIntent);    
}</code></pre><p>Rather than receiving updates from the Location Manager, this technique manually checks the last known location at a frequency determined by the maximum location update latency.</p><p>This legacy technique is significantly less efficient, so you may choose to simply disable background updates on pre-Froyo devices.</p><p>We handle updates themselves within the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/PassiveLocationChangedReceiver.java">PassiveLocationChangedReceiver</a> which determines the current location and starts the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlacesUpdateService.java">PlaceUpdateService</a>.</p><pre><code>if (location != null) {
  Intent updateServiceIntent = 
    new Intent(context, PlacesConstants.SUPPORTS_ECLAIR ? EclairPlacesUpdateService.class : PlacesUpdateService.class);
  
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_LOCATION, location);
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_RADIUS, 
    PlacesConstants.DEFAULT_RADIUS);
  updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_FORCEREFRESH, false);
  context.startService(updateServiceIntent);   
}</code></pre><h3>Using Intents to passively receive location updates when your app isn't active</h3><p>You’ll note that we registered the Passive Location Changed Receiver in the application manifest. </p>
<pre><code>&lt;receiver android:name=".receivers.PassiveLocationChangedReceiver"/&gt;</code></pre><p>As a result we can continue to receive these background updates even when the application has been killed by the system to free resources.  </p><p>This offers the significant advantage of allowing the system to reclaim the resources used by your app, while still retaining the advantages of a zero latency startup. </p><p>If your app recognizes the concept of “exiting” (typically when the user clicks the back button on your home screen), it’s good form to turn off passive location updates - including disabling your passive manifest Receiver.</p><h3>Being fresh means working offline</h3><p>To add offline support we start by caching all our lookup results to the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/content_providers/PlacesContentProvider.java">PlacesContentProvider</a> and <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/content_providers/PlaceDetailsContentProvider.java">PlaceDetailsContentProvider</a>.</p><p>Under certain circumstances we will also pre-fetch location details. This snippet from the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlacesUpdateService.java">PlacesUpdateService</a> shows how pre-fetching is enabled for a limited number of locations. </p><p>Note that pre-fetching is also potentially disabled while on mobile data networks or when the battery is low.</p><pre><code>if ((prefetchCount &lt; PlacesConstants.PREFETCH_LIMIT) &amp;&amp;
    (!PlacesConstants.PREFETCH_ON_WIFI_ONLY || !mobileData) &amp;&amp;
    (!PlacesConstants.DISABLE_PREFETCH_ON_LOW_BATTERY || !lowBattery)) {
  prefetchCount++;
      
  // Start the PlaceDetailsUpdateService to prefetch the details for this place.
}</code></pre><p>We use a similar technique to provide support for offline checkins. The <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlaceCheckinService.java">PlaceCheckinService</a> queues failed checkins, and checkins attempted while offline, to be retried (in order) when the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/ConnectivityChangedReceiver.java">ConnectivityChangedReceiver</a> determines that we’re back online.</p><h3>Optimizing battery life: Smart Services and using device state to toggle your manifest Receivers</h3><p>There's no point running update services when we aren’t online, so the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/services/PlacesUpdateService.java">PlaceUpdateService</a> checks for connectivity before attempting an update.</p><pre><code>NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &amp;&amp;
                      activeNetwork.isConnectedOrConnecting();</code></pre><p>If we’re not connected, the Passive and Active Location Changed Receivers are disabled and the the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/ConnectivityChangedReceiver.java">ConnectivityChangedReceiver</a> is turned on.</p><pre><code>ComponentName connectivityReceiver = 
  new ComponentName(this, ConnectivityChangedReceiver.class);
ComponentName locationReceiver = 
  new ComponentName(this, LocationChangedReceiver.class);
ComponentName passiveLocationReceiver = 
  new ComponentName(this, PassiveLocationChangedReceiver.class);

pm.setComponentEnabledSetting(connectivityReceiver,
  PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
  PackageManager.DONT_KILL_APP);
            
pm.setComponentEnabledSetting(locationReceiver,
  PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
  PackageManager.DONT_KILL_APP);
      
pm.setComponentEnabledSetting(passiveLocationReceiver,
  PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
  PackageManager.DONT_KILL_APP);</code></pre><p>The <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/ConnectivityChangedReceiver.java">ConnectivityChangedReceiver</a> listens for connectivity changes. When  a new connection is made, it simply disables itself and re-enables the location listeners.</p><h3>Monitoring battery state to reduce functionality and save power</h3><p>When your phone is on its last 15%, most apps are firmly in the back seat to conserving what watts you have remaining.  We can register manifest Receivers to be alerted when the device enters or leaves the low battery state.</p><pre><code>&lt;receiver android:name=".receivers.PowerStateChangedReceiver"&gt;
  &lt;intent-filter&gt;
    &lt;action android:name="android.intent.action.ACTION_BATTERY_LOW"/&gt;
    &lt;action android:name="android.intent.action.ACTION_BATTERY_OKAY"/&gt;
  &lt;/intent-filter&gt;
&lt;/receiver&gt;</code></pre><p>This snippet from the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/PowerStateChangedReceiver.java">PowerStateChangedReceiver</a> disables the <a href="https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/receivers/PassiveLocationChangedReceiver.java">PassiveLocationChangedReceiver</a> whenever the device enters a low battery state, and turns it back on once the battery level is okay.</p><pre><code>boolean batteryLow = intent.getAction().equals(Intent.ACTION_BATTERY_LOW);
 
pm.setComponentEnabledSetting(passiveLocationReceiver,
  batteryLow ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED :
               PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,  
  PackageManager.DONT_KILL_APP);</code></pre><p>You can extend this logic to disable all prefetching or reduce the frequency of your updates during low battery conditions.</p><h3>What’s Next?</h3><p>This is already a monster post, so I’m going to leave it there. I’ll follow up in the next week with a post on my personal blog, <a href="http://blog.radioactiveyak.com/">The Radioactive Yak</a>, that will go in to more detail on the <em>psychic</em> and <em>smooth</em> elements of this app like using the Backup Manager and the Cursor Loader.</p><p>I also plan to build a similar reference app for news apps, so that I can spend more time reading and less time waiting.</p><p>In the mean time, happy coding!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5447271527597768504?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/a-deep-dive-into-location/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Things That Cannot Change</title>
		<link>https://googledata.org/google-android/things-that-cannot-change/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=things-that-cannot-change</link>
		<comments>https://googledata.org/google-android/things-that-cannot-change/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 17:55:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[android market]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=03196c4b998349abd304f7bd6146afa9</guid>
		<description><![CDATA[[This post is by Dianne Hackborn, whose fingerprints can be found all over the Android Application Framework&#160;&#8212;&#160;Tim&#160;Bray]Sometimes a developer will make a change to an application that has surprising results when installed as an upd...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Dianne Hackborn, whose fingerprints can be found all over the Android Application Framework&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s1600/IMG_0089.jpg"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 262px; height: 400px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s400/IMG_0089.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5465289764591543458" /></a><p>Sometimes a developer will make a change to an application that has surprising results when installed as an update to a previous version&nbsp;&mdash;&nbsp;shortcuts break, widgets disappear, or it can’t even be installed at all.  There are certain parts of an application that are immutable once you publish it, and you can avoid surprises by understanding them.</p><h3>Your package name and certificate</h3><p>The most obvious and visible of these is the “manifest package name,” the unique name you give to your application in its AndroidManifest.xml.  The name uses a Java-language-style naming convention, with Internet domain ownership helping to avoid name collisions.  For example, since Google owns the domain “google.com”, the manifest package names of all of our applications should start with “com.google.”  It&rsquo;s important for developers to follow this convention in order to avoid conflicts with other developers.</p><p>Once you publish your application under its manifest package name, this is the unique identity of the application forever more.  Switching to a different name results in an entirely new application, one that can&rsquo;t be installed as an update to the existing application.</p><p>Just as important as the manifest package name is the certificate that application is signed with.  The signing certificate represents the author of the application.  If you change the certificate an application is signed with, it is now a different application because it comes from a different author.  This different application can’t be uploaded to Market as an update to the original application, nor can it be installed onto a device as an update.</p><p>The exact behavior the user sees when installing an application that has changed in one of these two ways is different:</p><ul><li><p>If the manifest package name has changed, the new application will be installed alongside the old application, so they both co-exist on the user’s device at the same time.</p></li><li><p>If the signing certificate changes, trying to install the new application on to the device will fail until the old version is uninstalled.</p></li></ul><p>If you change the signing certificate of your application, you should always change its manifest package name as well to avoid failures when it&rsquo;s installed.  In other words, the application coming from a different author makes it a different application, and its package name should be changed appropriately to reflect that.  (Of course it&rsquo;s fine to use the same package name for the development builds of your app signed with your test keys, because these are not published.)</p><h3>Your AndroidManifest.xml is a public API</h3><p>More than just your package name that is immutable.  A major function of the <a href="http://developer.android.com/guide/topics/manifest/manifest-intro.html%20">AndroidManifest.xml</a> is essentially to declare a public API from your application for use by other applications and the Android system.  Every component you declare in the manifest that is not private (that is whose <a href="http://developer.android.com/guide/topics/manifest/activity-element.html#exported"><code>android:exported</code></a> state is true) should be treated as a public API and never changed in a way that breaks compatibility.</p><p>A subtle but important aspect of what constitutes a break in compatibility is the <a href="http://developer.android.com/guide/topics/manifest/activity-element.html#nm"><code>android:name</code></a> attribute of your activity, service, and receiver components.  This can be surprising because we think of <code>android:name</code> as pointing to the private code implementing our application, but it is also (in combination with the manifest package name) the official unique public name for that component, as represented by the <a href="http://developer.android.com/reference/android/content/ComponentName.html">ComponentName</a> class.</p><p>Changing the component name inside of an application can have negative consequences for your users.  Some examples are:</p><ul><li><p>If the name of a main activity of your application is changed, any shortcuts the user made to it will no longer work.  A shortcut is an Intent that directly specifies the ComponentName it should run.</p></li><li><p>If the name of a service implementing a Live Wallpaper changes, then a user who has enabled your Live Wallpaper will have their wallpaper revert to the system default when getting the new version of your app.  The same is true for Input Methods, Accessibility Services, Honeycomb&rsquo;s new advanced Widgets, and so on.</p></li><li><p>If the name of a receiver implementing a Device Admin changes, then as with the live wallpaper example, the device admin will be disabled when the application is updated.  This also applies to other kinds of receivers, such as App Widgets.</p></li></ul><p>These behaviors are an outcome of how the Intent system is used on Android.  There are two main kinds of <a href="http://developer.android.com/reference/android/content/Intent.html">Intents</a>:</p><ul><li><p><b>Implicit Intents</b> only specify “what” they should match, using actions, categories, data, MIME types, and so on.  The exact components that they will find are only determined at run-time, by the Package Manager matching it against the current applications.</p></li><li><p><b>Explicit Intents</b> specify a single explicit “who” they should match, through a ComponentName.  Regardless of whatever else is in the Intent, it is only associated with the exact manifest package name and class name as given in its ComponentName.</p></li></ul><p>Both of these types of Intents are important to how Android interacts with your application.  A typical example of this is how users browse and select live wallpapers.</p><p>To let the user pick a live wallpaper, the first thing Android must do is show them a list of the available live wallpaper services.  It does this by building an implicit Intent with the appropriate action for a live wallpaper and asking the Package Manager for all services that support this Intent.  The result is then the list of live wallpapers shown to the user.</p><p>When the user actually selects a specific live wallpaper they want to use, however, Android now must build an explicit Intent that identifies that particular live wallpaper.  This is what is handed to the WallpaperManager to tell it which wallpaper to show.</p><p>This is why changing the name of the component in your manifest will cause the wallpaper to disappear: the explicit Intent that was previously saved is now invalid because the ComponentName it references no longer exists.  There is no information available to indicate what the new name of the component is.  (For example consider if your application had two different live wallpaper services the user could select.)  Instead, Android must treat that live wallpaper as uninstalled and revert to its default wallpaper.</p><p>This is how input methods, device administrators, account managers, app widgets, and even application shortcuts work.  The ComponentName is the public unique name of the components you declare in your manifest, and must not change if they are visible to other applications.</p><p>In conclusion: There are <em>some parts of your application that can not change</em>.  Please be careful.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8606917829468133591?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/things-that-cannot-change/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Introducing ViewPropertyAnimator</title>
		<link>https://googledata.org/google-android/introducing-viewpropertyanimator/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducing-viewpropertyanimator</link>
		<comments>https://googledata.org/google-android/introducing-viewpropertyanimator/#comments</comments>
		<pubDate>Mon, 30 May 2011 18:29:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=6dbe42644bf7e31436bff6f10ee0abbd</guid>
		<description><![CDATA[
[This post is by Chet Haase, an Android engineer who specializes in graphics and animation, and who occasionally posts videos and articles on these topics on his CodeDependent blog at graphics-geek.blogspot.com.&#160;&#8212;&#160;Tim&#160;Bray]In an e...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-1BZf5h1n6EU/TWau6V-R3PI/AAAAAAAAAR4/lAZK-xqge8U/s1600/SelfPortrait.jpeg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 269px; height: 320px;" src="http://3.bp.blogspot.com/-1BZf5h1n6EU/TWau6V-R3PI/AAAAAAAAAR4/lAZK-xqge8U/s320/SelfPortrait.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5577337505898945778" /></a>
<p><i>[This post is by Chet Haase, an Android engineer who specializes in graphics and animation, and who occasionally posts videos and articles on these topics on his CodeDependent blog at <a href="http://graphics-geek.blogspot.com">graphics-geek.blogspot.com</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>In an earlier article, <a href="http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.html">Animation in Honeycomb</a>, I talked about the new property animation system available as of Android 3.0. This new animation system makes it easy to animate any kind of property on any object, including the new properties added to the <code>View</code> class in 3.0. In the 3.1 release, which was made available recently, we added a small utility class that makes animating these properties even easier.</p><p>First, if you’re not familiar with the new <code>View</code> properties such as alpha and translationX, it might help for you to review the section in <a href="http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.html">that earlier article</a> that discusses these properties entitled, rather cleverly, “View properties”. Go ahead and read that now; I’ll wait.</p><p>Okay, ready?</p><h3>Refresher: Using <code>ObjectAnimator</code></h3><p>Using the <code>ObjectAnimator</code> class in 3.0, you could animate one of the <code>View</code> properties with a small bit of code. You create the <code>Animator</code>, set any optional properties such as the duration or repetition attributes, and start it. For example, to fade an object called myView out, you would animate the <code>alpha</code> property like this:</p><pre><code>    ObjectAnimator.ofFloat(myView, "alpha", 0f).start();</code></pre><p>This is obviously not terribly difficult, either to do or to understand. You’re creating and starting an animator with information about the object being animated, the name of the property to be animated, and the value to which it’s animating. Easy stuff.</p><p>But it seemed that this could be improved upon. In particular, since the <code>View</code> properties will be very commonly animated, we could make some assumptions and introduce some API that makes animating these properties as simple and readable as possible. At the same time, we wanted to improve some of the performance characteristics of animations on these properties. This last point deserves some explanation, which is what the next paragraph is all about.</p><p>There are three aspects of performance that are worth improving about the 3.0 animation model on <code>View</code> properties. One of the elements concerns the mechanism by which we animate properties in a language that has no inherent concept of “properties”. The other performance issues relate to animating multiple properties. When fading out a View, you may only be animating the alpha property. But when a view is being moved on the screen, both the x and y (or translationX and translationY) properties may be animated in parallel. And there may be other situations in which several properties on a view are animated in parallel. There is a certain amount of overhead per property animation that could be combined if we knew that there were several properties being animated.</p><p>The Android runtime has no concept of “properties”, so ObjectAnimator uses a technique of turning a String denoting the name of a property into a call to a setter function on the target object. For example, the String “alpha” gets turned into a reference to the <code>setAlpha()</code> method on View. This function is called through either reflection or JNI, mechanisms which work reliably but have some overhead. But for objects and properties that we know, like these properties on View, we should be able to do something better. Given a little API and knowledge about each of the properties being animated, we can simply set the values directly on the object, without the overhead associated with reflection or JNI.</p><p>Another piece of overhead is the <code>Animator</code> itself. Although all animations share a single timing mechanism, and thus don’t multiply the overhead of processing timing events, they are separate objects that perform the same tasks for each of their properties. These tasks could be combined if we know ahead of time that we’re running a single animation on several properties. One way to do this in the existing system is to use PropertyValuesHolder. This class allows you to have a single <code>Animator</code> object that animates several properties together and saves on much of the per-<code>Animator</code> overhead. But this approach can lead to more code, complicating what is essentially a simple operation. The new approach allows us to combine several properties under one animation in a much simpler way to write and read.</p><p>Finally, each of these properties on View performs several operations to ensure proper invalidation of the object and its parent. For example, translating a <code>View</code> in <code>x</code> invalidates the position that it used to occupy and the position that it now occupies, to ensure that its parent redraws the areas appropriately. Similarly, translating in <code>y</code> invalidates the before and after positions of the view. If these properties are both being animated in parallel, there is duplication of effort since these invalidations could be combined if we had knowledge of the multiple properties being animated. <code>ViewPropertyAnimator</code> takes care of this.</p><h3>Introducing: <code>ViewPropertyAnimator</code></h3><p><code>ViewPropertyAnimator</code> provides a simple way to animate several properties in parallel, using a single <code>Animator</code> internally. And as it calculates animated values for the properties, it sets them directly on the target <code>View</code> and invalidates that object appropriately, in a much more efficient way than a normal <code>ObjectAnimator</code> could.</p><p>Enough chatter: let’s see some code. For the fading-out view example we saw before, you would do the following with <code>ViewPropertyAnimator</code>:</p><pre><code>    myView.animate().alpha(0);</code></pre><p>Nice. It’s short and it’s very readable. And it’s also easy to combine with other property animations. For example, we could move our view in x and y to <code>(500, 500)</code> as follows:</p><pre><code>    myView.animate().x(500).y(500);</code></pre><p>There are a couple of things worth noting about these commands:</p><ul><li><p><code>animate()</code>: The magic of the system begins with a call to the new method animate() on the View object. This returns an instance of ViewPropertyAnimator, on which other methods are called which set the animation properties.</p></li><li><p>Auto-start: Note that we didn’t actually <code>start()</code> the animations. In this new API, starting the animations is implicit. As soon as you’re done declaring them, they will all begin. Together. One subtle detail here is that they will actually wait until the next update from the UI toolkit event queue to start; this is the mechanism by which <code>ViewPropertyAnimator</code> collects all declared animations together. As long as you keep declaring animations, it will keep adding them to the list of animations to start on the next frame. As soon as you finish and then relinquish control of the UI thread, the event queue mechanism kicks in and the animations begin.</p></li><li><p>Fluent: <code>ViewPropertyAnimator</code> has a <a href="http://en.wikipedia.org/wiki/Fluent_interface">Fluent</a> interface, which allows you to chain method calls together in a very natural way and issue a multi-property animation command as a single line of code. So all of the calls such as <code>x()</code> and <code>y()</code> return the <code>ViewPropertyAnimator</code> instance, on which you can chain other method calls.</p></li></ul><p>You can see from this example that the code is much simpler and more readable. But where do the performance improvements of <code>ViewPropertyAnimator</code> come in?</p><h3>Performance Anxiety</h3><p>One of the performance wins of this new approach exists even in this simple example of animating the <code>alpha</code> property. <code>ViewPropertyAnimator</code> uses no reflection or JNI techniques; for example, the alpha() method in the example operates directly on the underlying "alpha" field of a View, once per animation frame.</p><p>The other performance wins of <code>ViewPropertyAnimator</code> come in the ability to combine multiple animations. Let’s take a look at another example for this.</p><p>When you move a view on the screen, you might animate both the <code>x</code> and <code>y</code> position of the object. For example, this animation moves <code>myView</code> to x/y values of 50 and 100:</p><pre><code>    ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
    ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
    AnimatorSet animSetXY = new AnimatorSet();
    animSetXY.playTogether(animX, animY);
    animSetXY.start();</code></pre><p>This code creates two separate animations and plays them together in an <code>AnimatorSet</code>. This means that there is the processing overhead of setting up the <code>AnimatorSet</code> and running two <code>Animator</code>s in parallel to animate these x/y properties. There is an alternative approach using <code>PropertyValuesHolder</code> that you can use to combine multiple properties inside of one single <code>Animator</code>:</p><pre><code>    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
    ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
</code></pre><p>This approach avoids the multiple-<code>Animator</code> overhead, and is the right way to do this prior to <code>ViewPropertyAnimator</code>. And the code isn’t too bad. But using <code>ViewPropertyAnimator</code>, it all gets easier:</p><pre><code>    myView.animate().x(50f).y(100f);</code></pre><p>The code, once again, is simpler and more readable. And it has the same single-Animator advantage of the <code>PropertyValuesHolder</code> approach above, since <code>ViewPropertyAnimator</code> runs one single <code>Animator</code> internally to animate all of the properties specified.</p><p>But there’s one other benefit of the <code>ViewPropertyAnimator</code> example above that’s not apparent from the code: it saves effort internally as it sets each of these properties. Normally, when the <code>setX()</code> and <code>setY()</code> functions are called on <code>View</code>, there is a certain amount of calculation and invalidation that occurs to ensure that the view hierarchy will redraw the correct region affected by the view that moved. <code>ViewPropertyAnimator</code> performs this calculation once per animation frame, instead of once per property. It sets the underlying x/y properties of <code>View</code> directly and performs the invalidation calculations once for x/y (and any other properties being animated) together, avoiding the per-property overhead necessitated by the <code>ObjectAnimator</code> property approach.</p><h3>An Example</h3><p>I finished this article, looked at it ... and was bored. Because, frankly, talking about visual effects really begs having some things to look at. The tricky thing is that screenshots don’t really work when you’re talking about animation. (“In this image, you see that the button is moving. Well, not actually moving, but it was when I captured the screenshot. Really.”) So I captured a video of a small demo application that I wrote, and will through the code for the demo here.</p><p>Here’s the video. Be sure to turn on your speakers before you start it. The audio is really the best part.</p><iframe width="560" height="349" src="http://www.youtube.com/embed/abfLUJCCxsw" frameborder="0" allowfullscreen></iframe><p>In the video, the buttons on the upper left (“Fade In”, “Fade Out”, etc.) are clicked one after the other, and you can see the effect that those button clicks have on the button at the bottom (“Animating Button”). All of those animations happen thanks to the <code>ViewPropertyAnimator</code> API (of course). I’ll walk through the code for each of the individual animations below.</p><p>When the activity first starts, the animations are set up to use a longer duration than the default. This is because I wanted the animations to last long enough in the video for you to see. Changing the default duration for the <code>animatingButton</code> object is a one-line operation to retrieve the <code>ViewPropertyAnimator</code> for the button and set its duration:</p><pre><code>    animatingButton.animate().setDuration(2000);</code></pre><p>The rest of the code is just a series of <code>OnClickListener</code>objects set up on each of the buttons to trigger its specific animation. I’ll put the complete listener in for the first animation below, but for the rest of them I’ll just put the inner code instead of the listener boilerplate.</p><p>The first animation in the video happens when the Fade Out button is clicked, which causes Animating Button to (you guessed it) fade out. Here’s the listener for the <code>fadeOut</code> button which performs this action:</p><pre><code>    fadeOut.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            animatingButton.animate().alpha(0);
        }
    });
</code></pre><p>You can see, in this code, that we simply tell the object to animate to an alpha of 0. It starts from whatever the current alpha value is.</p><p>The next button performs a Fade In action, returning the button to an alpha value of 1 (fully opaque):</p><pre><code>    animatingButton.animate().alpha(1);</code></pre><p>The Move Over and Move Back buttons perform animations on two properties in parallel: x and y. This is done by chaining calls to those property methods in the animator call. For the Move Over button, we have the following:</p><pre><code>    int xValue = container.getWidth() - animatingButton.getWidth();
    int yValue = container.getHeight() - animatingButton.getHeight();
    animatingButton.animate().x(xValue).y(yValue);</code></pre><p>And for the Move Back case (where we just want to return the button to its original place at (0, 0) in its container), we have this code:</p><pre><code>    animatingButton.animate().x(0).y(0);</code></pre><p>One nuance to notice from the video is that, after the Move Over and Move Back animations were run, I then ran them again, clicking the Move Back animation while the Move Over animation was still executing. The second animation on the same properties (x and y) caused the first animation to cancel and the second animation to start from that point. This is an intentional part of the functionality of <code>ViewPropertyAnimator</code>. It takes your command to animate a property and, if necessary, cancels any ongoing animation on that property before starting the new animation.</p><p>Finally, we have the 3D rotation effect, where the button spins twice around the Y (vertical) axis. This is obviously a more complicated action and takes a great deal more code than the other animations (or not):</p><pre><code>    animatingButton.animate().rotationYBy(720);</code></pre><p>One important thing to notice in the rotation animations in the video is that they happen in parallel with part of the Move animations. That is, I clicked on the Move Over button, then the Rotate button. This caused the movement to stat, and then the Rotation to start while it was moving. Since each animation lasted for two seconds, the rotation animation finished after the movement animation was completed. Same thing on the return trip - the button was still spinning after it settled into place at <code>(0, 0)</code>. This shows how independent animations (animations that are not grouped together on the animator at the same time) create a completely separate <code>ObjectAnimator</code> internally, allowing the animations to happen independently and in parallel.</p><p>Play with the demo some more, check out the code, and groove to the awesome soundtrack for 16.75. And if you want the code for this incredibly complex application (which really is nothing more than five <code>OnClick</code> listeners wrapping the animator code above), you can <a href="https://sites.google.com/site/androidcontentfromchet/downloads/VPADemo.zip">download it from here</a>.</p><h3>And so...</h3><p>For the complete story on ViewPropertyAnimator, you might want to see the SDK documentation. First, there’s the <code><a href="http://developer.android.com/reference/android/view/View.html#animate()">animate()</a></code> method in <code>View</code>. Second, there’s the <code><a href="http://developer.android.com/reference/android/view/ViewPropertyAnimator.html">ViewPropertyAnimator</a></code> class itself. I’ve covered the basic functionality of that class in this article, but there are a few more methods in there, mostly around the various properties of <code>View</code> that it animates. Thirdly, there’s ... no, that’s it. Just the method in View and the ViewPropertyAnimator class itself.</p><p><code>ViewPropertyAnimator</code> is not meant to be a replacement for the property animation APIs added in 3.0. Heck, we just added them! In fact, the animation capabilities added in 3.0 provide important plumbing for <code>ViewPropertyAnimator</code> as well as other animation capabilities in the system overall. And the capabilities of <code>ObjectAnimator</code> provide a very flexible and easy to use facility for animating, well, just about anything! But if you want to easily animate one of the standard properties on <code>View</code> and the more limited capabilities of the <code>ViewPropertyAnimator</code> API suit your needs, then it is worth considering.</p><p>Note: I don’t want to get you too worried about the overhead of <code>ObjectAnimator</code>; the overhead of reflection, JNI, or any of the rest of the animator process is quite small compared to what else is going on in your program. it’s just that the efficiencies of <code>ViewPropertyAnimator</code> offer some advantages when you are doing lots of <code>View</code> property animation in particular. But to me, the best part about the new API is the code that you write. It’s the best kind of API: concise and readable. Hopefully you agree and will start using <code>ViewPropertyAnimator</code> for your view property animation needs.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1988587254462660030?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/introducing-viewpropertyanimator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>ADK at Maker Faire</title>
		<link>https://googledata.org/google-android/adk-at-maker-faire/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=adk-at-maker-faire</link>
		<comments>https://googledata.org/google-android/adk-at-maker-faire/#comments</comments>
		<pubDate>Fri, 20 May 2011 16:37:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=4d7d134cfb5c3b619eb11175387268d0</guid>
		<description><![CDATA[This weekend is Maker Faire, and Google is all over it.Following up on yesterday’s ADK post, we should take this opportunity to note that the Faire has chased a lot of ADK-related activity out of the woodwork.  The level of traction is pretty surpris...]]></description>
				<content:encoded><![CDATA[<p>This weekend is <a href="http://makerfaire.com/">Maker Faire</a>, and Google is <a href="http://googleblog.blogspot.com/2011/05/join-us-at-maker-faire.html">all over it</a>.</p><p>Following up on yesterday’s <a href="http://android-developers.blogspot.com/2011/05/bright-idea-android-open-accessories.html">ADK post</a>, we should take this opportunity to note that the Faire has chased a lot of ADK-related activity out of the woodwork.  The level of traction is pretty surprising giving that this stuff only decloaked last week.</p><h3>Convenience Library</h3><p>First, there’s a new open-source project called <a href="http://code.google.com/p/easy-peripheral-controller/">Easy Peripheral Controller</a>. This is a bunch of convenience/abstraction code; its goal is to help n00bs make their first robot or hardware project with Android.  It takes care of lots of the mysteries of microcontroller wrangling in general and Arduino in particular.</p><h3>Bits and Pieces from Googlers at the Faire</h3><p>Most of these are 20%-project output.</p><p><b>Project Tricorder</b>: Using the ADK and Android to build a platform to support making education about data collection and scientific process more interesting.</p><p><b>Disco Droid</b>: Modified a bugdroid with servos and the ADK to show off some <a href="http://www.youtube.com/watch?v=jwvkJVUECrg">Android dance moves</a>. </p><p><b>Music Beta, by Google</b>: Android + ADK + cool box with lights for a Music Beta demo.</p><p><b>Optical Networking</b>: Optical network port connected to the ADK.</p><p><b>Interactive Game</b>: Uses ultrasonic sensors and ADK to control an Android game.</p><p><b>Robot Arm</b>: Phone controlling robot arm for kids to play with.</p><p><b>Bugdroids</b>: Balancing Bugdroids running around streaming music from an Android phone.</p><h3>The Boards</h3><p>We gave away an ADK hardware dev kit sample to several hundred people at Google I/O, with the idea of showing manufacturers what kind of thing might be useful.   This seems to have worked better than we’d expected; we know of no less than <em>seven</em> makers working on Android Accessory Development Kits. Most of these are still in “Coming Soon” mode, but you’ll probably be able to get your hands on some at the Faire.</p><ol><li><p>RT Technology's <a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&amp;cPath=3_4&amp;products_id=1">board</a> is pretty much identical to the kit we handed out at I/O.</p></li><li><p>SparkFun has one in the works, coming soon.</p></li><li><p>Also, SparkFun’s <a href="http://www.sparkfun.com/products/10585">existing IOIO product</a> will be getting ADK-compatible firmware.</p></li><li><p>Arduino themselves also have an ADK bun in the oven.</p></li><li><p>Seeedstudio’s <a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">Seeeeduino Main Board</a>.</p></li><li><p>3D Robotics’ <a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">PhoneDrone Board</a>.</p></li><li><p>Microchip’s <a href="http://www.microchipdirect.com/ProductSearch.aspx?Keywords=DM240415">Accessory Development Starter Kit</a>.</p></li></ol><p>It looks like some serious accessorized fun is in store!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-249246057185003582?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/adk-at-maker-faire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Bright Idea: Android Open Accessories</title>
		<link>https://googledata.org/google-android/a-bright-idea-android-open-accessories/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-bright-idea-android-open-accessories</link>
		<comments>https://googledata.org/google-android/a-bright-idea-android-open-accessories/#comments</comments>
		<pubDate>Thu, 19 May 2011 16:54:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=cef3d0af6c4a7b924da93b64518a41a2</guid>
		<description><![CDATA[[This post is by  Justin Mattson, an Android Developer Advocate, and Erik Gilling, an engineer on the Android systems team.&#160;&#8212;&#160;Tim&#160;Bray]Android’s USB port has in the past been curiously inaccessible to programmers.  Last week at G...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-6gPYIOHI21k/TdVeaVkU4fI/AAAAAAAAAco/loQTjdLFPVw/s1600/androidusb.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 296px; height: 320px;" src="http://1.bp.blogspot.com/-6gPYIOHI21k/TdVeaVkU4fI/AAAAAAAAAco/loQTjdLFPVw/s320/androidusb.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5608492717518938610" /></a><p><i>[This post is by  <a href="http://twitter.com/cyngus">Justin Mattson</a>, an Android Developer Advocate, and <a href="http://www.bltww.com/">Erik Gilling</a>, an engineer on the Android systems team.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Android’s USB port has in the past been curiously inaccessible to programmers.  Last week at <a href="http://www.google.com/events/io/2011/%20">Google I/O</a> we <a href="http://www.youtube.com/watch?v=OxzucwjFEEs#t=36m10s">announced</a> the Android Open Accessory APIs for Android. These APIs allow USB accessories to connect to Android devices running Android 3.1 or Android 2.3.4 without special licensing or fees. The new “accessory mode” does not require the Android device to support USB Host mode. This post will concentrate on accessory mode, but we also announced USB Host mode APIs for devices with hardware capable of supporting it.</p><p>To understand why having a USB port is not sufficient to support accessories let’s quickly look at how USB works. USB is an asymmetric protocol in that one participant acts as a USB Host and all other participants are USB Devices. In the PC world, a laptop or desktop acts as Host and your printer, mouse, webcam, etc., is the USB Device. The USB Host has two important tasks. The first is to be the bus master and control which device sends data at what times. The second key task is to provide power, since USB is a powered bus.</p><p>The problem with supporting accessories on Android in the traditional way is that relatively few devices support Host mode. Android’s answer is to turn the normal USB relationship on its head. In accessory mode the Android phone or tablet acts as the USB Device and the accessory acts as the USB Host. This means that the accessory is the bus master and provides power.</p><h3>Establishing the Connection</h3><p>Building an Open Accessory is simple as long as you include a USB host and can provide power to the Android device.  The accessory needs to implement a simple handshake to establish a bi-directional connection with an app running on the Android device.</p><p>The handshake starts when the accessory detects that a device has been connected to it. The Android device will identify itself with the VID/PID that is appropriate based on the manufacturer and model of the device. The accessory then sends a control transaction to the Android device asking if it supports accessory mode.</p><p>Once the accessory confirms the Android device supports accessory mode, it sends a series of strings to the Android device using control transactions. These strings allow the Android device to identify compatible applications as well as provide a URL that Android will use if a suitable app is not found. Next the accessory sends a control transaction to the Android device telling it to enter accessory mode.</p><p>The Android device then drops off the bus and reappears with a new VID/PID combination. The new VID/PID corresponds to a device in accessory mode, which is Google’s VID 0x18D1, and PID 0x2D01 or 0x2D00. Once an appropriate application is started on the Android side, the accessory can now communicate with it using the first Bulk IN and Bulk OUT endpoints.</p><p>The protocol is easy to implement on your accessory. If you’re using the <a href="http://developer.android.com/guide/topics/usb/adk.html">ADK</a> or other USB Host Shield compatible Arduino you can use the <a href="https://android.git.kernel.org/?p=device/google/accessory/arduino.git;a=tree">AndroidAccessory library</a> to implement the protocol. The ADK is one easy way to get started with accessory mode, but any accessory that has the required hardware and speaks the protocol described here and laid out in detail in the <a href="http://developer.android.com/guide/topics/usb/adk.html#how">documentation</a> can function as an Android Open Accessory.</p><h3>Communicating with the Accessory</h3><p>After the low-level USB connection is negotiated between the Android device and the accessory, control is handed over to an Android application. Any Android application can register to handle communication with any USB accessory. Here is how that would be declared in your AndroidManifest.xml:</p><pre><code>&lt;activity android:name=".UsbAccessoryActivity" android:label="@string/app_name">
    &lt;intent-filter>
        &lt;action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
    &lt;/intent-filter>

    &lt;meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
               android:resource="@xml/accessory_filter" />
&lt;/activity></code></pre><p>Here's how you define the accessories the Activity supports:</p><pre><code>&lt;resources>
    &lt;usb-accessory manufacturer="Acme, Inc" model="Whiz Banger" version="7.0" />
&lt;/resources></code></pre><p>The Android system signals that an accessory is available by issuing an Intent and then the user is presented with a dialog asking what application should be opened. The accessory-mode protocol allows the accessory to specify a URL to present to the user if no application is found which knows how communicate with it. This URL could point to an application in Android Market designed for use with the accessory.</p><p>After the application opens it uses the Android Open Accessory APIs in the SDK to communicate with the accessory. This allows the opening of a single FileInputStream and single FileOutputStream to send and receive arbitrary data. The protocol that the application and accessory use is then up to them to define.</p><p>Here’s some basic example code you could use to open streams connected to the accessory:</p><pre><code>public class UsbAccessoryActivity extends Activity {
    private FileInputStream mInput;
    private FileOutputStream mOutput;

    private void openAccessory() {
        UsbManager manager = UsbManager.getInstance(this);
        UsbAccessory accessory = UsbManager.getAccessory(getIntent());

        ParcelFileDescriptor fd = manager.openAccessory(accessory);

        if (fd != null) {
            mInput = new FileInputStream(fd);
            mOutput = new FileOutputStream(fd);
        } else {
            // Oh noes, the accessory didn’t open!
        }
    }
}</code></pre><h3>Future Directions</h3><p>There are a few ideas we have for the future. One issue we would like to address is the “power problem”. It’s a bit odd for something like a pedometer to provide power to your Nexus S while it’s downloading today’s walking data. We’re investigating ways that we could have the USB Host provide just the bus mastering capabilities, but not power. Storing and listening to music on a phone seems like a popular thing to do so naturally we’d like to support audio over USB. Finally, figuring out a way for phones to support common input devices would allow for users to be more productive. All of these features are exciting and we hope will be supported by a future version of Android.</p><p>Accessory mode opens up Android to a world of new possibilities filled with lots of new friends to talk to. We can’t wait to see what people come up with. The <a href="http://developer.android.com/guide/topics/usb/adk.html">docs</a> and <a href="http://android.git.kernel.org/?p=device/google/accessory/demokit.git;a=summary">samples</a> are online; have at it!</p><p><i>[Android/USB graphic by Roman Nurik.]</i></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8454183178749627148?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/a-bright-idea-android-open-accessories/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Commerce Tracking with Google Analytics for Android</title>
		<link>https://googledata.org/google-android/commerce-tracking-with-google-analytics-for-android/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=commerce-tracking-with-google-analytics-for-android</link>
		<comments>https://googledata.org/google-android/commerce-tracking-with-google-analytics-for-android/#comments</comments>
		<pubDate>Thu, 05 May 2011 20:52:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=96dd56cc89c04b51ff6133c87a3b0258</guid>
		<description><![CDATA[[This post is by Jim Cotugno and Nick Mihailovski, engineers who work on Google Analytics&#160;&#8212;&#160;Tim&#160;Bray]Today we released a new version of the Google Analytics Android SDK which includes support for tracking e-commerce transactions.  ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Jim Cotugno and Nick Mihailovski, engineers who work on Google Analytics&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Today we released a new version of the Google Analytics Android SDK which includes support for tracking e-commerce transactions.  This post walks you through setting it up in your mobile application.</p><h3>Why It’s Important</h3><p>If you allow users to purchase goods in your application, you’ll want to understand how much revenue your application generates as well as which products are most popular.</p><p>With the new e-commerce tracking functionality in the Google Analytics Android SDK, this is easy.</p><h3>Before You Begin</h3><p>In this post, we assume you’ve already configured the Google Analytics Android SDK to work in your application. Check out <a href="http://code.google.com/mobile/analytics/docs/android/%20">our SDK docs</a> if you haven’t already.</p><p>We also assume you have a Google Analytics tracking object instance declared in your code:</p><pre><code>GoogleAnalyticsTracker tracker;</code></pre><p>Then in the activity’s onCreate method, you have initialized the tracker member variable and called start:</p><pre><code>tracker = GoogleAnalyticsTracker.getInstance();
tracker.start("UA-YOUR-ACCOUNT-HERE", 30, this);</code></pre><h3>Setting Up The Code</h3><p>The best way to track a transaction is when you’ve received confirmation for a purchase.  For example, if you have a callback method that is called when a purchase is confirmed, you would call the tracking code there.  </p><pre><code>public void onPurchaseConfirmed(List<PurchaseObject> purchases) {
 // Use Google Analytics to record the purchase information here...
}</code></pre><h3>Tracking The Transaction</h3><p>The Google Analytics Android SDK provides its own Transaction object to store values Google Analytics collects. The next step is to copy the values from the list of PurchaseObjects into a Transaction object.</p><p>The SDK’s Transaction object uses the builder pattern, where the constructor takes the required arguments and the optional arguments are set using setters:</p><pre><code>Transaction.Builder builder = new Transaction.Builder(
   purchase.getOrderId(),
   purchase.getTotal())
       .setTotalTax(purchase.getTotalTax())
       .setShippingCost(purchase.getShippingCost()
       .setStoreName(purchase.getStoreName());</code></pre><p>You then add the transaction by building it and passing it to a Google Analytics tracking Object:</p><pre><code>tracker.addTransaction(builder.build());</code></pre><h3>Tracking Each Item</h3><p>The next step is to track each item within the transaction. This is similar to tracking transactions, using the Item class provided by the Google Analytics SDK for Android. Google Analytics uses the OrderID as a common ID to associate a set of items to it’s parent transaction.</p><p>Let’s say the PurchaseObject above has a list of one or more LineItem objects. You can then iterate through each LineItem and create and add the item to the tracker.</p><pre><code>for (ListItem listItem : purchase.getListItems()) {
  Item.Builder itemBuilder = new Item.Builder(
      purchase.getOrderId(),
      listItem.getItemSKU(),
      listItem.getPrice(),
      listItem.getCount())
          .setItemCategory(listItem.getItemCategory())
          .setItemName(listItem.getItemName());

  // Now add the item to the tracker. The order ID is the key
  // Google Analytics uses to associate this item to the transaction.
  tracker.addItem(itemBuilder.build());
}</code></pre><h3>Sending the Data to Google Analytics</h3><p>Finally once all the transactions and items have been added to the tracker, you call:</p><pre><code>tracker.trackTransactions();</code></pre><p>This sends the transactions to the dispatcher, which will transmit the data to Google Analytics.</p><h3>Viewing The Reports</h3><p>Once data has been collected, you can then log into the Google Analytics Web Interface and go to the Conversions > Ecommerce > Product Performance report to see how much revenue each product generated.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-fmzQa1c5-VI/TcMPk3Z4beI/AAAAAAAAAcY/6u3uPpy9EDs/s1600/ecommerce.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 261px;" src="http://1.bp.blogspot.com/-fmzQa1c5-VI/TcMPk3Z4beI/AAAAAAAAAcY/6u3uPpy9EDs/s400/ecommerce.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5603339487401242082" /></a><p>Here we see that many people bought potions, which generated the most revenue for our application. Also, more people bought the blue sword than the red sword, which could mean we need to stock more blue items in our application.  Awesome!</p><h3>Learning More</h3><p>You can learn more about the new e-commerce tracking feature in the <a href="http://code.google.com/mobile/analytics/docs/android/">Google Analytics SDK for Android</a> developer documentation. </p><p>What’s even better is that we’ll be demoing all this new functionality this year at Google IO, in the <cite>Optimizing Android Apps With Google Analytics</cite> session.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5455646294646930134?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/commerce-tracking-with-google-analytics-for-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Customizing the Action Bar</title>
		<link>https://googledata.org/google-android/customizing-the-action-bar/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=customizing-the-action-bar</link>
		<comments>https://googledata.org/google-android/customizing-the-action-bar/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 21:28:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=a4154bcb17c1cdd963f98c4915509091</guid>
		<description><![CDATA[[This post is by Nick Butcher, an Android engineer who notices small imperfections, and they annoy him.&#160;&#8212;&#160;Tim&#160;Bray]Since the introduction of the Action Bar design pattern, many applications have adopted it as a way to provide easy ...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-BedyJC2N3Jw/TaYYDLK03tI/AAAAAAAAAWk/EmIS_WZ9Q9A/s1600/Nick.jpg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 133px; height: 200px;" src="http://1.bp.blogspot.com/-BedyJC2N3Jw/TaYYDLK03tI/AAAAAAAAAWk/EmIS_WZ9Q9A/s200/Nick.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5595186029871292114" /></a><p><i>[This post is by <a href="http://twitter.com/crafty">Nick Butcher</a>, an Android engineer who notices small imperfections, and they annoy him.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>Since the <a href="http://android-developers.blogspot.com/2010/05/twitter-for-android-closer-look-at.html">introduction</a> of the Action Bar design pattern, many applications have adopted it as a way to provide easy access to common actions.  In Android 3.0 (or Honeycomb to its friends) this pattern has been baked in as the default navigation paradigm and extended to take advantage of the extra real-estate available on tablets.  By <a href="http://developer.android.com/guide/topics/ui/actionbar.html%20">using the Action Bar</a> in your Honeycomb-targeted apps, you'll give your users a familiar way to interact with your application.   Also, your app will be better prepared to scale across the range of Android devices that will be arriving starting in the Honeycomb era.</p><p>Just because Action Bars are familiar, doesn’t mean that they have to be identical!  The following code samples and accompanying <a href="http://code.google.com/p/styled-action-bar/">project</a> demonstrate how to <a href="http://developer.android.com/guide/topics/ui/actionbar.html#Style">style</a> the Action Bar to match your application’s branding.  I’ll demonstrate how to take Honeycomb’s <code>Holo.Light</code> theme and customise it to match this blog’s colour scheme.</p><pre><code>&lt;style name="Theme.AndroidDevelopers" parent="android:style/Theme.Holo.Light">
…
&lt;/style></code></pre><h3>Icon</h3><p>This step is easy; I’ll use the wonderful <a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio</a> to create an icon in my chosen colour scheme.  For extra credit, I’ll use this image as a starting point to create a more branded <a href="http://developer.android.com/reference/android/app/ActionBar.html#setDisplayUseLogoEnabled(boolean)">logo</a>.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-VjORQbP9RUs/TaXcTZo3yxI/AAAAAAAAAU8/u8setg3cDd0/s1600/I1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 371px; height: 56px;" src="http://4.bp.blogspot.com/-VjORQbP9RUs/TaXcTZo3yxI/AAAAAAAAAU8/u8setg3cDd0/s400/I1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595120337935649554" /></a><h3>Navigation</h3><p>Next up, the navigation section of the Action Bar operates in three different <a href="http://developer.android.com/reference/android/app/ActionBar.html#setDisplayUseLogoEnabled(boolean)">modes</a>; I’ll tackle each of these in turn.</p><h4>Standard</h4><p>The Action Bar’s standard navigation mode simply displays the title of the activity.  This doesn’t require any styling... next!</p><h4>List</h4><p>To the left, a standard list drop-down; to the right, the effect we want to achieve.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-iq8YXQBQjTo/TaXccBS9wZI/AAAAAAAAAVE/3NdspdF2eB4/s1600/I2.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 154px;" src="http://1.bp.blogspot.com/-iq8YXQBQjTo/TaXccBS9wZI/AAAAAAAAAVE/3NdspdF2eB4/s400/I2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595120486020137362" /></a><p>The default styling in list navigation mode has a blue colour scheme.  This is evident when touching the collapsed control in both the top bar, and the selection highlight in the expanded list.  We can theme this element by overriding <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_actionDropDownStyle">android:actionDropDownStyle</a> with a custom style to implement our colour scheme:</p><pre><code>&lt;!-- style the list navigation -->
&lt;style name="MyDropDownNav" parent="android:style/Widget.Holo.Light.Spinner.DropDown.ActionBar">
    &lt;item name="android:background">@drawable/ad_spinner_background_holo_light&lt;/item>
    &lt;item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light&lt;/item>
    &lt;item name="android:dropDownSelector">@drawable/ad_selectable_background&lt;/item>
&lt;/style></code></pre><p>The above uses a combination of <a href="http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList">state list drawables</a> and <a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch">9 patch images</a> to style the collapsed spinner, the top bar of the expanded list and sets the highlight colour when picking an item.</p><h3>Tabs</h3><p>Here are the before-and-after shots on the tab navigation control:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-VTV2MmoW1Ig/TaXckPVWEzI/AAAAAAAAAVM/hJ0FFVCNUTs/s1600/I3.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 144px;" src="http://2.bp.blogspot.com/-VTV2MmoW1Ig/TaXckPVWEzI/AAAAAAAAAVM/hJ0FFVCNUTs/s400/I3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595120627227169586" /></a><p>The tab navigation control uses the standard blue colouring.  We can apply a custom style to <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_actionBarTabStyle">android:actionBarTabStyle</a> to set our own custom drawable that uses our desired palette:</p><pre><code>&lt;!-- style for the tabs -->
&lt;style name="MyActionBarTabStyle" parent="android:style/Widget.Holo.Light.ActionBarView_TabView">
    &lt;item name="android:background">@drawable/actionbar_tab_bg&lt;/item>
    &lt;item name="android:paddingLeft">32dp&lt;/item>
    &lt;item name="android:paddingRight">32dp&lt;/item>
&lt;/style></code></pre><h3>Actions</h3><p>Before-and-after on the individual items in the Action Bar:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-pSrGmu1ZGaI/TaXdUL8MXXI/AAAAAAAAAVk/hbe_m-1QIf8/s1600/I4.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 139px;" src="http://4.bp.blogspot.com/-pSrGmu1ZGaI/TaXdUL8MXXI/AAAAAAAAAVk/hbe_m-1QIf8/s400/I4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595121450950090098" /></a><p>The individual action items inherit the default blue background when selected.  We can customise this behaviour by overriding <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_selectableItemBackground">android:selectableItemBackground</a> and setting a shape drawable with our desired colouring:</p><pre><code>&lt;item name="android:selectableItemBackground">@drawable/ad_selectable_background&lt;/item></code></pre><p>The overflow menu also needs some attention as when expanded it shows a blue bar at the top of the list.  We can override <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_popupMenuStyle">android:popupMenuStyle</a> and set a custom drawable (in fact the very same drawable we previously used for list navigation) for the top of the overflow menu:</p><pre><code>&lt;!-- style the overflow menu -->
&lt;style name="MyPopupMenu" parent="android:style/Widget.Holo.Light.ListPopupWindow">
    &lt;item name="android:popupBackground">@drawable/ad_menu_dropdown_panel_holo_light&lt;/item> 
&lt;/style></code></pre><p>Selecting items within the overflow menu also show the default selection colour.  We can set our customised selection colour by overriding <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_dropDownListViewStyle">android:dropDownListViewStyle</a>:</p><pre><code>&lt;!-- style the items within the overflow menu -->
&lt;style name="MyDropDownListView" parent="android:style/Widget.Holo.ListView.DropDown">
    &lt;item name="android:listSelector">@drawable/ad_selectable_background&lt;/item>
&lt;/style></code></pre><p>These changes gets us most of the way there but it’s attention to detail that makes an app.  Check boxes and radio buttons within menu items in the overflow section are still using the default assets which have a blue highlight.  Let’s override them to fit in with our theme:</p><pre><code>&lt;item name="android:listChoiceIndicatorMultiple">@drawable/ad_btn_check_holo_light&lt;/item>
&lt;item name="android:listChoiceIndicatorSingle">@drawable/ad_btn_radio_holo_light&lt;/item></code></pre><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-X_Zw69Umrko/TaXdcr8smYI/AAAAAAAAAVs/dvXhHeOK6wg/s1600/I5.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 196px;" src="http://2.bp.blogspot.com/-X_Zw69Umrko/TaXdcr8smYI/AAAAAAAAAVs/dvXhHeOK6wg/s400/I5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595121596981090690" /></a><h3>Background</h3><p>I’ve left the background transparent as inheriting form Holo.Light works well for our desired palette.  If you’d like to customise it you easily override the <code>android:background</code> item on the <a href="http://developer.android.com/reference/android/R.styleable.html#Theme_actionBarStyle">android:actionBarStyle</a> style:</p><pre><code>&lt;style name="MyActionBar" parent="android:style/Widget.Holo.Light.ActionBar">
    &lt;item name="android:background">@drawable/action_bar_background&lt;/item>
&lt;/style></code></pre><h3>Bringing it all together</h3><p>Putting all of these components together we can create a custom style:</p><pre><code>&lt;style name="Theme.AndroidDevelopers" parent="android:style/Theme.Holo.Light">
    &lt;item name="android:selectableItemBackground">@drawable/ad_selectable_background&lt;/item>
    &lt;item name="android:popupMenuStyle">@style/MyPopupMenu&lt;/item>
    &lt;item name="android:dropDownListViewStyle">@style/MyDropDownListView&lt;/item>
    &lt;item name="android:actionBarTabStyle">@style/MyActionBarTabStyle&lt;/item>
    &lt;item name="android:actionDropDownStyle">@style/MyDropDownNav&lt;/item>
    &lt;item name="android:listChoiceIndicatorMultiple">@drawable/ad_btn_check_holo_light&lt;/item>
    &lt;item name="android:listChoiceIndicatorSingle">@drawable/ad_btn_radio_holo_light&lt;/item>
&lt;/style></code></pre><p>We can then apply this style to either an individual activity or to the entire application:</p><pre><code>
&lt;activity android:name=".MainActivity" 
          android:label="@string/app_name"
          android:theme="@style/Theme.AndroidDevelopers"
          android:logo="@drawable/ad_logo"></code></pre><p>Note that some of the system styles that we have overridden in this example will affect much more than the Action Bar.  For example overriding android:selectableItemBackground will effect many widgets which support a selectable state.  This is useful for styling your entire application but be sure to test that your customisations are applied consistently throughout.</p><h3>Familiar but styled</h3><p>Customising the action bar is a great way to extend your application’s branding to the standard control components.  With this power, as they say, comes great responsibility.  When customising the user interface you must take great care to ensure that your application remains legible and navigable.  In particular, watch out for highlight colours which contrast poorly with text and provide drawables for all relevant states.  Explore <a href="http://code.google.com/p/styled-action-bar/">this demo application</a> which exercises the functionality offered by the Action Bar and demonstrates how to theme it.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4881470559283876096?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/customizing-the-action-bar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Developer Challenge, Sub-Saharan Africa!</title>
		<link>https://googledata.org/google-android/android-developer-challenge-sub-saharan-africa/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=android-developer-challenge-sub-saharan-africa</link>
		<comments>https://googledata.org/google-android/android-developer-challenge-sub-saharan-africa/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 18:46:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=a9a79377c971f31406b0288e97667dbc</guid>
		<description><![CDATA[[This post is by  Bridgette Sexton, an innovation advocate for the African tech community.&#160;&#8212;&#160;Tim&#160;Bray]En Français.In the past year alone, we have met with over 10,000 developers and techies across Sub Saharan Africa. We are contin...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by  Bridgette Sexton, an innovation advocate for the African tech community.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p><a href="http://google-africa.blogspot.com/2011/04/android-developer-challenge-sub-saharan.html#french44">En Français</a>.</p><p>In the past year alone, we have met with over 10,000 developers and techies across Sub Saharan Africa. We are continually impressed by the ingenuity and enthusiasm of this community in solving real problems with technology. From applications that crowd-source traffic info to mobile registration of local businesses, handheld devices have taken center stage for consumers and developers in Africa.  With a number of countries in the region hovering around 80-90% mobile penetration, mobile is the screen size for the web and the communication experience. </p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-3f3Z4pRTCRM/TaXxjzD6eeI/AAAAAAAAAWE/5OJm_JINbr8/s1600/hands.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 376px;" src="http://1.bp.blogspot.com/-3f3Z4pRTCRM/TaXxjzD6eeI/AAAAAAAAAWE/5OJm_JINbr8/s400/hands.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5595143709382048226" /></a><p>Correspondingly, at every Google event in Africa, Android is the hottest topic; we know why.  Every day over 300,000 Android devices are activated globally! A growing number of these mobile devices are powering on for the first time in emerging markets like those in Africa. As Android users multiply, so does the appeal to for developers of building apps on this free open-source platform.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.google.com/insights/search/#q=android&geo=KE,ZA,SN&date=3/2008%2037m&cmpt=geo"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 500px; height: 198px;" src="http://1.bp.blogspot.com/-nzB725SaKOA/TacKFAtP_tI/AAAAAAAAAWs/GL18oTrBp4s/s400/trend.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5595452143236546258" /></a><p style="text-align: center;"><i>An increasing number of users are searching for 'Android' on Google in Sub-Saharan Africa</i></p><p>For all these reasons and more, we are proud to be launching the <a href="http://code.google.com/android/adcafrica">Android Developer Challenge for Sub-Saharan Africa</a>!</p><p>The Android Developer Challenge is designed to encourage the creation of cool and innovative Android mobile apps built by developers in Sub-Saharan Africa. Invent apps that delight users and you stand a chance to <em>win an Android phone and $25,000 USD</em>. To get started, choose from one of three defined eligible categories (see below), build an Android app in a team or by yourself, and submit it via the competition website by July 1st. The winning app will be announced on September 12th at G-Kenya. Get more details as well as Terms and Conditions on <a href="http://code.google.com/android/adcafrica/terms.html">our site</a>. </p><p>Categories for Entry:</p><ul><li><p>Entertainment / Media / Games</p></li><li><p>Social Networking / Communication</p></li><li><p>Productivity / Tools / Lifestyle</p></li></ul><p><i>(See <a href="http://code.google.com/android/adcafrica/terms.html">Terms &amp; Conditions</a> for more details!)</i></p><p>To launch this competition, we have teamed up with <a href="http://www.gtugs.org/">Google Technology User Groups</a> (GTUGs) across Africa to host Android Developer Challenge events. Check out our website for Android gatherings near you, and get coding! </p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2466540337821465424?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-developer-challenge-sub-saharan-africa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>I think I’m having a Gene Amdahl moment (http://goo.gl/7v4kf)</title>
		<link>https://googledata.org/google-android/i-think-i%e2%80%99m-having-a-gene-amdahl-moment-httpgoo-gl7v4kf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=i-think-i%25e2%2580%2599m-having-a-gene-amdahl-moment-httpgoo-gl7v4kf</link>
		<comments>https://googledata.org/google-android/i-think-i%e2%80%99m-having-a-gene-amdahl-moment-httpgoo-gl7v4kf/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 00:41:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=bb6645b5f1ffb6c12b60933f87623f27</guid>
		<description><![CDATA[[This post is by Andy Rubin, VP of Engineering&#160;&#8212;Tim Bray]Recently, there’s been a lot of misinformation in the press about Android and Google’s role in supporting the ecosystem. I’m writing in the spirit of transparency and in an attem...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Andy Rubin, VP of Engineering&nbsp;&mdash;Tim Bray]</i></p><p>Recently, there’s been a lot of misinformation in the press about Android and Google’s role in supporting the ecosystem. I’m writing in the spirit of transparency and in an attempt to set the record straight.  The Android community has grown tremendously since the launch of the first Android device in October 2008, but throughout we’ve remained committed to fostering the development of an open platform for the mobile industry and beyond.</p><p>We don’t believe in a “one size fits all” solution. The Android platform has already spurred the development of hundreds of different types of devices – many of which were not originally contemplated when the platform was first created. What amazes me is that even though the quantity and breadth of Android products being built has grown tremendously, it’s clear that quality and consistency continue to be top priorities.  Miraculously, we are seeing the platform take on new use cases, features and form factors as it’s being introduced in new categories and regions while still remaining consistent and compatible for third party applications.</p><p>As always, device makers are free to modify Android to customize any range of features for Android devices. This enables device makers to support the unique and differentiating functionality of their products.  If someone wishes to market a device as Android-compatible or include Google applications on the device, we do require the device to conform with some <a href="http://source.android.com/compatibility/overview.html">basic compatibility requirements</a>.  (After all, it would not be realistic to expect Google applications – or any applications for that matter – to operate flawlessly across incompatible devices).  Our “anti-fragmentation” program has been in place since Android 1.0 and remains a priority for us to provide <a href="http://android-developers.blogspot.com/2010/05/on-android-compatibility.html">a great user experience for consumers and a consistent platform for developers</a>. In fact, all of the founding members of the Open Handset Alliance agreed not to fragment Android when we first announced it in 2007.  Our approach remains unchanged: there are no lock-downs or restrictions against customizing UIs. There are not, and never have been, any efforts to standardize the platform on any single chipset architecture.</p><p>Finally, we continue to be an open source platform and will continue releasing source code when it is ready.  As I write this the Android team is still hard at work to bring all the new Honeycomb features to phones. As soon as this work is completed, we’ll publish the code. This temporary delay does not represent a change in strategy. We remain firmly committed to providing Android as an open source platform across many device types.</p><p>The volume and variety of Android devices in the market continues to exceed even our most optimistic expectations. We will continue to work toward an open and healthy ecosystem because we truly believe this is best for the industry and best for consumers.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1300495219992493265?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/i-think-i%e2%80%99m-having-a-gene-amdahl-moment-httpgoo-gl7v4kf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The IO Ticket Contest</title>
		<link>https://googledata.org/google-android/the-io-ticket-contest/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-io-ticket-contest</link>
		<comments>https://googledata.org/google-android/the-io-ticket-contest/#comments</comments>
		<pubDate>Fri, 01 Apr 2011 18:17:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=ec247e83b557dfae2e6dd824d63063ae</guid>
		<description><![CDATA[When Google I/O sold out so fast, were kicking around ideas for how to get some of our ticket reserve into the hands of our favorite people: Dedicated developers.  Someone floated the idea of a contest, so we had to pull one together double-quick.  You...]]></description>
				<content:encoded><![CDATA[<p>When Google I/O sold out so fast, were kicking around ideas for how to get some of our ticket reserve into the hands of our favorite people: Dedicated developers.  Someone floated the idea of a contest, so we had to pull one together double-quick.  You can read the questions and first-round answers <a href='https://sites.google.com/site/lastcallforio2011/quickfire-submissions'>here</a>.</p><p>We thought you would enjoy some statistics, mostly rounded-off:</p><ul><li><p><b>2,800</b> people visited the contest page.</p></li><li><p><b>360</b> people tried answering the questions.</p></li><li><p><b>1</b> person got all six right.</p></li><li><p><b>200</b> people did well enough to get into Round 2.</p></li><li><p><b>70</b> people submitted apps.</p></li><li><p><b>38</b> of the apps worked well enough to be worth considering.</p></li><li><p><b>10</b> apps (exactly) got a &#x201c;Nice&#x201d; rating from the first-cut reviewer.</p></li></ul><p>While we&#x2019;re doing numbers, let&#x2019;s investigate which of the Round-1 questions were hard.  In decreasing order of difficulty, identified by correct answer, we find: Dalvik (97.5% correct), 160 (96%), Looper (58.5%), LLVM (57%), <code>fyiWillBeAdvancedByHostKThx</code> (43%), and <code>PhoneNumberFormattingTextWatcher</code> (19.5%).</p><p>So, our thanks to the people who put in the work, and a particular tip of the hat to the deranged hackers er I mean creative developers who built three particularly-outstanding apps:</p><p>First, to Kris Jurgowski, who pulled an all-nighter and wrote a nifty little app... on a Motorola CLIQ running Android 1.5! Next, to Heliodor Jalba, whose app had some gravity-warping extras and was less than 11K in size.  And finally, to Charles Vaughn, whose app included a hilarious &#x201c;Party Mode&#x201d; that brought a smile to everyone&#x2019;s face.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4041652558717788500?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/the-io-ticket-contest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Identifying App Installations</title>
		<link>https://googledata.org/google-android/identifying-app-installations/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=identifying-app-installations</link>
		<comments>https://googledata.org/google-android/identifying-app-installations/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 20:08:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=dbbf8ac55cbc7db7ecdc636d05a42164</guid>
		<description><![CDATA[[The contents of this post grew out of an internal discussion featuring many of the usual suspects who&#8217;ve been authors in this space.&#160;&#8212;&#160;Tim&#160;Bray]In the Android group, from time to time we hear complaints from developers about...]]></description>
				<content:encoded><![CDATA[<p><i>[The contents of this post grew out of an internal discussion featuring many of the usual suspects who&rsquo;ve been authors in this space.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i><p>In the Android group, from time to time we hear complaints from developers about problems they’re having coming up with reliable, stable, unique device identifiers.  This worries us, because we think that tracking such identifiers isn’t a good idea, and that there are better ways to achieve developers’ goals.</p><h3>Tracking Installations</h3><p>It is very common, and perfectly reasonable, for a developer to want to track individual installations of their apps.  It sounds plausible just to call <a href="http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId()">TelephonyManager.getDeviceId()</a> and use that value to identify the installation.  There are problems with this:  First, it doesn’t work reliably (see below). Second, when it does work, that value survives device wipes (“Factory resets”) and thus you could end up making a nasty mistake when one of your customers wipes their device and passes it on to another person. </p><p>To track installations, you could for example use a <a href="http://en.wikipedia.org/wiki/Universally_unique_identifier">UUID</a> as an identifier, and simply create a new one the first time an app runs after installation.  Here is a sketch of a class named “Installation” with one static method <code>Installation.id(Context context)</code>.  You could imagine writing more installation-specific data into the <code>INSTALLATION</code> file.</p><pre><code>public class Installation {
    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {  
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }
}</code></pre><h3>Identifying Devices</h3><p>Suppose you feel that for the needs of your application, you need an actual hardware device identifier.   This turns out to be a tricky problem.</p><p>In the past, when every Android device was a phone, things were simpler: <code>TelephonyManager.getDeviceId()</code> is required to return (depending on the network technology) the IMEI, MEID, or ESN of the phone, which is unique to that piece of hardware.  </p><p>However, there are problems with this approach:</p><ul><li><p><b>Non-phones</b>: Wifi-only devices or music players that don’t have telephony hardware just don’t have this kind of unique identifier.</p></li><li><p><b>Persistence:</b> On devices which do have this, it persists across device data wipes and factory resets.  It’s not clear at all if, in this situation, your app should regard this as the same device.</p></li><li><p><b>Privilege</b>:It requires <a href="http://developer.android.com/reference/android/Manifest.permission.html#READ_PHONE_STATE">READ_PHONE_STATE</a> permission, which is irritating if you don’t otherwise use or need telephony.</p></li><li><p><b>Bugs</b>: We have seen a few instances of production phones for which the implementation is buggy and returns garbage, for example zeros or asterisks.</p></li></ul><h3>Mac Address</h3><p>It may be possible to retrieve a Mac address from a device’s WiFi or Bluetooth hardware.  We do not recommend using this as a unique identifier. To start with, not all devices have WiFi.  Also, if the WiFi is not turned on, the hardware may not report the Mac address.  </p><h3>Serial Number</h3><p>Since Android 2.3 (“Gingerbread”) this is available via <a href="http://developer.android.com/reference/android/os/Build.html#SERIAL">android.os.Build.SERIAL</a>.  Devices without telephony are required to report a unique device ID here; some phones may do so also.</p><h3>ANDROID_ID</h3><p>More specifically, <a href="http://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID">Settings.Secure.ANDROID_ID</a>.  This is a 64-bit quantity that is generated and stored when the device first boots.  It is reset when the device is wiped. </p><p>ANDROID_ID seems a good choice for a unique device identifier.  There are downsides: First, it is not 100% reliable on releases of Android prior to 2.2 (“Froyo”).  Also, there has been at least one widely-observed bug in a popular handset from a major manufacturer, where every instance has the same ANDROID_ID.</p><h3>Conclusion</h3><p>For the vast majority of applications, the requirement is to identify a particular installation, not a physical device.  Fortunately, doing so is straightforward.</p><p>There are many good reasons for avoiding the attempt to identify a particular device.  For those who want to try, the best approach is probably the use of  ANDROID_ID on anything reasonably modern, with some fallback heuristics for legacy devices.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-804809893012635561?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/identifying-app-installations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memory Analysis for Android Applications</title>
		<link>https://googledata.org/google-android/memory-analysis-for-android-applications/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=memory-analysis-for-android-applications</link>
		<comments>https://googledata.org/google-android/memory-analysis-for-android-applications/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 07:19:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false">https://googledata.org/?guid=4f9d20801b3421c66e52a5a33438b3f4</guid>
		<description><![CDATA[[This post is by Patrick Dubroy, an Android engineer who writes about programming, usability, and interaction on his personal blog.&#160;&#8212;&#160;Tim&#160;Bray]The Dalvik runtime may be garbage-collected, but that doesn't mean you can ignore memory...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-LRO5gpE7bMw/TYr0ANkY-6I/AAAAAAAAATQ/2ceHoVyL32E/s1600/dubroy.jpeg"><img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 154px;" src="http://1.bp.blogspot.com/-LRO5gpE7bMw/TYr0ANkY-6I/AAAAAAAAATQ/2ceHoVyL32E/s200/dubroy.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5587546572185992098" /></a><p><i>[This post is by Patrick Dubroy, an Android engineer who writes about programming, usability, and interaction on his <a href="http://dubroy.com/">personal blog</a>.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><p>The Dalvik runtime may be garbage-collected, but that doesn't mean you can ignore memory management. You should be especially mindful of memory usage on mobile devices, where memory is more constrained. In this article, we're going to take a look at some of the memory profiling tools in the Android SDK that can help you trim your application's memory usage.</p><p>Some memory usage problems are obvious. For example, if your app leaks memory every time the user touches the screen, it will probably trigger an <code>OutOfMemoryError</code> eventually and crash your app. Other problems are more subtle, and may just degrade the performance of both your app (as garbage collections are more frequent and take longer) and the entire system.</p><h3>Tools of the trade</h3><p>The Android SDK provides two main ways of profiling the memory usage of an app: the <em>Allocation Tracker</em> tab in DDMS, and heap dumps. The Allocation Tracker is useful when you want to get a sense of what kinds of allocation are happening over a given time period, but it doesn't give you any information about the overall state of your application's heap. For more information about the Allocation Tracker, see the article on <a href="http://developer.android.com/resources/articles/track-mem.html">Tracking Memory Allocations</a>. The rest of this article will focus on heap dumps, which are a more powerful memory analysis tool.</p><p>A heap dump is a snapshot of an application's heap, which is stored in a binary format called HPROF. Dalvik uses a format that is similar, but not identical, to the <a href="http://java.sun.com/developer/technicalArticles/Programming/HPROF.html">HPROF tool in Java</a>. There are a few ways to generate a heap dump of a running Android app. One way is to use the <em>Dump HPROF file</em> button in DDMS. If you need to be more precise about when the dump is created, you can also create a heap dump programmatically by using the <a href="http://developer.android.com/reference/android/os/Debug.html#dumpHprofData(java.lang.String)"><code>android.os.Debug.dumpHprofData()</code></a> function.</p><p>To analyze a heap dump, you can use a standard tool like <a href="http://download.oracle.com/javase/6/docs/technotes/tools/share/jhat.html">jhat</a> or the <a href="http://www.eclipse.org/mat/">Eclipse Memory Analyzer (MAT)</a>. However, first you'll need to convert the .hprof file from the Dalvik format to the J2SE HPROF format. You can do this using the <code>hprof-conv</code> tool provided in the Android SDK. For example:</p><pre><code>hprof-conv dump.hprof converted-dump.hprof</code></pre><h3>Example: Debugging a memory leak</h3><p>In the Dalvik runtime, the programmer doesn't explicitly allocate and free memory, so you can't really leak memory like you can in languages like C and C++. A "memory leak" in your code is when you keep a reference to an object that is no longer needed. Sometimes a single reference can prevent a large set of objects from being garbage collected.</p><p>Let's walk through an example using the <a href="http://developer.android.com/resources/samples/HoneycombGallery/">Honeycomb Gallery sample app</a> from the Android SDK. It's a simple photo gallery application that demonstrates how to use some of the new Honeycomb APIs. (To build and download the sample code, see the <a href="http://developer.android.com/resources/samples/get.html">instructions</a>.) We're going to deliberately add a memory leak to this app in order to demonstrate how it could be debugged.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-8-MGuEiLQTo/TYrxcSqFMDI/AAAAAAAAASo/41-cplx2gdU/s1600/honeycomb-gallery.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://3.bp.blogspot.com/-8-MGuEiLQTo/TYrxcSqFMDI/AAAAAAAAASo/41-cplx2gdU/s400/honeycomb-gallery.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587543756053491762" /></a><p>Imagine that we want to modify this app to pull images from the network. In order to make it more responsive, we might decide to implement a cache which holds recently-viewed images. We can do that by making a few small changes to ContentFragment.java. At the top of the class, let's add a new static variable:</p><pre><code>private static HashMap&lt;String,Bitmap&gt; sBitmapCache = new HashMap&lt;String,Bitmap&gt;();</code></pre><p>This is where we'll cache the Bitmaps that we load. Now we can change the <code>updateContentAndRecycleBitmap()</code> method to check the cache before loading, and to add Bitmaps to the cache after they're loaded.</p><pre><code>void updateContentAndRecycleBitmap(int category, int position) {
    if (mCurrentActionMode != null) {
        mCurrentActionMode.finish();
    }
 
    // Get the bitmap that needs to be drawn and update the ImageView.
 
    // Check if the Bitmap is already in the cache
    String bitmapId = "" + category + "." + position;
    mBitmap = sBitmapCache.get(bitmapId);
 
    if (mBitmap == null) {
        // It's not in the cache, so load the Bitmap and add it to the cache.
        // DANGER! We add items to this cache without ever removing any.
        mBitmap = Directory.getCategory(category).getEntry(position)
                .getBitmap(getResources());
        sBitmapCache.put(bitmapId, mBitmap);
    }
    ((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);
}</code></pre><p>I've deliberately introduced a memory leak here: we add Bitmaps to the cache without ever removing them. In a real app, we'd probably want to limit the size of the cache in some way.</p><h3>Examining heap usage in DDMS</h3><p>The Dalvik Debug Monitor Server (DDMS) is one of the primary Android debugging tools. DDMS is part of the <a href="http://developer.android.com/sdk/eclipse-adt.html">ADT Eclipse plug-in</a>, and a standalone version can also be found in the <code>tools/</code> directory of the Android SDK. For more information on DDMS, see <a href="http://developer.android.com/guide/developing/debugging/ddms.html">Using DDMS</a>.</p><p>Let's use DDMS to examine the heap usage of this app. You can start up DDMS in one of two ways:</p><ul><li>from Eclipse: click <em>Window &gt; Open Perspective &gt; Other... &gt; DDMS</em></li><li>or from the command line: run <code>ddms</code> (or <code>./ddms</code> on Mac/Linux) in the <code>tools/</code> directory</li></ul><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-9f0dBfEzjAY/TYryecq1eNI/AAAAAAAAASw/BwOdlTICEKA/s1600/ddms-toolbar.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 312px;" src="http://3.bp.blogspot.com/-9f0dBfEzjAY/TYryecq1eNI/AAAAAAAAASw/BwOdlTICEKA/s400/ddms-toolbar.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587544892612376786" /></a><p>Select the process <code>com.example.android.hcgallery</code> in the left pane, and then click the <em>Show heap updates</em> button in the toolbar. Then, switch to the <em>VM Heap</em> tab in DDMS. It shows some basic stats about our heap memory usage, updated after every GC. To see the first update, click the <em>Cause GC</em> button.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-VojtZFBXA3E/TYryrWDJLQI/AAAAAAAAAS4/hl5aecZuMXg/s1600/ddms-heap-usage.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 212px;" src="http://3.bp.blogspot.com/-VojtZFBXA3E/TYryrWDJLQI/AAAAAAAAAS4/hl5aecZuMXg/s400/ddms-heap-usage.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587545114173582594" /></a><p>We can see that our live set (the <em>Allocated</em> column) is a little over 8MB. Now flip through the photos, and watch that number go up. Since there are only 13 photos in this app, the amount of memory we leak is bounded. In some ways, this is the worst kind of leak to have, because we never get an <code>OutOfMemoryError</code> indicating that we are leaking.</p><h3>Creating a heap dump</h3><p>Let's use a heap dump to track down the problem. Click the <em>Dump HPROF file</em> button in the DDMS toolbar, choose where you want to save the file, and then run <code>hprof-conv</code> on it. In this example, I'll be using the standalone version of MAT (version 1.0.1), available from the <a href="http://www.eclipse.org/mat/downloads.php">MAT download site</a>.</p><p>If you're running ADT (which includes a plug-in version of DDMS) and have MAT installed in Eclipse as well, clicking the &ldquo;dump HPROF&rdquo; button will automatically do the conversion (using hprof-conv) and open the converted hprof file into Eclipse (which will be opened by MAT).</p><h3>Analyzing heap dumps using MAT</h3><p>Start up MAT and load the converted HPROF file we just created. MAT is a powerful tool, and it's beyond the scope of this article to explain all it's features, so I'm just going to show you one way you can use it to detect a leak: the Histogram view. The Histogram view shows a list of classes sortable by the number of instances, the <em>shallow heap</em> (total amount of memory used by all instances), or the <em>retained heap</em> (total amount of memory kept alive by all instances, including other objects that they have references to).</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-05qqw4YE3Nk/TYt9JGFSuCI/AAAAAAAAATg/pGny9cvfJdA/s1600/mat-histogram.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 316px;" src="http://4.bp.blogspot.com/-05qqw4YE3Nk/TYt9JGFSuCI/AAAAAAAAATg/pGny9cvfJdA/s400/mat-histogram.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587697357888337954" /></a><p>If we sort by shallow heap, we can see that instances of <code>byte[]</code> are at the top. As of Android 3.0 (Honeycomb), the pixel data for Bitmap objects is stored in byte arrays (previously it was not stored in the Dalvik heap), and based on the size of these objects, it's a safe bet that they are the backing memory for our leaked bitmaps.</p><p>Right-click on the <code>byte[]</code> class and select <em>List Objects &gt; with incoming references</em>. This produces a list of all byte arrays in the heap, which we can sort based on Shallow Heap usage.</p><p>Pick one of the big objects, and drill down on it. This will show you the path from the root set to the object -- the chain of references that keeps this object alive. Lo and behold, there's our bitmap cache!</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-J23Vk25ZXAI/TYt8-f-0SOI/AAAAAAAAATY/Iu8NtRYU9Vg/s1600/mat-references.png"><img style="border: 5px solid #ddd; display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 316px;" src="http://3.bp.blogspot.com/-J23Vk25ZXAI/TYt8-f-0SOI/AAAAAAAAATY/Iu8NtRYU9Vg/s400/mat-references.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587697175861938402" /></a><p>MAT can't tell us for sure that this is a leak, because it doesn't know whether these objects are needed or not -- only the programmer can do that. In this case, the cache is using a large amount of memory relative to the rest of the application, so we might consider limiting the size of the cache.</p><h3>Comparing heap dumps with MAT</h3><p>When debugging memory leaks, sometimes it's useful to compare the heap state at two different points in time. To do this, you'll need to create two separate HPROF files (don't forget to convert them using <code>hprof-conv</code>).</p><p>Here's how you can compare two heap dumps in MAT (it's a little complicated):</p><ol><li>Open the first HPROF file (using <em>File &gt; Open Heap Dump</em>).</li><li>Open the Histogram view.</li><li>In the Navigation History view (use <em>Window &gt; Navigation History</em> if it's not visible), right click on <em>histogram</em> and select <em>Add to Compare Basket</em>.</li><li>Open the second HPROF file and repeat steps 2 and 3.</li><li>Switch to the Compare Basket view, and click <em>Compare the Results</em> (the red "!" icon in the top right corner of the view).</li></ol><h3>Conclusion</h3><p>In this article, I've shown how the Allocation Tracker and heap dumps can give you get a better sense of your application's memory usage. I also showed how The Eclipse Memory Analyzer (MAT) can help you track down memory leaks in your app. MAT is a powerful tool, and I've only scratched the surface of what you can do with it. If you'd like to learn more, I recommend reading some of these articles:</p><ul><li><a href="http://dev.eclipse.org/blogs/memoryanalyzer/">Memory Analyzer News</a>: The official blog of the Eclipse MAT project</li><li>Markus Kohler's Java Performance blog has many helpful articles, including <a href="http://kohlerm.blogspot.com/2010/02/android-memory-usage-analysis-slides.html">Analysing the Memory Usage of Android Applications with the Eclipse Memory Analyzer</a> and <a href="http://kohlerm.blogspot.com/2009/07/eclipse-memory-analyzer-10-useful.html">10 Useful Tips for the Eclipse Memory Analyzer</a>.</li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-9125553152027591880?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/memory-analysis-for-android-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>The Android 3.0 Fragments API</title>
		<link>https://googledata.org/google-android/the-android-3-0-fragments-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-android-3-0-fragments-api</link>
		<comments>https://googledata.org/google-android/the-android-3-0-fragments-api/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 19:43:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[[This post is by Dianne Hackborn, a Software Engineer who sits very near the exact center of everything Android.&#160;&#8212;&#160;Tim&#160;Bray]An important goal for Android 3.0 is to make it easier for developers to write applications that can scale ...]]></description>
				<content:encoded><![CDATA[<p><i>[This post is by Dianne Hackborn, a Software Engineer who sits very near the exact center of everything Android.&nbsp;&mdash;&nbsp;Tim&nbsp;Bray]</i></p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s1600/IMG_0089.jpg"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 262px; height: 400px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/S9icFaUOpKI/AAAAAAAAACQ/Sp_fYopwsfw/s400/IMG_0089.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5465289764591543458" /></a><p>An important goal for Android 3.0 is to make it easier for developers to write applications that can scale across a variety of screen sizes, beyond the facilities already available in the platform:</p><ul><li><p>Since the beginning, Android’s UI framework has been designed around the use of layout managers, allowing UIs to be described in a way that will adjust to the space available.  A common example is a ListView whose height changes depending on the size of the screen, which varies a bit between QVGA, HVGA, and WVGA aspect ratios.</p></li><li><p>Android 1.6 introduced a new concept of screen densities, making it easy for apps to scale between different screen resolutions when the screen is about the same physical size.  Developers immediately started using this facility when higher-resolution screens were introduced, first on Droid and then on other phones.</p></li><li><p>Android 1.6 also made screen sizes accessible to developers, classifying them into buckets: “small” for QVGA aspect ratios, “normal” for HVGA and WVGA aspect ratios, and “large” for larger screens.  Developers can use the resource system to select between different layouts based on the screen size.</p></li></ul><p>The combination of layout managers and resource selection based on screen size goes a long way towards helping developers build scalable UIs for the variety of Android devices we want to enable.  As a result, many existing handset applications Just Work under Honeycomb on full-size tablets, without special compatibility modes, with no changes required.  However, as we move up into tablet-oriented UIs with 10-inch screens, many applications also benefit from a more radical UI adjustment than resources can easily provide by themselves.</p><h3>Introducing the Fragment</h3><p>Android 3.0 further helps applications adjust their interfaces with a new class called Fragment.  A Fragment is a self-contained component with its own UI and lifecycle; it can be-reused in different parts of an application’s user interface depending on the desired UI flow for a particular device or screen.</p><p>In some ways you can think of a Fragment as a mini-Activity, though it can’t run independently but must be hosted within an actual Activity.  In fact the introduction of the Fragment API gave us the opportunity to address many of the pain points we have seen developers hit with Activities, so in Android 3.0 the utility of Fragment extends far beyond just adjusting for different screens:</p><ul><li><p>Embedded Activities via ActivityGroup were a nice idea, but have always been difficult to deal with since Activity is designed to be an independent self-contained component instead of closely interacting with other activities.  The Fragment API is a much better solution for this, and should be considered as a replacement for embedded activities.</p></li><li><p>Retaining data across Activity instances could be accomplished through Activity.onRetainNonConfigurationInstance(), but this is fairly klunky and non-obvious.  Fragment replaces that mechanism by allowing you to retain an entire Fragment instance just by setting a flag.</p></li><li><p>A specialization of Fragment called DialogFragment makes it easy to show a Dialog that is managed as part of the Activity lifecycle.  This replaces Activity’s “managed dialog” APIs.</p></li><li><p>Another specialization of Fragment called ListFragment makes it easy to show a list of data.  This is similar to the existing ListActivity (with a few more features), but should reduce the common question about how to show a list with some other data.</p></li><li><p>The information about all fragments currently attached to an activity is saved for you by the framework in the activity’s saved instance state and restored for you when it restarts.  This can greatly reduce the amount of state save and restore code you need to write yourself.</p></li><li><p>The framework has built-in support for managing a back-stack of Fragment objects, making it easy to provide intra-activity Back button behavior that integrates the existing activity back stack.  This state is also saved and restored for you automatically.</p></li></ul><h3>Getting started</h3><p>To whet your appetite, here is a simple but complete example of implementing multiple UI flows using fragments.  We first are going to design a landscape layout, containing a list of items on the left and details of the selected item on the right.  This is the layout we want to achieve:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GTM_W5mVPTU/TUsiB0_SZiI/AAAAAAAAAQ0/FtxDiayMsN8/s1600/device-fragment-land.png"><img style="border: 5px solid #ddd;  display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 240px;" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/TUsiB0_SZiI/AAAAAAAAAQ0/FtxDiayMsN8/s400/device-fragment-land.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5569582778973054498" /></a><p>The code for this activity is not interesting; it just calls setContentView() with the given layout:</p><pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    &lt;fragment class="com.example.android.apis.app.TitlesFragment"
            android:id="@+id/titles" android:layout_weight="1"
            android:layout_width="0px"
            android:layout_height="match_parent" />

    &lt;FrameLayout android:id="@+id/details" android:layout_weight="1"
            android:layout_width="0px"
            android:layout_height="match_parent" />
    
&lt;/LinearLayout></code></pre><p>You can see here our first new feature: the <code>&lt;fragment></code> tag allows you to automatically instantiate and install a Fragment subclass into your view hierarchy.  The fragment being implemented here derives from ListFragment, displaying and managing a list of items the user can select.  The implementation below takes care of displaying the details of an item either in-place or as a separate activity, depending on the UI layout.  Note how changes to fragment state (the currently shown details fragment) are retained across configuration changes for you by the framework.</p><pre><code>public static class TitlesFragment extends ListFragment {
    boolean mDualPane;
    int mCurCheckPosition = 0;

    @Override
    public void onActivityCreated(Bundle savedState) {
        super.onActivityCreated(savedState);

        // Populate list with our static array of titles.
        setListAdapter(new ArrayAdapter&lt;String>(getActivity(),
                R.layout.simple_list_item_checkable_1,
                Shakespeare.TITLES));

        // Check to see if we have a frame in which to embed the details
        // fragment directly in the containing UI.
        View detailsFrame = getActivity().findViewById(R.id.details);
        mDualPane = detailsFrame != null
                &amp;&amp; detailsFrame.getVisibility() == View.VISIBLE;

        if (savedState != null) {
            // Restore last state for checked position.
            mCurCheckPosition = savedState.getInt("curChoice", 0);
        }

        if (mDualPane) {
            // In dual-pane mode, list view highlights selected item.
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            // Make sure our UI is in the correct state.
            showDetails(mCurCheckPosition);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("curChoice", mCurCheckPosition);
    }

    @Override
    public void onListItemClick(ListView l, View v, int pos, long id) {
        showDetails(pos);
    }

    /**
     * Helper function to show the details of a selected item, either by
     * displaying a fragment in-place in the current UI, or starting a
     * whole new activity in which it is displayed.
     */
    void showDetails(int index) {
        mCurCheckPosition = index;

        if (mDualPane) {
            // We can display everything in-place with fragments.
            // Have the list highlight this item and show the data.
            getListView().setItemChecked(index, true);

            // Check what fragment is shown, replace if needed.
            DetailsFragment details = (DetailsFragment)
                    getFragmentManager().findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index) {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);

                // Execute a transaction, replacing any existing
                // fragment with this one inside the frame.
                FragmentTransaction ft
                        = getFragmentManager().beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(
                        FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        } else {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }
}</code></pre><p>For this first screen we need an implementation of DetailsFragment, which simply shows a TextView containing the text of the currently selected item.</p><pre><code>public static class DetailsFragment extends Fragment {
    /**
     * Create a new instance of DetailsFragment, initialized to
     * show the text at 'index'.
     */
    public static DetailsFragment newInstance(int index) {
        DetailsFragment f = new DetailsFragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle savedInstanceState) {
        if (container == null) {
            // Currently in a layout without a container, so no
            // reason to create our view.
            return null;
        }

        ScrollView scroller = new ScrollView(getActivity());
        TextView text = new TextView(getActivity());
        int padding = (int)TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                4, getActivity().getResources().getDisplayMetrics());
        text.setPadding(padding, padding, padding, padding);
        scroller.addView(text);
        text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
        return scroller;
    }
}</code></pre><p>It is now time to add another UI flow to our application.  When in portrait orientation, there is not enough room to display the two fragments side-by-side, so instead we want to show only the list like this:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GTM_W5mVPTU/TUsiXt73RoI/AAAAAAAAAQ8/Jt6tXwJMrjw/s1600/device-fragment-port1.png"><img style="border: 5px solid #ddd;  display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/TUsiXt73RoI/AAAAAAAAAQ8/Jt6tXwJMrjw/s400/device-fragment-port1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5569583155036767874" /></a><p>With the code shown so far, all we need to do here is introduce a new layout variation for portrait screens like so:</p><pre><code>&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    &lt;fragment class="com.example.android.apis.app.TitlesFragment"
            android:id="@+id/titles"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
&lt;/FrameLayout></code></pre><p>The TitlesFragment will notice that it doesn’t have a container in which to show its details, so show only its list.  When you tap on an item in the list we now need to go to a separate activity in which the details are shown. </p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GTM_W5mVPTU/TUsipPriSTI/AAAAAAAAARE/-68jzx6xCII/s1600/device-fragment-port2.png"><img style="border: 5px solid #ddd;  display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://4.bp.blogspot.com/_GTM_W5mVPTU/TUsipPriSTI/AAAAAAAAARE/-68jzx6xCII/s400/device-fragment-port2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5569583456152865074" /></a><p>With the DetailsFragment already implemented, the implementation of the new activity is very simple because it can reuse the same DetailsFragment from above:</p><pre><code>public static class DetailsActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_LANDSCAPE) {
            // If the screen is now in landscape mode, we can show the
            // dialog in-line so we don't need this activity.
            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.
            DetailsFragment details = new DetailsFragment();
            details.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().add(
                    android.R.id.content, details).commit();
        }
    }
}</code></pre><p>Put that all together, and we have a complete working example of an application that fairly radically changes its UI flow based on the screen it is running on, and can even adjust it on demand as the screen configuration changes.</p><p>This illustrates just one way fragments can be used to adjust your UI.  Depending on your application design, you may prefer other approaches.  For example, you could put your entire application in one activity in which you change the fragment structure as its state changes; the fragment back stack can come in handy in this case.</p><p>More information on the Fragment and FragmentManager APIs can be found in the Android 3.0 SDK documentation.  Also be sure to look at the ApiDemos app under the Resources tab, which has a variety of Fragment demos covering their use for alternative UI flow, dialogs, lists, populating menus, retaining across activity instances, the back stack, and more.</p><h3>Fragmentation for all!</h3><p>For developers starting work on tablet-oriented applications designed for Android 3.0, the new Fragment API is useful for many design situations that arise from the larger screen.  Reasonable use of fragments should also make it easier to adjust the resulting application’s UI to new devices in the future as needed -- for phones, TVs, or wherever Android appears.</p><p>However, the immediate need for many developers today is probably to design applications that they can provide for existing phones while also presenting an improved user interface on tablets.  With Fragment only being available in Android 3.0, their shorter-term utility is greatly diminished.</p><p>To address this, we plan to have the same fragment APIs (and the new LoaderManager as well) described here available as a static library for use with older versions of Android; we&rsquo;re trying to go right back to 1.6.  In fact, if you compare the code examples here to those in the Android 3.0 SDK, they are slightly different: this code is from an application using an early version of the static library fragment classes which is running, as you can see on the screenshots, on Android 2.3.  Our goal is to make these APIs nearly identical, so you can start using them now and, at whatever point in the future you switch to Android 3.0 as your minimum version, move to the platform’s native implementation with few changes in your app.</p><p>We don’t have a firm date for when this library will be available, but it should be relatively soon.  In the meantime, you can start developing with fragments on Android 3.0 to see how they work, and most of that effort should be transferable.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7701195608532274601?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/the-android-3-0-fragments-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Processing Ordered Broadcasts</title>
		<link>https://googledata.org/google-android/processing-ordered-broadcasts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=processing-ordered-broadcasts</link>
		<comments>https://googledata.org/google-android/processing-ordered-broadcasts/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 00:02:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[[This post is by Bruno Albuquerque, an engineer who works in Google’s office in Belo Horizonte, Brazil. —Tim Bray]One of the things that I find most interesting and powerful about Android is the concept of broadcasts and their use through the Broa...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GTM_W5mVPTU/TTjQOQl9QbI/AAAAAAAAAQg/tOTOOiuuUT0/s1600/bga.png"><img style="border: 5px solid #ddd;  float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 185px; height: 228px;" src="http://1.bp.blogspot.com/_GTM_W5mVPTU/TTjQOQl9QbI/AAAAAAAAAQg/tOTOOiuuUT0/s320/bga.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5564426283007164850" /></a><p><i>[This post is by Bruno Albuquerque, an engineer who works in Google’s office in Belo Horizonte, Brazil. —Tim Bray]</i></p><p>One of the things that I find most interesting and powerful about Android is the concept of broadcasts and their use through the <a href="http://developer.android.com/reference/android/content/BroadcastReceiver.html">BroadcastReceiver</a> class (from now on, we will call implementations of this class “receivers”). As this document is about a very specific usage scenario for broadcasts, I will not go into detail about how they work in general, so I recommend reading the documentation about them in the <a href="http://developer.android.com/">Android developer site</a>. For the purpose of this document, it is enough to know that broadcasts are generated whenever something interesting happens in the system (connectivity changes, for example) and you can register to be notified whenever one (or more) of those broadcasts are generated.</p><p>While developing <a href="https://sites.google.com/a/bug-br.org.br/android/software/right-number">Right Number</a>, I noticed that some developers who create receivers for ordered broadcasts do not seem to be fully aware of what is the correct way to do it. This suggests that the documentation could be improved; in any case, things often still work(although it is mostly by chance than anything else).</p><h3>Non-ordered vs. Ordered Broadcasts</h3><p>In non-ordered mode, broadcasts are sent to all interested receivers “at the same time”. This basically means that one receiver can not interfere in any way with what other receivers will do neither can it prevent other receivers from being executed. One example of such broadcast is the <a href="http://developer.android.com/reference/android/content/Intent.html#ACTION_BATTERY_LOW">ACTION_BATTERY_LOW</a> one.</p><p>In ordered mode, broadcasts are sent to each receiver in order (controlled by the <a href="http://developer.android.com/guide/topics/manifest/intent-filter-element.html#priority">android:priority</a> attribute for the <a href="http://developer.android.com/guide/topics/manifest/intent-filter-element.html">intent-filter</a> element in the manifest file that is related to your receiver) and one receiver is able to abort the broadcast so that receivers with a lower priority would not receive it (thus never execute). An example of this type of broadcast (and one that will be discussing in this document) is the <a href="http://developer.android.com/reference/android/content/Intent.html#ACTION_NEW_OUTGOING_CALL">ACTION_NEW_OUTGOING_CALL</a> one.</p><h3>Ordered Broadcast Usage</h3><p>As mentioned earlier in this document, the ACTION_NEW_OUTGOING_CALL broadcast is an ordered one. This broadcast is sent whenever the user tries to initiate a phone call. There are several reasons that one would want to be notified about this, but we will focus on only 2:</p><ul><li><p>To be able to reject an outgoing call;</p></li><li><p>To be able to rewrite the number before it is dialed.</p></li></ul><p>In the first case, an app may want to control what numbers can be dialed or what time of the day numbers can be dialed. Right Number does what is described in the second case so it can be sure that a number is always dialed correctly no matter where in the world you are.</p><p>A naive BroadcastReceiver implementation would be something like this (note that you should associate this receiver with the ACTION_NEW_OUTGOING_CALL broadcast in the manifest file for your application):</p><pre><code>public class CallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Original phone number is in the EXTRA_PHONE_NUMBER Intent extra.
    String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);

    if (shouldCancel(phoneNumber)) {
      // Cancel our call.
      setResultData(null);
    } else {
      // Use rewritten number as the result data.
      setResultData(reformatNumber(phoneNumber));
  }
}</code></pre><p>The receiver either cancels the broadcast (and the call) or reformats the number to be dialed. If this is the only receiver that is active for the ACTION_NEW_OUTGOING_CALL broadcast, this will work exactly as expected. The problem arrises when you have, for example, a receiver that runs before the one above (has a higher priority) and that also changes the number as instead of looking at previous results of other receivers, we are just using the original (unmodified) number!</p><h3>Doing It Right</h3><p>With the above in mind, here is how the code should have been written in the first place:</p><pre><code>public class CallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Try to read the phone number from previous receivers.
    String phoneNumber = getResultData();

    if (phoneNumber == null) {
      // We could not find any previous data. Use the original phone number in this case.
      phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    }

    if (shouldCancel(phoneNumber)) {
      // Cancel our call.
      setResultData(null);
    } else {
      // Use rewritten number as the result data.
      setResultData(reformatNumber(phoneNumber));
  }
}</code></pre><p>We first check if we have any previous result data (which would be generated by a receiver with a higher priority)  and only if we can not find it we use the phone number in the EXTRA_PHONE_NUMBER intent extra.</p><h3>How Big Is The Problem?</h3><p>We have actually observed phones with a priority 0 receiver for the NEW_OUTGOING_CALL intent installed out of the box (this will be the last one that is called after all others) that completely ignores previous result data which means that, in effect, they disable any useful processing of ACTION_NEW_OUTGOING_CALL (other than canceling the call, which would still work). The only workaround for this is to also run your receiver at priority 0, which works due to particularities of running 2 receivers at the same priority but, by doing that, you break one of the few <a href="http://developer.android.com/reference/android/content/Intent.html#ACTION_NEW_OUTGOING_CALL%20">explicit rules</a> for processing outgoing calls:</p><blockquote><p>“For consistency, any receiver whose purpose is to prohibit phone calls should have a priority of 0, to ensure it will see the final phone number to be dialed. Any receiver whose purpose is to rewrite phone numbers to be called should have a positive priority. Negative priorities are reserved for the system for this broadcast; using them may cause problems.”</p></blockquote><h3>Conclusion</h3><p>There are programs out there that do not play well with others. Urge any developers of such programs to read this post and fix their code. This will make Android better for both developers and users.</p><h3>Notes About Priorities</h3><ul><li><p>For the NEW_OUTGOING_CALL intent, priority 0 should only be used by receivers that want to reject calls. This is so it can see changes from other receivers before deciding to reject the call or not.</p></li><li><p>Receivers that have the same priority will also be executed in order, but the order in this case is undefined.</p></li><li><p>Use non-negative priorities only. Negative ones are valid but will result in weird behavior most of the time.</p></li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8197669366211020559?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/processing-ordered-broadcasts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Have Androids. Will Travel.</title>
		<link>https://googledata.org/google-android/have-androids-will-travel/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=have-androids-will-travel</link>
		<comments>https://googledata.org/google-android/have-androids-will-travel/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 18:54:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[[The first part of this post is by Reto Meier. —Tim Bray]From c-base in Berlin to the Ice Bar in Stockholm, from four courses of pasta in Florence to beer and pretzels in Munich, and from balalikas in Moscow to metal cage mind puzzles in Prague - on...]]></description>
				<content:encoded><![CDATA[<p><i>[The first part of this post is by <a href="http://www.amazon.com/gp/product/0470565527?tag=interventione-20">Reto Meier</a>. —Tim Bray]</i></p><p>From c-base in Berlin to the <a href="http://www.google.com/images?hl=en&expIds=17050,25657,26486,26488,26492,26496,26504,27339,27642,27887,27951&sugexp=ldymls&xhr=t&q=ice+bar+stockholm&cp=9&qe=SWNlIEJhciBT&qesig=pUEDhq-tQJyKeY1fCiCDWg&pkc=AFgZ2tkImUSn1WJJn6Dok-ikanzCDxaHWyabg2z-XAfGNcWxlSKI0E0IKHotXhiw3Zq6jEtkIorZUDqTXY5hubLhikOK85vOlw&um=1&ie=UTF-8&source=univ&ei=5oELTYClLomdOuTVuJ0J&sa=X&oi=image_result_group&ct=title&resnum=4&sqi=2&ved=0CD8QsAQwAw&biw=1280&bih=680">Ice Bar</a> in Stockholm, from four courses of pasta in Florence to beer and pretzels in Munich, and from balalikas in Moscow to metal cage mind puzzles in Prague - one common theme was the enthusiasm and quality of the Android developers in attendance. You guys are epic.</p><p>For those of you who couldn't join us, we're in the middle of posting all the sessions we presented during this most recent world tour.  Stand by for links.</p><h3>Droidcon UK</h3><p>We kicked off our conference season at Droidcon UK, an Android extravaganza consisting of a bar camp on day 1 and formal sessions on day 2. It was the perfect place for the <a href="http://code.google.com/team/index.html?product=android%20">Android developer relations team</a> to get together and kick off three straight weeks of Google Developer Days, GTUG Hackathons, and Android Developer Labs.</p><h3>Android Developer Labs</h3><p>The first of our Android Developer Labs was a return to Berlin: home to c-base (a place we never got tired of) and the <a href="http://www.beuth-hochschule.de/%20">Beuth Hochschule für Technik Berlin</a>. This all day event cost me my voice, but attracted nearly 300 developers (including six teams who battled it out to win a Lego Mindstorm for best app built on the day.)</p><p>Next stop was <a href="http://picasaweb.google.com/francesca.tosi/AndroidDevelopersLabInFlorence">Florence</a> which played host to our first Italian ADL after some fierce campaigning by local Android developers. 160 developers from all over Italy joined us in beautiful Florence where the <a href="http://sites.google.com/site/firenzegtug/">Firenze GTUG</a> could not have been more welcoming. An afternoon spent with eager developers followed up by an evening of real Italian pasta - what's not to love?<p>From the warmth of Florence to the snow of Stockholm where we joined the <a href="http://sites.google.com/site/stockholmgtug/">Stockholm GTUG</a> for a special Android themed event at Bwin Games. After a brief introduction we split into six breakout sessions before the attendees got down to some serious hacking to decide who got to bring home the Mindstorm kit.</p><h3>Google Developer Days</h3><p>The <a href="http://googlecode.blogspot.com/2010/12/highlights-from-google-developer-day.html">Google Developer Days</a> are always a highlight on my conference schedule, and this year's events were no exception. It's a unique opportunity for us to meet with a huge number of talented developers - over 3,000 in Europe alone.  Each event featured a dedicated Android track with six sessions designed to help Android developers improve their skills.</p><p>It was our first time in Munich where we played host to 1200 developers from all over Germany. If there was any doubt we'd come to the right place, the hosting of the <a href="http://www.youtube.com/watch?v=Ts8vIUML37Y">Blinkendroid Guinness World Record</a> during the after-party soon dispelled it.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GTM_W5mVPTU/TS9N0l3MqsI/AAAAAAAAAQA/8StPsLmA7V0/s1600/IMG_2730.JPG"><img style="border: 5px solid #ddd;  display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 267px;" src="http://4.bp.blogspot.com/_GTM_W5mVPTU/TS9N0l3MqsI/AAAAAAAAAQA/8StPsLmA7V0/s400/IMG_2730.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5561749630738016962" /></a><p>Moscow and Prague are always incredible places to visit. The enthusiasm of the nearly 2,500 people who attended is the reason we do events like these. You can watch <a href="http://www.youtube.com/results?search_query=Android+googlegooroo+2010&aq=f">the video</a> for every Android session from the Prague event and check out <a href="http://www.google.ru/events/developerday/2010/moscow/agenda.html">the slides</a> for each of the Russian sessions too.</p><h3>GTUG Hackathons</h3><p>With everyone in town for the GDDs we wanted to make the most it. Working closely with the local GTUGs, the Android and Chrome teams held all-day hackathon bootcamps in each city the day before the big event.</p><p>It was a smaller crowd in Moscow, but that just made the competition all the more fierce. So much so that we had to create a new Android app just for the purpose of measuring the relative volume of applause in order to choose a winner.</p><p>If a picture is a thousand words, this video of the <a href="http://www.youtube.com/watch?v=EHN2VQOnUcw">Prague Hackathon in 85 seconds</a> will describe the event far better than I ever could. What the video doesn't show is that the winners of "best app of the day" in Prague had never developed for Android before.</p><p>In each city we were blown away by the enthusiasm and skill on display. With so many talented, passionate developers working on Android it's hard not to be excited by what we'll find on the Android Market next. In the mean time, keep coding; we hope to be in your part of the world soon.</p><h3>On To South America</h3><p><i>[Thanks, Reto. This is Tim again.  The South American leg actually happened before the Eurotour, but Reto got his writing done first, so I'll follow up here.]</i></p><p>We did more or less the same set of things in South America immediately before Reto’s posse fanned out across Europe.  Our events were in São Paulo, Buenos Aires, and Santiago; we were trying to teach people about Android and I hope we succeeded. On the other hand, I know that we learned lots of things.  Here are a few of them:</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GTM_W5mVPTU/TS9OyDJSQVI/AAAAAAAAAQQ/UVJsXlS_pN8/s1600/IMG_0151.jpg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 189px;" src="http://4.bp.blogspot.com/_GTM_W5mVPTU/TS9OyDJSQVI/AAAAAAAAAQQ/UVJsXlS_pN8/s200/IMG_0151.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5561750686570529106" /></a><ul><li><p>Wherever we went, we saw strange (to us) new Android devices.  Here’s a picture of a Brazilian flavor of the Samsung Galaxy S, which comes with a fold-out antenna and can get digital TV off the air.  If you’re inside you might need to be near a window, but the picture quality is fantastic.</p></li><li><p>There’s a conventional wisdom about putting on free events: Of the people who register, only a certain percentage will show up.  When it comes to Android events in South America, the certain-percentage part is wrong.  As a result, we dealt with overcrowded rooms and overflow arrangements all over the place.  I suppose this is a nice problem to have, but we still feel sorry about some of the people who ended up being overcrowded and overflowed.</p></li><li><p>Brazilians laugh at themselves, saying they’re always late. (Mind you, I’ve heard Indians and Jews and Irish people poke the same fun at themselves, so I suspect lateness may be part of the human condition).  Anyhow, Brazilians are not late for Android events; when we showed up at the venue in the grey light of dawn to start setting up, they were already waiting outside.</p></li><li><p>I enjoyed doing the hands-on Android-101 workshops (I’ve included a picture of one), but I’m not sure Googlers need to be doing any more of those. Wherever you go, there’s now a community of savvy developers who can teach each other through the finer points of getting the SDK installed and working and “Hello World” running.</p></li></ul><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GTM_W5mVPTU/TS9PO-wOYgI/AAAAAAAAAQY/jxttcbrcxPA/s1600/PS080591.jpg"><img style="border: 5px solid #ddd;  display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 266px;" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/TS9PO-wOYgI/AAAAAAAAAQY/jxttcbrcxPA/s400/PS080591.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5561751183607882242" /></a><ul><li><p>Brazil and Argentina and Chile aren’t really like each other.  But each has its own scruffy-open-source-geek contingent that likes to get together, and Android events are a good opportunity.  I felt totally at home drinking coffee with these people and talking about programming languages and screen densities and so on, even when we had to struggle our way across language barriers.</p></li></ul><p>The people were so, so, warm-hearted and welcoming and not shy in the slightest and I can’t think about our tour without smiling.  A big thank-you to all the South-American geeks and hackers and startup cowboys; we owe you a return visit.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4945448592503637711?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/have-androids-will-travel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Gingerbread NDK Awesomeness</title>
		<link>https://googledata.org/google-android/gingerbread-ndk-awesomeness/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=gingerbread-ndk-awesomeness</link>
		<comments>https://googledata.org/google-android/gingerbread-ndk-awesomeness/#comments</comments>
		<pubDate>Tue, 11 Jan 2011 21:13:00 +0000</pubDate>
		<dc:creator><![CDATA[Tim Bray]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[[This post is by Chris Pruett, an outward-facing Androider who focuses on the world of games. —Tim Bray]We released the first version of the Native Development Kit, a development toolchain for building shared libraries in C or C++ that can be used i...]]></description>
				<content:encoded><![CDATA[<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/TSzK0lzVTII/AAAAAAAAAPw/4Nd4Jng3Hyw/s1600/cpn.jpg"><img style="border: 5px solid #ddd;  float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 164px; height: 200px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/TSzK0lzVTII/AAAAAAAAAPw/4Nd4Jng3Hyw/s200/cpn.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5561042644745145474" /></a><p><i>[This post is by <a href="http://replicaisland.blogspot.com/">Chris Pruett</a>, an outward-facing Androider who focuses on the world of games. —Tim Bray]</i></p><p>We released the first version of the <a href="http://developer.android.com/sdk/ndk/">Native Development Kit</a>, a development toolchain for building shared libraries in C or C++ that can be used in conjunction with Android applications written in the Java programming language, way back in July of 2009.  Since that initial release we’ve steadily improved support for native code; key features such as OpenGL ES support, debugging capabilities, multiple ABI support, and access to bitmaps in native code have arrived with each NDK revision.  The result has been pretty awesome: we’ve seen huge growth in certain categories of performance-critical applications, particularly 3D games.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_GTM_W5mVPTU/TSzJh86IG2I/AAAAAAAAAPo/Ie82krwgqcE/s1600/ndk-awesomenss-graph.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 347px; height: 242px;" src="http://2.bp.blogspot.com/_GTM_W5mVPTU/TSzJh86IG2I/AAAAAAAAAPo/Ie82krwgqcE/s400/ndk-awesomenss-graph.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561041225018514274" /></a><p>These types of applications are often impractical via Dalvik due to execution speed requirements or, more commonly, because they are based on engines already developed in C or C++.  Early on we noted a strong relationship between the awesomeness of the NDK and the awesomeness of the applications that it made possible; at the limit of this function is obviously infinite awesomeness (see graph, right).</p><p>With the latest version of the NDK we intend to further increase the awesomeness of your applications, this time by a pretty big margin.  With NDK r5, we’re introducing new APIs that will allow you to do more from native code.  In fact, with these new tools, applications targeted at Gingerbread or later can be implemented entirely in C++; you can now build an entire Android application without writing a single line of Java.</p><p>Of course, access to the regular Android API still requires Dalvik, and the VM is still present in native applications, operating behind the scenes.  Should you need to do more than the NDK interfaces provide, you can always invoke Dalvik methods via JNI.  But if you prefer to work exclusively in C++, the NDK r5 will let you build a main loop like this:</p><pre><code>void android_main(struct android_app* state) {
    // Make sure glue isn't stripped.
    app_dummy();

    // loop waiting for stuff to do.
    while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;

        // Read events and draw a frame of animation.
        if ((ident = ALooper_pollAll(0, NULL, &events,
                (void**)&source)) >= 0) {
            // Process this event.
            if (source != NULL) {
                source->process(state, source);
            }
        }
        // draw a frame of animation
        bringTheAwesome();
    }
}</code></pre><p>(For a fully working example, see the native-activity sample in NDK/samples/native-activity and the <a href="http://developer.android.com/reference/android/app/NativeActivity.html">NativeActivity documentation</a>.)</p><p>In addition to fully native applications, the latest NDK lets you play sound from native code (via the <a href="http://www.khronos.org/opensles/">OpenSL ES API</a>, an open standard managed by Khronos, which also oversees OpenGL ES), handle common application events (life cycle, touch and key events, as well as sensors), control windows directly (including direct access to the window’s pixel buffer), manage EGL contexts, and read assets directly out of APK files.  The latest NDK also comes with a prebuilt version of STLport, making it easier to bring STL-reliant applications to Android.  Finally, r5 adds backwards-compatible support for RTTI, C++ exceptions, wchar_t, and includes improved debugging tools.  Clearly, this release represents a large positive ∆awesome.</p><p>We worked hard to increase the utility of the NDK for this release because you guys, the developers who are actually out there making the awesome applications, told us you needed it.  This release is specifically designed to help game developers continue to rock; with Gingerbread and the NDK r5, it should now be very easy to bring games written entirely in C and C++ to Android with minimal modification.  We expect the APIs exposed by r5 to also benefit a wide range of media applications; access to a native sound buffer and the ability to write directly to window surfaces makes it much easier for applications implementing their own audio and video codecs to achieve maximum performance.  In short, this release addresses many of the requests we’ve received over the last year since the first version of the NDK was announced.</p><p>We think this is pretty awesome and hope you do too.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7223117186480622657?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/gingerbread-ndk-awesomeness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
	</channel>
</rss>
