Mark L. Murphy's Blog, page 56

July 4, 2014

A Uri Is Not (Necessarily) a File

Google is advising developers to stop sending file:/// Uri values to other apps, whether via the data field in an Intent (e.g., ACTION_VIEW) or via an extra (e.g., EXTRA_STREAM with ACTION_SEND). There is no guarantee that the other app will have the ability to access that file, and making the file MODE_WORLD_READABLE is not great from a security standpoint.



Instead, you will increasingly need to handle the receipt of content:// Uri values.



Ideally, nowadays, those Uri values are “openable”. You can perform the following operations on such Uri values:





Open them via openInputStream() (and occasionally openOutputstream()) on ContentResolver





Find their MIME type via getType() on ContentResolver





Find out their DISPLAY_NAME and SIZE — the OpenableColumns — via a query() on the Uri (again, using a ContentResolver, or in theory a CursorLoader)





FileProvider from the Android Support library serves openable Uri values from files on internal and external storage. My StreamProvider serves openable Uri values from more locations, including assets and raw resources. The Storage Access Framework is designed around openable Uri values. And you can create your own ContentProvider that serves up openable Uri values.



The legacy convention was that a content:// Uri might not be openable directly. Instead, it pointed to a database row, retrievable via query(), and you would look in the _DATA column for how to access the actual data. Some providers no doubt continue to use this pattern. The rules for what the _DATA column would be were not well documented, but by convention they tended to be a path to a file. The problem is that this runs afoul of Google’s current guidance, as there is no guarantee that other apps can access such a file.



Do not blindly assume that if you get a content:// Uri that it is for the _DATA pattern. If you query() the Uri and do not get a _DATA value back, try using the Uri directly with ContentResolver. Or, perhaps do the inverse: try to open a stream on the Uri, and if that fails, then see if the _DATA pattern is in play.



An increasing percentage of the content:// Uri values you get will be openable, as more and more developers adopt FileProvider, the Storage Access Framework, and other things that adopt the openable-Uri pattern. Ignoring such Uri values, such as by crashing or rejecting a request when you do not find a _DATA value, will diminish the value of your app.



A hat tip to Stack Overflow users iforce2d and matiash for spurring me to do more analysis of some prominent Android apps that crashed when accessing FileProvider.

 •  0 comments  •  flag
Share on Twitter
Published on July 04, 2014 20:00

July 3, 2014

Consuming AARs from Eclipse

Increasingly, you will find that libraries for Android developers come only in AAR form. For example, many of the libraries that are part of the “L” Developer Preview have only been shipped to date in AAR form.



This is wonderful if you are using Gradle for Android, with or without Android Studio. It is less than wonderful if you are using Eclipse/ADT.



Fortunately, a StackOverflow user named FD_ came up with a basic recipe for converting an AAR into an Android library project, one that can be used from Eclipse/ADT. I have tested the recipe, have confirmed that it appears to work, and have created a Ruby script to automate the conversion.



The steps that my deaar script goes through are reminiscent of FD_’s recipe:





UnZIP the AAR into some directory.





Create an empty directory that will be the home for the Android library project. For the rest of these steps, I will refer to this as “the output directory”.





Copy the AndroidManifest.xml, res/, and assets/ directories from the AAR into the output directory.





Create a libs/ directory in the output directory. Copy into libs/ the classes.jar from the root of the unZIPped AAR, plus anything in libs/ in the AAR (e.g., mediarouter-v7 has its own JAR of proprietary bits).





Decide what build SDK you want to try to use. You might just choose the highest SDK version you have installed. Or, you can use the android:minSdkVersion and the -vNN resource set qualifiers to get clues as to what a good build SDK might be. If desired, create a project.properties file with a target=android-NNN line, where NNN is your chosen build SDK. Or, you can address this in Eclipse later on.





Import the resulting project into Eclipse, and if needed adjust the build SDK (Project > Properties > Android). Also, you will need to attach to this library project any library projects it depends upon (e.g., mediarouter-v7 depends upon appcompat-v7).





This is all based on the current AAR packaging, and therefore is subject to change.



Also, be sure to see if the AAR is natively available as an Eclipse-friendly Android library project, such as from an open source project’s repository. For example, all of my CWAC libraries ship as Eclipse-friendly Android library projects, in addition to AARs (and, for those not needing resources, JARs). This sort of AAR conversion should be an avenue of last resort, not the first thing you try.



