27 Jan 2016, 09:27

Free Coffee!

I drink some of the best coffee in the Bay Area, every day, for free. Here’s how I do it.

Step 1

This may sound like cheating, but the easiest way to drink amazing coffee all the time is to learn to make amazing coffee yourself. I’ve spent years working on this skill, learning a bunch of different methods of brewing and extracting coffee, learning what works and what doesn’t. For me, that’s more than just knowing how to make a good pot of coffee.

I worked at a couple of coffee shops when I was in high school and college. I’ve had an espresso machine at home for around 14 years now, and this past year is when I finally started getting the extractions that I wanted consistently. It doesn’t need to take 15 years to do, having good equipment helps a lot, and that was somewhat of a barrier for me until now. Even with a great espresso machine and knowing how to pull an excellent espresso, I’m still learning how to really nail the latte. I’ve been making progress:

latte art collage

Over the years, I’ve also learned pour-over, cold brew, siphon, and french press. I’ve done cowboy coffee on a few occasions. All this to say, that at home, I’m capable of making coffee that rivals most coffee shops around. No, I’m not better than Blue Bottle, or Chromatic, but most of the time, I don’t have a reason to buy coffee out.

Step 2

Get some good equipment. The first thing is a burr grinder. You’ll want to grind your coffee just before you brew it. It starts oxidizing very quickly once ground, as that happens the flavor disappears.

grinder 1 grinder 2

I would also recommend a cheap kitchen scale, so that you can use a consistent amount of coffee, to make your coffee more consistent. A good rule of thumb is 7g of coffee per serving (6oz for drip, 4oz for french press).

If you’re into drip coffee, I’d suggest finding a drip machine that uses a stainless steel insulated carafe, instead of a glass carafe with a heating element. I would also try to find one that heats the water to between 190-200ºF, which is a typical suggested extraction temperature.

For espresso, you’ll probably want to start with a less expensive machine like a Gaggia and work your way up. I love my Expobar, it has delivered results that I have not seen on the lower end machines that I’ve used. Espresso is a bit of an expensive hobby.

expobar espresso machine

Step 3

Roast coffee at home. This is where you start saving money. Roasting at home means that you get the freshest possible beans, for cheaper than the grocery store brand (probably). Can you buy 1lb of beans that were roasted yesterday for $6.50? If you can, then maybe you don’t need a roaster.

Roasting is a skill itself, and will take some time to get the hang of, but it’s totally worth it. If you are into espresso, the difference in flavor will be obvious, and you’ll start to wonder why you should pay for espresso out. You’ll be drinking the freshest coffee possible, and freshness is what brings you flavor.

roasted coffee

Roasting is a bit of a hassle, but once you get into it, it’s really not that bad. I know the timing of my machine for the batches that I roast, so I know the 3-4 minute window where I need to be watching my machine, and paying close attention. (Warning, beans can catch fire while roasting, you’re going to need to know what to look out for in that case - primarily fire in your roaster.)

Step 4

Sell half of your roasted beans for twice what you bought them for raw. E.g., buy 1lb of raw beans for $6.50, roast it, sell half of that for $6.50. I tend to roast about 340g of raw beans, which comes out to around 290g roasted, and then sell 145g of that for $5. I tend to sell around 3 batches of the 145g beans per week, and drink about the same amount at home. Quick note here, I make sure to buy larger quantities of beans (12-16lbs) using Sweet Maria’s fixed shipping option to keep shipping costs low.

What’s great is that this is a good deal for your friend who’s buying it too. It’s cheaper for your friend than buying a higher end brand that is fresh. I sell mine by the gram, so 290g (~10oz) is $10, or $11.75 for 12oz. According to Instacart, buying coffee from Whole Foods would be expensive: Philz is $14.50 for 12oz, Blue Bottle is $12-14 for 8oz, Stumptown is $17 for 12oz, same as Ritual, SightGlass is $16 for 12oz, FourBarrel is $18 for 12oz.

Conclusion

Has it all been worth it? For me it has been. Since I started this whole process years ago, it’s difficult to calculate the savings. However, let me give it a try. Let’s say that 5 times a week, you go out for coffee, either for espresso, or a latte, or just a regular coffee. I’m going to assume that each trip is going to average $3.50. That’s $17.50 per week, or $910 per year. Let’s add to that making coffee at home, with some reasonable quality grocery store beans at $12/lb, where you go through 0.5lbs per week, that’s another $312 per year brewing coffee at home, and adds up to a total of $1,222 annually.

