Mark L. Murphy's Blog, page 53

January 18, 2015

Getting a JAR into Android Studio

Brian Marick writes:




I am stunned, as if struck by a ball-peen hammer, by how hard it is to say “use this jar” to Android Studio 1.0.2. If it’s even possible.




It’s certainly possible, and in a standard Android Studio project it
is pretty easy. Whether it is the right solution, though, is another matter.



I would recommend that you do some poking around and see if the library
is offered as an artifact in some place like Maven Central. The
“Gradle, please” Web site can help
with this, or you can use the Project Structure dialog in Android
Studio itself (File > Project Structure from the main menu).
Specifically, the Dependencies tab for your module
(e.g., app) has a similar search feature to what “Gradle, please” offers.
Just use the + button and choose a “library dependency”, then search.



Whether you find the artifact from “Gradle, please” or add it via
the Project Structure dialog, the result is pretty much the same:
a compile statement added to your module’s build.gradle file:



dependencies {
compile 'com.squareup.okhttp:okhttp:2.2.0'
// and perhaps other lines here
}


Using the artifact means that chained dependencies (e.g., the JAR
depends upon other JARs) are handled for you, and updating to a
newer version of the JAR is simply a matter of updating the version
number in the compile statement. Plus, your version control system
is now tracking what version of the JAR you are using, as opposed
to checking in some random JAR binary.



But, suppose you have a random JAR (andataco.jar), and you cannot
find an artifact for it.



If your module’s build.gradle file has the standard new-project
dependencies closure:



dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}


then all you need to do is put the JAR in libs/ within the
module, and you are done. The compile fileTree() statement
says “yo, Gradle, take all the .jar things in libs/ and
compile ‘em into the project”. That will add the JAR to the
compile-time classpath and, for an Android project, also package
the JAR’s contents into your APK file.

 •  0 comments  •  flag
Share on Twitter
Published on January 18, 2015 03:45

January 15, 2015

Library Authors: You Can't Always Get What You Want

Given the rise of Android Studio, more and more Android library authors
are creating Android library projects and publishing them as AARs,
as opposed to trying to stick to plain JARs. Nowadays, this approach
as the added benefit offering manifest merging, so a library author
can contribute elements to the manifest:





<uses-permission> and <uses-feature> elements that the library
needs for various operations




components (e.g., <activity>) elements, to save the developer using
the library to have to manually add them




a <uses-sdk> element, with the library author’s own take on what
the minSdkVersion and targetSdkVersion should be




and so on





Library authors should not get complacent, though, and assume that
just because they ask for it in the library’s manifest, that they will
get it. Developers have the ability to reject anything introduced
by the library’s manifest, through two major approaches:





Add tools:node="remove" attributes to copies of elements to be blocked,
such as having tools:node="remove" on a <uses-permission> element
to specifically block libraries from adding that permission requirement




Add tools:overrideLibrary to the <uses-sdk> element, indicating
libraries whose opinions on minSdkVersion and targetSdkVersion
should be ignored





Library authors need to practice defensive programming and make sure
that they react to the environment around them.



If you gotta gotta gotta have some permission, make sure that your
library “fails fast”, so that the developer is guaranteed to find out
that blocking the permission is not supported. This may come about
naturally by use of your library, such as a camera library failing
quickly when trying to use android.hardware.Camera if the
CAMERA permission were blocked. However, if the permission is essential
but may not be used until later in the workflow, use PackageManager
to determine if you have the permission, and fail early on with your
own exception, rather than wait.



If the permission is not essential for the overall library, but it is
essential for some feature of the library, try to gracefully degrade
if the feature is used but the permission is blocked. For example,
some app developers try to avoid WRITE_EXTERNAL_STORAGE for fear of
backlash from users. If your app would default to using external storage
for something (and therefore perhaps needs this permission), see if
there is a workaround (e.g., have the file on internal storage and use
FileProvider to serve it to third-party apps). Or, simply fail the
request, ideally in some way that allows the user to understand what
is going on or for the app developer to react to the missing feature.
So, if you need WRITE_EXTERNAL_STORAGE and do not have it, through
some custom checked exception, or have a canUseXXXFeature() method
that the app developer should call to determine if the feature can be
used, or something.



The same holds true for anything else that you introduce in the
manifest:





If you specify a minSdkVersion, recognize that your vote may be
ignored, so you may be running on an older device. Where possible, try
to handle that gracefully (e.g., use Build.VERSION.SDK_INT to see what
you really are running on and react). Or, check the version information
up front and fail fast, or at least introduce a warning to alert the
developer that you’re not responsible for any VerifyError crashes
due to your running on an older-than-expected Android device.




If you specify a targetSdkVersion, you should be able to find out what the actual
targetSdkVersion is from the ApplicationInfo object that you can
get from PackageManager.




If you added components and planned on trying to use those components
yourself (e.g., register a PendingIntent pointing to a BroadcastReceiver
that you had set up in your manifest), you can use PackageManager to
determine if you actually have that BroadcastReceiver registered in the
manifest.




And so on.





Of course, this is all a pain. I need to do a better job of this myself
for my CWAC libraries.



:: adds item to to-do list::



On the other hand, we really should have been doing this sort of thing
before manifest merging came about, as we were expecting the app developer
to manually set up these things in their app’s manifest… and they might
not. Just because we can automate putting our requirements in the manifest
does not eliminate our need to validate what we got and handle differences
appropriately. As some
old British guys have pointed out for years,
you can’t always get what you want.

 •  0 comments  •  flag
Share on Twitter
Published on January 15, 2015 22:20

January 8, 2015

Moar Webinars!

I have a new crop of webinars going on over the next couple of months:





Android Studio for Eclipse Users is a quick tour of Android Studio, pointing out key differences between how Eclipse worked and how Android Studio works.





A Peek at JobScheduler, which, as the title suggests, reviews the JobScheduler system service that was added to Android 5.0, as an alternative to AlarmManager for periodic work.





What’s New with Notifications covers some of the changes that arose in 2014 related to the use of Notifications, such as customizing them for Android Wear and Android 5.0’s new behaviors.





Making Sense of Storage, covering the differences between internal, external, and removable storage, plus how ContentProviders are replacing direct filesystem access for accessing another app’s files.





(NOTE: those of you who signed up for the “Making Sense of Storage” from mid-December that was canceled due to technical difficulties, Dozeo is working again, and I have added another edition of that webinar for noon US Eastern on January 22nd)



Remember: active subscribers have access codes on the Warescription site for 80% off the already-cheap registration fees for these webinars!

 •  0 comments  •  flag
Share on Twitter
Published on January 08, 2015 18:53

January 1, 2015

Warescription Site Revamp

The Warescription site has been rewritten to use Bootstrap 3, for better use on mobile devices and a cleaner look in general.



The same functionality exists as before, in largely the same organization, though the navigation is now a top nav bar rather than a side nav bar. Existing subscribers should have little trouble finding where everything is — let me know if I am mistaken in that assessment.



However, there are two deprecations.



First, temporarily, subscribing via Bitcoin is unavailable. I should have that working again in a couple of days. Credit card, debit card, and PayPal are all available.



Second, Google logins are no longer supported. Google’s support for OpenID 2.0 is ending in April 2015, and neither of their alternatives are palatable. Worse, something in the OpenID handling on the new site works for other OpenID providers (e.g., Stack Exchange) but not Google, and it is not something that I can readily fix. If you subscribed and used a Google account for setting up your Warescription account, contact me and I can work with you to get your Warescription moved over to another Warescription site account.



If you run into any problems with the new site, please let me know, so that I can work to fix it.

 •  0 comments  •  flag
Share on Twitter
Published on January 01, 2015 16:25

Warescription Site Downtime

Tomorrow (1 January 2015), I will be replacing the Warescription site with a new Boostrap3-based site. This will result in a bit of site instability, at around 13:00 UTC (8am US Eastern), while I make the upgrade.

 •  0 comments  •  flag
Share on Twitter
Published on January 01, 2015 03:33

December 18, 2014

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

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



This update includes:





Moving coverage of Android Studio and Gradle for Android to 1.0. This includes overhauling the first couple of tutorials to deal with the new Android Studio setup process. This also includes warnings that Google has discontinued Eclipse support.





Initiated coverage of Material Design. Right now, the focus is on the core themes, the impacts of Theme.Material on widgets and the action bar, and the application of tints. Additional Material Design technical coverage, such as elevation and its relationship to things like RelativeLayout, will come in future updates. However, the focus of the book will be on engineering aspects, not design aestethics, as I have the design acumen of your average hamster.





Overhauled the AppCompat chapter to update it for the now-current release. This not only includes the new Material-ish action bar but the AppCompat tints of select Theme.Holo widgets.





Moved the chapters that touch on Play Services to the new granular dependencies. In particular, this involved modifying all of the Maps V2 samples (and the associated chapter), to cover getMapAsync(). I also removed the action bar list navigation from the Maps V2 samples, as action bar navigation has largely been deprecated.





Updated the coverage of greenrobot’s EventBus, particularly moving to the latest version and switching to NoSubscriberEvent instead of ordered events to handle “update the UI or raise a Notification” patterns.





Removed the Nokia X chapter, may it rest in peace.





