Monthly Archives: November 2014

Fixed coding problem, found a new one.

Yesterday I wrote about a problem I had in figuring out how to add images to the app in a certain way.

Today I found the solution. My attempt yesterday was to put the images in the drawable folder, I needed to get bitmaps of these images in order to copy them to a new folder. This took about 10 seconds. Today I’ve put the images in the assets folder, and now I can use a different method to copy the files to a local folder.

This link helped me out:

Yay, problem solved. So now I thought I would do some extra tests and put the app live.

Emulate Nexus 10

I have a Nexus 7, and it makes sense to test the app on a bigger tablet. So I use the emulator for that. The emulator crashed a couple of times, but once I figured out I needed to restrict the amount of RAM the emulator could use I was good to go.

So I open the app, click on my book, and I get my first crash. The error points to a place that I was afraid it would. First I need to explain something that the Android team forgot to build.

The goal: Add a button above a grid of book covers. If the user scrolls the grid, the button must scroll with it out of screen. Once the user clicks a cover, it must open the correct book. If the user does a long press, the user can select view/edit/delete book. 

Grid, button on topIf I would like to do this for a list. The code would be quite simple. With the key piece of code looking like this: MyLayoutView.addHeaderView(header).

For a grid, there is no ‘addHeaderView’ method. The people at Google must have found this annoying when they created their Google Photos app back in 2013, so they made some custom code to fix the problem for their own app. Then they shared this piece of code, as you can read in this stack overflow post.

There also is a popular library shared by Etsy. But it doesn’t include the long press functionality.

First a little rant: I can’t get my head around that there where developers at Google working on their photos app and noticed that a piece of basic android code was missing for the gridview and then only fixed it for themselves. By only sharing the code, without documentation, it becomes clear that they don’t care that beginning developers might find a subclassed gridview implementation an extra hurdle to take.

Besides that it’s stupid that it’s not part of core Android to add an header to a gridview, the solution created by Google appears to be broken. When I click a cover, it refers to the wrong book. After some testing, it became clear that the number of columns was effecting what ID I was sending when I clicked a cover. Part of the ‘fun’ of having to implement the a subclassed gridview, is that the counting of columns methods was no longer working. I needed the number of columns to be able to get the correct ID to refer to the correct book.

I ended up with measuring the width of the screen, and using the width of the column to count the number of columns by hand. Not super elegant, but it works. Or, as I should say now, it worked.

Apparently something is different in Nexus 10, so it doesn’t work anymore.

Here are my options:

  • Use a listview
    This would amount to admitting defeat.
  • Use a gridview, drop the long press, and use the library provided by Etsy
    This would also amount to admitting defeat.
  • Use a listview, and simulate a gridview by adding a multiple covers for every row (list view item)
    This would probably work, but it’s not clear to me yet how I would deal with different screen sizes (landscape / portrait). It’s probably quite some work for me.
  • Try to find a different library that can add a header
    I might try this, but I don’t expect to find something that is tested on a lot of devices and use cases.
  • Try to change my code somehow to circumvent the issue
    The core of the problem is that I don’t understand why the solution Google brought me is giving me problems. And this has to do with that I don’t understand how that piece of code is working, because I’m rather new at coding in general. So figuring out how to work around a problem that I don’t understand is rather difficult.
  • Launch the app only for Nexus 7 (2013)
    I know it works on this device, because I have one. The upside is that I get to launch the app and will be able to get feedback on it. I can then update the app and include more devices later on.
  • Do more testing on the emulator to try to better understand what is going on for the Nexus 10
    I’m trying to do this, but my computer is having major problems with running the emulator, my browser and Android Studio. It works, but it takes me about 10 minutes to see an update to the app and being able to test it. Also Android Studio is becoming slower and slower. To make it more fun, logcat (the way you get feedback on crashes) is no longer filtering for my app, so I need scroll through a whole bunch of not relevant logs to find out what’s going on.
  • Go to sleep, and see what tomorrow brings
    Just to be clear, this is my non-day-job-side-project so I won’t be able to really delve into this tomorrow. I’ll probably go with launching for Nexus 7 only tomorrow.

So why am I sharing all this?

  1. I want to give a full picture of what it takes to create these apps. I wrote about the concept, the UX, the analytics, marketing, graphics, but I haven’t written a lot about the coding part yet.
  2. I’m hoping that in writing down what my problem is, it will become clearer to myself how to find a solution.
  3. I’m a bit frustrated and felt the need for a little ranting. I’m so close to launching the app..