If you try the deaar script and run into problems with it, please use the support options listed in the project’s README. If you run into AARs that do not appear to work using this script, drop me a line.

 •  0 comments  •  flag
Share on Twitter
Published on July 03, 2014 10:36

July 2, 2014

The Busy Coder's Guide to Android Development Version 5.9 Released

Subscribers now have access to the latest release of The Busy Coder’s Guide to Android Development, known as Version 5.9, in all formats. Just log into your Warescription page and download away, or set up an account and subscribe!



This updates begins the Big Book Pivot of 2014. Of note on the pivot:





All of the samples in the trails chapters have been de-Sherlocked, using the native action bar and fragments. They also all have build.gradle files, albeit ones using the classic Eclipse project structure and relying upon libs/ instead of Maven dependencies.





The tutorials have also been de-Sherlocked, using the native action bar and fragments. They also have been updated to simplify them somewhat (e.g., get rid of DownloadManager dependnecy) and use better techniques (e.g., event bus instead of broadcasts).





For those of you who are part-way through the tutorials using an earlier edition of the book, you are probably best suited to continue using the earlier edition. Your alternative will be to start over.



Also, the sheer number of changes means that it looks like a lot of the chapters were updated, though in many cases it is mostly just changing superclasses, imports, and the like.



Beyond the pivot work, this update includes:





A new chapter on the Android 4.4 printing framework





A new chapter on creating a MediaRouteProvider, to allow RemotePlaybackClient-enabled apps to work with your own custom remote media player





A completely rewritten chapter on BlackBerry, to bring the coverage up to speed for the 10.3 BlackBerry OS and its Android runtime





Improvements to the coverage of Gradle, Presentation, inSampleSize, and Fire TV





Various errata fixes





The next update will be the milestone Version 6.0 (“Motto: Trying To Stay Ahead of Android Version Numbers”). This update will include Android Studio coverage, specifically:





Android Studio instructions will be added to the tutorials, along with changing the tutorials’ command-line instructions to move to Gradle and away from Ant





Covering Android Studio equivalents to everything in the book that covers Eclipse





Adding Gradle build files for all of the core chapters’ samples, and ensuring that all of the projects can be loaded into Android Studio (despite using the Eclipse project structure for most of them, to maintain compatibility with Eclipse)





I also plan to clean up all of the core chapters, with rewrites as needed.



I will cover bits and pieces of new material, but not that much, along the lines of today’s Version 5.9. Once the pivot is behind me, I can return to my regular focus on expanding coverage in new areas, with a particular 2014 emphasis on “L”.



Version 6.0 is tentatively slated for release in early September.

 •  0 comments  •  flag
Share on Twitter
Published on July 02, 2014 14:09

June 30, 2014

Dealing with L Deprecations: bindService()

In my post noting API changes in “L”, I mentioned that bindService() now no longer supports implicit Intents. Unfortunately, some things require that at present… such as Google’s in-app purchasing (IAP) API.



(another hat tip to Alex Curran for pointing that out)



The real solution is for anyone exposing APIs that require service binding to move to explicit Intents, perhaps employing a wrapper JAR that is the actual API to hide those service details. In the case of IAP, Google should talk to Google to learn what Google’s expectations are in this area, so Google can modify Google’s code to work with Google’s code. However, depending on how quickly Google talks to Google and can ship a new version of the Google IAP API, you may have to deal with this more yourself.



The primary workaround is to simply not raise your targetSdkVersion past 19, as this behavior should only kick in at that point. But, that then inhibits your ability to work with some of the “L” stuff for testing and preparing to take advantage of the new, um, materials.



If you need to bind to a service and you need to convert an implicit Intent to an explicit Intent, use PackageManager. The simple solution is to use resolveService(), given the implicit Intent. That will tell you the “best service” for the implicit Intent. You can then call setComponentName() on the implicit Intent to make it explicit, using the information in the ResolveInfo returned by resolveService(). A better approach is to use queryIntentServices() and confirm that the list returns only one entry — if not, somebody else is trying to intercept your IAP calls. And an even better approach would be to employ some signature pinning, to ensure that you’re talking to the real IAP… but that’s a security measure, not one specifically dealing with the “L” bindService() issue.



