Friday, January 13, 2012

Highlights from Android's New Design Docs

I've just finished reading through the wonderful new Android Design site Google just released.  A lot of the information is stuff you should already know if you're an Android developer.  However, I took notes of pages/information that I found particularly interesting (or new for ICS).  Listed in order of appearance on the site:

48dp Rhythm - Like me, you may have implicitly noticed this pattern before, but it's good to see it stated so explicitly.  (Same with the 8dp gap.)

Back vs. Up - Having been confused on the exact distinction for a while, this page is a breath of fresh air.

Action Bar Pattern - This entire page should be required reading for everyone.  It definitely looks like the Action Bar is the future, and this is the instruction manual.

Long Touch Multiselect - Breaking news: long touch no longer activates the contextual menu.  Now, it is purely for activating selection (aka multiselect).  Every longtime Android developer should be aware of this change.

(Personally, I didn't even notice this change despite owning a Galaxy Nexus for a month.  Perhaps that's because not even every Google app has switched to the new design yet.  Or perhaps it's because long touch is just not an intuitive way to design any functionality - I've long since given up putting any core functionality into long touch.  Still, it's worth noting the design shift.)

Android is not the iPhone - At least, that's what this section *should* be called.  This page will be most useful for showing to your designer or boss how Android differs from iPhone and why you shouldn't just port assets and design directly from one to the other.

Tuesday, January 10, 2012

GridLayout Library for Android 1.5+ Support

If you're like me, when you first heard about GridLayout, you were excited.  Then disappointed, because it's currently only available for Ice Cream Sandwich.  That is true no longer - I've taken the time to port a working version of it all the way back to Android 1.5 and above.

Check out the android-gridlayout library here.

The one caveat is that there is one method in GridLayout that I was not able to port back.  As a result, when you change the visibility of a child View of a compatibility GridLayout, you should also call GridLayout.notifyChildVisibilityChanged().

Let me know what you think, especially if there are any bugs.

Tuesday, December 20, 2011

Sharing with Gmail

I read through the Android Training docs recently and came across a section which I thought I could use to improve sharing on Rage Faces (by getting rid of the need for an SD card-based share system):

Write the data to a file in your own application directory using openFileOutput() with mode MODE_WORLD_READABLE after which getFileStreamPath() can be used to return a File. As with the previous option, Uri.fromFile() will create a file:// style Uri for your share intent.
However, this setup fails to work with the Gmail.  When you try to share with Gmail in this manner, an error message pops up in the logs:

file:// attachment paths must point to file:///mnt/sdcard. Ignoring attachment file:///data/data/com.idunnolol.ragefaces/files/share.png
I'm not sure why Gmail arbitrarily rejects attachments not on the SD card, but it pretty much cuts you off from sharing files with MODE_WORLD_READABLE.  Unfortunately sharing with Gmail feels like an essential part of the app so I'm going to have to stick with SD card sharing.

Monday, October 31, 2011

TextWatchers and onRestoreInstanceState()

There's a small timing issue I'd like to mention because it's bitten me a few times now.

When you want to observe changes to an EditText, you add a TextWatcher to it (via TextView. addTextChangedListener()). There are a lot of uses for TextWatchers, like implementing your own autocomplete or filters based on a dynamic EditText. The only thing you have to be careful of is whether the text was changed by the user or the code - the listener fires either way.

What's worth knowing about an EditText is that it will save and restore the state of the text inside of it within your Activity. That means that when you rotate the screen, the EditText will restore the text that was inside of it. And most importantly, the automated restoring of the text on rotation causes the TextWatcher's methods to fire. Like I said - the TextWatcher doesn't discern between whether the user changed the EditText or the system did.

The solution is simple - just don't add the TextWatcher until after the EditText's content has been restored. It restores itself in Activity.onRestoreInstanceState(), which makes Activity.onResume() the preferred time to add TextWatchers to any EditTexts.

Monday, October 10, 2011

Android Drawable XML Talk

I recently gave a talk on the basics of Android drawable resources (via XML).

There's a recording I made of the talk - not super, but functional. I had to split it into two parts because of time restrictions on YouTube. Here's part one and part two.

I also have a few links that may be useful (whether you watch the talk or not):

- The slides for the presentation

- Official Android drawable resource documentation

- My drawable XML documentation

- The github project with my samples

Monday, September 26, 2011

Logc.at

A few developers and I have formed a new Android development blog. We snagged what I think is an awesome and nerdy url: logc.at.

I will still be writing here - this blog is intended for one-off coding issues that I want to document. The new blog will be a place for me to write about Android development in a more general manner. Instead of assisting with individual hurdles, I hope my articles there will help one become a better Android developer (or at least pick up a few tips).

My first post is about working with JSON on Android. Check it out!

Tuesday, August 2, 2011

New to Android: More Style Restrictions

There have been two changes the Android platform build tools which have caught me off guard. You may run into these problems when you next update your aapt. Both of them cause compilation errors, so they're not easy to ignore, but it's not immediately obvious how to fix either.

Change #1: Implicit parenting now requires a parent

Suppose I have this style defined in styles.xml:

<style name="Widget.MyWidget.Small"> ... </style>

It was named that way after how Android sets up their widget styles (for example, "Widget.RatingBar.Small"). One thing to know is the implicit aspects to using dots in the naming is that you automatically parent all the styles before the dot. So "Widget" is the parent of "Widget.MyWidget", and "Widget.MyWidget" is the parent of "Widget.MyWidget.Small".

In the new version of aapt, you'll see this error:

Error retrieving parent for item: No resource found that matches the given name '@Style/Widget.MyWidget'.

This happens now because aapt is stricter with regards to style parenting. Before, if there was no parent, it would just ignore this oversight; now it requires a parent.

There are two possible solutions:

1. Rename the style so that it doesn't use implicit parenting with dots.

2. Create the parent styles. They could either be empty, or you could actually use them for something.

I think #1 makes more sense, unless you actually have a use for the parent styles.

Change #2: Some android styles are now enforced as private

Before, you used to be able to get away with parenting some non-public Android styles:

<style name="MyRatingBar" parent="@android:style/Widget.RatingBar.Small"> ... </style>

However, these styles have always been intended to be private, and the latest aapt will not allow you to build with a private parent defined. A Google employee explained the reason why this is no longer allowed:

For the framework, only public resources are guaranteed to only have the same integer, build after build. The integer of private resources integer will change from build to build. This means that your custom style is referencing a parent that *will not* be valid once installed on a device. It'll referenced either another resources or none at all, and it won't do what you want.


That seems reasonable to me. The solution is to just import the entire style into your styles.xml; all the styles are open source anyways.