Saturday, April 19, 2014

Monkey Write presentation

When I was a kid, I learned Chinese the old fashion way. Each day we had to practice one character, and fill it in a 10 by 10 grid. It was boring and repetitive. With Monkey Write I want to make it fun to learn to write, and I always had children in mind. However, as a one-woman development shop there were always so many things to do, and I did not get a chance to cater the app to schools.

That is, until I heard from a parent today. Lorie emailed me and let me know that her son really enjoys Monkey Write, and she wondered if it would be possible to have workbooks that align with the syllabus at his Chinese immersion school. This is the birth of the Immersion series in Monkey Write. I have since published multiple workbooks under the Immersion series. Other parents got curious about Monkey Write, so Lorie gave a presentation on it!

This is the most rewarding part of being an independent developer. I get to talk directly with my users, hear their stories, and add features that they care about. Thank you for making my day, Lorie!

Tuesday, January 28, 2014

Monkey Write: Brush strokes

Back when I started Monkey Write at the AT&T hackathon, I was already varying the pen stroke width by the pressure of the touch events. But the pressure ranges change a lot on depending on the device. I was not able to get consistent stroke rendering with all those pressure ranges, so I only vary the stroke width by pressure if I know it is from the active stylus reported via an HTC PenEvent.

I was really excited when I saw the beautiful Markers app. Its pressure-sensitive strokes work on many devices, plus it is open sourced with Apache License 2.0, so all I have to do is to integrate that into Monkey Write. Well, all I have to do is to find time to integrate that into Monkey Write, which I finally did!

PressureCooker

When I first looked into the Markers code I was very amused by the PressureCooker class. What a name! It calibrates the pressure coming from a series of touch events, which is what I need. I lifted that class and put it into Monkey Write, but that alone did not make beautiful strokes. This was where I stopped the first time I looked into Markers, for the rest involves a more complicated co-ordination among the Slate, TiledBitmapCanvas and SpotFilter classes.

Markers architecture

I finally set aside some time to understand how Markers work.

  1. Convert each incoming touch event into a Spot.
  2. Add the Spot to a SpotFilter.
  3. The SpotFilter takes a Plotter in its constructor. After filtering it calls the plot() function of the Plotter.
  4. The Plotter renders the Spot on screen. In Markers this is handled by the inner class MarkersPlotter in Slate, which draws on the TiledBitmapCanvas.

Where is the PressureCooker, you ask? It is used inside the plot() function. Instead of using Spot.pressure directly, it is calibrated by the PressureCooker.

Monkey Write modifications

Here is what I did to incorporate Markers stroke rendering into Monkey Write:

  1. Replace my own class with Spot to store touch events.
  2. Add a TiledBitmapCanvas to the character writing custom view (called SketchPad).
  3. Make SketchPad implement Plotter, which takes a Spot and renders to the TiledBitmapCanvas.
  4. Add a SpotFilter to SketchPad. As touch events are captured by onTouch, pass the Spots to the SpotFilter.
  5. In SketchPad.onDraw(), call TiledBitmapCanvas.drawTo() after rendering the base character to show the pen strokes.
  6. After the user writes a stroke, grade it. If it was not a good stroke, call TiledBitmapCanvas.step(-1) to remove that stroke.

Pen styles

After I set up the basic pressure cooking and spot filtering I started to experiment with different pen styles. This essentially means changing the pen tip, or how to render each touch point aka Spot.

Basic style

The basic style renders the pen tip as a solid circle. Fairly straight forward:

c.drawCircle(x, y, r, mPaint);

Brush style

Markers has an airbrush style, which draws a bitmap as the pen tip. I looked at the bitmap and thought, hey, that's just a RadialGradient! I decided to generate that programmatically so I can vary the alpha value on the fly:

private Shader createBrushShader(
    float width, float alphaStart, float alphaEnd) {
  final float center = width / 2;
  final float radius = Math.max(1, width / 2);
  final int red = Color.red(mPaint.getColor());
  final int green = Color.green(mPaint.getColor());
  final int blue = Color.blue(mPaint.getColor());
  return new RadialGradient(
      center, center, radius,
      Color.argb(alphaStart, red, green, blue),
      Color.argb(alphaEnd, red, green, blue),
      Shader.TileMode.CLAMP);
}
mPaint.setShader(mBrushShader);
c.drawCircle(x, y, r, mPaint);
I update mBrushShader with createBrushShader() whenever the user changes the width or alpha from the UI.

Pencil style

Once I started playing with Shaders I could not stop. I decided to mimic a pencil stroke on a rough paper by plotting little dots at the pen tip.

private Shader createPencilShader(float alpha) {
  final int size = 32;
  int color = Color.rgb(
      Color.red(mPaint.getColor()),
      Color.green(mPaint.getColor()),
      Color.blue(mPaint.getColor()));
  float threshold = alpha / 255f;

  int[] colors = new int[size * size];
  for (int i = 0; i = threshold) ? 0 : color;
  }

  Bitmap bitmap = Bitmap.createBitmap(
      colors, size, size, Bitmap.Config.ARGB_8888);
  return new BitmapShader(
      bitmap, TileMode.REPEAT, TileMode.REPEAT);
}
mPaint.setShader(mPencilShader);
c.drawCircle(x, y, r, mPaint);

I use a BitmapShader to draw the little dots. It is a tiling bitmap, each pixel is either transparent or the chosen color. The lower the alpha value, the more transparent pixels.

Constant width

Finally I want to provide an option for users who don't want variable width. This is achieved by ignoring the pressure from the touch event and supplying a constant value to the pen tip renderer.

Mix and match

With that you can have a lot of fun making different pen styles.

Here is a very transparent blue stroke. Looks like water, doesn't it?

You can pick different styles for different strokes:

Hopefully these beautiful strokes will make it even more fun to practice writing Chinese. Download Monkey Write and try them out!

Monday, January 27, 2014

Authoring for Pluralsight

When I decided to become a public speaker, I had no idea where it would lead me. I have met many wonderful people at various conferences, and it opens so many doors. So when my friend Corey Latislaw asked me if I'd like to be introduced to Pluralsight to record some video classes, I went, "Sure!"

Audition

The first step to becoming a Pluralsight author is to submit an audition video. You pick a topic, create the slides and demo, and explain everything in 10 minutes. It was a bit challenging to find a bite-sized topic like that, but I lifted a part from my Bust the Android Fragmentation Myth talk and created a video for it:

Once the audition video is accepted, we need to come up with an outline for my first course. I went through my existing talks to see what makes sense for the Pluralsight audience, and decided to author a course on Android Layout Fundamentals based on my Android Layout 101 talk.

Equipment

For software, I have already downloaded Camtasia for the audition video. Now I need hardware as well. Namely, a microphone. I bought the Rode Podcaster as recommended by Pluralsight. It was quite pricey, but I figured I'd use it to record pronunciations for Monkey Write as well, so it should be a good investment.

Recording

Here comes the meat of the process: recording the videos. Initially I thought it will be like giving live talks, but it turned out to be quite different. First of all, if I stutter or make a mistake at a live talk, I simply move on. There is no "undo" when you are on stage. But when I record, I feel obligated to edit out the bloopers, so that introduced quite a lot of extra work.

The format of my slides are also a bit different. I like using "highlight slides" to focus attention on the point I am giving. So I will have a slide like this:

public void someFunction() {
  doSomething();
  doSomethingImportant();
  doSomeOtherThing();
}

And the next slide will highlight the part I am addressing:

public void someFunction() {
  doSomething();
  doSomethingImportant();
  doSomeOtherThing();
}

With Camtasia I can add highlighting to the video afterwards, and I found that better than slides highlighting because I can sync it up to the audio. I highlight the words exactly when I am describing them with my voice. The syncing makes the focusing even stronger, and it gives a good cadence to the video.

Review

A pluralsight course consists of multiple modules, each of which needs video clips, slides, demo code and assessment questions. I was focusing on the video part and recorded three modules before I realized I should have completed a single module and submit that for review. So I prepared the rest of the module and sent it off to the editorial team. Overall feedback was good, but I had a few issues:

  • My 'p's are popping. I need to adjust the microphone distance.
  • The volume needs to be more consistent
  • I need to introduce each of my modules

I wish I got the feedback before I recorded so many clips already! I should have submitted my very first clip and waited for feedback before proceeding. Now I know!