Note that you really want to convert the implicit Intent to an explicit one by adding the ComponentName. For all you know, the service in question actually looks at the action string, and so constructing a new explicit Intent without that action string would perhaps cause problems.



Note that I have not personally tried all aspects of this technique, let alone on “L”, and so your kilometerage may vary. That being said, it’s how I would approach the problem, assuming that I was stuck in this situation.

 •  0 comments  •  flag
Share on Twitter
Published on June 30, 2014 09:10

June 29, 2014

And Now, Your 'L' API Change WTFs

With each Android release, Google issues an API differences report, outlining things that were added, changed, or removed in a new API level compared to the previous one.



For whatever reason, the “L” Developer Preview’s differences report is published, along with the JavaDocs, in a poorly-structured ZIP archive.



I always review this to see what’s different beyond the sorts of changes that get more disclosure, coverage in Google I|O presentations, etc. And “L” has some significant changes.



NOTE: This analysis is based on the preview. It is entirely possible that some of the things in here will revert back to previous implementations by the time “L” ships as Android 5.0 (or whatever they call it). Hence, while this blog post represent areas of concern, be sure to double-check with the shipping version when it actually does ship.



NOTE #2: In Android, “deprecated” means “we think that there is a better solution, and we can’t guarantee that we will support what’s here indefinitely, but at the moment at least, it should work”.



Of note, with regressions bolded:





Action bar navigation, of all forms, is deprecated. This includes both action bar tabs and drop-down (“list”) navigation. It does not include the “custom view navigation” (e.g., browser address bar). I suppose the eliminates my concerns over the behavior of action bar tabs…





Part of the reason for this is that the action bar is being pulled out into something more readily manipulable by us developers. Activity has a setActionBar() method, taking a Toolbar parameter. Toolbar basically looks like a simplified action bar and can be placed in arbitrary spots elsewhere in your view hierarchy, in contrast with the locked-to-the-top action bar.





Activities can be “persistable”, in that they “persist across reboots”. I am guessing that this is tied into the new extension of “recents” to include documents. As a side effect of this, we have new flavors of onSaveInstanceState() and kin on Activity that allow us to populate both a Bundle and a PersistableBundle, the latter of which presumably survives the reboot.





getRecentTasks() and getRunningTasks() on ActivityManager are now deprecated and will return a reduced result set on L and higher devices.





BatteryManager now gives us the ability to directly access battery information, without having to fuss with registering a null receiver for ACTION_BATTERY_CHANGED.





bindService() now requires an explicit Intent, if your targetSdkVersion is set to L or higher. I would consider using implicit Intents here to be a code smell anyway, but if you are using them with your service, be forewarned. UPDATE: According to Alex Curran, this breaks the in-app purchasing (IAP) integration code.





We now have getExternalMediaDirs(), which is a bit like getExternalFileDirs(), but represent directories that will be scanned by the MediaStore.





A boatload of new stuff has been added to DevicePolicyManager for those of you using the device admin APIs.





FragmentBreadCrumbs is now deprecated, for the six of you who were using that class. :-)





There is a new LauncherApps class that helps simplify finding the relevant launchable activities. This is tied into the new managed profiles system.





MediaStore has been augmented with MediaStore.Audio.Radio. It is largely undocumented, and so it is unclear if this is referring to streaming radio stations, classic broadcast radio (e.g., FM), or something else.





The TOP_LEVEL_* patterns in Patterns are now deprecated, presumably reflecting the fact that the number of top-level domains is expanding rapidly.





Android now has some amount of tracking of “power save mode”, with an isPowerSaveMode() on PowerManager and an ACTION_POWER_SAVE_MODE_CHANGED broadcast. Whether this is for OEM-specific modes or for some new common power save framework in Android, I cannot say.





In what might be a first, something was “undeprecated”, specifically INSTALL_NON_MARKET_APPS on Settings.Secure, as it was moved back there from Settings.Global.





WebSettings now lets you control mixed-content mode, referring to whether WebView should load insecure content from a secure origin.





There are many other changes as well, particularly ones tied to “big ticket” changes in L, but these were ones that caught my eye.

 •  0 comments  •  flag
