Mark L. Murphy's Blog, page 75
April 25, 2012
How I Isolated the Adobe Reader Activity Issue
Earlier today, somebody posted a question on StackOverflow regarding a SecurityException when trying to send a PDF to Adobe Reader via ACTION_SEND. I thought it might be useful to write up how I went about determining the nature of the problem.
The question author took care of my first guess for me, by indicating that the ACTION_SEND code worked fine with other PDF apps. That eliminated any issue regarding read permissions on wherever the PDF was stored (not mentioned in the question).
Fortunately, I have two apps installed on my Galaxy Nexus relevant to this issue. One is Adobe Reader, as you might expect. The other is AppXplore, published by Sony (or Sony Ericsson, as their app description still lists them).
AppXplore is a very handy app for inspecting the manifest of another application installed on your device. Simply running AppXplore and tapping on an app brings up general information about the app itself. Then, choosing a “Show manifest file” options menu item brings up a scrollable TextView of the contents of the manifest… more or less. It is actually “a regenerated verison of AndroidManifest.xml from application’s binary package and may not match exactly with the original AndroidManifest.xml file”.
However, it is certainly ample for problems like this. And, there are no pesky software piracy issues typically involved in getting one’s hands on an APK file for an app on the Play Store.
The SO question helpfully listed the activity that was failing: ARSendForSignature. Scrolling down in the generated manifest for Adobe Reader shows that ARSendForSignature indeed has an <intent-filter> for ACTION_SEND. However, it also has android:exported="false".
The default exported state for Android components is:
Components with an <intent-filter> are exported and can be launched by other applications
A ContentProvider is exported by default, despite having no <intent-filter>
Everything else is not exported by default and therefore cannot be launched by other applications
The android:exported attribute on an <activity> allows you to override those defaults.
So, what happens?
The user does something in the original activity that triggers a startActivity() with an ACTION_SEND Intent for the application/pdf MIME type. The chooser lists all activities that have an <intent-filter> matching that specification. When the user taps on the chooser item for Adobe Reader, the chooser crashes, because it cannot start up Adobe Reader’s ACTION_SEND activity, because it is marked as not exported.
The real problem here is the chooser. The chooser should be filtering out anything that is not exported and is not from its own application, no matter what the <intent-filter> may have. That’s why I went ahead, reproduced the problem with my own code, and filed an issue.
Tactically, though, Adobe should either mark this activity as being exported (so ACTION_SEND works) or remove the <intent-filter> (thereby having it not appear in choosers for ACTION_SEND).
April 11, 2012
Making BACK Way Too Complicated
Last summer, I wrote a blog post, BACK Means Back, decrying some developer's choices regarding the BACK button (e.g., "I need to override the BACK button to launch a context menu").
Here I am again, this time, though, complaining about confusing new policies coming from Google itself. Google, it seems, wants app developers to lie to users, and that is difficult to fathom.
Let's pretend that you are using a Web browser, like Google Chrome. Let's pretend that you click on a link that opens a fresh browser tab. When you switch to that tab, the back button of the browser is disabled. That makes sense, as there is no history. One could argue that the back button might be enabled and would completely destroy the tab, but that might be seen as a bit too aggressive.
What Google wants, in effect, is for the back button to be enabled, and pressing that back button a few times in sequence would lead the users through Web pages that the user never visited that the Web site happens to want to show that, in theory, represents "the complete upward navigation path to the" Web site's home page. In other words, the back button should represent fake browsing history, suggesting that the user clicked on some series of links (or whatever) to get to a particular point, when in fact they did nothing of the sort.
If Google did this with Chrome, I would expect a major "WTF?" reaction to come from the browsing public, not to mention having a handful of security researchers pointing out some pretty big holes in this scheme.
Yet this is what they want developers to now do for handling the BACK button in Android, for activities launched from notifications, home screen app widgets, and the like. At least, that is what they are asking developers to do in the Android Design site.
Moreover, the justification given by Google engineers ("BACK should not cross task boundaries") does not make a lick of sense. By that argument, the BACK button can never lead to home screen. Yet, in their own example, the BACK button does just that. However, instead of it returning to the home screen immediately, we first lead the user to some activity that they never visited, and only then do we go to the HOME screen on the next BACK press.
Google's recommendation here, IMHO, violates the Principle of Least Surprise. Users should never, from a single BACK press, have to ask the question, "WTF just happened?". Yet, that is what Google is advising.
The overriding principle should not be "BACK should not cross task boundaries". The overriding principle should be "BACK should behave like it would on a Web browser wherever humanly possible", since that is where users first encounter the notions of BACK and HOME. BACK on a Web browser would never do what Google proposes BACK do in an Android app.
I like the Android Design site in principle. In practice, the fact that it has few justifications for its prescriptions and few implementation details means that it is doubly frustrating. That being said, I will generally advise developers to adhere to what is in the Android Design site. But I will not do so for things that, in my not-completely-unreasoned opinion, violate fairly basic UX concepts like the Principle of Least Surprise, unless somebody convinces me that the benefits are worth the attendant costs. I await convincing arguments in this case.
IOW, IMHO, BACK still means back.
March 31, 2012
Omnibus v0.3 Released
Version 0.3 of the omnibus edition of The Busy Coder's Guide to Android Development, as re-envisioned as part of The Big Book Reboot, is available to most subscribers. Those who subscribed after 8am Eastern Time on March 31st will start getting the Omnibus next week.
This week, the Omnibus is still only available in EPUB and MOBI. However, the MOBI file is the new hybrid of the classic Mobipocket format and Amazon's new KF8 format. The file size is a bit bigger, but it will give richer results on KF8-capable devices, such as the Kindle Fire (and, I think, other Android devices with the Kindle app). Notably, the KF8 format supports my changebars, which is very useful. If you encounter compatibility issues with the new MOBI file, though, please let me know.
From a content rendering standpoint, change bars have been extended to include bulleted lists. This time around, all bullets have change bars, but starting with Version 0.4, only the new/changed ones will be marked.
The highlights of this update include:
A revamped chapter on adapters and AdapterView, with a more concise description of how to create simple lists with custom row contents
A revamped chapter on JARs and Android library projects, including coverage of installing the Android Support package
A completely rewritten chapter on using the action bar, emphasizing the use of ActionBarSherlock for backwards compatibility
A brand new chapter on Android's process model
The action bar coverage is the first example of where the rebooted book will depart from the original. The reboot will be centered on Android 2.x-4.x, adding support for future versions of Android as they arise. Coverage of 1.x will be limited, to both simplify the material and to focus on current recommended practices.
Version 0.4 should be released in 1-2 weeks, with a revamped chapter on introductory use of fragments, the ViewPager widget, and more. There is also a decent chance that PDF support will be available with the 0.4 release.
If you encounter problems with the Omnibus or have other Omnibus-related feedback, please contact me at omnibus /at\ commonsware.com.
March 29, 2012
UX Strategy Vs. UX Tactics
Juhani Lehtimäki, in his awesome Android UI Patterns blog, has a post up today entitled "Multi-platform Frameworks Destroy Android UX". In it, he complains about the UX supplied by tools like PhoneGap.
To some extent, I agree with him, insofar as a stock PhoneGap app will not behave quite the same as a native Android app. Mr. Lehtimäki appears to believe that a PhoneGap app would land in the "uncanny valley" where a Web app would not, and I certainly disagree on that point (they're both in the valley). However, it would be ridiculous of me to claim that the experience of using a PhoneGap app and the experience of using a native Android app are identical.
Tactically, if you are writing a native Android application, you owe it to your users to aim for maximum platform UX fidelity.
Strategically, a "UX über alles" mindset, decrying the use of tools lihe PhoneGap, is simplistic.
In the real world, budgets are not infinite. Talent is not universal. Time is not available on tap, to pour out whatever you need. While maximum platform UX fidelity is an admirable goal, so is accessibility, internationalization to all the world's languages, a test suite rich enough to take years to run, etc. Choices like PhoneGap vs. a suite of native apps is a strategic choice, and such choices need to take into account all the constraints and all the goals. And at the end of the day, platform UX fidelity may not be deemed that important for a given app.
I suspect that Mr. Lehtimäki is focused on apps distributed via Google Play. In that situation, the strategic value of platform UX fidelity will be relatively high, and therefore may drive people away from PhoneGap. However, Google Play is but one channel. There are other audiences than the general public, and for some audiences and circumstances, platform UX fidelity may not be as critical.
From 2003 through 2009, in a mix of part-time and full-time work, I helped build out the IT capabilities of a friend's civil engineering firm. My predecessor (a civil engineer by training and a "computer guy" by personal interest) took them from nothing to the Stone Age, relatively speaking. I brought them all the way up to, say, the Bronze Age, in terms of capability.
You might wonder why I didn't get them all the way to flying cars.
The reason is that they are a civil engineering firm. They do not need flying-car-level IT capabilities, any more than they need gigawatt lasers for surveying. They do not have the budget to support flying cars.
As a result, UX tended to be highly variable. Some software, like AutoCAD and ArcGIS, clearly had some attention paid to UX, though often times it was lost in sea of complexity. On the far other end of the spectrum, they probably still, to this day, use a handful of MS-DOS applications, whose UX is atrocious by modern standards (and weren't exactly top-notch back when MS-DOS was still relevant as an OS). They moved from an accounting system with lousy UX to a new accounting system with lousy UX. Some portions of their business were organized by means of some simple Excel spreadsheets (with limited UX). I tried to avoid writing much custom software for them, anticipating future maintenance issues, but what I did write did not have UX as top priority.
I imagine that Mr. Lehtimäki might brand me and this whole firm as a bunch of heretics.
Truth be told, all else being equal, they would have been better served with better UX. But that wasn't among the top criteria — meeting functional requirements and budget constraints were. For example, QuickBooks has better UX than either their old or new accounting packages, but we could not figure out how to get QuickBooks to do what they needed to have done on the billing side, and therefore QuickBooks was not an option, UX notwithstanding.
If this firm were to someday get into custom-writing mobile apps for their field crews, PhoneGap might be a fine solution. Yes, platform UX fidelity would be lower, but platform UX fidelity would be somewhere around "does not increase the generation of belly button lint" in terms of their priorities. It might well be substantially easier for them to support a mixed bag of device platforms via PhoneGap than to develop and maintain 2-3 native apps, depending upon whether those apps were within PhoneGap's capabilities.
Even firms that create off-the-shelf software for civil engineers might tend towards PhoneGap, if they can deliver the desired functionality for lower development costs and if they believe that they will be able to compete effectively despite the lower platform UX fidelity. Competition may be sufficient to drive them to native apps, just as competition on Google Play is what presumably drives Mr. Lehtimäki to rail against PhoneGap. But, again, this is a strategic decision, and there are many more factors in play than just platform UX fidelity.
In the fullness of time, the amount of development work for Google Play apps will be dwarfed — by an order of magnitude — by the amount of development work for more focused audiences, such as employees of a business. After all, that's how software is outside of mobile, and it seems unlikely that the Android ecosystem will somehow fail to match it.
It is important for those deciding between PhoneGap, other cross-platform solutions, or a basket of native apps, to understand the platform UX fidelity issue. At the same time, it is simplistic to claim that "targeting multiple platforms with one app does not work", merely when it is a sub-optimal choice for platform UX fidelity. Everybody — developers, managers, and those of us giving advice to them — needs to go into these decisions with eyes wide open.
In a perfect world, we could write cross-platform apps with perfect platform UX fidelity. As I have pointed out on many occasions, in a perfect world, I would have hair. As I am presently as balding as ever, I surmise that this is not a perfect world, and therefore platform UX fidelity has to slug it out with all the other admirable goals in software development.
March 26, 2012
The Busy Coder's Guide to Advanced Android Development Version 2.6 Released
The Busy Coder's Guide to Advanced Android Development Version 2.6 is now available for subscribers in all formats.
This update, representing ~35 pages of new material, adds:
Light coverage of developing for the oh-so-disappointing NOOK Tablet and Blackberry Playbook
A new chapter on working with rich text (e.g., Spanned and Spannable objects)
A tweaked set of camera samples, to overcome a bug whereby the apps would crash if you pressed the power button while the preview was active
There should be another update to this material in another month. Whether that update comes in the form of a change to this specific title, or gets rolled into The Big Book Reboot and the omnibus title, is unclear right now. My gut tells me that there will be one more update to this title, but I am not completely certain.
March 22, 2012
AsyncTask: Beware of Curves Ahead
Somebody tweeted yesterday a link to this code change to AsyncTask This suggests that the core Android team made good on a veiled threat of changing the AsyncTask behavior to only execute one task at a time.
That being said, in some tests this morning, I cannot seem to get the lightly-documented behavior. If I fire up several AsyncTask instances, they still all seem to run in parallel on 4.0.3 in the emulator and on a Nexus S. Perhaps somebody on the core android team has a different definition of "serialized" than I do – I was expecting behavior more like IntentService, where each command sent to it will be processed one at a time, not in parallel.
It is very possible that parts of this patch did not make it into the product as yet. If nothing else, the JavaDocs for execute() do not match the JavaDoc comment on execute() as shown in the patch. And, there was no note of an AsyncTask behavior change in the API Level 14 or 15 SDK release notes, and I would hope that a change of this magnitude would not be swept under the rug.
That being said, I would keep a very close eye on AsyncTask for the foreseeable future. If you are definitely relying on AsyncTask using multiple threads in parallel, you should consider starting to use executeOnExecutor() instead of execute(), perhaps using the stock THREAD_POOL_EXECUTOR, or perhaps using your own Executor.
And, in the meantime, I get to figure out why the R17 tools seriously screwed up Eclipse's ability to build projects…
March 19, 2012
Omnibus v0.2 Released
Version 0.2 of the omnibus edition of The Busy Coder's Guide to Android Development, as re-envisioned as part of The Big Book Reboot, is available to most subscribers. Those who subscribed after noon Eastern Time on March 18th will start getting the Omnibus next week.
This week, both EPUB and MOBI editions are available, though change bars probably are not available to MOBI readers.
From a content rendering standpoint, change bars have been extended to include code listings, so listings that change or are new will be flagged. This time around, all code listings have change bars, but starting with Version 0.3, only the new/changed ones will be marked.
This update adds three more tutorials, plus chapters on basic UI construction. There has been some reorganization of material, and a bit more Eclipse coverage than before, but nothing massive, so subscribers who have read through this sort of material in the original Guide will find little new.
Version 0.3 should be released in about a week. Tutorials will be on hold for a while, with more emphasis on the reorganized chapters and updated material.
If you encounter problems with the Omnibus or have other Omnibus-related feedback, please contact me at omnibus /at\ commonsware.com.
March 13, 2012
One Fewer Google I|O 2012 Attendee
They just launched the Google I|O 2012 conference site, and it is immediately apparent that I will not be attending, most likely, as they require Google+ to sign up.
There is no obvious reason why this would be technically necessary. It is hard to imagine that it is impossible to create a conference registration site without Google+, considering that there are countless other conference registration sites that have managed to pull off the trick. Heck, there were even conference registration sites before Google+ existed.
Instead, I have to assume that they are mandating Google+ just because they can.
Some people have wondered why I have not simply joined Google+. After all, you might think that somebody deeply involved with Android must love all things Google and therefore would have jumped at the chance to join Google+. And, at one time, that probably would have been true.
Partly, I am not involved in Google+ because I do not need yet more communication channels. I already spend countless hours supporting Android developers, and I manage to do all that simply with a Twitter account, a StackOverflow account, and an email account (which, admittedly, at the moment is Gmail, pending finding a suitable replacement). I am not a member of Facebook, nor LinkedIn, nor any of the scads of other social networks out there, either.
Partly, I am generally concerned about privacy and look upon all social networks with a degree of skepticism.
Mostly, though, I am not involved in Google+ because Google blew what goodwill it had with me with repeated screwups with related services, and I just cannot trust them anymore.
I used to use Google Reader for keeping up with RSS feeds and such. However, Google Reader kept somehow leaking my information. I don't know what, and I don't know how, considering I had done everything I could to tell Reader not to publish stuff. Yet, I would find people commenting about what I was reading in Reader, despite my best efforts. Hence, I dumped Reader.
When Google Buzz debuted, I immediately tried to turn it off, for all the above reasons. This too proved problematic, as every so often, I would get some indication that perhaps I had somehow gotten a Buzz profile (or whatever they called it), again despite my best efforts.
This all is on top of the screwup with Google Apps for Business that I blogged about last summer.
In theory, I could set up a pseudonymous Google Account and try to add Google+ to it. However, they also require Google Wallet, which while technically not as preposterous, would make setting up the pseudonymous account that much more challenging. And it is insulting that I would need to go to all that length for the right to hand over $900 to attend a conference.
And, of course, I might go through all that hassle and still not be able to attend, if last year's registration fiasco is any indication. The only reason I got to attend last year was because they offered pre-registration for some people who had attended previous years' conferences, and preliminary indications are they are not doing the same thing this year.
I will continue to mull this over during the next two weeks, to see if I can figure out a low-friction, high-privacy means of signing up for Google I|O 2012. I am not hopeful, and I am even less hopeful that Android development in general will remain "free as in speech", if Google expands upon its Google+ mandates.
March 12, 2012
The Omnibus Begins
The Big Book Reboot is an effort to rebuild the CommonsWare Android books into a single integrated ebook, focusing on the current recommended practices for Android application development (e.g., fragments).
Eventually, the results of the Reboot will be Version 4.0 of The Busy Coder's Guide to Android Development. Interim editions of the Reboot, though, are being made available to subscribers and are referred to as the Android Development Omnibus (or simply the Omnibus, for short).
Subscribers who log into their Warescription page will see a new row in the books table for Version 0.1 of the Omnibus in EPUB format. New updates to the Omnibus are expected weekly.
The Reboot is also rebooting the book generation process used here at CommonsWare, so the next couple of months will have a few rocky patches. Your patience is greatly appreciated.
The Omnibus has about a half-dozen chapters at the moment, covering setting up the development tools, creating an initial project, and examining the project's contents (particularly the manifest). Much of this is the same material as seen in The Busy Coder's Guide to Android Development.
Subscribers are welcome to peek at the Omnibus and provide feedback on what is there. As the weeks progress, some of the material added to the Omnibus will be completely new and potentially of interest to long-time readers. The Omnibus should be complete sometime in May, if all goes according to plan. Given my surname, that's far from certain.
Some other notes about the Omnibus:
The Omnibus is being manually generated for now. This means that people who newly subscribe, or renew an expired subscription, will not be able to download the Omnibus until the next weekly update. The Omnibus will be automatically generated by the time is is completed and replaces the other books.
The cover for Version 0.1 of the Omnibus is simply the last cover from The Busy Coder's Guide to Android Development. I will try to remember to customize the cover a bit for the next update.
The Omnibus will show changed material in two places. In the Table of Contents, changed sections will be listed in bold italic font, and that should be usable on all reader software. Specific new and changed paragraphs will be highlighted with change bars down the right side of the page. However, many readers screw up the HTML/CSS that the book requests and will not show the change bars. Recent tests indicate that Mantano Reader is the only EPUB reader that reliably shows the change bars. The "changed material" markers for Version 0.1 are inaccurate, as a side-effect of this initial release. Future versions should accurately show what changed from the previous release.
As mentioned, Version 0.1 is only available in EPUB. MOBI support should come next week with Version 0.2. PDF support should start up in April. And there will be other options coming online as well, one of which you will learn about in the coming weeks.
The Warescription Web site was updated to list the Omnibus, and it was updated to the latest GWT to hopefully help a bit with browser compatibility. By the time the Omnibus is completed, the Warescription Web site will be rewritten as a classic Web site, eliminating GWT and hopefully eradicating any compatibility issues.
You can read more about The Big Book Reboot in The Big Book Reboot: Why and The Big Book Reboot: The Trails.
If you encounter problems with the Omnibus or have other Omnibus-related feedback, please contact me at omnibus /at\ commonsware.com.
March 8, 2012
The Two Sides of Piracy
Android developers and the tech media often complain about rampant piracy of Android apps. Apps are usually uploaded to pirate sites within minutes of their release, courtesy of Google's inadequate security on the feed powering Google Play/Android Market/whatever. Developers and pundits worry about lost revenue, trojans being added to the pirated apps, and so on.
Worrying and complaining about that stuff is perfectly fine.
However, I find it curious that the same groups — and, in some cases, the same individuals or firms — who complain about stuff being pirated have no qualms about pirating apps themselves. Whether it is developers grabbing pirated copies of the Google Play/Android Market/whatever client for their emulator or Lifehacker espousing the download of pirated copies of HTC Beats or the Amazon Kindle app, people seem to have no problems pirating stuff when it benefits them.
This is classic hypocrisy, "do as I say, not as I do" behavior.
If you wish to have a debate as to whether such-and-so app should be freely distributable, such as the Google Play/Android Market/whatever client, go right ahead. Specifically with respect to that app, I have heard arguments on both sides.
And if you feel that violating the copyrights of others is your way of demonstrating against oppressive copyright regimes (i.e., "sticking it to The Man"), that's your prerogative.
But those who pirate the works of others have no grounds to complain when others pirate their own apps though. What's good for the goose is frequently good for the gander, after all.


