Profile

Cover photo
Taylor Perkins (hwrdprkns)
Works at Rdio
Attended Tufts University
Lives in San Francisco, CA
181 followers|269,052 views
AboutPostsPhotosVideos+1'sReviews

Stream

 
Clam caking
1
Add a comment...
 
People just need to be convinced it's worth the time!
 
Android App Polishing: Reducing User Frustration

With the release of Capitaine Train for Android[0], several people recently asked me how we implemented some of the tips & tricks available in the application (some of these tricks are barely visible but remember, I love details :p). In order to showcase some of the most interesting application bits of code, I thought it could be helpful to Android developers to start a small series of posts. Feel free to comment this article if you want me to describe something you found nice in the Capitaine Train application.

Capitaine Train Android relies on an internal "search" API that, in turn, also relies on some carriers APIs we don't have control on. For instance, when a user is looking for a train, the Android app asks Capitaine Train servers. Then, Capitaine Train asks all supported carriers for their available trains for the requested search params. Once carriers respond to our servers, we find the best prices, combine results, do whatever-we-think-is-the-best-to-filter-and-sort-results and finally send results to the Android application. While the process is simple (at least in theory…), it also implies, by transitivity, Android apps relies on some - sometimes slow - servers we don't control: carriers' servers.

Because of the potentially long "search" API calls we had to find a way to indicate the user something was loading. In the early - internal only - alpha versions of Capitaine Train Android, we quickly integrated a circular/indeterminate ProgressBar. But users (i.e. Capitaine Train employees) were not satisfied with it. Indeed, most of them were annoyed by the loading time. This mutiny quickly demonstrated displaying a simple loading indicator was not enough. We also had to reduce user frustration. We finally decided to completely redesign the loading screen by using a determinate ProgressBar and adding a fancy animation.

The main idea behind the ProgressBar is obviously to indicate the user the approximate amount of time remaining before the results are displayed. The current version of Capitaine Train is based on an hardcoded average search duration (based on our experience). But we have an opened issue in our issue tracker to enhance the search duration approximation using previous device/connectivity searches. The ProgressBar is animated thanks to an ObjectAnimator:

private static final TimeInterpolator GAUGE_ANIMATION_INTERPOLATOR = new DecelerateInterpolator(2);
private static final int MAX_LEVEL = 10000;

ObjectAnimator.ofInt(mProgressBar, "progress", 0, MAX_LEVEL)
    .setDuration(GAUGE_ANIMATION_DURATION)
    .setInterpolator(GAUGE_ANIMATION_INTERPOLATOR)
    .start();

The ProgressBar is entirely customized using a LayerDrawable[1] defined in XML. As ProgressBar requires, the two layers are tagged with some special framework-defined identifiers: @android:id/background for the background and @android:id/progress for the actual progress. Note you can also use @android:id/secondaryProgress if you use the "secondary progress" capabilities from ProgressBar:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape>
            <solid android:color="@color/ct_dark_gray_10p"/>
            <corners android:radius="8dp" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <solid android:color="@color/ct_green"/>
                <corners android:radius="8dp" />
            </shape>
        </clip>
    </item>

</layer-list> 

We also added a fancy and funny gif-like animation to the loading screen. We wanted to reduce user frustration by attraction his/her attention on something different that the painful loading indicator. The current animation is rather simple and simulates a train going forward. I would have loved to make something more polished but I'll be honest with you: I did this in a rush :s. I clearly need to find time to implement some other nice ideas on this screen.

The implementation of the animation is a little bit trickier and relies on both a LayerDrawable[1] containing both a background (the train image with no rails) and an AnimationDrawable for the animated rails. We could have implemented it with a single AnimationDrawable[2] (it was actually the case in the first version) but the current implementation reduces our APK size quite significantly:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/background"
        android:drawable="@drawable/ic_train_no_rails"/>

    <item
        android:id="@+id/rails"
        android:drawable="@drawable/animated_rails"/>

</layer-list>

The @drawable/animated_rails Drawable is defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:duration="50">
        <inset
            android:drawable="@drawable/animated_rails_1"
            android:insetBottom="6dp"
            android:insetLeft="66dp"
            android:insetRight="66dp"
            android:insetTop="150dp" />
    </item>

    <item android:duration="50">
        <inset
            android:drawable="@drawable/animated_rails_2"
            android:insetBottom="6dp"
            android:insetLeft="66dp"
            android:insetRight="66dp"
            android:insetTop="150dp" />
    </item>

    <item android:duration="50">
        <inset
            android:drawable="@drawable/animated_rails_3"
            android:insetBottom="6dp"
            android:insetLeft="66dp"
            android:insetRight="66dp"
            android:insetTop="150dp" />
    </item>

</animation-list>

In general, always try to avoid loading indicators/screens. When you are in control of the entire API chain, this can be done fairly easily. Unfortunately we are not living in an ideal world and it may be necessary sometimes to overcome/hide some issues with loading screens. If you end up implementing a loading screen in your application, do everything you can to reduce users frustration. 