Yep, now it’s time to go to sleep.

Update 19 nov

I fixed it, at least for the Nexus 7 and the emulator for Nexus 10. The next day I had a computer restart, and with a more responsive computer I was able to do some testing on the emulator. My ‘counting by hand’ of the columns was not working correctly because I was taking a too small measurement of the column.

Simple things sometimes seem so difficult in Android development

For those interested, I’d like to share an example of how difficult it can be to get something done that seems to be simple.

The goal: include a number of images in the app, store the location of the images in the database.

I’ve created a picture book app, where users can create and edit picture books based on their own images. I store the images in a folder inside the app, and keep track of these files in a database. Now I want to provide one picture book with the app, so the bookshelf isn’t empty.

To break it down I want to:

  1. Add images to my project, probably somewhere in the resources folder
  2. When the app starts for the first time, I want to create records in the database that refer to these images. So a book can be created, just like a book that the user can create.

To lighten up this somewhat depressing post, here’s one of the images in the book.

Titan Moonbase

So this gives me two main questions:

  1. In what folder do I need to store the images?
  2. How do I store the paths of these images in the database?

Starting point: Android documentation
First let me try to find an answer to my first question; where to store the images.

It seems I have (at least) three options:

  • The assets folder
  • The drawable folder inside res
  • The raw folder inside res

Too bad it is not explained in the documentation when to use what folder. The documentation seems to assume that I want to access the files, but don’t care about the path. Here’s the most informative part for my quest, at the section explaining the ‘raw’ folder.

What I’m missing is the high level concept. Why does Android have these layers between files and code? Why not just have a folder and a way to refer to them.

Conclusion question 1) I don’t know where to put the images.. so I’ll just put it in the drawables folder.

Now let’s try to investigate how to access the resources later on:

It explains that for all the files included in resources, such as the drawable files, have a unique ID referring to it. It then goes on about how you can access those files in code (r.string.hello) or via XML (/@string/hello).

I have used this way to access files many times before. But now I become aware how much of this is a black box. For instance, what is the path to the launch icon file of my app? I have no idea where it is actually stored.

Since the official documentation didn’t seem to help me, I tried googling for answers. I ended up with stack overflow pages like these:
“..But it sounds like you don’t really need a path to asset files. You should look into these functions..   ..These functions allow you to get input stream or file descriptor for any of your assets. Here is an example:”

And this is where I get stranded on all these stack overflow pages. Every time I find someone who seems to ask exactly the same question as I do, the answer ends up saying that it’s smarter not to use the path but some other way to access these files. And since this is not my goal, I’m stuck again.

Conclusion question 2) I don’t know how to access these files. My mental model of how Android works is probably flawed in some ways.

Now what to do?

  1. Copy all images to a folder inside the app
    One way to go about this, is that I use the access of the files to make a copy to a folder and use that path to store in the database. But that would make the app quite slow when it first starts and has to do all the copying. I feels like it should be much easier to do this. I know I can include images and even show them, so it shouldn’t be difficult to store a reference to the file.
  2. Keep Googling, hoping to find an answer
    I’ve tried this for a couple of hours, and it hasn’t brought me as much as I hoped..
  3. Launch the app without an example book.
    This is not an option, since I believe it is needed for a good experience. Also I’ve spent 40 hours drawing the book, so not using it would make me sad.
  4. First learn more about the inner workings of Android
  5. Hard code my example book
    Just don’t use the database, and store it inside variables. While this sounds nice, it breaks the ‘edit’ mode of the book. Also I am stubborn enough that I now want to know how to do it properly and not circumvent it.

So I ended up with going for #1 making a copy of all files. Creating a bitmap for every image using BitmapFactory.decodeResource, and then storing it in the correct folder using Bitmap.Compress. This takes at least 10 seconds, so I have to put it in an async task.

Now I need to figure out a way to let the user know it needs to wait about 10 seconds and just do nothing so I can create a book for them.. Quite a horrible way to experience your first 10 seconds of the app. So for now I’ll just go to sleep and see if I can think of something better later this week.

Working on picture book for inside my app

Version 1.0 of my picture book app is done, so it’s almost ready to put on Google Play.

I want to include one book inside the app that shows the purpose of the app. It’s about two characters who are going to travel and need to select what book to take along their trip. I’m using the Bamboo Paper app by Wacom to draw the pages.

Here’s a preview of one of the books the characters might take on their trip: