When I prepared my Android Layout 101 talk, I looked for an easy way to put my slides online. I started with Landslide because it has a lot of options: table of contents, speaker notes, export to pdf etc. But then I hit a major limitation: I wanted to show xml files with certain words highlighted. Since Landslide generates syntax-highlighted html with pygments, there is no easy way to add custom style. This was a tie-breaker for this particular talk I need the answers highlighted within the xml context.
I looked around some more and settled with the Google HTML5 slide template. I edit the html directly, and syntax highlighting is done by javascript, so I can layer my own css style on top. I really miss the compact Markdown syntax for Landslide, but the flip side is that I lose fine styling control.
A bonus for using the Google HTML5 slide template is that it works with my wireless presenter, so I can be anywhere in the room. Very convenient.
We started with the Hello World app, gradually introducing more and more layout types and attributes. From time to time I showed a screenshot and asked everyone to modify the xml file to achieve the same layout.
"hmm... how I do get the buttons to go to the second line?"
By the end of the workshop we were implementing this screen:
This can be done with either LinearLayout or RelativeLayout. The LinearLayout version uses a nested horizontal LinearLayout to specify the second row, with android:gravity="right" to scoot the buttons over. One of the students, Anne, went on to experiment with setting android:layout_gravity="right" on the buttons themselves, but that did not work. We were quite baffled.
Turns out android:layout_gravity="right" is only honored by a vertical LinearLayout, not horizontal one. I guess the LinearLayout expects to put down one View after another horizontally, so if it puts the first button to the right, the second button would have nowhere to go. As a result it simply ignores the layout_gravity attributes. Still, it was rather confusing, and it is precisely the kind of nuance you only find out when you get your hands dirty.
The screenshot exercises gave everyone a chance to put theory into practice, and see how the elements interact with each other. You can try them as well. Just go to http://www.sqisland.com/talks/android-layout-101. Even if you are already familiar with the basic layout components, you may still want to check out puzzles at the end. Some of the solutions may surprise you!
Puzzle Pal caters to puzzle aficionados who want a little help, but often people download it without reading the description, and get disappointed because it is not a game. So I am always elated to read a review of someone who appreciates it. Today I saw one in the NOOK store:
If you use an app and you like it, go write a nice review. That's what fuels developers to create even more awesome apps!
I have always been intrigued by the idea of programming for good, and tried many times to contribute to open source projects. Finally I got my acts together and attended Random Hacks of Kindness this weekend.
As my newbie, my goal was simple: observe how a charity hackathon is run, contribute whatever I can. Random Hacks of Kindess maintains a list of project proposals at the website, and we could use that as a starting point. However, the site was down during the day. Fortunately some people came with project ideas, and we heard 6 people explain their projects. We then split into groups, essentially interviewing the different projects to figure out which one was want to spend time on.
I ended up working on the project proposed by Sarah Filley, Drop2Drink. Apparently San Francisco uses potable water for fire fighting, so to ensure that there is enough drinking water during an emergency, the City of San Francisco has designated 67 Emergency Drinking Water Fire Hydrants, marked with a blue water drop. Sarah would like to use them as anchors to spread awareness for diaster preparation.
We gathered around and brainstormed. Since the group was quite large, it took a while to hear everybody. While all the talking was happening, Christiaan was typing furiously. He was grabbing the address of the hydrants from a PDF and populating a Fusion Table with it. By the time we wrote all our ideas on the white board, he had a Google Map showing all the hydrants! Awesome. Initially I was a bit worried since there was a lot more talking than doing, but seeing the map made me feel much better.
Lunch came and went, and we split into a few subteams: website, foursquare, tropo and QR code. I was in charge of the dynamic part of the website, generating one page per hydrant. Finally I got to code! I set up an appengine instance, fetched the data from Fusion Table, and populate each page with a row. This serves as the landing page when people click on a map marker, or scan the QR code we were putting on the hydrants themselves.
It didn't take me that much time to set up the base site, but the iterations were a bit slow, mostly because I had a sore throat and I couldn't talk. That turned out to be a huge problem. Since I was there to help with a problem defined by others, communication was really important. I would say the split is 80/20 - 80% talking, 20% coding. And since I couldn't talk, I couldn't contribute as much as I'd like to. By the end of Saturday I actually lost my voice, so I stayed home on Sunday to rest. I really wished I didn't have a sore throat!
All told I had a great experience, and I would probably attend more charity hackathons, knowing that the most important aspect is co-ordination. In a way it's leadership bootcamp: you meet tons of new people, try to figure each person's skill and passion, and align everything to the project goal. It's an interesting challenge.
I attended the NOOK Apps Workshop at App Dev Hackathon, and decided to submit Puzzle Pal to the NOOK store just to see how it works.
Bundle the dictionary
Puzzle Pal was first developed for the G1, which has very little on-device space for apps. This drove the decision to deliver the wordlist in a separate package for storing on SD card. But it makes the initial install a little cumbersome, requiring the user to juggle between two apps. Since the NOOK store has an approval process, I decided it is easier to have a single package with the wordlist bundled. It only adds 1MB to the package, which is not a big deal as long as you are not running the G1 :)
Test on the emulator
I did a round of testing on the emulator from the NOOK sdk. Everything works fine except the about dialog. The AlertDialog on NOOK uses a white background even if you specify a dark theme, so the white text on my about dialog was not visible. I used a WebView to link to the data source for the wordlist, setting the text color with css. With the NOOK, I had to switch AlertDialog.Builder.setMessage so the system can set both the background color and the text color. The side effect is that I could not have clickable links, which is fine. I simply spell out the url.
The many steps of app submission
Now my app is ready, I started the app submission process. Man, there are so many steps!
Upgrade to NOOK App Developer status
I signed up at the Nook Developer Site to download the SDK, but to submit an app, my account needs to be upgraded to developer status. I did not understand why. Fortunately since I attended the NOOK Apps Workshop, I was granted access fairly quickly.
Get the developer account approved
Next I had to fill in tons of information including my bank account and tax information. And all these needs to be approved. Why? I am not even selling anything. I just want to offer Puzzle Pal for free. Again, the saving grace was that it took only a few hours for the account to be approved.
Get the app metadata approved
Finally I got to the point where I filled in the basic information for my app. They wanted a 300x300 icon. No problem, I resized mine that way. A few screenshots with the app running on the NOOK. Fair request, I captured a few. I put everything together, and BAM, the icon was rejected. Why? Because it has a transparent background. What? What's wrong with a transparent background? And oh, it cannot be white either. Why? I ended up adding a random blue gradient background to my icon. But this is so arbitrary.
And now I wait for the metadata to be approved. That didn't take long, because some script rejected it, saying that the description "makes references to the app being for a phone". I was pretty sure I did not do that, but I checked my description text anyway. Turns out I said you can use Puzzle Pal for "phone spell", which is a standard puzzle technique to translate numbers to letters according to the dial pad, e.g. 3569377 becomes FLOWERS. I didn't have the energy to explain that, so I just removed the words "phone spell" from the description.
Get the apk approved
Finally I got to upload my apk! That turned out to be the easy part. No issues whatsoever, the apk was approved within a day.
Check the NOOK store
I was waiting patiently for Puzzle Pal to show up at the NOOK store, which should take 24 to 48 hours according to the status message for my app. A week went by and nothing happened. I filed a ticket to figure out why. Someone responded within a few hours:
Hello! Yes, it's being worked on and hopefully resolved by the end of the week. Stay tuned on this. You've done everything right, we're working on our build system and your account had missing information which is on us.
Very happy that they reassured me that I've done everything right. Also very happy that I pinged them, because I had no idea that my account had missing information.
Two days after I filed the ticket, Puzzle Pal is on the NOOK store today!
I did not expect this to be such an adventure. How I miss the straightforward Android Market! Hopefully they will streamline the process so us developers can focus on producing wonderful apps instead of stressing over getting our apps approved and published.
In The Game a couple weeks ago, one of the puzzles involves replacing a letter in a word to form another word. To my horror Puzzle Pal didn't know how to solve it! I quickly added a new solver and posted an update to the Android Market.
While I was at it, I realized that Puzzle Pal also didn't have a ROT 13 decoder, useful for geocaching, so I added that as well.
I have been looking for secure ways for my Android apps to share data, and was looking into permissions. In particular, the signature level in android:protectionLevel looks really promising:
A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user's explicit approval.
The idea is to have a main app for displaying data, and multiple modules supplying the data. Permissions only work with one of the four application components: Activity, Service, ContentProvider, and BroadcastReceiver. ContentProvider is the logical choice for serving data.
Loading sqlite database from resource
It is a bit of a pain to write a ContentProvider, though. Since all I wanted was to test the permissions, I took a shortcut: I followed this tutorial and loaded a sqlite database from resource. To automate the database creation, I wrote a script to load the data from a tab-delimited file.
Permission setup
It took me many tries to get the permissions right. I know that the <provider> need to request the permission, but where do I declare it? I tried both in the module and the main app, but no luck, the main app could use the ContentProvider no matter how I signed the apps. Turns out it was a stupid error: I declared the permission with the <provider>, inside of the <application> block. It should go outside!
So the formula looks like this:
Declare the permission in the provider app
Request the permission in the provider app
Use the permission in the consumer app
When everything was setup properly, it was very satisfying to see my app throwing java.lang.SecurityException when I sign it with a non-matching certificate.
As I am sitting in the Portland airport waiting for my flight back to San Francisco, I look back at the great times I had at the Grace Hopper Celebration last week. This is my third time attending GHC, and I always come back fully energized. What makes GHC so wonderful? It's all about connections.
Connecting to others like you
It can feel lonely being a woman in a male-dominated field like computer science. Simply being in the same venue with almost 3000 other women sends a very strong signal: you are not alone. As you sit in various sessions, you get to meet people in the same situation as you. You realize that you are a victim of the Imposter Syndrome, that everyone in the room also thought they got to where they are because they are lucky, not because they are good. You chat with the woman sitting next to you at lunch, making a deep connection because both of you are a few years into your job and unsure what to do next. You swap tips, you hear great advice, you share your stories, and you immerse yourself in the solidarity of your fellow women in computing.
Connecting to others unlike you
While it is energizing to meet people just like you, it is also empowering to see women thriving in so many different ways. You see a young professor doing groundbreaking research. You see a mother of six going back to school for a PhD and loving it. You see an executive taking the helm of a large corporation. You see an undergrad leading a non-profit project and making an impact. It shows you that success comes in many different sizes and shapes, and opens your eyes to the possibilities of greatness for yourself.
Connecting to yourself
When was the last time you took time to think about yourself and your career? At Grace Hopper Celebration, you step away from your daily responsibilities and think about the big picture. What I want to do? How do I get there? You are surrounded by amazingly supportive people, helping you recognize your achievements, hearing your fears and concerns, giving you tips and advice, and urging you to take charge of your future. You feel energized because you got to lift your head above the daily grind and see what's out there in the horizon. Your newfound
connections let you know that you are not alone, that others before you have struggled and succeeded, and wherever you want to go, you will get there. It's a wonderful feeling.
One of the first things I did after winning an Android tablet from the AT&T hackathon was to download Puzzle Pal. It worked, but was only rendering itself in a teeny tiny window in the middle. Time to recompile it with the latest SDK so it knows what to do with tablets.
I thought all I needed to do was to recompile, but it still didn't expand to fill up the whole space. Turns out I need to tell it not to run under compatibility mode for tablets in uses-sdk in AndroidManifest.xml:
And then I ran into another issue: the sudoku grid was not accepting inputs. Not quite sure what changed between the SDK versions, but now the view needs to implement TextWatcher and update the grid onTextChanged.
I didn't get a chance to optimize the UI for tablets, so the Braille decoder looks a bit silly. In any case, please grab the latest version from Android Market and let me know if you run into issues.
I met a bunch of Android developers at the AT&T Mobile Hackathon SF, who told me about the App Dev Hackathon at Santa Clara today. Since I had such a great experience at the AT&T one, I decided to attend.
Sponsors and Prizes
Same as last time, there was a list of sponsors and prizes:
Tropo: Amazon Kindle for all members of a winning team that uses the Tropo API in their application.
Pioneer: $1000 cash for the best mobile app using the Zypr API.
appMobi: Amazon gift cards to the most interesting apps using appMobi's SDK. $150 for 3rd place, $350 for 2nd place, $500 for 1st place.
immersion: 5 $100 gift cards awarded to the team that makes the best use of the appMobi plugin.
Rovi: Two $500 Amex gift cards for best apps using Rovi APIs.
Sierra Trading Post: Use the Sierra Trading Post API. $1000 cash + 5x$100 Sierra Trading Post gift cards for best app, $250 cash + 5x$50 Sierra Trading Post gift cards for most creativ app.
Crittercism: Use Crittercism SDK. Top prize: Kindle Fire. Runner up: Automatic Nerf Gun.
HTC: Best app with the pen api wins the AT&T Jetstream tablet.
Guess I got lucky, since I have two existing apps that play very well with two of these APIs.
Dr Mila
A few months ago I went to SuperHappDevHouse and wrote an email gateway to Freebase. The idea was that when I travel, I often need to look up something when I don't have internet: an artist from the magazine on the plane, a signpost on the road to a tourist spot, etc. I wanted a way to queue up my queries to run when I got to a wifi spot, and it occurred to me that my email outbox is the perfect solution. All I need is a server that can read email, search the internet, and reply with the results. The email client will take care of the queuing, fetching, and offline storage. So I coded that up in an afternoon, and named it Dr Mila, with Mila being an anagram of mail.
The email gateway works this way: you send an email to ask@drmila.com with your query as the subject line, and Dr Mila replies with information from Freebase, sending images as attachments. I wanted to use Tropo to add an SMS gateway to the service.
At the presentation Tropo mentioned that if all I needed was SMS, I should use some other service instead. I didn't catch the name, so I went to their table right away. The "other service" is Smsified, also provided by Voxeo, the parent company of Tropo.
I managed to receive SMS pretty easily, but sending didn't work. Back to the table, and Adam from Tropo debugged it with me, using curl. And it didn't work because I did not provide any authentication. I was wondering about that when I was following the instructions from the message sending documentation. Turns out authentication was covered in Overview, but of course I jumped right into the section that interested me, and missed it. Not a big deal, it was very easy to fix once I knew what I needed to do.
In my first test I just sent the whole article from freebase, and got maybe 12 SMS as a result, because it exceeded the 140 character limit. As a quick workaround I took the first sentence from the description. Most articles have the first sentence as the summary, so that worked pretty well.
Movie Jot
I finished adding SMS to Dr Mila around 1:30pm, so I decided to work on my second app, Movie Jot. The idea is that I want to take advantage of html5 offline storage to quickly record something, and look it up on the internet later. The keen reader will notice that both Movie Jot and Dr Mila share the same offline theme, which is not a co-incidence. I am rather frustrated that most apps assume that my device is always connected to the internet. I decided to target specifically for movies since my friends often mention interesting movies at dinner, and I just want to quickly jot that down instead of spend 3 minutes looking it up on the internet right away.
I had a working version of Movie Jot, powered once again by Freebase. Since rovi has a nice DVD database, I thought I would change the backend to point to it instead.
As I was loading up the rovi documentation, someone tapped on my shoulder. He saw my screen, and wanted to introduce himself since he was from rovi. I took the opportunity to tell him what I wanted to do, and he gave me a quick rundown of generating md5 signatures for the API, and how to fetch images and synopsis. That saved me quite some documentation searching time. I put everything together, and was rather pleased to see that the synopsis quality from rovi was quite a bit higher than freebase.
Sierra Shake
I was done with Movie Jot at around 4pm, and took a break to talk to people around the hall. We had until 6:30pm to enter our apps for demo, and since I heard so much about quick development on appMobi, I decided to give it a shot. I tried to get the XDK, but made the mistake of clicking "Deny" when it wanted to access my hard disk. I went to the appMobi table and they helped me by running javaws -viewer and deleting the appMobi entry so I could restart.
Once I had the XDK up and running, I just stared at it, looking for a place to type my code. Finally realized that the XDK was like the browser, and you use a separate editor to write the html and javascript. Once I realized that I was able to code up my app pretty quickly. Since I didn't have a lot of time, all I did was use the Sierra Trading Post API to display a random product when you shake the phone. Actually I didn't even have time to implement the shake detection, so I just hooked a click event on an empty area to trigger the fetch.
Even though I wrote a rather silly app, I got a chance to see the whole appMobi tool chain, which was quite interesting. It was a Chrome extension that uses Java to access your local file. To test on the device, you download an Android app called applab, and use the mobile browser to authenticate and load the app you want to test. Pretty neat.
Demos
The organizers did not set up a projector for demoing on the device, so it was a little bit tricky. I used the Google Voice interface to show the SMS messages for Dr Mila, and passed my phone around for the judges to test. One of them entered "tears" as the query, and Dr Mila replied with "Tears are the secretions of the glands that clean and lubricate the eyes." Not bad. Movie Jot is an html5 app, so I just demoed it on Chrome on my laptop. For Sierra Shake, I used the XDK, which sufficed.
Prizes
Turns out Movie Jot was the only app using rovi, so I won the prize. It wasn't really a competition when there were no competitors, but hey, I am not complaining. I also won a iPod nano from Tropo, which I didn't even know was on the prize list. Again, not complaining at all.
The only complaint I have for the event was that the tables were way too high for a small person like me. Maybe I should bring a cushion next time. But that's going a bit overboard, no? I already brought a salad for dinner since last time I was starving at the SF hackathon. At this rate I would be lugging along my whole house!
I have not been doing Android development for a while, and decided to get my feet wet again by signing up for my very first hackathon. Most hackathons last until the wee hours of the night, so I was rather excited to find one that was scheduled for 10am to 8:30pm, when I am normally awake. It was the AT&T Mobile Hackathon in San Francisco on October 22, 2011.
Preparation
Since it was a mobile hackathon, I knew I was going to be coding either in Android or html5. Last time I did any Android development was more than a year ago though, so I downloaded the latest SDK and updated my Eclipse setup. I then read through the email from the organizers to see if there were any rules. I didn't see any, because the email mostly consisted of the list of hot sponsored prizes:
Tons and tons of Apple Gift Certificates for the top 3 teams, provided by AT&T and Apigee
Top hackathon team (yes, the entire team) will receive AT&T Mobile Hotspot Elevate devices (wifi pucks) with 1 month of free service courtesy of Sierra Wireless
Amazon certificates for Best App Built with the YP API
The top two apps built with the HTC OpenSense SDK's Pen API will get two exclusive new AT&T Jetstream tablets
Top two apps which leverage the Galaxy S2's GPU the best (can be GPU tweeks for exisiting games) - Two (2) Galaxy S2 - Sponsored by ARM
Top app built with ARM NEON instruction API - ODROID - Sponsored by ARM
The sponsored prizes really reminded me of Iron Chef. The secret ingredient was the API, and the dish was the app. Of course you can also just write any mobile app without using the sponsor APIs, but I thought it was much more fun to compete with a common ingredient. Though I wasn't sure how anyone was going to build an app with the ARM NEON instruction API just like that...
Tables and Talks
I took the Caltrain up, and arrived quite a bit earlier than 10am. They were still setting up the breakfast area and the sponsor tables when I got there. Since I ate already, I went to check out the different sponsors. The HTC table really caught my eyes with their gadget - the new JetStream tablet. Michael from HTC carefully unwrapped one from his towel (!) and showed me the cool apps using the pen. I was hooked, and decided then and there that I my secret ingredient would be the pen api.
As more participants showed up, we were ushered into a big conference room, where the organizers explained the schedule for the day. Each sponsor then gave a quick overview of their api, before we broke for lunch.
Environment setup
With a plate of Mediterranean food in my hand, I looked around for a nice table to set up shop, and stumbled upon a conference room with a few other developers who were already looking at the HTC pen api. Perfect.
First order of business: get an emulator running with the pen api enabled. The HTC dev site has instructions with screenshots, but unfortunately the Ice Cream Sandwich UI was rather different, so it took me a while to figure out how to give it my downloaded zip files. Even more unfortunate, I could not create an AVD even after importing the HTC add-ons! I asked David from HTC for help, and he had the exact same problem. Perry, a fellow hackathon participant, got an AVD created before he upgraded to Ice Cream Sandwich, so David and I decided to blame Ice Cream Sandwich.
Assigning blame made me feel better, but did not actually address the problem. I was going to beg David to let me develop directly on the device, but then I got this brilliant idea - I could just copy the AVD from Perry! Armed with a USB thumb drive, I obtained the precious AVD files, and voila! Emulator up and running.
Next task: try out the demo projects that came with the pen api add-on. This was when hacking with others really helped, since someone in the room already tried running the demo projects, and found out that only the compatibility demo worked. That saved me the trouble of running into dead ends.
The idea
Finally I was ready to hack out my app. With the pen api as my secret ingredient, I thought it would be natural to use it to write. Not just write anything, but write Chinese, since I still don't type Chinese very fast. But then I realized that not everyone knows Chinese, so hey, I could build an app to teach people to write Chinese! The idea was simple enough for a day's work - load a Chinese character in the background, use the pen to trace it, and when you are done, hide the character so you could see what you actually wrote.
Technical hurdles
The compatibility demo has code for converting onTouchEvent into lines on a SurfaceView, so my little app was already capturing the pen strokes and drawing them on the screen. I thought I would just wrap the SurfaceView with FrameLayout and stick in a view underneath to display the Chinese character. Alas, not so simple, since you cannot put anything beneath a SurfaceView. I brought my problem to Leigh from HTC, and she casually commented, "couldn't you just draw the background directly on the SurfaceView?" And I said, "you're right!", and rushed back to code some more.
At this point the inevitable happened: the wifi stopped working. With so many contests accessing the net at the same time, I was not surprised. My app did not actually need the internet, but to code it, I need access to Android documentation. I wished I downloaded the documentation when I was at home! Oh well. Stephan, who was sitting to my right, just calmly pulled out his tether device and moved on. Now that's what I call prepared! Fortunately we were sitting in a conference room, and I noticed ethernet cables coming out of the phones in the middle of the table. I grabbed one, plugged it in, and phew, it was connected. Back to business again.
The rest of the app was relatively straight-forward. Initially I used drawText for the background Chinese character, but the default font was really ugly. I didn't have time to figure out how to include a prettier font, so I took a shortcut and just displayed an image of a beautiful Chinese character.
Polishing
By now it was 6pm, and I had a working demo. But it didn't really use the pen api. Yes, you could use the pen to trace the character, but you could also use your finger. We need to submit our app by 7pm, so I didn't have a lot of time. I decided to use the pressure from the pen to vary the stroke width, and started pouring over the HTC documentation. Not sure if I was stressed or what, but for the life of me I just couldn't find the function to get the pressure. I asked David from HTC for help. He couldn't find the function in the documentation either, but had some unpublished sample code, so once again I whipped out my USB thumb drive and got some precious files. The function turned out to be dead simple: it was just event.getPressure() from the MotionEvent. I added that to my app, and spent the rest of the time tweaking the numbers to make the strokes look alright.
Show time
At 7:30pm we all went back to the big conference room for demos. I was the second in line to present, and gave a pretty short demo. But people seemed to like it!
There were a lot of interesting apps, and I was rather impressed by the work everyone managed to do in a day. It took an hour for everyone to demo, and then the judges got together to vote. Afterwards, it was the announcements. They first announced the overall winners. I was very pleasantly surprised when they called out "Calligraphy" for first prize! They tagged on to say that I was also one of the two winners for the pen api category. Double happiness!
Winners of the pen api contest. Bruce from HTC brought giant zucchinis as prizes!
During the day someone from Microsoft developer relations was going around asking people to fill out a survey. They would raffle out two people to win an XBox 360 with Kinect, and they announced the results at the end. As luck would have it, I was one of the winners! Beginner's luck, I suppose?
The organizers and sponsors were quite generous, and gave out a lot of prizes. More at the AT&T Developer Program Blog.
Parting thoughts
I had so much fun at my first hackathon. Working side by side other developers was really nice, and have direct help from the API publishers made the process much smoother. If are were sitting on the fence, I definitely recommend going to one.
Here are a few things I learned:
Assume that the internet will stop working at some point, and download the SDK/documentation beforehand.
Sit with people working on similar projects. The cross pollination is amazing.
Don't be shy to ask for help. People are super friendly, and you don't really have a lot of time to repeat mistakes anyway.
A big hand for the organizers and sponsors! Thank you for this very fun event. I especially enjoyed working with the HTC team.