A couple weeks ago, two events coincided: 1) I was getting fed up with the recipe app I was using and 2) my wife was taking an online course in Android app development.
The recipe app I was using (I won’t mention it by name, but pick one at random; they’re all pretty much like this) did OK for a free app. You could type in recipes, view them, and share them. But it had some annoying behaviors.
If you happened to tap on the left or right edge of the recipe you were viewing, it’d flip to the previous or next recipe in the list. I understand this is supposed to simulate turning the pages of a book but, seriously, who wants or needs that? I can’t count the number of times I accidentally flipped from, say, “Chickpea Curry” to “Chilaquiles Brunch Casserole” in mid prep. “Add in the chickpeas, garlic, garam masala, curry … tortillas where you’d like each egg to go.” Yeah. Not helpful.
On top of that (like, literally on top), the app is ad-supported. Fine, OK, gotta pay the bills somehow, I guess. But the ads, which normally behaved themselves and sat quietly down in the bottom sixth of the screen, would suddenly, without warning, fill half the page. This seems to be designed to get users to accidentally click through on ads while scrolling through a recipe. But, see, you know what I’m usually doing when I’m scrolling through a recipe? Cooking. I don’t have time to learn more about somebody’s “all-natural meats” while my roux is threatening to turn into a scorched, lumpy mess.
So, overall, not a great user experience.
That leads us to event #2. Amanda was taking an online course on Android development. Every so often I’d listen in on the lessons, and I’d pick up some of the terminology: Activity, Intent, Fragment…
I got to thinking maybe I should try making an app. A recipe app, specifically.
I had a pretty good idea of what I wanted…
- List recipes by name
- View and edit a recipe
- Paste a plain-text recipe into the app, and have it break it up into title, ingredients, directions.
- Backup and restore the entire recipe collection in plain-text, human-readable format.
Nice To Have
- Share one recipe, or the entire collection (IM, email, etc),
- Convert a recipe from imperial units to metric, and vice-versa.
- Scale the recipe by changing the number of servings, and have the ingredients update in a meaningful manner.
- Capture a recipe from a saved image or the phone’s camera, and convert that into text.
About that “update in a meaningful manner” thing… This stems from a recipe for fried rice that I acquired some time ago. One of ingredients was “6 tbsp soy sauce”, to which I said, “oh hell no”, scratched it out and wrote in “1/3 cup”. Close enough.
That was an important feature for me. The last thing I wanted was a 2-serving recipe for chili that uses 1 tablespoon diced jalapenos to say 8 tablespoons when scaled up to 16 servings. It should say 1/2 cup, dammit.
So, where to start… Install Android Studio and start playing?
Yikes. OK, sure, I was familiar with IntelliJ, which Android Studio is based on, and I’ve been programming in Java pretty much since it existed, but developing an Android app is a different animal entirely. There’s all sorts of plugins and libraries and settings to deal with. And the prospect of laying out an app screen so that it’ll look OK in both portrait and landscape mode, on a wide variety of devices was a bit daunting.
Tip: Learn how ConstraintLayout works, then bash your head against it until it does what you want. After that, it’ll be your best friend. Even then, you’ll change one parameter, and all your buttons will jump to the upper-left corner of the screen. Friends can be like that sometimes.
Once I got the main visual logistics out of the way, I started working on the logic behind the screens.
Just sifting through a block of text, and slicing it up into title, ingredients and directions isn’t too hard, as long as the text is formatted nicely. I started off looking for keywords, like “ingredients”, “you will need”, “directions”, “instructions”, “preparation”. Failing that, I looked for blank lines between the sections. Failing that, I grabbed the first non-blank line as the title, then scanned through the remaining text for anything that looks like an ingredient. End result? Works OK most of the time.
The image capture and text recognition wasn’t terribly difficult. Turns out there’s something called TextRecognizer that you can import and use. It does most of the work for you.
What turned out to be much more difficult was sharing the recipe collection. I figured, how had could that be? Convert all the recipes to plain text, and attach them to an email, right? Yeah, not so much. In order to attach a text file to an email, you have to save it first. And Android really doesn’t want just any old app poking around in their file system. You have to specify that you’re going to require file permissions, indicate the exact path that you want to read and write, and then, when the app actually runs, you have to ask the user for permissions to read and write files. I think that’s all there was. Might’ve been something about sacrificing a goat to the File System gods, or maybe staring into a mirror and chanting “Gary Kildall” three times. My memory of the ordeal’s a bit hazy.
And then there’s the whole bit about converting measurements that are in the middle of the directions. Honestly, I should’ve left that alone. I shouldn’t just said, “Hey, work it out for yourself.” But, no, I had to go and try it. Think about it: any of the following are perfectly valid phrases in recipe directions.
- add 1 cup marinara
- add 1½ cups marinara
- add 1 1/2 cups marinara
- add 1-1/2 cups marinara
- add 1.5 cups marinara
- add another cup of marinara
Trying to parse through that leads you down a rabbit hole where you’re wrangling regular expressions that look like Alan Turing and Julia Child got stoned one night in Amsterdam, and tried to invent a computer using kitchen gadgets.
I think I’ve got it right now. Of course, I’ve said that four times before, and been wrong. Every so often, I’ll be playing with the number of servings and something like “add 2/3 1/1.5 cups marinara” will show up. FFFFFFFFUUUUUUUU….
And there’s still the problem of whether you should scale up an ingredient in the directions. If you’re scaling a small lasagna into a big lasagna, the amount of sauce you want to use per layer should increase. If you’re scaling two calzones to eight calzones, the amount of sauce you need per calzone shouldn’t increase. I still haven’t worked that one out.
On the other hand, I did get the app done (more or less) and it does work (more or less). At the very least, it’s really satisfying to be able to open up an old binder, point the camera at a page, and have it just work.
Two weeks after I started, I felt the app was good enough to put up on the Android app store. I was wrong, but I put it up there anyway. Now, a week after that, it’s in pretty good shape. I think.
If you want to try it out, it’s available here: Recipe Wizard.
I promise, it’s safe. It’s free. There’s no ads. It doesn’t share, or even look at personal info. All it cares about is recipes. No, seriously, if someone used the app’s camera mode to take a picture of you dressed up as Frank-N-Furter, it wouldn’t even react unless you were holding a recipe card.
And, before anyone asks… No, I won’t be doing an iOS version. But, if some else wants to take a stab at it, I’d be more than happy to share any algorithms that might help.
- I think I’ve figured out a solution to the issue of scaling measurements within the directions (lasagna vs calzones). A new release should be rolling out shortly that incorporates a “magic” button that lets the user pick which measurements should stay the same.
- I’ve received a report of a crash on a Lollipop tablet. The device randomly hard-reset itself. Not entirely sure if the app was responsible, since it wasn’t running at the time. Would be interested in feedback from people with other devices running Lollipop, Marshmallow, Nougat and Oreo.