Thursday, September 29, 2011

Android’s HTTP Clients

Jesse Wilson

[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 uploads and downloads, configurable timeouts, IPv6 and connection pooling.

Apache HTTP Client

DefaultHttpClient and its sibling AndroidHttpClient are extensible HTTP clients suitable for web browsers. They have large and flexible APIs. Their implementation is stable and they have few bugs.

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.

HttpURLConnection

HttpURLConnection 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.

Prior to Froyo, HttpURLConnection had some frustrating bugs. In particular, calling close() on a readable InputStream could poison the connection pool. Work around this by disabling connection pooling:

private void disableConnectionReuseIfNecessary() {
// HTTP connection reuse which was buggy pre-froyo
if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
System.setProperty("http.keepAlive", "false");
}
}

In Gingerbread, we added transparent response compression. HttpURLConnection will automatically add this header to outgoing requests, and handle the corresponding response:

Accept-Encoding: gzip

Take advantage of this by configuring your Web server to compress responses for clients that can support it. If response compression is problematic, the class documentation shows how to disable it.

Since HTTP’s Content-Length header returns the compressed size, it is an error to use getContentLength() to size buffers for the uncompressed data. Instead, read bytes from the response until InputStream.read() returns -1.

We also made several improvements to HTTPS in Gingerbread. HttpsURLConnection attempts to connect with Server Name Indication (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.

In Ice Cream Sandwich, we are adding a response cache. With the cache installed, HTTP requests will be satisfied in one of three ways:

  • Fully cached responses are served directly from local storage. Because no network connection needs to be made such responses are available immediately.


  • 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 304 Not Modified status. If the content is unchanged it will not be downloaded!


  • Uncached responses are served from the web. These responses will get stored in the response cache for later.


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:

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) {
}
}

You should also configure your Web server to set cache headers on its HTTP responses.

Which client is best?

Apache HTTP client has fewer bugs on Eclair and Froyo. It is the best choice for these releases.

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 HttpURLConnection; it is where we will be spending our energy going forward.

How to Find Visited Pages in Google Search

I'm not sure if this is a new feature, but it's pretty useful. Like most websites, Google's search engine changes the color of visited links from blue to purple. All browsers handle links this way by default, but websites can alter the colors using some CSS code.

If you're logged in using your Google Account and Web History is enabled, Google saves all the search results you visit to your Web History. When you're using a different browser or a different computer and you're logged in using the same account, Google changes the color of the visited links from blue to purple, irrespective of the browser or computer you've used to visit them. For example, I searched for [haploid] using Chrome, I clicked on one of the results, then I tried the same query in Internet Explorer and the page I've visited in Chrome already had a purple link.


Google also has a search filter that lets you restrict the results to visited pages. Just click "More search tools" in the sidebar and select "Visited pages". For pages you're visiting frequently, Google shows an annotation below the snippet: "You've visited this page X times. Last visit: ...". When you mouse over the snippet, Google suggests to +1 the link: "You've visited this page X times. +1 to recommend it on Google search!".


{ Thanks, KoalaBear. }

Wednesday, September 28, 2011

"Google+ Is Google Itself"

If you thought that Google+ is just a separate service you can easily ignore if you don't want to use it, you were wrong. In an interview with Steven Levy, Bradley Horowitz - Google's VP of products - says that Google+ is actually Google itself.
Until now, every single Google property acted like a separate company. Due to the way we grew, through various acquisitions and the fierce independence of each division within Google, each product sort of veered off in its own direction. That was dizzying. But Google+ is Google itself. We're extending it across all that we do — search, ads, Chrome, Android, Maps, YouTube — so that each of those services contributes to our understanding of who you are.

Redesigning all Google services to match the Google+ interface is not just about consistency, it's also a way to show that they're part of the same super-service, an encompassing layer that makes them work together.

Google+ made Android's camera app integrate with Picasa Web Albums, Google Talk integrate with YouTube and Google Docs. It's likely that Google+ will make Google services more useful by combining their strengths. That's probably the reason why you'll use Google+ even when you're not going it to Google+ and you'll end up joining Google+ even if you don't like social networks.

Google Instant Tweaks

