Mark L. Murphy's Blog, page 76
March 5, 2012
The Busy Coder's Guide to Advanced Android Development Version 2.5 Released
The Busy Coder's Guide to Advanced Android Development Version 2.5 is now available for subscribers in all formats.
I had planned on covering developing for the NOOK series of tablets/e-readers in this edition. That did not happen, in part due to personal health issues stealing too much time from my schedule, and in part due to some apparent problems with the NOOK Developer Web site.
This release adds ~30 pages of material, including:
A chapter on advanced database techniques, specifically covering the use of SQLiteAssetHelper (for packaging databases with your app) and SQLCipher for Android (for encrypting your databases)
A chapter on advanced broadcast techniques, specifically covering ordered broadcasts (based on this old blog post) and LocalBroadcastManager
A new section covering the use of content providers as a plugin mechanism, specifically to isolate permissions and reduce the number of permissions required by the main app
A new paragraph clarifying that the rules for sizing app widgets changed with API Level 14
Clarification regarding the status of the tapjacking attack vector, as described in this blog post
Errata fixes
I am anticipating another update to this book in about a month. Here, I will try again to cover the NOOK series, along with the Blackberry Playbook.
March 3, 2012
Tapjacking, Defunct?
I and others railed about the tapjacking attack vector on Android in the past year or two. In fact, I had been told by the Android security team that tapjacking was a feature, not a bug.
It would appear Google had a change of heart.
Sam Lu wrote in a few days ago to report that the tapjacking demonstration code from The Busy Coder's Guide to Advanced Android Development no longer worked as of Android 4.0.3. He even isolated some changes made to Android itself that would explain the altered beahvior. It definitely appears that Android 4.0.3+ devices are no longer vulnerable. A tapjacker can no longer intercept touch events, even using code that had worked on prior versions of Android.
Now, it is entirely possible that there's another way to set up the tapjacking attack that avoids the block Google put into place, though it is not obvious how that might be accomplished — I tried some things with no success.
Many thanks to Google for fixing this security hole, and many thanks to Mr. Lu for pointing it out!
February 23, 2012
Think About Principles
A blogger posted today about a rather unfortunate app that makes a game out of virtually killing real people, with a focus on "hobos". The blogger in question is up in arms about the app and is "hoping people will use their voice [sic] to get [such] garbage thrown out of the Android Market".
This is indicative of two problems:
The blogger in question appears to be ignorant of the Streisand effect.
The blogger in question may not be thinking in terms of principles and their application.
To publish apps on the Android Market, a developer must agree to the Android Market Developer Distribution Agreement, the Android Market Developer Program Policies, and the Content Rating Guidelines. Apps failing to comply with these agreements are subject to removal from the Market. Conversely, apps that do comply with these agreements are supposed to be left alone.
In this respect, Google is stating its principles regarding apps on the Market.
Having a debate on whether those principles are the right ones is wonderful.
Having a debate on whether Google truly abides by those principles would be awesome.
Having a debate on whether any given app runs afoul of those principles would be excellent.
However, the phrasing from the blog post in question suggests that the blogger cares not a whit about the principles. Rather, the blogger intimates that Google should abandon the principles in the face of outrage.
This is scary.
It is scary because a capricious Google could start banning apps and developers for any reason they desire. We're already halfway there by Google apparently not actually telling people why their apps were banned, suggesting capriciousness even if the principles were truly applied faithfully.
Now, we most certainly could have a debate on whether there should be an "outrage" clause added to the principles. Along the way, though, we would need to discuss how outrage should be measured and how countervailing opinions can be taken into account. The result would probably be rules akin to how Wikipedia editors work, and those principles are often the source of complaint as well.
Had the blogger in question simply pointed out that the cited app presumably violates the "Violence and Bullying" clause in the Android Market Developer Program Policies, and asked people to make this point clear to all parties, I would not have quibbled.
We need to focus on the principles, not ask that random apps be banned for random reasons based solely upon the opinion of random people.
Of course, that's just my opinion… :-)
January 30, 2012
The Busy Coder's Guide to Advanced Android Development Version 2.4 Released
The Busy Coder's Guide to Advanced Android Development Version 2.4 is now available for subscribers in all formats.
This release adds:
A section on using RemoteViews as the basis for a plugin framework, to allow one app to add to the UI of another app.
A chapter on the challenges for writing for the WIMM One wearable Android device.
More coverage of the Loader framework, particularly on what occurs with a Loader during different events, such as the activity being destroyed, the device being rotated, etc.
Brief coverage of the impact of the split action bar on action modes.
A bug fix and explanation for the FeedsActivity, to repair a flaw whereby multiple fragments would overlay each other if you rotated the screen while in the tabs mode.
Errata fixes
I am anticipating another update to this book in about a month. One of the highlights of that release will be coverage of developing for the NOOK line of Android devices.
January 27, 2012
Think Enterprise (No, Not Starships or Rental Cars...)
This is another in my series of public service announcements, trying to point out that the Android app world does not begin and end with the Android Market…
Android continues to climb in the enterprise. For example, Motorola Mobility has been pushing the envelope on enterprise Android, not only in terms of devices with additional built-in enterprise features (that you can tie into via SDK add-ons), but also a dedicated section of the MOTODEV site for enterprise development.
Big businesses have big needs, often different needs than do individual consumers. Big businesses have big requirements that may be hurdles that your competition is unwilling to climb. And, big businesses have big budgets, relative to what you might be making off of the Market or other wide-area distribution channels.
But big businesses will not be buying apps off the Android Market en masse. Sure, individual employees may buy apps here and there, but the Android Market simply does not support the sort of enterprise licensing that big businesses are used to. Instead, you would likely need to strike individual deals with individual enterprises, no different than how enterprise software has been sold for a long time.
So, you need to ask yourself:
Do I have something that enterprises might like?
Do I have the means of going after the enterprise market, in terms of sales contacts, somebody to actually do the sales and marketing, etc.?
Do I have a means of providing technical support that will meet the demand (e.g., do I have to provide front-line support?) and will scale to the client size?
If the answer to all is "yes", you have serious potential in the enterprise space and should be strongly considering how you can approach it, whether directly or through some sort of channel partner (e.g., trying to get device manufacturers to bundle your app on their enterprise-focused devices).
Even if you say "no" to the latter two bullets, consider whether you could say yes with some sort of additional support (e.g., funding to hire a salesperson), and then how you might get that additional support (angel investors, Kickstarter campaign for related technology, etc.).
January 24, 2012
Be Careful With Static Stuff on AsyncTask
I was writing a sample app to run on the WIMM One wearable Android device, and I ran into a strange error. The flow was:
Run an activity, which detected that we had no data, raised a dialog, and finished once the dialog closed.
Along the way, the activity sent a command to an IntentService to go get the data.
The next time you would launch the activity, you would get a warning about "sending message to a Handler on a dead thread", and the activity would not fully start.
I, being a bit cocky, assumed that the problem was something with the WIMM environment.
Ummmm… not so much. I screwed up. In fact, I had seen reference to this problem before, but never fully appreciated what it meant until I ran into it myself.
The problem was that the load-the-data logic for the activity was using an AsyncTask. That, on its own, is not a problem — in fact, it's desirable (particularly on environments where you can't use loaders).
However, AsyncTask has static data members. And one of the limitations of those static data members is that they need to be initialized on the main application thread.
Normally, this is not a problem, as you usually only reference the AsyncTask class on the main application thread, when you go to create your first instance of the task to execute.
In my case, though, I had moved some common logic into a static method on my AsyncTask subclass… and I was calling that static method from the IntentService in onHandleIntent(). That was the first time I referenced my AsyncTask subclass, and it was on a background thread. That initialized a static Handler used by AsyncTask on the background thread, not the main application thread.
The error message was pointing out that the AsyncTask static Handler was associated with a thread (the one from onHandleIntent()), which was now dead.
The solution: simply move the static method elsewhere.
The moral of this story is to be very careful about when you first use AsyncTask. Some people have resorted to using a custom Application object and touching an AsyncTask subclass in onCreate(), just to make sure that it is properly initialized. While IMHO that is not necessary, you do have to pay attention.
Many thanks to the WIMM team for pointing out my error. You can find out more about this issue on the Android issue tracker.
January 16, 2012
Secure Against Screenshots
Ice Cream Sandwich now allows the user to capture screenshots of the contents of the device screen, by simultaneously pressing the Power button and the Volume Down button.
(which, in practice, seems to be a lot harder than you might think…)
This has been an oft-requested feature, so it will make many users happy.
Note that this is not available via the SDK, so malware should not be able to screen-capture arbitrary stuff in your app. However, for the user's benefit, there may be reasons to block screenshots from certain of your activities.
To do that, use FLAG_SECURE:
public class FlagSecureTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(LayoutParams.FLAG_SECURE,
LayoutParams.FLAG_SECURE);
setContentView(R.layout.main);
}
}
Normally, when a user takes a screenshot, a Notification will be raised to indicate success and provide access to the screenshot in the Gallery app. With FLAG_SECURE in place, the Notification will be "Couldn't capture screenshot".
A Proof Is Worth a Thousand Posts
Android has flaws. Heaven knows, I've posted my share of bug reports over the years.
However, the key to a bug report, as every developer should know, is a reproducible test case. In other words, proof of the bug. Without such proof, claims of bugs are at best unfounded and, at worst, trolling.
I mean, I can claim that I'm the real author of Shakespeare's plays, but unless I can provide some proof of this claim (beyond sharing a hairline with the Bard), nobody is going to take me seriously.
(besides, if I either have a time machine or the key to living a few hundred years, do you honestly think I'd be writing this blog post?)
That leads us to the recent shenanigans by a certain developer on the android-developers Google Group.
In that thread, the developer in question claims that hardware acceleration is slowing down his code. This, in unto itself, is eminently possible, as Romain Guy points out in his various replies. Certain anti-patterns are going to be hard for the GPU to handle, resulting in faster performance with no GPU assistance (i.e., without hardware acceleration).
The problem is that the developer has steadfastly declined to actually provide a reproducible test case, despite requests from many group members for such evidence. The fact that Mr. Guy is taking this developer as seriously as he is stands testament to Mr. Guy's patience. And, lacking a reproducible test case, even if there is a genuine problem here, there is nothing anyone can really do about it.
Contrast this with this thread.
Here, a developer pointed out some oddities with the behavior of many tabs in the action bar (scrollable in portrait, but converted into a drop-down in landscape). Initially, the developer provided a screenshot, but that was it. I requested, and received, a sample project demonstrating the issue. And, sure enough, the sample project does show the phenomenon. As a result, I filed an issue — while I suspect that the behavior we see "is the way it is", perhaps we can get some better documentation so we know what to expect.
To paraphrase a certain web-slinger's uncle, "with great claims come great responsibility for great proof". If you are going to claim development-related bugs in Android, provide a reproducible test case.
January 5, 2012
The Busy Coder's Guide to Advanced Android Development Version 2.3 Released
The Busy Coder's Guide to Advanced Android Development Version 2.3 is now available for subscribers in all formats.
This release adds:
A partial chapter on Google TV app development. It covers most of the technical aspects. I need to add substantial coverage of how to design for "the 10-foot view" (a.k.a., "the 304.8cm view"), but I need a bit more practical experience with that first.
A chapter on the quirks for developing apps for the Kindle Fire.
The material on serving files from a ContentProvider via openFile() has been updated and restored.
The Camera/Picture sample has been updated to show how to specify a particular image size for the picture to be taken (and works around a bug in a certain popular handset).
The chapter on the Loader framework has been augmented with coverage of how to create loaders for things other than a Cursor, in this case showing how to create a SharedPreferencesLoader.
Errata fixes
I am anticipating another update to this book in about a month. In parallel with these extensions, I am embarking on the Big Book Reboot, which I outlined last month. Stay tuned to this blog for more on that project.
December 14, 2011
The Big Book Reboot: The Trails
As I mentioned previously, my books need a reboot.
Right now, the prose is divided into four books. One, Android Programming Tutorials, is broken out because it is a very different style than the rest. The others mostly are split up just to make things easier for print editions, since there are page count limitations when printing and binding.
My vision for the Big Book Reboot is to merge them all into one large book for the digital editions.
There are several reasons for this:
You can search across them better
I can create cross-references between more of the material, rather than being limited to links within a single book
You only have to worry about downloading one book, rather than keeping track of four (and, eventually, more)
Most importantly, I can better organize the material to take advantage of that new-fangled "hyperlink" thingy (more on this in a moment)
Now, it may turn out that the file size becomes too unwieldy, to the point where some readers cannot process it. In that case, I'll fall back to having things be in separate tomes.
The organizational structure I am envisioning is a set of linked "trails". Each trail is a sequence of chapters. There will be one "main" trail and a whole series of "side" trails.
The main trail pretty much the bare bones of creating a basic Android app. It will consist of:
a subset of what is presently in The Busy Coder's Guide to Android Development,
a couple of topics (e.g., testing, production) from The Busy Coder's Guide to Advanced Android Development, and
an interleaved set of tutorials, replacing the current Android Programming Tutorials (yes, I am re-re-rewriting that stuff)
Even within the subset of chapters, the prose will be tighter, focusing on one solution that works for today's devices and, as far as I know, tomorrow's. For example, the focus will be on using the action bar and menu resource XML, with coverage of other alternatives (e.g., creating menus in Java code) moved off the main trail.
The objective is for the main trail to be fairly short, as hand-hold-y as the reader wants via the tutorials, and reflecting current patterns more than the legacy from Android 1.0. Note that I will probably elect to "spackle over" various rough spots in the presentation via technology, using CWAC or third-party components to simplify getting somebody up to speed, with details and explanations of those components' respective magic being off-loaded to side trails.
The side trails will be linked to from the main trail at various points (plus will be in the overall table of contents and all that). Each side trail will take a deeper dive into some concept that the main trail touches upon only in part. So, for example, while the action bar and menu resource XML will be covered in the main trail, the following related topics would appear in a side trail:
context menus
creating such menus via Java instead of resource XML
action modes (replacing context menus for native Android 3.0+ devices)
and so on. Though I may pull action modes into the main trail someday,
if action modes becomes available in a backwards-compatible fashion.
The main trail gets a newcomer from nothing to a fairly complete app; the side trails cover all of the polish or features that, while very useful, are not necessarily essential for creating that fairly complete app.
Readers will still be able to work through all of the book front-to-back if desired, as I will organize the side trails to make that reasonable. However, the expectation is that people will read the main trail front-to-back and refer to the side trails as they try to figure out how to implement certain UI patterns or run into certain problems.
If you wanted to think about this in classic book terms, imagine that there would be one "essentials" book comprising the main trail, and one or more "advanced" books collecting the various side trails. In fact, that may well be how I organize print editions, once I have the digital editions established.
If you have concerns about this plan, join the cw-android Google Group and speak up! I'll be providing more details in the coming weeks, notably an outline of the various trails.