Share on Twitter
Published on June 29, 2014 08:42

June 27, 2014

Developer Preview Rules of the Road

Google I|O 2014 so far has been marked by a distinct emphasis on “coming soon” rather than “right now”. Of course, the biggest element of that is today’s planned release of the Android L Developer Preview.



Dave Burke apparently said in the Android Fireside Chat that the developer preview model is likely to be a fixture going forward (hat tip to Dave Smith for tweeting that, as I was having some livestream issues). However, we have not had a developer preview since the Android 1.x days, and many of you reading this blog post were not doing Android development way back then.



One of the keys with a developer preview is expectation management, between Google and developers, and to a lesser extent between developers and power users. Here is my take on the rules of the road for the L developer preview.



YMMV

L is going to be big, big enough that IMHO it is fairly safe to assume that this will be branded “Android 5.0”. But L is also a moving target, as some of the presentations indicated that work is continuing on L, at least at the framework level. What we will get today probably closely resembles – but is not identical to – the bits that are given to the OEMs to begin integration on new handsets. But it will not be the final version of an Android 5.0, and there’s a decent chance that there will be a “fast follow” 5.0.1 that fixes some things, possibly in ways that affect us as developers.



Hence, this developer preview will contain a lot of things that will wind up in L, but not everything in L will be in the developer preview. Please do not panic when L does ship to see things that you did not see in the preview.



Caution: Switchbacks Ahead

Conversely, it is possible that there will be things in the developer preview that might be intended for L but get stripped out late.



Perhaps there are too many bugs, and they lack the calendar time to get them fixed for a 5.0 release. This could result in a patch-level release that bumps the API level, as we saw most recently with Android 2.3 (API Level 9) and Android 2.3.3 (API Level 10).



Perhaps it is more generally “not ready for prime time” and is moved back to the drawing board for consideration in some future Android update. The Bluetooth APIs in the pre-1.0 beta releases of Android suffered this fate, not returning to the SDK until Android 2.0, while they were retooled during the intervening year-plus.



It is fine, even intended, that you use the developer preview to start making plans, and even code, to support L when L becomes available. However, just be careful to manage your L time investment properly, in case some developer preview piece that you are “hanging your hat on” winds up being pulled from the final release.



Bridge Ices Before Road

Just because your app works awesome on the developer preview of L does not mean that it will work awesome on L itself. Again, there will be differences, many beneath the level of the SDK, and some of those differences could have an impact on your app.



The developer preview is a way to spread out the work to get your app L-ready. However, it is not a replacement for testing on L itself, to make sure your app really does what it is supposed to do on what users will be using (L), as opposed to what you were initially given for testing (L developer preview).



Stay On Your Side of the Road

It is conceivable that we will get access to some of the source code that forms the developer preview.



It is also conceivable that you feel that you are not limited by source code availability, and that you will use reverse-engineering tools to figure out what is going on “under the hood”.



That is fine. However, be careful how you use that knowledge because, again, the preview release is not the final release. In particular, while using this stuff to experiment with a backport (where none is available) is fine, I’d be a bit hesitant about releasing a backport based solely on the preview bits.



Caution: Construction Ahead

While what we are getting today is a “developer preview”, not only developers will be previewing it. If, as described, there are hardware images available to load onto some recent Nexus devices, there will be non-developer power users who will elect to start running L, and some of them will be trying to use your app.



On the plus side, if your app starts crashing, and you are collecting crash logs, this will give you valuable intel on where things need work in your app to get it to work on the L developer preview, and perhaps on L itself.



On the other hand, you may also wind up with a lot of support questions related to L, more so than you would normally have for a non-existent release.



Power users often poke around with various features that are supposed to be developer-only, whether that is ART previews, READ_EXTERNAL_STORAGE previews, etc. Unfortunately, not all of those power users understand that “preview” does not mean “instantly works”. You may get some complaints as a result, and it will be up to you to decide how much to cater to users of a preview release of Android.



Scenic Lookout Ahead on Right

Don’t let these rules scare you. Developer previews are awesome, in that we actually have time to try to adapt to new Android releases, rather than having releases land like cartoon anvils on our roadmaps whenever Google decides to ship them. We may not have budgeted time to consider Theme.Material, or new notification styles, or employing JobScheduler to replace select uses of AlarmManager. At least now we have the opportunity to consider them.



Android 5.0 will not ship until October or November, in all likelihood, giving us months of lead time, lead time that we are not used to having. Use the time wisely, and your app can shine on Lollipop, Lemonhead, Lindt, or Limburger, whenever the new Android release ships and under whatever name it ships.

 •  0 comments  •  flag
Share on Twitter
Published on June 27, 2014 08:17

Android Wear and Play Services

Near as I have been able to determine, it is possible to create an Android Wear “micro app” as an ordinary Android SDK project, subject to the limitations imposed by the platform (e.g., no WebKit). However, it would appear that you need to use the Play Services Framework to communicate from the phone/tablet to the Android Wear device and back again. And I’m unclear whether it is possible for a device sans Play Services to be able to deploy the micro app to the Android Wear-able.



(if anyone knows of techniques to avoid this dependency, please write about them!)



This means that Android Wear isn’t an Android accessory, it’s a Google accessory.



When I tweeted my dismay about this, I received some push-back. And since it is difficult for me to explain this in 140 characters, we’ll go with a blog post instead…



I have blogged about the fact that the Play Services framework is proprietary and its ramifications before.



From a technical standpoint, I can see some arguments in favor of using a proprietary library for access to proprietary Web services. Basically, the library is, in effect, the Web service API, not the on-the-wire HTTP-based (or whatever-based) protocol. Having the library be open source would effectively require the on-the-wire protocol to be the API, with the library being a convenience wrapper. That’s certainly a viable route, and most public Web sites with Web services do just that. But if Google doesn’t want to make the on-the-wire protocol be the API, now or long term, that is Google’s decision.



Where I have problems with stuff being poured into Play Services is where no Google Web service should be involved. In that previous post, I mentioned the new LocationClient as being problematic, as there shouldn’t be anything in there inextricably tied to Google’s Web services. Even more dramatic are the hardware-specific ties:





Google clearly promotes the Cast SDK for working with Chromecast (and, eventually, Android TV), despite the fact that RemotePlaybackClient in the Android SDK may meet the needs of most developers





And now, Android Wear is effectively tied to Google, if indeed you cannot really create effective Wear apps without Play Services





Or, as I tweeted:




Requiring a proprietary library to mediate [communications] from an open source OS to an open source OS separated by inches is ridiculous.




But, then again, as Al Sutton pointed out, Android Wear isn’t really running an open source OS. Neither does Chromecast.



This is not to say that developers should bypass Play Services on philosophical grounds. It does mean that developers that are inextricably tied to Play Services leave out a growing chunk of the Android ecosystem, the ones outside of the Play Services sphere (Amazon’s Kindle Fire/Fire Phone/Fire TV, BlackBerry’s Android runtime, Nokia X, etc.). Gradle’s product flavors can help with this somewhat, but only to a point.



All I ask is for developers to make decisions with eyes wide open. Technically, depending upon Play Services is not that different than is depending upon some other library project. Tactically, it might even be the right decision. Strategically, just be aware that you are no longer developing for Android, but instead are developing for Play Services (using a lot of Android APIs), and that’s a more-controlled subset of the Android ecosystem.



And now, if you’ll excuse me, I’ll return to listening to the screams of anguish out on Stack Overflow from people trying to make sense of the new tools release and the L Developer Preview…

 •  0 comments  •  flag
Share on Twitter
Published on June 27, 2014 08:17

June 17, 2014

The ART of Garbage Collection

The ART documentation in the Android SDK has been updated (hat tip to Juan David Sánchez for pointing it out).



And it hints at something that I had been really hoping for, once I saw the I|O presentation description for the talk on ART mention “garbage collection”. Quoting the documentation:




…a compacting garbage collector is under development in the Android Open-Source Project (AOSP) to improve memory management. Because of this, you should avoid using techniques that are incompatible with compacting GC (such as saving pointers to object instance data). This is particularly important for apps that make use of the Java Native Interface (JNI).




This is big. Really big. Because our heap is really small.



However, the reason why we get so darned many OutOfMemoryErrors isn’t because we are out of memory. Instead, there is no single block of memory that is big enough for our request.



In Java, on the JVM, if there is no single block of memory big enough, that means that we are actually out of memory (with respect to this request, anyway). That is why the exception is OutOfMemoryError and not CouldYouAskForSomethingSmallerPlzKThxByeError.



