Archive for the ‘Uncategorized’ Category

Sunday, January 3rd, 2010

Over two years have passed since the first Android SDK was released.  The first entry on this blog was written a little under two years ago.  It has been a long, fun ride and even though this blog hasn’t been too active I have been working with Android much of that time.

For the last one and a half years I have been working on a full time Android consulting project.  The contract doesn’t let me talk about what I do during the day, but I have kept myself busy in my spare time with some personal projects as well as a tiny bit of side-client work.  I have decided to create a “portfolio”, of sorts, of some of my most complete and polished applications.  I have written some short descriptions of some of the more interesting pieces of each application and a little background on how they came about.  They are all available on the Android Market and feedback is definitely welcome.

We are just a few days away from the public release of the Nexus One and Android is finally getting the attention it deserves.  This will be the year that Android really breaks out with tons of devices on the way.  It is a great time to be an Android developer and I definitely look forward to all the new opportunities this exciting year will bring!

Applications

Monday, June 22nd, 2009

Twitter recently made a streaming API available that allows developers to get real-time status updates using HTTP streaming. You can read about the specifics of the API here. There are a few different levels of streaming that developers can use, most of the more heavyweight streams require explicit permission and some kind of agreement with Twitter. Streams are available in JSON and XML, you can also get a delimited stream which tells you how many bytes each status uses to make I/O a little easier. I am going to show you how to use Apache HttpClient 4.0 and the XPP XML Pull Parser library to write a simple client to consume the publicly available “spritzer” stream.

Setting Up The Client
The first step is to set up the HTTP client. The API uses your twitter username and password with basic authentication to authenticate. We will configure our HttpClient with our twitter user name and password as the credentials for the “stream.twitter.com” scope.


        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf-8");

         SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

         ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params,
                registry);
        DefaultHttpClient client = new DefaultHttpClient(manager, params);

        client.getCredentialsProvider().setCredentials(new AuthScope("stream.twitter.com", 80),
                new UsernamePasswordCredentials("username", "password"));

Requesting And Parsing
Next we will create the Get request for the “spritzer” stream and perform the request. After that we will open a pull parser on the network stream and “pull” the xml from the stream as it comes in.

Each status update comes in the format:


<?xml version="1.0" encoding="UTF-8"?>
<status>
....
</status>

It is important to note that each status has the xml document tag at the beginning.

Most of the parsing code is the result of a lot of trial and error so it is not the prettiest. See the comments towards the bottom for some important comments about the implementation.


        HttpGet get = new HttpGet("http://stream.twitter.com/spritzer.xml");
        try {
            HttpResponse resp = client.execute(get);
            int statusCode = resp.getStatusLine().getStatusCode();

        if (statusCode == 200) {
                InputStream stream = resp.getEntity().getContent();
                XmlPullParserFactory factory;
                factory = XmlPullParserFactory.newInstance();
                XmlPullParser parser = factory.newPullParser();

                parser.setInput(stream, "utf-8");
                while (true) {
                    int event = parser.next();
                    if (event == XmlPullParser.START_TAG) {
                        String name = parser.getName();
                        if (name.equals("status")) {
                            String text = null;
                            String screenName = null;
                            while (true) {
                                event = parser.next();
                                if (event == XmlPullParser.START_TAG) {
                                    name = parser.getName();
                                    if (name.equals("text")) {
                                        text = parser.nextText();
                                    } else if (name.equals("user")) {
                                        String userName;
                                        while (true) {
                                            int eventUser;
                                            eventUser = parser.next();
                                            userName = parser.getName();
                                            if (eventUser == XmlPullParser.START_TAG) {
                                                if (userName.equals("screen_name")) {
                                                    screenName = parser.nextText();
                                                }
                                            } else if (eventUser == XmlPullParser.END_TAG
                                                    && userName.equals(("user"))) {
                                                break;
                                            }
                                        }
                                    }
                                } else if (event == XmlPullParser.END_TAG
                                        && parser.getName().equals("status")){
                                    break;
                                }

                            }
                            //output username and status to console, you will want to parse and dispatch whatever
                            //information you need to something that does something a bit more substantial

                            System.out.println(screenName + ": " + text); //insert money making method here

                            //IMPORTANT HACK
                            //because each stream starts with an <xml/> document tag
                            //we have to reset the input of the parser to the stream
                            parser.setInput(stream, "utf-8");
                        }
                    } else if (event == XmlPullParser.END_TAG
                            && parser.getName().equals("statuses"))
                        break;

                }

            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }

Here is the entire source you should be able to build it and run it in the console without many problems, but remember never try to actually read the stream.

stream

Thursday, October 23rd, 2008

The G1 came out this week and I have been putting it through the paces. I really like the seamless transition between developing with the emulator and developing on the device. I think overall it is a very strong first device for Android, but I think that normal users may not recognize some of the more powerful features of the platform.

The Intent system allows for applications and activities to interact with each other, so that you can have applications using the features of other applications. I think this is a really interesting concept and think it could lead to a less application-centric view of phone operation towards a more feature-centric view. Instead of developing an entire application, developers can develop specific features that perform a very specific task. These features can be used by other applications to create new and interesting functionality.

I think the best example of this concept is Barcode Scanner. Barcode Scanner is the application specific manifestation of ZXing which I blogged about previously. Installing it lets you scan bar and QR Codes and lets you perform search actions or interact with the results(like an e-mail address or phone number). The two shopping applications CompareAnywhere and ShopSavvy use the ZXing library themselves for doing barcode scanning, but they include the ZXing library as part of their application bundle.

In my previous entry I mentioned that I would like to see specific Intents that let you use the encoding and decoding ability of ZXing from other applications and the ZXing team responded that the latest build had this exact functionality! Now all you have to do is install Barcode Scanner on your phone and your applications can take advantage of its features. Specifically, it provides Intents that allow your application to use the encoding and decoding functionality. The Intent mechanism makes it almost too simple to integrate this functionality into your application.

Encoding – “com.google.zxing.client.android.ENCODE”

To encode a string into a QR Code Simply create an Intent with the Decode action specified, two string extras specifying the Type and Data and call startActivity():


Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
				intent.addCategory(Intent.CATEGORY_DEFAULT);
				intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
				intent.putExtra("ENCODE_DATA","HELLO WORLD");
startActivity(intent);

The string values for the Intents and the extras values can be found in the Intents and Content classes in the ZXing source code.

Decoding – “com.google.zxing.client.android.SCAN”

Bringing up the decoding camera interface is just as easy as encoding with the added step of having it return the decoded value of the barcode to our main application.


Intent intent = new Intent("com.google.zxing.client.android.SCAN");
				intent.addCategory(Intent.CATEGORY_DEFAULT);
				startActivityForResult(tent,0);

The big difference here is that we are using startActivityForResult which will allow the scanning activity to return the results of the scan back to our app. In the Activity that launched the decode intent we can extract the results of the scan in the onActivityResult method by simply accessing the string extra “SCAN_RESULT”.


data.getStringExtra("SCAN_RESULT");


You can now use these features to do all kinds of interesting things. I am currently interested in transferring data between phones by encoding the data in a QR code and having the other phone retrieve it by simply pointing it at the other camera’s screen. You could also encode movie ticket information into a QR code and have it displayed on the phone so it can be scanned at the theater.

I hope this post showed you how useful Barcode Scanner can be for your application and it’s users. Now if someone could do something about the reviewers in the android app store…..

Thursday, October 23rd, 2008

Long since the radical ideas of the 60s (and the namesake of this blog), comes a walking house!