Cutting the investment above down to the bare essentials, you could pick up a 1lb roaster for $370 (Behmor 1600 Plus), a nice grinder for $130 (Baratza Encore), a Gaggia Classic for $300, and a pour-over v60 for $20. That’s an initial one-time investment of $820. If you get up and running roasting and selling your beans quickly, you could save money the first year, and even afford to get a nice espresso machine like mine by the second year, and still come out ahead.

Even if you ended up not selling beans, you’d likely use around 1lbs per week (making a bit more at home, and not going out), so you would spend around $338 annually.

It’s a bit of work roasting so frequently, but I really enjoy my time with my coffee.

26 Jan 2016, 11:42

Quitting Junk Food

doughnuts

I recently wrote about my New Year’s resolution of not quitting things, and it has taken me a while to figure out what to start. I could get into this circular logic loop and try to explain why I haven’t picked something yet, but that seems like a waste of pixels. Whatever, here goes.

For the next 30 days, I’m going to be eating healthier. I’m going to try this for one month, evaluate, and iterate. From today until Feb 26, each day, I am going to do the following:

  • Track my eating on MyFitnessPal (MFP)
  • Try to hit the following general numbers:
    • Calories - 1800
    • Carbs - 180
    • Fat - 60
    • Protein - 135
    • Cholesterol - 300
    • Sugar - 70
  • For any day where I’m within 10% of every number, I will count that day as a success
  • I will use a habit tracking app to track successful days
  • Success of this goal will be 23 successful days of the 30

If you’d like to connect on MFP, my username there is emil10001.

Now for some questions to help me set exepctations. Doing something like this actually becomes harder when you write publicly about it, because you get feedback that your brain interprets the same way as it does if you’d actually accomplished the thing.

Why don’t I do this already, what are the barriers? Logging food in MFP every day is time consuming and cumbersome. I’m going ot try to cut down on how much effort it takes to do this, by creating recipes and standard meals that I can reuse and quickly enter. I also occasionally enjoy baking and eating sweets. I’m not saying that I’m going to cut this out completely, but I’ll at least be more consious of its impact, by logging those foods and cutting back as needed.

Alcohol is another one that could do with another round of cuts. I typically drink Old Rasputin Russian Imperial Stout, which is by far my favorite beer, but also around 300 calories per bottle. While I have significantly cut down my alcohol intake since the summer, I could afford to cut it further, even without cutting it out completely. Again, every time I drink it, I’m going to log it, and cut back as needed.

Why do I feel the need to do this now? What is the goal? What’s my motivation? This is something that I’ve been doing something off and on for years. It’s not new. My goals are basically two-fold, first to lose some excess weight, and second to feel better overall and be healthier. I feel like this is one of those little things that can really have a big impact on my daily mood, and how I feel about myself.

I have noticed in the past, that eating well tends to improve my mood, and how I feel about myself. Successfully doing this helps to motivate me to do other things that I want to do. I think that it is one of the most basic, simple things that I can do that will have a large impact.

It is going to be difficult to cut down on the junk, especially cutting down enough to get within 10% of my daily goals. But, I think that if I can allow myself to fail a little, and keep going, then I think that I will be able to complete this goal.

18 Jan 2016, 09:56

Blogging tools - creating Hugo blog posts from Android

I am starting this post on my phone. I realized that one of the roadblocks that I have is that the workflow for creating new blog posts from my phone was nonexistent. I had a git client, and a Markdown editor, but Hugo uses special headers, and I also needed to be able to publish on my server.

writing tools on Android

Here’s what I did:

  1. Built an Android app to generate the header, and add it to my clipboard. Source
  2. Add a script to my server for easy publishing.
  3. Set up JuiceSSH, so that I can log into my server from my phone.

jotterpad preview

New header

With those couple things, I can now do the end-to-end process of creating and publishing blog posts from my phone. Here’s how that goes:

  1. In git client, pull from remote
  2. Create new file in repo
  3. Open file in JotterPad
  4. Run my HugoNew app
  5. Paste header into new post file
  6. Save file, and push to get repo
  7. Log into my server and run publish script

It still needs work (no image support yet), since it is a lot of steps, but it is a start.

Note - I added the images from my laptop. Here’s the source code for my Android app.

08 Jan 2016, 10:15

Quitting

Ever since New Year’s day, I’ve been thinking about what this year’s resolution should be. I have reflected a bit on the last year, and overall, I’m very happy with my 2015. My biggest accomplishment, was entering fatherhood, and not feeling like I have been faking it. Second to that, was that I finally am starting to feel like I have some effective tools to combat depression. (But, that’s a whole other topic.) The two of those things together really made 2015 a great year for me.

However, for 2016, I’d like to approach the year with a little more focus, and clarity, with a small goal for something that I’d like to make a habit of. I figure that if I can do something small as a habit for a whole year, it can snowball something small into something much larger.

Last night, I was watching one of Casey Neistat’s latest vlogs, called “Losers and Closers”. It got me thinking a lot about quitting, or rather, about not quitting. Neistat takes the view that quitting is never OK, and you should always try to finish everything. Here’s the video:

I don’t think that I’m going to be that strict with myself, however, what it got me thinking about was a lot of little projects that I’ve started that could have been more interesting than they were, if I’d bothered to finish them. Or, if I had stuck with some really good habits that I had tried to keep, that the results would have been really great.

The problem that I have with projects is that I’ve constantly got new ideas, and after I’m about half-way into building one thing, lots of times, I drop it and move on to another thing. For example, a couple of years ago I started building this website about things that I built on a weekly basis. I put a couple of weeks into it, but never finished it, and haven’t updated the project list in forever. Last summer, I built an Android app that I can use for Cognitive Behavioral Therapy, but never cleaned it up for release. More recently, I started writing about building public APIs on the phone with Android, and while I haven’t given up on that yet, I also haven’t added to that collection in over a month. This isn’t true of everything that I start,

As far as habits, it’s probably the same story as everyone else. Here’s another Casey Neistat’s videos that talks about that:

2016 Resolution

Getting to the point, for 2016, I’m not going to quit either projects or habits. What this means for habits is that I’m going to have to be very careful about what I try to start, because I’ll be committing to doing it for a whole year. For projects, it means that I can’t drop off whatever I’m currently working on for something new and exciting. Or, that I’ll have to interleave projects to keep up progress on everything. While I do have a couple of projects ongoing right now, as soon as I finish them, my plan is to try to only do one at a time.

I am also going to do something very different this year to try to work towards this goal, which is to publicly post at the start of a project, that I’m starting something. I hate talking about things until they’re done, but I think that this is going to be important.

Finally, I know that I’m going to fail at this from time to time. That’s OK. I am not looking for perfection, I am looking for improvement.

03 Jan 2016, 09:52

AirPair is obfuscating their otherwise useful blog posts

This morning, I was poking around looking for an article on using AngularJS with EJS. They use some similar syntax, and I wanted to make sure that I wouldn’t be running over myself too much by using them together. (I still don’t have an answer, but if I find a good one, I’ll link it on this post.) In my search, I stumbled on this article:

airpair article

Great! This looks like exactly what I’m looking for. I scroll down to check out the code.

airpair article

The code on AirPair’s blog posts is obfuscated. They want me to sign in with my GitHub account, just to see their code examples, and to make their blog post not worthless? WTF?

I did a quick search to see if others were complaining about this. This was about how I felt:

It gets better:

Write access, they want write access to my GitHub account so that I can read their dumb blog post?!? To be fair, they may have changed that, but still, seriously?

Look, I get it, you’re a company trying to sell your product, and you think that this would be a great way to get leads. Right? That’s fine, I guess, but this seems like an unnecessarily crappy way of going about it.

Here’s why, first, from my perspective, the developer community is quite unique in its culture of sharing information. We figure stuff out, and then tell our peers how we did it to make their lives easier (or as notes to our future selves). We typically do this for free. Now, if you’re going to go and write a book, by all means charge for it. That represents a significant amount of work and knowledge. However, for a little blog post or article, just about everybody in our community has converged on the idea that this stuff should be free.

Second, when you write most of an article in clear-text, and then start obfuscating the important bits that start about half-way down the page, you end up putting people in a position of either taking a loss on the time that they spent in their initial reading, or giving up information that they otherwise wouldn’t (and really shouldn’t if it’s still write access). That’s crappy thing number two.

Crappy thing number three is that again, most of the article’s in clear-text, and you can get the same search traffic as actual complete content. This, again, tricks users into visiting you.

The reason that I bothered to write this isn’t because I think that AirPair is a terrible company. It seems like their core business is a great idea, and something that would be very useful. I hope that their company does well. The reason that I’m writing this is to make sure that people know that when they see ‘airpair’ in their search results, that that is a junk link, and they should skip that result and move on.

AirPair, if you see this, please stop the shenanigans and gimmicks, and be straight with people. It’s really too bad too, since there are plenty of other ways of getting what you want (like newsletters with collections of useful posts on topics that people care about), without doing this sort of thing. Also, if you didn’t obfuscate your content, you might start becoming more of a popular resource for this content, which would potentially increase your traffic, and probably help your branding quite a bit. As it stands, I’ll remember AirPair only as something to avoid.

16 Dec 2015, 11:53

Suggestions for Wearables and Automation

google glass

I’ve been thinking a lot about automation recently. One of the big questions that I ask myself over and over is, what can I stop spending so much time on? What are things that I’m not great at that could get better through automation?

I have a list of general things that I think would be fun to try automating (which I’ll write about later), but of the list of tools, I think that wearables present an interesting opportunity for automation. The problem is, that I am having trouble thinking of what I could do there.

So, I figured that I would ask what people think about this? I’m sure that there are lots of people out there with Glass or Android Wear who dreamed of what they could do with those devices. If those dreams involved automating something, what were they?

08 Dec 2015, 09:11

Testing in Android

On November 23 & 24, I attended the first ever Android Dev Summit. The following are notes that I took during talks. I have included the video of the talk as well. Again, these are my notes from the talk, not my original content.

Chiu-Ki Chan (Android GDE) took really great notes during the session as well, here’s what she had:

People want automated testing. Android has not provided a ton of testing APIs, and it hasn’t evolved much since API level 3. Until recently.

Android provided tools for testing:

  • Android Studio / Gradle
  • Android Testing Support Library
  • Espresso

Refactor across unit and instrumentation tests.

Hermetic testing

isolate tests from external dependencies

Flaky tests are worse than no tests. (When it fails sometimes.)

Steps:

  1. Isolate from external dependencies
    • Especially the network
  2. Replace the components that talk to external dependencies, with things that replace with fake data
  3. Using product flavor ‘mockDebug’, with source sets
  4. Inject lives in both mock and prod source sets

When to use:

  • Mock mode for manual testing & concurrent development
  • Prod mode for end-to-end tests
    • great pre-release check

testing pyramid

Unit testing

unit test business logic

Unit tests are fundamental. Run locally, generally fast, should be small and well contained. Focused on methods.

Don’t put everything into Activities, it makes it really hard to test. Move business logic out, so that it is more testable.

Mockable Android Jar.

Android Studio helps with Test-Driven-Development. If everything is set up correctly, AS can even help with new features, if tests are defined first.

UI Testing with Espresso

android espresso

Integration and UI tests check your application through its interface. You need a device or emulator for this. CloutTest Lab allows you to test on real devices.

UI testing is hard! Espresso helps with this.

Tried to ask: What would a user do?

Find, perform, check

onView(ViewMatcher)
    .perform(ViewAction)
    .check(ViewAssertion);

04 Dec 2015, 10:00

Keep it Secret, Keep it Safe

cover slide

On November 23 & 24, I attended the first ever Android Dev Summit. The following are notes that I took during talks. I have included the video of the talk as well. Again, these are my notes from the talk, not my original content.

Android SSL Training Docs.

Protecting the network traffic in your app.

  • High level TLS, and why you should use it
  • Using TLS, checking your work
  • Mistakes and misconfigurations

Why

The network is not to be trusted. This has always been true, but especially for mobile devices.

  • Devices connect to many different networks
    • Coffee shop wifi
    • Anyone can run an open wifi
  • Devices do sensitive transactions wirelessly

Canonical examples of sensitive traffic

  • login for banking
  • credit card details
  • private personal photos
  • emails
  • sensitive web traffic
  • health information

On the server-side, you should secure your traffic. All traffic must be protected.

  • Modify non-sensitive traffic (e.g. Time Warner)
    • inject exploits
    • modify content
    • replace images
  • Tracking and snooping

Goal the network cannot affect the security of your device.

Enter TLS

  • Transport Layer Security
    • Previously known as SSL
    • Usable with any protocol
  • Establishes an end-to-end channel between two peers
    • Integrety
    • Confidentiality
    • Hard part - knowing you’re talking to the right peer
  • Safe by default
    • Modern platforms have safe defaults and it is just as simple as using TLS.

Using TLS

Using standard HTTP libs, replace http:// with https://. Use SSLSocket for socket connectisons.

HostNameVerifier.verify

ssllabs has a good intro for server-side.

Checking your work

  • Hardcoded URLs - what about redirects?
  • Server provided - maybe you forget on the server?
  • Third-party code - how do you check them?

New feature in Marshmallow.

  • Strict mode clear text detection
  • usesClearTextTraffic flag in manifest

Strict Mode

Uses packet inspection to catch all non-TLS traffic. Useful during development to make sure that all traffic is going over TLS. Some false-positives, e.g. HTTP proxies, protocols with STARTTLS logic, or secure traffic that doesn’t begin with a TLS Hello.

usesClearTextTraffic

AndroidManifest.xml:

<application android:usesClearTextTraffic="false">

Supported: * HttpsUrlConnection * OkHttp, apache

Why block vs upgrade

  • Older devices left out.
  • Upgrade logic isn’t always well defined for non-HTTP protocols

Blocking will fail quickly, and obviously. Fixes will be true for all devices.

Mistakes and misconfigurations

Using the default implementation is a good idea. However, you can override the defaults with insecure code.

Legacy servers, with legacy clients choosing what cert to present for a connection.

TLS with Server Name Identifier (2.3+) extension solves some problems around knowing who you’re talking to.

Some internet routing may not support all of the TLS protocols, and may downgrade to SSLv3.

How do you know if you trust this chain of certificates? What ships with your devices?

How can you trust the CAs on the device? (e.g. Lenovo.)

Your app can use its own CA, which may make sense for various applications. However, the example code out there may not be great. Documentation.

What Google’s doing

Vulnerability alerts and blocks

Google is going to be scanning the Play Store, running static analysis on apps, looking for vulnerabilities. They will alert developers, and remove apps that have not been fixed. Here’s the slide that discusses that:

vulnerable apps

03 Dec 2015, 10:00

What is App Indexing?

And, what’s the difference between App Indexing and Deep Linking?

Deep Linking - Not new. Opening a link from search or any other app in your app. That same link that would normally open a web page, is opening the same (or very similar) content in your app.

App Indexing - New-ish. Reporting back to Google what content and web addresses are being opened by users in your app. Allows for auto-complete of searches with app and previously visited content.

Using both together allows Google to put a button on search results that allows users to install and open pages with your app using deep linking.

auto complete search

How do I enable App Indexing for my app?

  1. You have a website with content
  2. Verified website’s domain in the Google Search Console
  3. Have an app that opens content that is the same as your web content
  4. Implement an intent-filter for your site in your app
  5. Clicking links for your website opens the content in your app
  6. AppIndexing API called whenever content in app is loaded, or the user leaves the app
  7. Publish app
  8. Add the android-app:// version to your Google Search Console, and associate it with your website!
  9. Verify domain in Play Console

Aside from the Google Play app publishing process, this should be doable end-to-end in about two hours, if you are starting from scratch with your app. If you already have an app, you should be able to do it in less than 20 minutes.

Let’s take a quick look at all the pieces. The code that I’m using comes from the blog example that I built and have hosted on GitHub. First, we’ll go over the deep-linking part, then we’ll look at what needs to be added to make App Indexing work.

Deep-Linking

AndroidManifest.xml support for deep linking:

<activity
    android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="http"
            android:host="ejf.io" />
    </intent-filter>
</activity>

In onStart of the MainActivity, load up the URL in the webview to make the deep-linking work:

@Override
public void onStart() {
    super.onStart();
    mClient.connect();

    Intent intent = getIntent();
    String action = intent.getAction();
    Uri data = intent.getData();

    if (Intent.ACTION_VIEW.equals(action) && null != data)        
        webview.loadUrl(data.toString());
}

App Indexing

App’s build.gradle:

dependencies {
    // ...
    compile 'com.google.android.gms:play-services-appindexing:8.3.0'
}

AndroidManifest.xml support for Google APIs:

<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

MainActivity get GoogleApiClient for App Indexing:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    mClient = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    // ...
}

I added a listener on my WebView to run some code when the page finishes loading. This is we let the App Indexing API know that we’ve started viewing the page:

webview.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        // Define a title for your current page, shown in autocompletion UI
        final String title = view.getTitle();
        Uri webUri = Uri.parse(url);
        Uri appUri = Uri.parse("android-app://io.ejf.blogapp/https/"
                + webUri.getHost() + webUri.getPath());

        // Construct the Action performed by the user
        Action viewAction = Action.newAction(Action.TYPE_VIEW, title, webUri, appUri);
        // Call the App Indexing API start method after the view has completely rendered
        AppIndex.AppIndexApi.start(mClient, viewAction);
    }
});

We call the App Index end command in onStop:

@Override
public void onStop() {
    // Call end() and disconnect the client
    // Define a title for your current page, shown in autocompletion UI
    final String title = wv.getTitle();
    if (null != wv.getUrl() && null != wv.getUrl()) {
        Uri webUri = Uri.parse(wv.getUrl());
        Uri appUri = Uri.parse("android-app://io.ejf.blogapp/https/" + webUri.getHost() + webUri.getPath());
        Action viewAction = Action.newAction(Action.TYPE_VIEW, title, webUri, appUri);
        AppIndex.AppIndexApi.end(mClient, viewAction);
        mClient.disconnect();
    }
    super.onStop();
}

Testing deep-linking and App Indexing

In order to test deep-linking from cli:

# adb shell am start -a <action> -d <data> <package>
adb shell am start -a android.intent.action.VIEW -d “http://www.example.com/app/some-great-content” com.example.app

If you have App Indexing set up, you should be able to go to Google Search on your phone, and begin typing the title of the page that you just visited. After just a couple of characters, you should be given an auto-complete result for your app.

Why do I want App Indexing for my app?

There are two basic benefits of adding in App Indexing. The first is user acquisition, the second is reengagement.

Google’s basic argument is that as the number of available apps grows, and the content accessible in those apps grows, users are going to begin to rely more heavily on search. Users will start with a Google Search to look for content either on the web or on their device. If there are results that are app-based, users may tend to prefer those results over others that are purely web-based. App Indexing puts an app badge, and possible install button (if the user doesn’t have the app), on your search result. The other nice thing that it does is allows users to auto-complete a Search with content from an app.

For non-content focused apps, the benefits are obviously a little less clear. However, you could deep-link any pages that you have on your website, serve them up in-app, and then use traditional web SEO to drive installs. This is nice because web SEO is much easier to do than ASO (App Store/Search Optimization).

Some of the numbers that Google has given about success cases for this feature are as follows:

  • The Guardian - 4.5% increase in CTR from search results
  • Etsy - 11.6% increase in app traffic from referrals
  • Tabelog - 9.6% increase in app traffic to restaurant pages

This feature is also really easy to implement for apps that are already serving up content. Adding this feature really shouldn’t take more than about 20 minutes.

02 Dec 2015, 13:40

Notes on the Android Support Library

On November 23 & 24, I attended the first ever Android Dev Summit. The following are notes that I took during talks. I have included the video of the talk as well. Again, these are my notes from the talk, not my original content.

Chiu-Ki Chan (Android GDE) took really great notes during the session as well, here’s what she had:

  • What?
  • Why?
  • Gotchas?
  • How?
  • Bugs?

What?

Lots of stuff. Started out simple, but it’s grown. There are multiple support libs, providing different utilities. They’re a bridge for getting newer functionality on older API level devices.

The core v4/13:

Animation

ViewCompat.animate()

Fragments

FragmentActivity.getSupportFragmentManager()

Features

<android.supportv4.ViewPager> // or something

Infrastructure

  • RecyclerView
  • appcompat - large chunks of the UI toolkit

Higher Level:

  • mediarouter - chromecast
  • design
  • preferences
  • leanback - TV

Why?

Unbundled releases:

  • Not tied to platform releases
  • Bug fixes
  • New features

RecyclerView

  • Component providing data-set windowing
  • Improves upon an existing framework (?)
  • Backports to v7

Provides:

  • Animation
  • Pluggable
  • Enforcing

AppCompat

  • UI compatibility layer for v7+
  • Backport framework features, but no more
  • Goal: stay up to date with framework

Provides:

  • Themes
  • Toolbar
  • Tinting

Design

  • UI feature lib
  • Provides features not in the framework
  • Goal: implement high-level UI components

Provides:

  • FloatingActionButton - FAB
  • NavigationView - NV
  • Snackbar (like Toast with an action)
  • TabLayout - TL

Percent

  • UI feature lib
  • Provides percent based layouts
  • FrameLayout and RelativeLayout

Allows you to define layout elements as percentages of the parent.

Gotchas

Library major version number is the minimum compile sdk version.

E.g. lib v23.1.0 needs compileSdkVersion 23.

Dex limit, all of the compat libs add up to a third of the dex size. Using proguard: minifyEnabled true, you can cut it down to something more manageable. With new AS tools, no need to re-run proguard on every iteration.

How?

Using a variable can help to keep all the support dependencies at the same, correct, version in the build.gradle file.

ext {
    supportLibVersion = "23.1.1"
}

dependencies {
    compile "com.android.support:appcompat-v7:${supportLibVersion}"
    compile "com.android.support:design-v7:${supportLibVersion}"
}

Bugs

http://b.android.com