#gde   #android   #AndroidAppPolishing  

[0]: https://play.google.com/store/apps/details?id=com.capitainetrain.android
[1]: http://developer.android.com/reference/android/graphics/drawable/LayerDrawable.html
[2]: http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html
1
Add a comment...
 
It would be awesome if #okhttp  had a very similar api to HttpWebRequest. Just used HttpWebReqeust for the first time the other week and it was dead simple.
Name, Description. Public property Supported by Portable Class Library Supported in .NET for Windows Store apps, Accept, Gets or sets the value of the Accept HTTP header. Public property, Address, Gets the Uniform Resource Identifier (URI) of the Internet resource that actually responds to the ...
1
Add a comment...
 
 
Vault: an advanced Storage Access Framework example

Recently, I’ve been working on the new Android Storage Access Framework which introduces an abstraction layer between apps that work with files and apps that can store those files. This is powerful because apps like QuickOffice can now use simple intents to open and save documents using any storage app that implements a DocumentsProvider.  The DocumentsProvider API is designed to support a wide range of storage types, including cloud storage, physical media, etc.

https://developer.android.com/guide/topics/providers/document-provider.html

As an advanced DocumentsProvider example, I wrote “Vault” which encrypts all files that a user saves inside.  It keeps data encrypted with AES-128 while at rest, and uses Unix pipes to encrypt/decrypt data on the fly.  It protects the encryption key by wrapping it using a hardware-backed KeyStore, if available.  It also uses a new feature of ParcelFileDescriptor to detect when a remote process has encountered an error or crashed, indicating that any partially written data should be ignored and rolled back.

https://android.googlesource.com/platform/development/+/master/samples/Vault/

Hopefully this advanced example is helpful as you look at implementing your own DocumentsProvider.  :)
1
Add a comment...
 
Does anyone know why the DataSource class is hidden in the MediaFramework? 

#AndroidDev   #Android  
Let apps provide a custom data source for extractors Adds android.media.DataSource, which is modeled after its native namesake, and a new method on MediaExtractor that lets apps specify their implementation of a DataSource as the source of data for the extractor.
1
Add a comment...
Have him in circles
181 people
Calvin Hopkins's profile photo
Karen Rose Lazaga's profile photo
Archee Fesariton's profile photo
Elise Hsu's profile photo
Simon Burns's profile photo
Donghui Chen's profile photo
Aida Behmen-Milicevic's profile photo
Karen Orozco Gutierrez's profile photo
Jordan Potter's profile photo
 
Yummy east coast food
1
Add a comment...
 
Time for a new work computer? Make life easy for yourself by using this script to export all of your brew (and cask) packages.

Then just copy the file to your new computer. Bundle the Brewfile and profit!
1
Add a comment...
 
Thanks for the great okhttp library! I'm curious as to what the timeline is for the new async functionality. I know its in master currently, but is there a release timeline for it?
1
Jake Wharton's profile photoTaylor Perkins (hwrdprkns)'s profile photoJesse Wilson's profile photo
3 comments
 
Yup. I'm just about to finish the last big refactoring for 2.0. Then it's time to stabilize and bake.
Add a comment...
 
Steph curry needs to stop turning the ball over. 
1
Add a comment...

Taylor Perkins (hwrdprkns)

commented on a post on Blogger.
Shared publicly  - 
 
Any benchmarks as to how much of an improvement this is over the Xamarin networking stack? 
Thursday Night 04 Oct 2013 on xamarin. Fast HTTP with ModernHttpClient. Today, I open-sourced a drop-dead simple way to make your code using HttpClient run way faster on Android and iOS, called ModernHttpClient. Binary Release · GitHub Repo. Using this library is basically the easiest thing in ...
1
Add a comment...
 
They really could have come up with a better name for this library...
1
Add a comment...
People
Have him in circles
181 people
Calvin Hopkins's profile photo
Karen Rose Lazaga's profile photo
Archee Fesariton's profile photo
Elise Hsu's profile photo
Simon Burns's profile photo
Donghui Chen's profile photo
Aida Behmen-Milicevic's profile photo
Karen Orozco Gutierrez's profile photo
Jordan Potter's profile photo
Work
Occupation
Mobile Software Engineer
Skills
Software, Business Development, Electrical Engineering
Employment
  • Rdio
    Software Engineer, 2012 - present
    I focus on the Android and iPhone apps at Rdio.
  • Advent Software
    Software Intern, 2011 - 2012
  • Taggstr
    COO, 2009 - 2011
  • Typhoon Studios
    Business Development
Places
Map of the places this user has livedMap of the places this user has livedMap of the places this user has lived
Currently
San Francisco, CA
Previously
Medford, MA - San Jose, CA
Story
Tagline
Let whoever can win glory before death. When a warrior is gone that will be his best, and only bulwark.
Education
  • Tufts University
    Electrical Engineering, 2008 - 2012
  • Valley Christian High School
    College Preparatory, 2004 - 2008
  • Laurelwood Elementary School
Basic Information
Gender
Male
Looking for
Friends, Dating, A relationship, Networking
Relationship
Single
Taylor Perkins (hwrdprkns)'s +1's are the things they like, agree with, or want to recommend.
Chromium Blog: Making the web faster with SPDY and HTTP/2
blog.chromium.org

accessibility (1); benchmarks (1); beta (1); blink (1); chrome apps (3); Chrome Frame (1); chrome web store (26); chromeframe (3); chromeos

Android 4.3 APIs | Android Developers
developer.android.com

API Level: 18. Android 4.3 ( JELLY_BEAN_MR2 ) is an update to the Jelly Bean release that offers new features for users and app developers.

Rdio
market.android.com

Discover your next favorite song with Rdio, a service for streaming unlimited music—on-demand and ad-free—on your Android device. With over

Google Maps
market.android.com

Download the latest release of Google Maps, and never carry a paper map again. Get Google Maps with Navigation (Beta), Places, and Latitude

Music
market.android.com

Official Android player for Music Beta by Google. The Music application features a redesigned UI and now supports Music Beta by Google. Mu

Rdio .
plus.google.com

Music to your ears.

End Piracy, Not Liberty – Google
www.google.com

Millions of Americans oppose SOPA and PIPA because these bills would censor the Internet and slow economic growth in the U.S.. Two bills bef

Galaxy Nexus
www.google.com

Galaxy Nexus. First phone with Android 4.0, Face Unlock, Android Beam, an amazing HD screen and 4G LTE fast.

Nexus S – The new Android phone from Google
www.google.com

Nexus S is the newest Android phone from Google. With Gingerbread, fast just got faster.

Android SDK Reference Search
chrome.google.com

Adds an 'ad' omnibox command and view source links for the Android SDK class and XML references.

Google Wallet - make your phone your wallet
www.google.com

Google Wallet is an app that makes your phone your wallet. Tap, pay, and save with virtual cards and offers on your phone.

Google+
market.android.com

Real-life sharing rethought for the web, wherever you are. Google+ for mobile makes sharing the right things with the right people a lot sim

Google+: real life sharing, rethought for the web.
www.google.com

Google+ aims to make sharing on the web more like sharing in real life. Check out Circles, Messenger and Hangouts, just a few of the things

Google Voice (by Google) - Chrome Web Store
chrome.google.com

Make calls, send SMS, preview Inbox, and get notified of new messages. (US only)

AR.FreeFlight
market.android.com

Pilot the AR.Drone, the first quadricopter that you can fly with Android devices Welcome to the 1st official application made for piloting t

Google Docs - Online documents, spreadsheets, presentations, surveys, fi...
docs.google.com

Create and share your work online and access your documents from anywhere. Manage documents, spreadsheets, presentations, surveys, and more

BrowserTexting
chrome.google.com

Write, send &amp; receive SMS text messages in Chrome via your Android phone!

Dropbox - Apps on Android Market
market.android.com

Dropbox lets you bring all your photos, docs, and videos anywhere. Dropbox is a free service that lets you bring all your photos, docs, and

Google I/O 2012: After Hours
developers.google.com

Google I/O 2012 June 27-29, 2012 Moscone Center, San Francisco. Schedule: Sessions. Sessions · Code Labs · Agenda. Events. I/O Extended · I/

Good place to hit some practice clubs
Public - 8 months ago
reviewed 8 months ago
Good cheap sandwich
Public - 8 months ago
reviewed 8 months ago
The Calamari appetizer was delicious. I didn't have a main course, but otherwise the Monk Brew was great and so was the atmosphere. The overall quality of the food was high and I would come back here again.
Public - 2 years ago
reviewed 2 years ago
This is a good place to target watch with a cup of coffee. I was reading a book, outside on the patio and had a good time. The Americano I got was good; not the best coffee in my life, but I also paid $3 for it so I didn't expect it to be. Overall, this place is not bad for grabbing a drink and chilling for a while. The busy nature of Market street makes it a great place to chill and/or hangout.
Food: Very GoodDecor: Very GoodService: Excellent
Public - 2 years ago
reviewed 2 years ago
21 reviews
Map
Map
Map
Often has long lines but has an automated machine which is good for purchasing stamps quickly. The automated machine has no line.
Public - a year ago
reviewed a year ago
Wasn't a bad place. The Mama's omelette was pretty delicious. The latkes I had were a tad overcooked but still tasty. Overall, this is a decent, reasonable spot to have breakfast or brunch.
Food: Very GoodDecor: Very GoodService: Very Good
Public - 2 years ago
reviewed 2 years ago
Great spot to eat. We had to wait about an hour, however the food was delicious. I had the bread pudding with fried banana which was very tasty. Overall, great spot to have breakfast.
Food: ExcellentDecor: Very GoodService: Very Good
Public - 2 years ago
reviewed 2 years ago