Various bug fixes and other minor improvements.





The next update is tentatively slated for late January 2015.



Note that a few items are targeted for removal next year:





Eclipse instructions in the tutorials will probably be removed in mid-2015. Eclipse information elsewhere will remain, perhaps switching to covering the Eclipse Andmore distribution. However, I am only going to maintain tutorials for official IDEs, because maintaining the tutorials is a pain in various body parts.





The ActionBarSherlock chapter will be pulled sometime in early 2015, as the project is formally deprecated.

 •  0 comments  •  flag
Share on Twitter
Published on December 18, 2014 23:16

December 11, 2014

A Presentation Sabbatical

I am going to be taking a sabbatical of sorts from presentations at conferences, meetups, and the like.



In the past year, I have delivered 16 such presentations, including a pair of half-day workshops. I have probably done ~40 presentations dating back to the beginning of 2012. And, since I don’t like repeating myself, most of those presentations were newly crafted for that event, or were substantial rewrites from past presentations.



While delivering presentations helps me to be useful to the Android developer community, I do need a bit of a break to “recharge the batteries”, as it were.



I will eventually return to submitting papers for conferences and such, but probably not until at least the latter half of 2015, and perhaps beyond. There are a few things that I want to get done first. When I return to presenting, I will probably start with events in the local area first, before getting to events on the US West Coast or overseas.



I apologize to anyone who is disappointed in me due to my sabbatical plans.

 •  0 comments  •  flag
Share on Twitter
Published on December 11, 2014 17:51

Manufacturers, Keep Your Hands Off My Zygote

As I often say, Android being open source is a double-edged sword.



(actually, I’m thinking that perhaps it is a more topologically-complex sword with lots and lots of edges, but I digress…)



Open source allows lots of people to get involved in creating Android devices, not limited to traditional form factors like phones. On the other hand, the ability for manufacturers to tinker with Android leads to compatibility problems. That in itself is not a problem… unless the manufacturer also wants app markets like the Play Store and Amazon AppStore for Android, and the compatibility problems have the potential to affect lots of apps.



One area of compatibility issues that has become more prominent is manufacturers messing with the zygote.



The zygote is a process, created when Android boots up, that contains the runtime (Dalvik or ART), framework classes and other JARs, and native libraries. When our app’s process is created, it is forked from the zygote. This is so Android can leverage the Linux kernel’s copy-on-write memory sharing, so the memory footprint of each of our processes is mostly limited to our own classes and other JARs, our own native libraries, and whatever we allocate on the heap.



Developers used to other environments will recognize the terms “DLL hell” and “JAR hell”. Any place where libraries are shared, changing those libraries affect all consumers of those libraries. The primary spot on Android where we get these effects is in the zygote, as our own classes and libraries are (usually) isolated per app.



Hence, when manufacturers change what is in the zygote, compared to what is normal for that version of Android, compatibility issues can result, such as:





Samsung, on various 4.2 devices, put appcompat-v7 into the zygote, causing apps using the now-current appcompat-v7 to have conflicts





LG, Samsung, and others, sometimes replace SQLite with newer versions, which probably will be OK, but that’s not assured





This is on top of Google’s under-the-surface and largely-undocumented zygote contents, such as the stripped-down edition of Legion of the Bouncy Castle that led to the development of Spongy Castle. That, at least, is fairly common across devices.



Sometimes, it would appear that manufacturers modify the zygote to have some library available in common for all their own apps. That is what I have to assume the rationale was for Samsung’s addition of appcompat-v7 to the zygote. This is simply sloppy, trading off the compatibility of countless apps to save a handful of KB of disk space.



Sometimes, the changes might be to address bug fixes that their own apps happen to trip over. This could be the reasoning behind the higher SQLite versions that LG and others have employed. That is certainly cool, though a bit more transparency would be helpful, and the fixes could still introduce compatibility problems.



Device manufacturers need to be very careful when altering what is in the zygote. Android is open, and device manufacturers have the freedom to alter what they want. Freedom to implement does not mean freedom from responsibility, though. Manufacturers that want apps from third-party developers need to ensure that the zygote the manufacturer uses is compatible with the zygote that third-party developers are expecting.



In other words, not all zygotes are created equal.

 •  0 comments  •  flag
Share on Twitter
Published on December 11, 2014 17:51

December 8, 2014

Dealing with the Bulk-Closed Android Issues

Somebody (“e…@google.com” for many of them) closed ~11890 issues out at http://b.android.com, marking them as “Obsolete”.



