Sunday, December 5, 2010

QR Code Generator in Chrome

Here's a quick and easy way to generate QR codes in Chrome. The result is that you will be able to type "qr[tab]" in the browser, paste a URL, and instantly get back a QR code. ("qr[space]url" also works)

How to set it up:

  • Open preferences, Basics => Search => Manage.
  • Click "Add...":
      
        Name: QR Generator
        Keyword: QR
        URL: http://chart.apis.google.com/chart?cht=qr&chs=350x350&chl=%s
      

The Setup:



The Result:

Wednesday, November 17, 2010

Better Javadocs in Maven

Over the summer, I worked with Google's Android team on a project called Doclava. Doclava is a tool that generates modern javadocs for your project, including a refreshed look-and-feel, javascript-based search that works both on- and off-line, and federated documentation, so your project can link against others. For example, a method print(String theString) would have the "String" class link to the relevant documentation in the JDK.

Last week, we got Doclava added to the Maven repository. Now, Maven users can add support for Doclava by simply copying a few lines of configuration into the pom.xml file!

To check it out for yourself, see the Getting Started guide.

Tuesday, April 27, 2010

HTML simplified with JQuery: Building a Table of Contents

I recently wrote up a bunch of documentation for my research project Junction. I wanted to build a Table of Contents, but knew I would be editing the text a lot. So I thought I'd write a ToC plugin for JQuery.

A little Googling turned up a few workable plugins, but it turned out to be easier to write my own than to embed someone else's. Not that embedding was hard, just that writing the plugin was very easy.

My implementation builds a table of contents as a set of nested lists, and is generated by scanning the page for header tags (h1, h2, h3).

You can have a look at my code running "live" on that documentation page (http://mobisocial.stanford.edu/?page=junction).

I guess this post also acts as a shameless promotion for Junction, a platform for writing platform-spanning activities. So go check that out.

Wednesday, March 17, 2010

Speech Writing: How I learned to stop worrying and love the Speech

Recently, I had the honor and chore of writing a speech as the Best Man in my BFF's wedding. It stressed me out. A lot. But it really doesn't have to.
I am clearly no expert on public speaking, and as such, I think I can give out some advice that I gained along the way that others might find useful. I got some simple tips from friends and a few realizations along the way that helped a lot.
Writing your Speech:
1. YOU ARE WRITING A SPEECH.
Duh, right? But remember it. It's different than writing an essay. Don't use big flowery words if you don't usually say them. Keep your sentences short.
2. KEEP IT STRUCTURED
It really helped me to come up with an overall structure beyond "intro", "middle", "end". There are a few you can use, and you can mix/match them. This isn't a strict requirement, but it really helped me turn my ideas into a coherent speech. I roughly used chronology to keep my flow. You could bullet-point attributes, and expand on each. Or something else.
3. MAKE IT PERSONAL, KEEP IT ACCESSIBLE
There's a balance you should try and hit here. You want to tell stories that are personal, but you should keep in mind that the married couple are two of many people in the room. Make sure you tell stories and anecdotes in a way that other people can follow.
4. PRACTICE, PRACTICE, PRACTICE
Saying it out loud is very different than reading it on paper. Practice to yourself. Practice to someone else. Time it, and make sure it's a good length. No one wants a 15 minute speech.
5. TAKE CRITICISM
When you practice with other people, remember that they are better representative of the audience than yourself. So trust what they say.
Delivering your Speech:
1. BREATH. MANY TIMES.
Make notes in your speech. Remember to breath, and slow yourself down.
2. READ IT, BUT ONLY IF YOU HAVE TO
Don't stress out about memorizing it. If you can, that is hugely great. But if it's going to stress you out and mess you up, don't worry. And if you are reading it, do it with some emotion and presence. You're not reading a novel; it's still a speech.
You should, though, at least give an on-the-fly introduction. It will help you settle in and adjust to your speaking persona. Thank the appropriate people, congratulate the appropriate people. But secretly use this time to settle yourself in.
3. BE PRESENT
If the audience is laughing, pause and let them laugh. If you get a bit emotional in your speech, great, let that happen. Just keep yourself in the moment.
That's it. Like I said, I'm no pro, but hopefully something here will help you write your killer speech.

Monday, November 9, 2009

Droid

A solid smartphone on Verizon running Android? I couldn't resist, so I was one of the first in line on release day, and so far I love it. It's quite an upgrade and I've been impressed with how solidly it was put together, both in terms of hardware and software. But there are plenty of glowing reviews on the web, and so rather than rehashing what everyone else is saying, I thought I'd lay out my nitpicks and feature requests, both in terms of the user-experience and SDK features.

User Experience

Okay, so we'll start off with a common complaint from reviews. The camera blows, and it seems to be a software problem. Fix it. The flash is actually impressive for the size, but what's the point if the camera can't hold a focus.

Voice search is excellent. So is voice dial. But why are they not better integrated? I should be able to search for "dial 4085559210" to call that number. Right now, it picks up the text very accurately, but then searches google for the result. Bummer. Also, voice search should search over the nicknames I've entered. I don't want to say "Call Barbara", I want to say "Call Mom".

Easy access to more power modes. I love airplane mode. It's easy to enable and puts my phone in a more-silent-than-silent state, which I prefer during meetings and sleep. It would be great to support other profiles, specifically a "power saving" mode that enables only basic voice features, shuts down most background services, and keeps the screen dim. Good for long weekend outings.

Lost phones: Let me specify a list of contacts that can be called without entering the unlock code. This can help people return my phone if they feel so inclined. It's probably good enough to just let them call my favorites.

Long pressing the home screen brings up the list of recent apps. Why can't I long press one of those to kill it? Or restart it? The GUI should be updated to provide these options for the focused activity with one click.

Panning between home screens: make it faster. It should be powerful enough, and we see other plenty smooth animations. The pixels between screens are almost totally static, save for the widgets, so they should be cacheable in a framebuffer and the animation should be silky smooth. Of course this is probably a complicated issue, but it's the first thing people notice when they play with the phone.

SDK

Named intents. Intents are really great, but I have some issues. The information I should need to know to call an explicit intent are: (1) the name of an action and (2) the name of a package. I don't care which class within that package handles my request- that's for them to figure out.

Furthermore, intents should be manageable in the Manifest:

<namedIntent label="ScanQR">
   <action>com.google.zxing.client.android.SCAN</action>
   <package>com.google.zxing.client.android</package>
</namedIntent>
Later, in code:
Intent intent = new NamedIntent("ScanQR");

Additionally, we can use this (optional) package information to determine dependencies of our application, which the user can be requested to install. We can add a <mandate>optional/required</mandate> field as well.

Which brings up the next point... Improved dependencies in the manifest. We should be able to depend on other activities, services, as well as shared libraries (I'm sure there are much deeper issues that may make this very difficult..) For example, I've written several small apps, all of which require the SMACK XMPP library. This library is large, and it would be great to only require it once.

As a bonus, the system can integrate with Maven and other build systems in the future. This isn't work the android team should have to do, but it should be a consideration and left as a possibility for 3rd party work.

The Media Player sucks. Not just the interface, but the API as well. Why can't I send it an m3u to play? I want to take advantage of its widget and playlist GUI. Consistent view for the user, less work for me. And if the API were properly specified, they could drop in another player.

Timeline Layers: the map layers are cool, although I haven't seen whether or not they are customizable. Either way, I want to be able to add data to a timeline, and have a collective view. My note-taking apps should attach updates. My music player a play history. GPS tracks my steps. Put them all together in one timeline GUI.

ADT

The "sample" apps are great, and could be the start of something much bigger. But when I select one, I am set up with a project that edits the sample directly. This is just wrong- it should make a copy of the code and put it in my workspace so I don't ruin the original example.

Friday, October 16, 2009

Checking for Internet Availability on Android

I've been writing a good handful of net-enabled apps for Android and wanted a simple class to make sure the internet is available. If there is connectivity, the application should continue to run. Otherwise, the user should be prompted that the internet is not available, with the ability to "retry" or "cancel". If they choose to cancel, a different branch of code is executed. The behavior is seen in many of the built-in Android apps. My solution uses callbacks to get the job done. Hopefully the example speaks for itself, and the two required classes follow. You'll need an additional permission for the package to work- ACCESS_NETWORK_STATE. Also, Blogger is basically the worst possible way I could imagine posting code to the internet. If you have a better suggestion, I'd be happy to hear it.

Example

This snippet can be placed inside of an Activity, often in onCreate or similar lifecycle method.
WaitForInternetCallback callback =
 new WaitForInternetCallback(this) {
 public void onConnectionSuccess() {
  Log.d("test","We have internet!");
 }
 
 public void onConnectionFailure() {
  Log.d("test","failed to get internet connectivity...");
 }
 };
   
try {
 WaitForInternet.setCallback(callback);
} catch (SecurityException e) {
 Log.w("test","Could not check network state.", e);
 callback.onConnectionSuccess();
}
Here are the associated classes:

WaitForInternetCallback

package edu.stanford.prpl.junction.impl;

import android.app.Activity;

public abstract class WaitForInternetCallback {
 protected Activity mActivity;
 
 public WaitForInternetCallback(Activity activity) {
  mActivity=activity;
 }
 
 public abstract void onConnectionSuccess();
 public abstract void onConnectionFailure();
}

WaitForInternet

package edu.stanford.prpl.junction.impl;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.util.Log;

public class WaitForInternet {
 
 /**
  * Check for internet connectivity.
  * The calling context must have permission to
  * access the device's network state.
  *
  * If the calling context does not have permission, an exception is thrown.
  *
  * @param WaitForInternetCallback
  * @return
  */
 public static void setCallback(final WaitForInternetCallback callback) {  
  final ConnectivityManager connMan = (ConnectivityManager) callback.mActivity
    .getSystemService(Context.CONNECTIVITY_SERVICE);

  final MutableBoolean isConnected = new MutableBoolean(connMan
    .getActiveNetworkInfo() != null
    && connMan.getActiveNetworkInfo().isConnected());
  if (isConnected.value) {
   callback.onConnectionSuccess();
   return;
  }
  
  final MutableBoolean isRetrying = new MutableBoolean(true);

  /* dialog */
  final AlertDialog.Builder connDialog = new AlertDialog.Builder(callback.mActivity);
  connDialog.setTitle("Network not available");
  connDialog
    .setMessage("Your phone cannot currently access the internet.");
  connDialog.setPositiveButton("Retry",
    new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialogInterface, int i) {
      synchronized (isRetrying) {
       isRetrying.notify();
      }
     }
    });
  connDialog.setNegativeButton("Cancel",
    new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialogInterface, int i) {
      synchronized (isRetrying) {
       isRetrying.value = false;
       isRetrying.notify();
      }
     }
    });

  new Thread() {
   public void run() {
    while (!isConnected.value && isRetrying.value) {
     callback.mActivity.runOnUiThread(new Thread() {
      @Override
      public void run() {
       connDialog.show();
      }
     });

     synchronized (isRetrying) {
      try {
       isRetrying.wait();
      } catch (InterruptedException e) {
       Log.w("junction", "Error waiting for retry lock", e);
      }
     }

     isConnected.value = (connMan.getActiveNetworkInfo() != null && connMan
       .getActiveNetworkInfo().isConnected());
    }
    
    if (isConnected.value) {
     callback.onConnectionSuccess();
    } else {
     callback.onConnectionFailure();
    }
   }
  }.start();
 }
}

class MutableBoolean {
 public boolean value = true;

 public MutableBoolean(boolean v) {
  value = v;
 }
}

Wednesday, July 29, 2009

XMPP on Android using Smack

I just went through the experience of running XMPP on Android, using the excellent Smack library. I take very little credit for getting it working, and just wanted to document my research in one place. The end result: XMPP running on Android SDK 1.5, using Smack 3.0.4 (svn revision 10869), including full support for bundled extensions. Note that at the time of writing, Smack 3.1.0 is available, but 3.0.4 was sufficient for my needs.

The first useful post I found was from Davanum Srinivas, found here. I had mixed results, and looked for a more source-level approach.

Reading through the comments, I found a link to Peter Neubauer's post here. The smackdiff file was exactly what I was looking for.

To apply the patch and build your own .jar, you'll need three tools installed: svn, diff, and ant. Looking at the .diff, the patch is against revision 10869 of the smack repository: http://svn.igniterealtime.org/svn/repos/smack/trunk. I checked out the source and applied the patch like this:

$ svn co -r 10869 \
     http://svn.igniterealtime.org/svn/repos/smack/trunk smack-android
$ cd smack-android/source
$ patch -p0 -i /path/to/smack.diff
$ cd ../build
$ ant
$ cd ../target

If all went well, you should see smack.jar and smackx.jar, and a few others. These .jar's should work on android, but there's one more catch. My application is using the MultiUserChat extension. The smack extensions are loaded based on a file in smack.jar's META-INF directory. So, when I build my .apk, I simply copied the contents of both smack.jar/META-INF and smackx.jar/META-INF into my apk's META-INF, and everything worked!

Note that one important function of the patch is to remove SSL from Smack, so SSL will not work on this build.

An issue I have not yet worked through is how to automatically import the files from this META-INF directory. I am using Maven to build my .apk (using maven-android-plugin) and have not yet found the best practice for copying these files, so if you have ideas, please post them.

Many thanks to Peter Neubauer and the Smack/Android teams for their work!