Demo

I never live code during my talks because so many things can do wrong. But with video I have more control, and I demoed some Android tools in the last module of Android Layout Fundamentals. I did not realize how hard it is to talk and type at the same time! I considered recording the demo first, adding the voice-over later, but figured I'd forgotten what I was trying to explain by the time I go back to do the voice-over. So instead I type-and-talk while I could, and stopped typing to focus on talking while I couldn't.

Tips and Tricks

I learned a few techniques after producing the first course:

  • To ensure consistent volume, do not stop recording if you make a mistake. Just stop to recompose yourself, and say it again. Later you can edit out the mistakes and silences. I found it hard to speak at the exact same loudness if I stopped talking for too long.
  • I don't like to script my talks, but I noticed that I re-record a lot when I tried to define a concept. So now I write down the definitions and edit them to my liking before I record. By reading out the written definitions I can often do it in one take, which is a major time saver.
  • I love my Kinesis keyboard, but it makes a lot of noise when I type, and it's a bit distracting in the video. So I type on the keyboard of my laptop instead.
  • When doing demos, don't worry too much about talking and typing at the same time. I type, and then explain. Later I split the video and audio tracks in Camtasia and splice them back together so I am talking over the demo.
  • When you are talking during the demos, do not jitter the mouse! It makes the video splicing much harder.

It's live!

I started recording in September, and thought I'd be done by November. But of course things always take longer than expected. I finished everything by mid-December though, so the delay wasn't too bad. And it was so exciting to see my course go live!

I have not received my first royalty check yet, so I cannot tell you if this is worth doing financially. But the Pluralsight people have been super friendly and helpful, and I really enjoyed working with them. In fact I am already thinking about my next courses!

If you are sitting on the fence about becoming a Pluralsight author, go for it! It's very satisfying to see your knowledge solidified in the form of a video course. Ping me if you have questions, or would like to be introduced to the editorial team!

(Full disclosure: I earn a referral bonus when I introduce people to Pluralsight who go on to publish a course)

Thursday, January 16, 2014

Talk at CodeChix + ACM

Yesterday I was invited to speak at the Bay Area ACM meeting, co-hosted by CodeChix. I wanted to bring a topic that is interesting to the general audience, so I decided to Bust the Android Fragmentation Myth with them.

I treat my overview talks quite differently from my deep-dive talks. For deep dives, I jump into the nitty-gritty details fairly quickly, packing my slides densely with tips and tricks. But for overview talks, I go over the problem definition first. In this case, how to develop for so many different Android devices?

I then walked through a Hello World example to give some basic Android background. With all that set, I deliver the meat of the talk, the various techniques for responsive and progressive development.

After the talk I was chatting with some of the audience, one of whom had no programming experience but enjoyed my talk nonetheless. I was very happy to hear that. She asked me for advice to prepare herself before coming to tech events, to which I said, "ask questions". Ask if you don't understand something. Ask for more information if something is interesting and you want to learn more. She looked a bit disappointed since I was telling her something she already was doing, but at the end of the day there is always more to learn, so my rule of thumb is get fresh information while you are at the event. To give her something concrete, I pointed her to my Android Layout Fundamentals video course. Hopefully that'll be useful!

Monday, November 18, 2013

AnDevCon SF

It's AnDevCon time again! This time I did something slightly different. Instead of giving lectures, I gave a workshop. It was a hands-on session to build a custom view called FractionView.

My most popular talk is Android Custom Components. I have given it many times already, and people are still requesting it, so I know the material is very much in demand. But since I offered it during the past 3 AnDevCon already, I thought I'd change it up a bit and go deep with a workshop. I want people to come in not knowing anything about custom view and walk out with one built from scratch.

The challenge of a hands-on workshop is pacing. I allowed plenty of time for people to complete the exercises, stressing that they should interrupt and ask questions. Some of the exercises were copy-and-paste, others were tasks with guidelines only. This way people had a chance to apply the knowledge right away, hit some of the common mistakes, recover, learn and remember.

I also added an extra-credit exercise for people who were ahead to keep busy. It was very well received. In fact some people wanted more! I will do that in my next workshop.

Keynote

