About a year ago I have wrote about a certain SQLite gotcha on Android. tl;dr: in some cases when you create a view with unions, SQLite cannot determine a type of the column, and since Android binds all selection arguments as strings, SQLite ends up comparing X with “X”, concludes those are not the same thing and returns fewer rows than you’d expect.
Recently the same problem reared it’s ugly head. It turns out that it’s very easy to create in a view a column with undefined type. It might happen in case of joins, using aggregation functions, subqueries, etc. pretty much anything more fancy than simple select. Therefore I recommend checking the columns type using the pragma table_info(table) command for every view:
1234567
sqlite> .head on
sqlite> .mode column
sqlite> pragma table_info (v);
cid name type notnull dflt_value pk
---------- ---------- ---------- ---------- ---------- ----------
0 test 0 0
If the type of a column is undefined and you need to use this column in your selection arguments, you should add the UNION with an empty row with well defined column types:
1234567
sqlite> CREATE TABLE types (i INTEGER, t TEXT);
sqlite> CREATE VIEW vfix AS SELECT i AS test FROM types WHERE 1=0 UNION SELECT * FROM v;
sqlite> pragma table_info (vfix);
cid name type notnull dflt_value pk
---------- ---------- ---------- ---------- ---------- ----------
0 test INTEGER 0 0
Last weekend I have found some time again to work on the MicroOrm. Basically it’s something like google-gson for Android database types – Cursors and ContentValues.
With help from +Mateusz Herych and +Bartek Filipowicz I have, hopefully, finalized the API of the v1.0. The initial draft of the library supported only basic field types: primitives and their boxed equivalents and of course strings. The current version allows registering adapters for any non-generic types. +Mateusz Herych added also the @Embedded annotation which allows easy nesting of POJOs which are represented by multiple columns.
Those two mechanisms should allow you to write the entity objects for almost any data structure you have.The only unsupported cases are generic entities and generic fields in entities. I decided to leave them out of the first release, because due to type erasure in java the implementation is not straightforward and I don’t have such cases anywhere in my code anyways.
The next step is using the library in the existing project. I intend to use it in Base CRM, which should be sufficiently large project to reveal any MicroOrm’s shortcomings.
About once a month I interview potential employees at Base CRM. The nice thing about this is that I usually learn a thing or two. The not-so-nice thing about it is that sometimes you have to tell someone that there is much they have to learn.
At this point most of the candidates ask “OK, so what else should I know?”. I used to give some ad-hoc answer for this question, but it’s not the best idea, because I tend to forget to mention about some stuff; and even if I don’t miss anything, the candidate probably won’t remember half of what I said because of the stress accompanying the job interview.
Anyways, I decided to write down the list of Android learning materials, blogs, libraries, etc. I recommend reading about.
Android basics
Some people’s Android knowledge can be summed up as “Activities + AsyncTasks”. That’s not enough to write anything more complex than Yet Another Twitter Feed app, so if you seriously think of being the Android developer, go to http://developer.android.com/guide/components/index.html and fill the gaps in your education.
At the very least you should also know about Fragments and Loaders. If you want to persist the data, I recommend using the ContentProvider. It looks like a hassle to implement at first, but it solves all the issues with communication between Services and UI. While we’re at the Services: you should know the difference between the bound Service and started Service, and you should know that most likely all you need is the IntentService. You should also know about BroadcastReceivers, and what is the ordered broadcast and sticky broadcast. Pay attention on what thread the different components operate.
Last week I had to write some fromCursor() and getContentValues() boilerplate. Again. I finally got fed up and decided to write a library to replace all the hand rolled crap.
You may ask, why not use some existing ORM solution? There are plenty, five minutes with Google yielded these results:
The problem is, all those solutions are all-or-nothing, full blown ORMs, and all I need is the sane way to convert the Cursor to POJO and POJO to ContentValues.
And thus, the MicroOrm project was born. The public API was inspired by google-gson project and is dead simple:
I’d like to keep this library as simple as possible, so this is more or less the final API. I intend to add the MircroOrm.Builder which would allow registering adapters for custom types, but I haven’t decided yet to what extent the conversion process should be customisable.
The elephant in the room is obviously the performance. Current implementation is reflection-based, which incurs the significant overhead. I did some quick benchmarking and it seems that the MicroOrm is about 250% slower than the typical boilerplate code. Sounds appaling, but it’s not that bad if you consider that a) the elapsed time of a single fromCursor call is still measured in 100s of microseconds and b) if you really need to process a lot of data you can fall back to manual Cursor iteration. I’m also considering changing the implementation to use code generation instead of reflection, similarly to Jake Wharton’s butterknife, which should solve the performance problems.
In the following weeks I’ll try to adapt the Base CRM code I’m working on to use the MicroOrm, and I expect this project to evolve as I face the real-life issues and requirements. All feedback, comments, ideas and pull requests are more than welcome. You can also show the support by starring the project on Github.
The Google I/O 2013 has come and gone and one of the many things left in its wake is the new revision of Android SDK Tools and ADT plugin for Eclipse. If you haven’t let Eclipse go in favor of new hot Android Studio (which is what Mark Murphy, a.k.a. commons guy, recommends BTW) and you upgraded to the latest Android SDK Tools, you’ll probably have some issues with building your old projects.
After installing all the updates from Android SDK Manager and updating the ADT Eclipse plugin your projects will simply fail to build, with the errors pointing to the R class in gen folder. If you try to build the project with ant you’ll get more meaningful “no build tools installed” message. After re-running the Android SDK Manager, you should see an additional item in Tools section called Build-tools. Go ahead and install it.
Now your project will build (you might have to restart the Eclipse), but if you use any external libraries from your projects libs directory, your app will crash on the first call using this libs. To fix this you have to go to the project Properties, Java Build Path, Order and Export tab and check the “Android Private Libraries” item. The previous name for this item was “Android Dependencies” and apparently the build rules for those two are not updated correctly.
Of course new projects created with revision 22 of Android tools doesn’t require jumping through all those hoops.
I just spend few hours analyzing and fixing a memory leak in Android application. With every orientation change the full Context, including the whole Activity was leaked. Long story short, the problem was caused by misuse of CursorAdapter: in subclass constructor we called CursorAdapter(context, null, false) instead of CursorAdapter(context, null, 0).
The difference is quite subtle. If you use the second constructor, you have to take care of handling content updates yourself. If you use the first constructor, the CursorAdapter will register an additional ContentObserver for you, but you need to manually reset the Cursor.
The funny thing is, this behavior is described in javadocs, but the documentation is spread between the constructor and FLAG_REGISTER_CONTENT_OBSERVER flag documentation. The second part contains most crucial information: you don’t need to use this flag when you intend to use your adapter with CursorLoader.
Of course there is such field in this class, it works on every other Android hardware I have access to. This was a debug build, so it couldn’t have been the Proguard issue. The other functionality from the com.google.i18n.phonenumbers package worked fine, the issue only appeared if I wanted to format a phone number using this specific format.
Long story short, it turns out that some old version of libphonenumber, which doesn’t support this particular phone number format, is included in the Android build on my 3.2 device. You can verify such thing by calling:
inside a project without any libs – on this single 3.2 device it will return the valid Class object, on every other device I tried it throws ClassNotFoundException.
I started to wonder if any other libraries are affected, so I picked up some class names from the most popular libraries (as reported by AppBrain) and it seems there might be a similar issue with Apache Commons Codec jar. Fortunately there are no issues with stuff like Guava, GSON or support lib.
What’s the workaround for this issue? Fork the library and change the package name.
Every time I work on the UI of Android app I get the feeling that there is either something terribly wrong with the Android UI framework or with my understanding of how it works. I can reason about how the app works on the higher level, but I cannot apply the same methodology to Android UI, except for the simplest designs. I have read a lot of Android source code, I have written few dozens of sample-like apps, but I still cannot just think of the views structure, type it in and be done – for complicated layouts with some optional elements (i.e. which are sometimes visible and sometimes gone) I need at least few attempts and, I confess, sometimes I’m desperate enough to do the “let’s change this and see what happens” coding. Extremely frustrating.
I’m going to describe my struggles with Android UI on this blog, so if I’m doing something terribly wrong, hopefully someone will enlighten me by posting a comment; and in case something is terribly wrong with Android UI framework, I might be able to help other programmers in distress.
Today I have a simple task for you: create a button with some text and icon to the left of the text. The contents (both icon and text) should be centered inside the button.
That’s simple right? Here’s the XML layout which comes to mind first:
Someone decided that compound drawables should be always draw next to the View’s padding, so we have to try something else. For example TextView centered inside the FrameLayout.
Almost there, but the text has a wrong size and color. There is something called textAppearanceButton, but apparently it’s not what the Buttons use:
OK, so let’s use the buttonStyle again, this time on TextView:
Now we need to get rid of the extra background, reset minimum height and width and make it not focusable and not clickable (otherwise tapping the caption won’t have any effect):
We’d really like to use is something like textAppearance="?android:attr/buttonStyle.textAppearance", but there is no such syntax. How about extracting all the attributes from TextView into some buttonCaption style with ?android:attr/buttonStyle parent? No can do either: you can only inherit your style from the concrete @style, not from the styleable attribute.
But what we can do is to use Button and create a style with no parent: Android will use the default button style and apply our captionOnly style:
Last November I wrote about the new feature in rev11 of Android support package – Fragments nesting. Recently I had an opportunity to use this feature in practice and I’d like to share my experience with it.
The basics are simple: each FragmentActivity and each Fragment has it’s own FragmentManager. Inside the Fragment you may call getFragmentManager() to get the FragmentManager this Fragment was added to, or getChildFragmentManager() to get the FragmentManager which can be used to nest Fragments inside this Fragment. This basic flow works fine, but I have found two issues.
If you have a Fragment with nested Fragments and you save its state with saveFragmentInstanceState() and try to use it in setInitialSavedState() on another instance of this Fragment, you’ll get the BadParcelableException from onCreate. Fortunately it’s an obvious bug which is easy to fix: you just need to set the correct ClassLoader for a Bundle containing this Fragment’s state. There is a patch for it in support library project Gerrit, and if you need this fix ASAP you may use this fork of support lib on Github.
The second issue is related with the Fragments backstack. Inside each FragmentManager you may build stack of Fragments with FragmentTransaction.addToBackStack() and later on use popBackStack() to go back to the previous state. Pressing hardware back key is also supposed to pop the Fragments from the back stack, but it doesn’t take into account any nested Fragments, only Fragments added to the Activity’s FragmentManager. This is not so easy to fix, but you may use the following workaround:
Quick explanation: together with the actual backstack entry we want to add, we also add the fake backstack entry with empty Fragment to top level FragmentManager and set up OnBackStackChangedListener. When user presses hardware back button, the fake backstack entry is popped, the backstack listener is triggered and our implementation pops the backstack inside our Fragment. The backstack listeners are not persisted throughout the orientation change, so we need to setup it again inside onCreate().
Note that there are two issues with this workaround: it allows adding only one backstack entry and this setup won’t be automatically recreated from state saved by saveFragmentInstanceState() (fortunately it does work with orientation change). Both issues probably can be solved by some additional hacks, but writing workarounds for workarounds is not something I do unless I really have to, and in this case I neither issue affected me.
Besides those bumps the nested Fragments are a real blessing which allows much more cleaner and reusable code.
Recently I wanted to open a markdown email attachment on my Nexus 4, but after clicking “readme.md” instead of seeing the file contents I saw this message:
I downloaded few apps from Google Play, but the message was still appearing. The same applications could open a local markdown file, so I went back to GMail app to download the attachment, but another unpleasant surprise awaited me:
There is no “overflow” menu on the attachment (see the screenshot below), which means I couldn’t access the “Save” option, so I could open it as a local file.
At this point I was:
Pissed off, because, cmon, GMail is probably the most used app working on the mature operating system and I can’t download a fucking file with it.
Curious, because it looked liked an interesting issue with GMail app.
The first clue was in the GMail logs in the logcat:
Note the Uri: there is no file name and no file extension, and the mime-type is a generic application/octet-stream (most likely because the “md” extension is not present in libcore.net.MimeUtils). The markdown viewers/editors I downloaded probably register intent filters for specific file extensions, so they don’t know they could handle this file. It sucks big time, because it means that the applications for viewing files with non-standard extensions would have to register for application/octet-stream mime-type, and even though they handle very specific file types they all appear in the app chooser dialog for many different file types, which defeats the whole purpose of Android Intent system and reduces the UX.
My first idea was to create an “GMail Attachment Forwarder” app which registers for any content from GMail, gets the attachment mail by querying the DISPLAY_NAME column on the Uri supplied by GMail, save this information along with original GMail Uri in public ContentProvider, and start the activity using Uri exposed by my ContentProvider which does contain attachment name. This ContentProvider should also forward any action to original GMail Uri.
Unfortunatly I was foiled by the ContentProvider’s permissions systems: the Activity in my app was temporarily granted with the read permissions for GMail’s ContentProvider, but this permissions did not extend to my ContentProvider and the app I was forwarding the attachment to failed because of the insufficient permissions.
This approach didn’t work, but having a catch-all handler for GMail attachments unlocked the attachment actions. I also noticed that when the attachment is downloaded, the GMail uses a slightly different intent:
This led me to plan B: have an app which enables the attachment download and use other apps to open downloaded attachments. I renamed my app to GMail Attachment Unlocker, cleared the manifest and source folder leaving only a single, automatically closing activity:
The full source code is available on my Github (althought there really isn’t much more than what is posted here). In the end I also ended up writing my own markdown viewer (source code in another repo on my Github), because none of the apps I have downloaded properly rendered tags (hint: you have to use WebView.loadDataWithBaseUrl instead of WebView.loadData).