When Google launched Instant, the main goal of this feature was to guess your query before you finish typing it and to instantly display the results. This works well if your typing a popular query, but what happens when Google can't autocomplete your query and you're a slow typist? You'll usually see the results for partial queries that include the words you haven't finished typing.

Now Google no longer includes the word you're currently typing if it's not very likely that it's a complete word. If you type [android qualcomm qua], Google will only show the results for [android qualcomm]. When your query becomes [android qualcomm quad], Google no longer ignores the third word. Here's another example:


If you actually want to find the results for a query and Google ignores the last word, you can always press Enter, click the Search button or click "Search instead for ...".

Dynamic Views, New Blogger Templates

Blogger launched in March five blog views that used cutting-edge technologies to transform a blog into a Web app. Back then, visitors had to enter a special URL like gmailblog.blogspot.com/view/sidebar or install a Chrome extension to switch to one of the new interfaces. Six months later, Blogger created two new views (classic and magazine) and added the list of dynamic views to Blogger's template editing section so that blog authors can replace their template with one of the seven views that are now available.


There are three kinds of dynamic views: photo-oriented templates (flipcard, mosaic, snapshot), text-oriented templates (classic, sidebar) and magazine-like templates (magazine, timeslide). If you don't have a photoblog, classic, sidebar and magazine are the best dynamic views for your blog. Blogger's new templates bring a lot cool features and change the way readers interact with a blog. Infinite scrolling replaces pagination, blog posts are loaded using AJAX, Blogger caches blog posts so they load faster, images are downloaded as you browse, you can use keyboard shortcuts (j/k or n/p) to go to the next or previous post just like in Google Reader. There's also instant search that shows the list of results as you type.



While dynamic views have many cool features, there are also many downsides. They're not very customizable: you can only upload a header image and customize the background colors. When you pick one of the views, all the gadgets you've added will disappear. It's also annoying that blog posts no longer open in separate pages: they open either in lightbox-like panes or in a homepage-like interface, next to other posts (here's an example). Just like the mobile template, dynamic views only work with Blogger's commenting system, so you won't be able to use Disqus. It will be interesting to see how search engines handle the new templates, considering that blog posts are loaded using JavaScript and HTML pages are almost empty.

I don't intend to switch to one of the dynamic views, but my favorite templates are sidebar and magazine. You can always bookmark these links or use Google's Chrome extension, which needs to be updated to add support for the two new dynamic views. Some Google blogs have already switched to the new templates: Blogger Buzz, Gmail Blog, Google Docs Blog and LatLong.

Google Reader, Replaced by Google Sites in the Navigation Bar

Google Reader users probably noticed that the feed reader has been replaced by Google Sites in the main navigation bar. To visit Google Reader, they need to click "More" and then click "Reader" in the list of Google services.


Unlike the last time when Reader was replaced by Google Sites, this time is not an accident. A Google employee explained that this is a permanent change.
While the link to Reader has moved, you can continue to access Google Reader under the "More" dropdown. Or, you can also set a specific bookmark to reader.google.com for one-click access. Depending your browser, try dragging http://reader.google.com right from this post onto the bookmark bar on your browser (usually below the URL bar).

Google has usually made changes in the navigation based on the popularity of the services and it's likely that Reader's popularity is declining, while Google Sites gains more users. According to Google Trends, the queries [google reader] and [google sites] have almost the same search volume in the US.


Like Picasa Web Albums, Google Reader doesn't have a new interface based on Google+. The latest features added to Google Reader were comment moderation and integration with Google Buzz, a service that will soon disappear.

{ Thanks, Cougar. }

Friday, September 23, 2011

Google's New Search Interface Disables Many Shortcuts

With the latest redesign of the search results pages, Google made it more difficult to use most of the keyboard shortcuts that allowed you to quickly select a result or see a small preview.

Until now, you could type your query, press Enter to hide the list of suggestions and press Enter once again to go to the first result. If you didn't like the first result, you could press the down arrow to select the second result. Google also included a keyboard shortcut for Instant Previews: the right arrow. None of these shortcuts are available in the latest interface, at least not by default. Now you need to press Tab after performing a search to enable the old keyboard shortcuts.

Here's a search results page after typing a query (notice that there's no arrow next to the first result):


Here's what happens when you press Tab (you can use the up/down arrows, but the shortcut for Instant Previews no longer works):


Google probably disabled these features because not many people used them and a lot of users complained that the shortcuts made navigation more difficult. Power users need to learn that Tab enables keyboard shortcuts, but having to enable the feature every time you use Google Search is annoying. After all, shortcuts were supposed to make your life easier and help you be more productive.

Google Instant shortcuts are still available. You can continue to use the up/down arrows to select a different search suggestion, the right arrow to visit the first result for the search suggestion, Tab to use Google's suggestion and continue to type your query, Esc to select the query so you can quickly overwrite it.

{ via Google Search Help Forum }

Thursday, September 22, 2011

New Interface for Google Instant Previews

Google tweaked the UI for Instant Previews and made the search interface a lot cleaner. There's a new large icon for Instant Previews, but it's only displayed when you mouse over a snippet. Click the new icon or only hover over the gray bar and you'll see a much bigger screenshot.


"Instant Previews have been around since last year, allowing you to click on the magnifying glass to the right of the result to see a visual overview of a page. Now these previews are no longer even a click away: if you move your mouse over a search result, arrows will appear. Hover over them to see a visual preview of that result," explains Google.

Clicking the snippet no longer triggers an Instant Preview in the new interface. Unfortunately, the keyboard shortcut has been disabled, so you can longer get a glimpse of the page using the right arrow.

Google now repeats the title of the page and the URL next to the screenshot, while the links to the cached page and to other similar pages are included in the new enlarged snippet. It's a bad news for those who frequently use the "cache" link, who now have to spend more time to find it.

The only action that's still displayed is the Google +1 button, but you need to log in to see it. Probably Google wanted to emphasize the button, which is now placed next to the URL.

Here's the old interface:

Body Browser, No Longer a Google Service

One of the coolest apps launched by Google last year will have a new owner. Google Body Browser was a great way to show the power of WebGL, but it was also a useful app for exploring the human body. Body Browser will continue to exist, but it will be owned by Zygote Media Group.
As Google Labs winds down, we will be retiring Google Body. However, you will soon be able to find its functionality elsewhere. We are working on open-sourcing the code that powers Google Body so that anyone will be able to create and run a searchable 3D viewer. We are also working with our partner, Zygote Media Group, on an application called Zygote Body. This application will be free, available on the web and on Android, and will enable students, teachers, and others using Google Body to continue to have access to a human anatomy browser.


Wednesday, September 21, 2011

Euro Android Developer Labs

This series started last month, and now registration is open for the European leg:

  • Berlin — September 28 and 29.

  • London — October 3 and 5.

  • Paris — October 27 and 28.

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.

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.

Tuesday, September 20, 2011

Google Wallet

Google found an interesting way to launch the Google Wallet app for Android: as an over-the-air update for Sprint Nexus S 4G phones. Google Wallet makes use of the NFC chip from Nexus S phones and allows you to make credit card payments at physical stores using your Android smartphone.

"Google Wallet enables you to pay with your Citi MasterCard credit card and the Google Prepaid Card, which can be funded with any of your existing plastic credit cards. As a thanks to early adopters, we're adding a $10 free bonus to the Google Prepaid Card if you set it up in Google Wallet before the end of the year," informs Google. The Google Prepaid Card is powered by MasterCard and Money Network and it's a temporary solution until you can add credit cards from other companies. Google says that the application could add support for Visa, Discover and American Express cards in the future.

Google Wallet is more than a contactless payment solution: it's a virtual wallet that could store information about your credit cards, coupons, loyalty cards, gift cards, tickets and much more. It's also a great opportunity for Google to integrate Google Offers and make it easier to use by allowing consumers to pay, redeem offers and earn loyalty points in a single step using their mobile phone. Google says that it doesn't have access to the list of products you buy, but this feature could be added in the future.

While Google Wallet seems to be a convenient solution, many people might not use it because of privacy or security reasons. Google says that the payment credentials are stored in a separate chip called Secure Element and only authorized programs can initiate transitions. Google Wallet users need to enter the PIN to confirm a payment, so someone who finds an Android phone can't use the app because he doesn't know the code.

Google's vision is to create "an open commerce ecosystem" that will support many payment instruments, APIs that enable adding loyalty points, transferring offers, receipts and more. Google Wallet is Google Checkout's extension to offline payments and it's a big opportunity for Google to create a successful payment system. PayPal will soon offer a similar service and Apple's iPhone 5 could include a NFC chip, so Google Wallet will have some competition.

Google+ for Everyone

Three months after the launch, Google+ no longer requires invitation and it's available to anyone who has a Google account. "For the past 12 weeks we've been in field trial, and during that time we've listened and learned a great deal. We're nowhere near done, but with the improvements we've made so far we're ready to move from field trial to beta," informs Google.

The service has improved a lot, more quickly than any other Google product ever released. After announcing the public data APIs, Google added support for Hangouts in the Android app and added the option to broadcast a Hangout, but only for a small number of users. "We're starting with a limited number of broadcasters, but any member of the Google+ community can tune in. In fact: we'll be hosting our very first On Air hangout with will.i.am on Wednesday night, September 21. For more information visit will.i.am's profile on Google+."


Hangout has many other features you can preview by clicking "Try Hangouts with extras": screensharing, sketchpad, Google Docs integration and named hangouts "for when you want to join or create a public hangout about a certain topic".


The search box is now more useful because you can use it to find posts from your friends and from other Google+ users. Google also lets you restrict your results to people and save your search.


Google doesn't disclose the number of Google+ users, but a Comscore report from August estimated that "in just one month, Google+ has captured 25 million visitors". It's likely that Google+ has a lot more users today and the number will grow, now that the service no longer requires invitation. Google+ is the first social service launched by Google that's actually successful.

Monday, September 19, 2011

Preparing for Handsets

[This post is by Scott Main, lead tech writer for developer.android.com. — Tim Bray]

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.

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 — an app developed for Honeycomb is compatible with a device running ICS, which could be a tablet, a phone, or something else.



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.

Making your Honeycomb app for tablets only

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 <supports-screens> declaration to your manifest:

<manifest ... >
<supports-screens android:smallScreens="false"
android:normalScreens="false"
android:largeScreens="false"
android:xlargeScreens="true"
android:requiresSmallestWidthDp="600" />
<application ... >
...
</application>
</manifest>

This describes your app’s screen-size support in two different ways:

  • It declares that the app does not support the screen size buckets “small”, “normal”, and “large”, which are traditionally not tablets


  • It declares that the app requires a screen size with a minimum usable area that is at least 600dp wide


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 requiresSmallestWidthDp 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.

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.

The catch is that you must compile your application against Android 3.2 or higher in order to use the requiresSmallestWidthDp 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 minSdkVersion. When you’re making final preparations to build your release candidate, change the build target to Android 3.2 and add the requiresSmallestWidthDp attribute. Android versions older than 3.2 simply ignore that XML attribute, so there’s no risk of a runtime failure.

For more information about why the “smallest width” screen size is important for supporting different screen sizes, read New Tools for Managing Screen Sizes (really; it’s got lots of things you need to know).

Making your Honeycomb app work on handsets

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.

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.

Here are two guidelines to help make your Honeycomb tablet app work well on handsets:

  • Build your design around Fragments that you can reuse in different combinations, in single-pane layouts on handsets and multi-pane layouts on tablets


  • Be conservative with your Action Bar design so the system can adjust its layout based on the screen size


Creating single-pane and multi-pane layouts

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:

  • 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 — swapping the fragments within the activity when necessary.


  • 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.


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 — 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.

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.

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:

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.

Here’s res/layout/main.xml for handsets:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.example.android.TitlesFragment"
android:id="@+id/list_frag"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>

And res/layout-large/main.xml for tablets:

<?xml version="1.0" encoding="utf-8"?>
<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">
<fragment class="com.example.android.TitlesFragment"
android:id="@+id/list_frag"
android:layout_width="@dimen/titles_size"
android:layout_height="match_parent"/>
<fragment class="com.example.android.DetailsFragment"
android:id="@+id/details_frag"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

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).

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:

  • Do not manipulate one fragment directly from another.


  • Keep all code that concerns content in a fragment inside that fragment, rather than putting it in the host activity’s code.


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.

For example, Activity A from above handles item selections like this:

/** 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);
}
}

When DisplayActivity (Activity B) starts, it reads the data delivered by the Intent and passes it to the DisplayFragment (Fragment B).

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.

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 Honeycomb Gallery sample.

Making the Action Bar work on handsets

As long as you’ve been using the framework’s implementation of ActionBar 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:

  • When setting a menu item to be an action item, avoid using the “always” value. 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.


  • When possible, provide icons for all action items and declare showAsAction="ifRoom|withText". 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.


  • Avoid using custom navigation modes in the action bar. Use the built-in tab and drop-down navigation modes — 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.


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.

Some other tips

  • When working with a ListView, 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.


  • Create alternative resource files 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.


Testing your handset support

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.

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 res/layout-large/main.xml, use res/layout-land/main.xml). 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.

Conclusion

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.

So if you have a Honeycomb tablet app out there (and by that, I mean an app with minSdkVersion="11" 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.

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.

Stay tuned to the blog for more information about ICS as it nears release.

Saturday, September 17, 2011

Blogger's Slideshow Feature

Blogger added a feature that makes it easier to view multiple photos. When you click on an image from a Blogger post, a LightBox-like overlay shows a bigger version of the image and lets you view the other images in a slideshow. The feature was borrowed from Google+, it's enabled by default and can't be disabled from the settings page.

If you want to open an image in a new tab, middle-click on the URL displayed below the image or right-click the link and select "open link in new tab". The slideshow supports keyboard shortcuts: left/right arrows, j/k, n/p to navigate, Esc to close the slideshow.




{ Thanks, Petros and Cougar. }

Thursday, September 15, 2011

Rich Snippets for Apps

Now that both the Apple App Store and the Android Market have Web interfaces, Google decided to show better snippets for the results from these sites. The next time you search for [Angry Birds], [Cut the Rope], [Shazam] or [ASTRO File Manager], you'll find results that include a small icon, the app's rating, the number of reviews and the price. For now, only the results from the Android Market include thumbnails.


Google also shows rich snippets for review sites like CNET. If you own an app store or you have a site that allows users to download software, you can get similar snippets by adding some special markup. "When you mark up software application information in the body of a web page, Google can identify it and, when users search for apps, use this information to better display your app details in search results."

YouTube's New Video Editor

YouTube has a new online video editor that lets you trim the video, rotate it, remove shaky camera motions, adjust the contrast, saturation and color temperature, apply simple effects like "sepia", "cartoon", "thermal" and add a free audio soundtrack from YouTube's library.

While the editor is pretty basic, the main advantage is that you can replace the original video, but this only works if your video has less than 1,000 views and YouTube hasn't received a copyright complaint from a third-party. There's also a "save as" option that lets you save the edited version as a new video.



How to find the new editor? Make sure you're logged in, go to "My videos & playlists" and click "Edit video" next to the video you want to edit. You can also open a video you've uploaded and click "Edit video".


To make things more confusing, YouTube has another video editor that lets you mix your videos and Creative Commons videos from other YouTube users, add audio soundtracks from YouTube's library and apply transitions.

Wednesday, September 14, 2011

Google Goggles Makes Your Phone's Camera Smarter

Google Goggles is an application that's sometimes useful, but it's not good enough to use it every time you want to find something about an object. The Android app has a new feature that integrates it with the Camera app, uploads all the photos you're taking to Google's servers and shows notifications in the status bar if Goggles found something useful. It may sound spooky, but it makes your phone's camera smarter.

"With this new opt-in feature in Goggles, you can simply photograph an image using your phone's camera, and Goggles will work in the background to analyze your image. If your photo contains items that Goggles can recognize, the app will notify you," explains Google. The feature is disabled by default, but you can enable it from the settings page by choosing "Search from Camera".



It's probably a good idea to only enable this option when you're on vacation or when you're planning to photograph barcodes for products you want to buy. It's also useful if you're in a bookstore and you want to "bookmark" some books.

Google Mobile's help center informs that "each Goggles query consumes approximately 100 KB of data" and you can limit the amount of data that's consumed by selecting "Search on WiFi networks only" under "Mobile Connection".

"Search from Camera" is one of the features that won't be available in the Google app for iPhone because iOS' background APIs aren't that powerful. If you have an Android device, install Google Goggles 1.6 from the Android Market.

More Options for Google Flight Search

Google Flight Search has a homepage, is now included in the search sidebar and offers more options, but only for US locations. Search Engine Land reports that "this is the first product to emerge from Google's controversial acquisition of travel software company ITA, which closed in April".

If you search for [flights from San Francisco to Houston] and choose "Flights" from the sidebar, Google shows a list of flights and lets you filter them by the number of stops, airline, outbound time, price and duration of flight.

There's also a dynamic map that lets you change your destination and a smart chart for filtering long and expensive flights. Just click the "limits" button and use the sliders to customize the filters. By default, Google only shows the best flights.

If you click the arrows from the From or To drop-downs, you can select some of the nearby airports. You can also enter multiple locations separated by commas.



The calendar is also smart because it lets you find the cheapest flights and plan your trips accordingly.


Once you've picked an outbound flight, you can also choose a return flight. Google sends you to the airline sites to book your flights, but it's interesting to notice that the links are labeled as ads.



"This is just an early look: the takeoff, not the final destination! You may notice that at the moment we include a limited number of U.S. cities and show results for round-trip economy-class flights only. We're working hard to improve this feature and look forward to sharing more updates," explains Google.

For locations outside of US, Google still shows a static OneBox with a list of flights, but this tool is not interactive. For some reason, Google shows the same OneBox if you enter US locations and doesn't link to the advanced flight search engine.


Update. Philip Cunningham, an eagle-eyed reader, spotted a mistake: the link to Recipe Search is spelled "receipts" in Flight Search. Another mistake is that Google still shows icons next to the specialized search options.

Tuesday, September 13, 2011

Thinking Like a Web Designer

[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-development is a relatively new profession, the community is growing by sucking in experts from related domains, one being web design and development.

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.

In this blog post, we’ll walk through a few web development features and look for matches in the world of Android UI development.

Device resolutions and physical sizes

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.

Let’s look at some ways in which CSS and Android allow for flexible and adaptive layouts.

Providing custom layouts for different resolutions

CSS3 media queries 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.

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 res/layout-xlarge or res/layout-sw600dp (smallest width 600 density-independent pixels) directories. Note that the latter syntax requires Android 3.2 or later.

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:

#leftPane {
display: none;
}

@media screen and (min-device-width:600px) {
#leftPane {
display: block;
}
}

The same could be accomplished on Android using multiple layout directories:

res/layout/foo.xml:

<FrameLayout>
<!-- a single pane -->
<View android:id="main_pane">
</FrameLayout>

res/layout-sw600dp/foo.xml:

<LinearLayout android:orientation="horizontal">
<!-- two panes -->
<View android:id="left_pane">
<View android:id="main_pane">
</LinearLayout>

As a side note, if you plan on creating multi-pane layouts, consider using fragments, which help break up your screens into modular chunks of both layout and code.

There are also other neat ways of using resource directory qualifiers. For example, you could create values/dimens.xml and values-sw600dp/dimens.xml files specifying different font sizes for body text, and reference those values in your layouts by setting android:textSize="@dimen/my_body_text_size". The same could be done for margins, line spacing, or other dimensions to help manage whitespace on larger devices.

‘Holy grail’ layouts

Web developers have long dreamt of an easy way to build a ‘holy grail’ 5-pane layout (header/footer + 3 vertical columns). There are a variety of pre-CSS3 tricks including position:fixed, float:left, negative margins, and so on, to build such layouts but CSS3 introduced the flexible box module, which simplifies this tremendously.

Figure: An archetypal “holy grail” layout

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.

LinearLayout has this neat way to stretch its children to fit the remaining space, or to distribute available space to certain children, using the android:layout_weight attribute. If a LinearLayout has two children with a fixed size, and another child with a nonzero layout_weight, 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 Layout Tricks: Creating Efficient Layouts.

Let’s take a look at some example code for implementing such a ‘holy grail’ layout on Android and on the web:

<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">

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

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

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

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

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

</LinearLayout>

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

</LinearLayout>

Note: Android tablet apps in landscape will generally show an action bar 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.

And here’s an example implementation using the CSS3 flexible box model; notice the similarities:

<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;
}
</style>

<div id="container">
<div id="top"></div>
<div id="middle">
<div id="left"></div>
<div id="center"></div>
<div id="right"></div>
</div>
<div id="bottom"></div>
</div>

Layered content

In CSS, with position:absolute, 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 layout_gravity attributes indicating alignment with the parent frame layout.

Below is a contrived example of a FrameLayout with three children.

Figure: Example FrameLayout with three children (2 with top-left and 1 bottom-right alignment)

Figure: Isometric view of the example FrameLayout and its children.

The code for this example is as follows:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="200dp">

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

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

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

</FrameLayout>

Scrollable content

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.

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.

It’s also possible to add custom scrolling to views by using methods like View.scrollTo and helpers like Scroller in response to touch events. And for horizontal, snap-to-page-bounds scrolling, one can use the excellent new ViewPager class in the support library.

Below is an example of a ScrollView containing a single TextView child and the code needed to implement something like this.

Figure: A TextView inside a ScrollView, scrolled about half way.


<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- the scrollable content -->
<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..." />

</ScrollView>

Custom layouts

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.

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 here). 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.

Device densities

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.

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 <img> at 100% browser zoom up to 240px on a 240dpi screen, such that its physical width is always 1”.

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 -webkit-max-device-pixel-ratio and <meta> viewport arguments such as target-densitydpi=device-dpi. For an in-depth discussion on how to tame this mobile browser behavior see this blog post: Pixel-perfect Android web UIs.

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.

Features you don’t have out of the box

There are a few features that web designers and developers rely on that aren’t currently available in the Android UI toolkit.

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.

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 Canvas drawing methods, similar to HTML5’s canvas APIs, to render vector graphics. There are also community projects such as svg-android that support rendering a subset of the SVG spec.

Conclusion

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’ll find you’re not alone.

Dash, Google's Alternative to JavaScript

An internal Google document from October 2010 provides some information about Google's strategy for the future of JavaScript. Google will continue to work on improving JavaScript and adding new features to ECMAScript Harmony, but it will also develop a new language called Dash that will try to solve JavaScript's problems, while offering better performance, the ability "to be more easily tooled for large-scale projects" and better security features.
The goal of the Dash effort is ultimately to replace JavaScript as the lingua franca of web development on the open web platform. We will proactively evangelize Dash with web developers and all other browser vendors and actively push for its standardization and adoption across the board. This will be a difficult effort requiring finesse and determination, but we are committed to doing everything possible to help it succeed.

While Dash is catching on with other browsers, we will promote it as the language for serious web development on the web platform; the compiler allows such developers to target other browsers before those browsers implement Dash.

The Dash language effort will be driven by Lars Bak and his team in the Aarhus office.

Google also develops a cloud IDE called Brightly that will probably the first app written in Dash. The Dash VM and Dash Cross Compiler could be available later this year, according to the document.

"Our approach is to make an absolutely fantastic VM/Language and development environment and build great apps that fully leverage it in order to help other browsers see the wisdom in following. Once Dash has had a chance to prove its stability and feasibility, we are committed to making Dash an open standard with involvement from the broader web community," explains Google.

Update (October 10): The language is called Dart.

{ via Reddit }

Google Chrome's New Bookmarks UI

Google Chrome 15 brings some new ways to access your bookmarks. There's a new bookmarks menu below the "new incognito window" option that lets you quickly find your bookmarks. This feature is already available in Chrome 14 (now in beta), but the bookmarks menu is more prominently displayed in Chrome 15.


The new tab page no longer includes the bookmarks bar if this feature is disabled. The main reason for removing the bar is that the new tab page now includes a special section for bookmarks, next to the sections for apps and frequently visited pages. Bookmarks are displayed just like apps, but the thumbnails are much smaller and they seem to be blank, at least for now. You can now drag bookmarks to the list of apps, reorder them or remove them without using the bookmark manager.


While there are many advantages to the new interface for browsing and managing bookmarks, the thumbnail view is not very useful if you have a lot of bookmarks in a folder. Page titles are truncated to the first 10-15 characters and it's not always easy to find a bookmark. A list view is more space-efficient.

Google Drive, a New Name for the Google Docs Homepage?

TechCrunch has recently reported that the subdomain drive.google.com has been added to a Chrome file and a Google Docs message includes a reference to Google Drive.



The source code of Google Docs files has many messages related to "Google Drive", but all of them have one thing in common: they replace similar messages that include "Documents List". Here are two examples: "items haved been removed from your Documents List" / "items haved been removed from your Google Drive", "Add to my Documents List" / "Add to My Google Drive".


This suggests that Google Drive could be the new name of the Google Docs List, while Google Docs could be detached from the file storage interface and only be an online office suite. Google Docs is not the right name for an online storage application that lets you upload not just documents, but also music, videos, archives, photos and other files. Hopefully, the rebranding will bring more free storage, file syncing apps for mobile and desktop and integration with third-party apps.

Steven Levy's "In the Plex" included an interesting story about Google Drive being superseded by Google Docs because "files are so 1990". Google's Sundar Pichai said that "when people use our Google Docs, there are no more files. You just start editing in the cloud, and there's never a file." Google Drive might be a better name for a service that stores user files, whether they're created using Web apps, mobile apps or desktop apps.

Google Tweaks the Search Interface

After a few weeks of testing various changes to the search results pages, Google redesigned the interface and added some of the experimental features. The search options sidebar no longer uses icons, there's a new section that displays the service's name ("Search") and the number of search results.




Google also tweaked the colors of the links and URLs, as you can see in the image above, which compares the new interface (left) with the old interface (right).

Monday, September 12, 2011

More Carrier Billing Options on Android Market



[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]



Over the past year, we’ve seen very strong growth in the number of Android users around the world. To make it easier for those users to purchase their favorite apps and games on Android Market, we’re bringing Direct Carrier Billing to additional carrier networks in South Korea, the UK, and Germany.



In South Korea, we’ve begun a phased rollout of the service to users on the top two carrier networks — SK Telecom and KT Corporation. When complete, the rollout will reach more than 10 million users, who will be able to charge their Android Market purchases straight to their phone bills.



In Europe, we’re rolling out the service to users on two popular regional carriers, Vodafone UK and Vodafone DE. Initially, the service will be available only to users who have purchased their devices through Vodafone’s online and retail channels.



The new launches expand the network of carriers already offering direct billing service in the US on the T-Mobile, AT&T, and Sprint networks, and in Japan on SoftBank, KDDI, and NTT DOCOMO networks.



Direct Carrier Billing is a key payment option for users worldwide, especially in regions where credit cards are less common. We will continue to partner with more operators to offer this payment option to their Android users. Watch for more announcements in the weeks ahead.

Saturday, September 10, 2011

Google Groups Has a New Interface

Google Groups is the latest Google service redesigned to look like Google+. New buttons, new icons, new scrollbars, new search box and a smoother interface that makes Google's help forums look outdated.

Since the current Google Groups UI is inspired by Google Reader, we can expect to see a revamped Google Reader with a similar interface.



If you miss the small arrow that allowed you to hide the sidebar, use the "f" keyboard shortcut, which hides both the sidebar and the search box.


{ Thanks, Filipe, François and Elchanan. }

Thursday, September 8, 2011

iPhone App for Blogger

Blogger has an app for iPhone and it's better than the corresponding Android app, which has improved a lot in the past months. Both apps let you edit your existing posts and create new posts, add images to your posts, include labels and geolocate your posts.

They're pretty basic, but the iPhone app has a better interface, it's easier to use and pays attention to detail. For example, the iPhone app includes the URL of the blog next to the name when you switch to a different blog, so that it's easier to identify a blog. The Android app only shows the names. To publish a post in the iPhone app, you need to tap the "Publish" button, which is always displayed at the top of the screen. In the Android app you need to scroll to the bottom of the post to find the "publish" button.



"With the Blogger app, you can write a new blog post and publish it immediately or save it as a draft right from your iOS device. You can also open a blog post you've been working on from your computer and continue editing it while you're on-the-go. Your blog posts are automatically synced across devices, so you’ll always have access to the latest version," informs Google.