Workshops happened on Tuesday, the day before the conference started. That meant I could enjoy the rest of the conference without distractions from getting ready to deliver my own sessions. Cool!

Reto Meier from Google opened the conference with a wonderful keynote. He urged us to push the boundaries of the system, not only by claiming the benefits, but also showing us why we were not doing it already.

Engineers have two time assessments for tasks: 5 minute or forever. Incremental improvements are often seen as "taking only 5 minutes", and it feels good to get things done. Going into the unknown, however, is daunting. For instance a lot of developers have been putting of in-app purchase, because "it will take forever". Turns out "forever" could end up being just 2 hours. So take the plunge and try something new. Make a big change. It may not be as daunting as you presumed.

Talks

I have always learned a lot from the talks at AnDevCon, so I was a bit surprised to find that I felt I was going to fewer deep-dive sessions than before. Looking into it a bit more, I realized there were still a lot of advance topics on the schedule, but I attended quite a few of them at previous AnDevCons already, and there were some slots with multiple talks I wanted to go. The conference is so much more than just the talks, though. I had many great conversions over lunch, at social breaks, after sessions chatting with other attendees, etc etc. And of course, at the women luncheon as well.

Women luncheon

I have attended the women luncheons at every AnDevCon, and it was always fun to hang out with fellow women attendees. This time I was hosting the luncheon with Sonia Sharma from Google, and I was actually a bit stressed about it, almost more than my workshop. I felt that the fun came from spontaneity, not something I could plan or practice. So we went for table topics, hoping to seed the conversations and let the attendees take it from there. I am happy to report that it worked quite well!

Sunday, September 22, 2013

Strange Loop: Go beyond your day-to-day

When I first heard of the Strange Loop conference, my immediate reaction was, "that is not a conference for me". I was under the impression that it was for language designers to discuss DSLs, type systems, variable binding etc, and not application developers like me.

I was not planning to attend the conference, let alone submit a talk proposal, until I saw an email on the DevChix mailing list. It was an invitation to join a Google Hangout with the Strange Loop organizer to learn more about the conference. Curious, I went and asked questions about the kind of talks they were looking for, and decided to submit a proposal after all. Two, in fact, a deep-dive talk and a overview talk, since I was still not sure what works best for this conference. A few weeks later, I got an email from Strange Loop, telling me they'd like to hear me Bust the Android Fragmentation Myth.

When I boarded the plane for St Louis, I was still not sure if Strange Loop is for me. It seems so far away from what I do. But coming back, I realized that being far away from what I do turns out to be a good thing. It gives me a chance to sample various exciting developments in my field, and it was a lot of fun to step back the day-to-day tasks and look at the big picture.

Opening keynote

Strange Loop opened with a keynote by Jenny Finkel from Prismatic.

Before I get into the talk, please take a moment to admire the venue. Yup, it was an opera house! Such a beautiful place.

The keynote was wonderful, with enough technical details to let us peek behind the curtains of the Prismatic recommendation engine, but not too much to be dry. I enjoyed it a lot.

That was a perfect opening to the rest of the conference. Over the two days I went to many different talks, and listened to great variety of topics. Here are some of them.

Visualization Driven Development

It is common to visualize data after we deployed our software. But in the Visualization Driven Development talk, the speaker argued that we should use visualization during development as well, as a tool like printing log statements and examining state via the debugger. Relying solely on text during development is like picking music by reading its score. (Edit: the example was picking wedding music for an engaged couple, not professional musicians)

Learnfun and Playfun

How do you teach the computer to play video game? Tom 7 went for a pretty simple metric: bits should go up! It was a really light-hearted talk, with lots of cool demos. Check out the videos on his web site.

Natural Language Processing

I studied NLP in grad school, but haven't used it for a long long while. The NLP talk was a nice trip down the memory lane, but also showed me the power of open source. There are so many tools for text processing now! I am especially impressed by nltk, a python library. Reminds me of import antigravity from xkcd.

Bust the Android Fragmentation Myth

My talk was in the late afternoon on the first day.

This is the second time I gave this talk, the first time being OSCON. As usual, I polled my audience before starting, and the Strange Loop crowd had a lot more mobile developers. As a result I sped past the hello world fairly quickly, and spent more time on resource folders.