Some of the issues are old, others not so old — it seems like they were bulk-closed if they were opened on December 4th 2013 or earlier. They are not tied to any particular piece of hardware. Personally, I have had issues closed that ranged from bug reports to enhancement requests. Curiously, none of my many documentation bugs seemed to be closed.



While some of the closed issues are indeed “Obsolete”, I can state positively that some are not. Whoever decided to do this rage-closing of issues seems to have done so algorithmically, not tied to whether or not the issue is actually “Obsolete”.



For example, this feature request, to have FileProvider served from assets, is still outstanding, as FileProvider still does not have that as a feature. While I provided that sort of functionality in my StreamProvider, FileProvider could still be outfitted with that functionality. After all, about 4.5 years after I first published my WakefulIntentService, support-v4 and support-v13 gained WakefulBroadcastReceiver, which fills the same niche.



If you opened or are otherwise invested in one of the issues that were bulk-closed, please re-evaluate whether the issue is still valid or not. For example, this issue of mine is truly obsolete, insofar as action bar list and tab navigation are now deprecated, and Google’s philosophy is that bugs in deprecated code are perfectly legitmate.



If you find issues that were marked as “Obsolete” and are definitely still valid, please re-open them. If the originals were widely-starred, consider posting a comment in the now-closed issue pointing to the reopened issue. That way, those still following the concern can follow the new issue, and those seeing the new issue can find the context from the original. Also, this will help us minimize duplicate reopened issues. For example, I opened this issue and cross-linked it with its now-closed counterpart. I will be handling other issues of mine over the next few weeks, if others don’t beat me to them.



I have no problems with Google taking steps to clean up the Android issue tracker. I think it could have been handled with more aplomb. And, as usual, developers in the community have to repair the damage.

 •  0 comments  •  flag
Share on Twitter
Published on December 08, 2014 09:04

December 1, 2014

My Mistakes with CWAC-Camera

My CWAC-Camera library is an attempt to make taking pictures with Android’s Camera API somewhat easier, to hide a lot of the fiddly bits with previews and so forth.



It also serves as an abject lesson in the problems with writing reusable libraries, as I made mistakes along the way… mistakes that will now require me to pretty much rewrite the library from scratch.



Of note:





I envisioned the library as being a wrapper around Camera, rather than being a clean abstraction around the act of taking pictures and recording videos. As a result, I exposed bits of the Camera subsystem, notably Camera.Parameters. Google has now deprecated the Camera API, replacing it with android.hardware.camera2. A cleaner abstraction would also make it easier to blend in other camera APIs (e.g., SONY’s remote camera stuff) that might not show up under Camera.





I envisioned the library as being a replacement for the ACTION_IMAGE_CAPTURE and ACTION_VIDEO_CAPTURE Intent actions, as third-party camera apps definitely vary in how well they support those actions. However, I did not more forcefully restrict the scope to be just that functionality, and I did not design an API around extensibility. As a result, when requests came in for new functionality, either the functionality had to be in the library, or the functionality would not exist. This was rather frustrating, as it meant a lot of extra code in the library for scenarios that are not really all that near any itches that I was really seeking to scratch. A camera library, more so than many libraries, needs a small core with an extension model that allows other developers to add plugins to the library to handle their own itches without having to re-develop the core.





My lack of scope control and extensibility also makes it very difficult to rewrite the implementation without breaking the API. Of note, some devices seem to not like it if you change the camera parameters on the fly, and that’s difficult for me to fix within the confines of my current API.





I suck at JavaDocs. I’m much more fond of long-form prose than short-form method and parameter descriptions.





I still need a library for my core use case: replacing the ACTION_IMAGE_CAPTURE and ACTION_VIDEO_CAPTURE Intent actions. But I cannot rely upon Camera for the long term — if device manufacturers have inconsistent Camera support now, Camera support will only decline now that Camera is deprecated. And, I really need to address the extensibility issue, as otherwise this library will be an unmaintainable mess for the long term.



So, in mid-December, I’ll begin rewriting the library. This will take some time, as the new android.hardware.camera2 API seems to be your typical under-documented Android API. I will work on patching a few bugs in the existing library, particularly ones that do not involve API changes, but for the time being, significant work on the existing library is frozen pending the rewrite.



The rewritten library will share some common aspects with the existing one: CameraFragment and CameraView, for example. I am even looking to add a drop-in replacement for ACTION_IMAGE_CAPTURE and ACTION_VIDEO_CAPTURE Intent actions, to make it easier to move to a library from relying upon third-party camera apps. However, the other aspects of the API are going to change, hopefully for the better. I will provide instructions to help those migrating from the old to the new API as the new library starts to stabilize.



In other words, stay tuned for further developments.

 •  0 comments  •  flag
Share on Twitter
Published on December 01, 2014 21:22