However, the JVM has one thing that the Dalvik VM does not: a compacting garbage collector.



When we write programs in a language running on a runtime supporting garbage collection, we create a bunch of objects, and we later release some subset of those objects. The other ones we hold onto for a while, because we are still using them. In Android, for example, our Application, our ContentProviders, our Threads, our own static data members, and so on are going to live for quite some time, in many cases for the duration of the process. Anything they can reach also will not get garbage-collected. So, we allocate a bunch of memory and release some of that memory as our app runs.



With a compacting garbage collector, the long-lived objects get slid around in memory, to allow the freed-up blocks of memory to be coalesced. The net is that all free heap space should be available as one contiguous block, eligible for allocation.



(the details are more complicated than that, but this is a blog post, not a dissertation)



With a non-compacting garbage collector, nothing is slid around in memory. We wind up with heap fragmentation, as what was once a pristine 16MB (or 32MB, or 48MB, or whatever) heap now is a bunch of objects with interspersed free memory. Even though we might have 10MB of free heap space, if the largest single block of that free heap space is only 1MB, we cannot allocate an 8MB Bitmap, because there is no free block big enough.



The Dalvik VM has a non-compacting garbage collector.



The ART VM has a non-compacting garbage collector… today. If the work going on in the AOSP pans out, ART will get a compacting garbage collector in the future. And if they’re advising us to pay attention to this in our native C/C++ code with the NDK, they must feel reasonably good that their hard work on the compacting garbage collector will pan out.



When that happens, and ART is turned on by default for all users of some new version of Android, OutOfMemoryErrors will not completely go away, but they should become less frequent and more accurately represent the error message itself.



I, for one, welcome our new ARTist overlords.

 •  0 comments  •  flag
Share on Twitter
Published on June 17, 2014 22:28

May 9, 2014

Presentations From a Service

For a while now, I have been saying that the only way to use the Presentation class to display stuff on a TV/monitor/projector is through an Activity, because Presentation inherits from Dialog. That is true.



Sometimes, I would say that the only way to display stuff on a TV/monitor/projector is through an Activity. That, as it turns out, is not true.



One Stack Overflow answer led to my own Stack Overflow question on the subject, and with the help of those SO contributors I eventually figured out how to drive an external display without an Activity.



I wrapped that pattern up into a PresentationService that I have added to my CWAC-Presentation library. PresentationService clones some of the logic from Presentation and Dialog, enough to allow you to define a View that will be shown on a Window connected to the Display object representing the external display.



The biggest limitation is that we have to use a TYPE_SYSTEM_ALERT Window, which in turn requires the SYSTEM_ALERT_WINDOW permission. This is a permission that I really try to avoid, both as a developer and as a user. Ostensibly, it is there because otherwise a Service could draw over the main display without the user being aware of it. Perhaps in the future, a Service rendering to an external display might be able to avoid this permission or switch to some alternate, less-scary permission.



I hope to cover the implementation of PresentationService in the next update to my book. If you simply want to use it, the project README contains basic instructions for using it, and there is a dedicated sample project showing how to use it.

 •  0 comments  •  flag
Share on Twitter
Published on May 09, 2014 17:23

May 5, 2014

MediaRouter Webinars

Another pair of webinar topics have been added to the roster, both related to MediaRouter.



The first (“MediaRouter and RemotePlaybackClient”) covers how to write an app looking to consume media routes on a device like a Chromecast. We will see how to use MediaRouteActionProvider to find the Chromecast and how to use RemotePlaybackClient to have the Chromecast play back the desired media.



The second (“‘Cast’ To Your Own Device”) covers how to allow your device — or your app running on a device like a Fire TV or an OUYA — to be visible on phones and tablets as an available media route. We will see how to set up the MediaRouteProvider to advertise your route when it is available and what steps you will then need to take to fulfill the remote playback requests.



These are each scheduled for four different dates and times in June and July, to try to provide you with enough options to find one that you can attend.



Subscribers can visit their Warescription page to get the discount codes for these, though they are also open to the public.



If you have any questions regarding the webinars, let me know.

 •  0 comments  •  flag
Share on Twitter
Published on May 05, 2014 22:22