Afternoon keynote

In the afternoon keynote, Jen Myers gave a passionate speech on making software accessible to everyone. She viewed the current status as a legacy system, and showed us how to improve it by small focused refactoring. She shared stories from Girl Develop It, of empowerment through inclusion. She also emphasized the importance of role models, with wonderful examples such as Sally Ride, Neil deGrasse Tyson and Nichelle Nichols.

The Birth and Depth of Javascript

Strange Loop offers an opportunity to look into the future, and in this talk, the speaker took it quite literally: it was given from the perspective of 2035! In this future, Javascript, together with asm.js, would allow any language to be compiled to run in the browser. Not only the talk itself was entertaining, but the audience also asked questions in the same spirit, one even asked the speaker to predict the future, seeing that this was a "historical" talk.

Java Puzzlers

I have seen the Java Puzzlers talk a few years ago at Google, and totally loved it. It was given in the style of Click and Clack from CarTalk, complete with overalls for the speakers. The puzzles exposed some unexpected behaviors of the Java language, and offers suggestions to avoid the pitfalls. This talk has a completely new set of puzzles, and is as delightful as always.

City Museum

On top of all these wonderful talks, Strange Loop has another cool offering: the conference party at the City Museum. Instead of a museum, it is better to think of it as a giant playground, with lots of secret passageways, multi-storey slides, cages and spirals, and suspended vehicles like a school bus and a plane.

I was having fun exploring the different nooks and crannies on the first three floors, and then heard someone talking about the roof top garden. What, there is more? I found the elevator up, and was treated to a nice cityscape. Plus lots of slides, including one that went all the way down to the third floor. As looked around, I realized that there were more playground outside the building, with a big ball pit, an airplane, and lots of caged passageways.

Given the size of some of the openings this is clearly designed for children, but that did not stop the hundreds of geeks from exploring the place, including yours truly. I had so much fun!

Friday, September 13, 2013

360|iDev

Did you know how I got started in iOS development? At a iOS workshop at Devoxx, a java conference. I have always wanted to learn about iOS, so I went to the workshop, and from there I went on to publish my first iOS app, Heart Collage.

A few months after I published Heart Collage, I saw the call for speakers for 360|iDev, an iOS conference. Thinking about my experience at Devoxx, I decided to submit an introduction to Android session. And it was accepted!

Intro to Android for iOS developers

It was quite challenging to condense the vast sea of Android knowledge into a 50-minute talk, so I focussed on providing a framework for people to explore further. I mapped parallel concepts between iOS and Android to quickly get people up to speed, and then went on to explain two aspects that are rather different on Android: layouts and intents.

I was a little bit worried to be an Android developer among an iOS crowd, but people were super friendly, and my session was very well attended. For the rest of the conference I kept sitting next to people who were at my session, and they said they enjoyed it a lot, gaining an appreciation for the Android platform. This makes me very happy, to help break down the artificial segregation of technologies.

iOS talks

I went to many different talks, soaking up as much iOS knowledge as I can. I learned about custom controls, computer vision, auto layout, UIKit Dynamics, the Objective-C runtime etc etc. Some of it totally went over my head (method swizzling I'm looking at you), but I walked away with lots of concrete knowledge, and got so excited that I played with it right away, at Game Jam.

Game Jam

On Tuesday night there was Game Jam, for people to get together and write games. Initially I wasn't going to participate, but after going to the computer vision talk, I decided to see if I can implement the prototype of a game idea that I had for a while: Color Hunt.

Color Hunt randomly generates a color for you to find it with the camera. For the longest time I thought I needed some complex algorithm to compare colors, and then I saw the Rubik's Cube solver example from the computer vision talk, which uses hue for color detection. So I took the camera code from Heart Collage, grabbed the pixels in the middle of the screen, extracted the hue value and compared it to the target color. It worked!

Community

I had a great time at 360|iDev. The organizers, John and Nicole Wilker, put in a lot of effects to foster the community. The quality of the talks were very high, but more importantly there was a lot of opportunities to mingle with everybody, at lunch, at the evening receptions, at game jam. I have met many people that I know I will keep in touch with, and that is the best part of conferences. On top of that I also came home with a prototype for my game! How awesome is that?