Category Archives: My Picture Books

Android app for creating and reading picture books, based on your own pictures and audio.

Update My Picture Books app – Export books with a zip

It has been over a year since I updated My Picture Books.

MPB StatsFebr 2016

You can see that with about 350 active users this app needs a little love and attention. So I went over the feedback to see how I could best improve the app.

Comment on this blog:

Sinisa commented”.. Also, option to export as PDF will be awesome, or even better if you can export with all features as in app. I mean with audio, text and pictures. Importing other books will bring this app to new level…”

Reviews on Google Play

Sherry San Diego: “I’d like to have the option to keep my work in private & at the same time, be able to share my books (or the links to my books) to others if I want to.”

Gabby D: “I wish I could be able to share it”

Chandra Praba “Amazing app. How can I share my book..”

Exporting your books

As a first step towards sharing, today I added an export feature. The app will create a zip file that contains all images, audio and HTML files to display the books. You can for instance send it via e-mail or store it in your Dropbox folder. For this update, the HTML file is very basic, there is no page flipping, you just scroll to see the pages.

Play audio on Chrome browser

You can also play the audio you might have recorded with a page, but not all browsers can handle the file type that is used. The means you have to use Chrome if you want to listen to your recordings.

There is not yet an import feature, but I created a JSON file that will make it easier to add this in the future.

Download the Android app here. Let me know what you think!

Lovely feedback on my My Picture Books app

It has been a while since I did any work on My Picture Books. It’s always a nice to get some feedback in my inbox. Carlos gave me an ok to share it here:

It’s a great app, very easy to use. My little students (5&6 years old) are able to create their own albums.

I’d like to suggest you only one thing. If you can to make an option to share the albums it will be the perfect app.

If you don’t know the app, here is a quick introduction:

Really great to learn that children of that age are able to use the app. Being able to share, or even export your books requires quite some work, and I’m not even sure how to best go about it. But it got me thinking about the app again.

Like with Idea Growr, the app doesn’t have an online back-end, so I’m first looking into what can be done in the device. I’ll try to create a little prototype that at least will be able to export an HTML file with images and figure out if that works.

Option A or B for the promo image on Google Play, what do you think?

I made two options for the promotional feature grahpic on Google Play for My Picture Books. It’s the graphic that is shown at the top of the app page in the Google Play app.

Option A

MPB AOption B

MPB BWhat do you think?

The thought behind both graphics is that I wanted to visualise how the app works in simple manner. I first created option A, I think it’s nice that the book sort of pops out. Then I created option B, that seems more balanced and easier on the eye.

Working on adding audio feature to My Picture Books

I’m working on adding audio to My Picture Books app for creating and reading children books, based on your own photos.

Route 1: using an intent to record audio

My first attempt was to use Android systems of ‘intents’. An intent in android is something that is used to communicate with other apps. For instance for editting images, the app uses a certain intent, the user is asked to pick an app to edit the image. After the editting is done, my app receives the editted image from the other app.

Intents work like this, the app shoulds the name of the specific intent, and then Android gives back all the apps that say they can do something with that intent. And I was happy to learn there is an intent for connecting with an app that record audio. The intent is as follows:

When testing on my mobile phone everything went great. After completing the update of my app, I wanted to do a little test on my tablet and then put the udpate live that evening. The test revealed a bit of a setback. It appears that not all phones and tablets have apps that can deal with this intent. So for some user it would not be possible to record audio.

Route 2: Still use the intent, but advice users to download a specific app for audio recording. 

As a first update, testing out if people would appreciate an audio feature, I thought it might be good enough to just advice people to download app X to record audio. So I started to look for apps that could receive the RECORD_SOUND_ACTION.

Finding a valuable answer to this question using Google is hard. Too hard. Try searching something like “android app for recording audio receiving intent record_sound_action”. You get results like this on StackOverflow that don’t include an answer to my problem.

Since Googling failed me, I downloaded a whole bunch of audio recording apps. Only one of them accepted the intent, but it had annoying ads and I was not comfortable with recommending people this app.

Route 3: Code a simple audio recorder myself

So now I’m back to the coding board, coding my own audio recorder. It’s not super difficult, but still it requires learning some new code, creating a new interface and doing extra tests. It’s probably about 8 hours of extra work for me, while I was hoping to put the update live at the beginning of this week. On the other hand, I’m learning new stuff, and that’s sort of the whole idea of these pet project; creating tools and learning new stuff :).

A new goal emerged

After testing a number of audio recording apps, it struck me that there are quite a lot of recorders with advanced features, but they are paid apps or have ads. But it’s not easy to find a super simple audio recorder that only does record, stop, play, save. So I’d like to fill this void, and I can combine it with my ambition to learn how to implement material design. This can be my next little pet project. A super simple, but good looking one screen app to record audio quickly. And it would accept the RECORD_SOUND_ACTION intent :).

In case you are wondering, learning these new skills like dealing with images, audio and material design, are all part of the bigger plan to do a major update on Idea Growr. More on that later.

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: