Ground-Up Android, Part 5: Tweeting and Debugging

by Yoni Samlan on Oct 7, 2009

This is part 5 of a 5-part series on introductory Android development. If you’re just arriving, you should head on over to Part 1. Warning: While the general ideas and Android-specific code contained here still apply, the Twitter-specific portions are now outdated thanks to the so-called “OAuthocalypse,” Twitter’s phasing out of HTTP basic auth.

In Part 4, we dug into accessing our Views from our Activity’s code, and registered an OnClickListener to handle the user’s interactions with our button. In the final part (a big one!) we’ll cover using J2SE libraries, debugging, and Android permissions.

So far we’ve gotten a lot done without too much “boilerplate” coding, and that’s great. But what we don’t have (yet) is an application that leaves its mark on the world. After all, what’s a Twitter application if people can’t benefit from your 140 characters of deep, meaningful insight into the state of the world (or what you ate for breakfast)?

On the shoulders of giants

One great thing about Android is that you have access to a full J2SE stack. That means you can take advantage of lots of libraries other suckers wonderfully generous people have already written. There are some caveats — code using some kinds of runtime code modification / introspection or deep JVM voodoo won’t work properly under Dalvik, for example — but many simpler libraries can be partially reused or just dropped in wholesale in JAR form. For twitter, there’s a great super-light library called JTwitter, released with an LGPL license. Go ahead and download that now — I’ll wait.

Done? Great! Put the .jar file into your project. I’ll create a /lib folder in our project and drag the file there, but you could also keep it in a totally separate folder on your computer to be linked as an external .jar in the project. Then go to Project -> Properties and add the .jar file (add as an external if you’re keeping the .jar outside your project’s folder). And that’s it — Android’s SDK tools take care of turning the compiled code in the .JAR file into proper Android Dalvik bytecode behind the scenes.

Now let’s wire that Twitter code in.

Add at the top of the Activity class:

1
2
public static final String TWITTER_USERNAME = "someusername";
public static final String TWITTER_PASSWORD = "somepassword"; //this is a very bad idea for a real product.

And add to our onclick handler right before popping up that Toast:

1
2
Twitter twitter = new Twitter(TWITTER_USERNAME, TWITTER_PASSWORD);
twitter.updateStatus(twitterStatus);

(Again, you’ll get easily-corrected missing-import errors – let Eclipse autofix that for you by importing winterwell.jtwitter.Twitter).

Advance warnings

Cool – before we run it, though, here’s 3 big caveats/notes:

  1. For the purposes of this demo, I’m hardcoding a password into my file. Don’t do this. You probably want to use OAuth, or at least prompt the user for their password and store the encrypted version somewhere.
  2. This is running in the same thread as your UI. This makes your app hang during the operation, and could lead to the user being prompted to end your app for being unresponsive (the dreaded “ANR” dialog). For a real app, you’d run the twitter-posting in a separate thread or as a background service, but that’s outside the scope of this tutorial.
  3. This actually won’t work yet – trust me, I’m showing you how to debug things. Pretend to be surprised, though.

Go ahead and run the app in debug mode in the emulator (run -> debug -> Android Application). When it loads up, type in a message and click the Tweet! button.

Click 'Tweet!', and then...

Click 'Tweet!', and then...

You’ll find yourself rudely thrown back into Eclipse with this error message:

Oh no!

Oh no!

When things go wrong

Whoops! So your code isn’t doing what you expect — and worse yet, it blows up and crashes – hard. Once upon a time you’d have to know a series of arcane serial debugging commands to get anything resembling useful output from a mobile phone application. But thanks to the magic of DDMS (Dalvik Debug Monitoring Service), debugging your code is as minimally painful as anything I’ve used until now, and is *actually* less painful than a root canal! Let’s step through the Perspective you get thrown into in Eclipse.

The debug perspective

The debug perspective

You’ll notice you can use the Debug panel to view the current state of our application as well as any variables. You can also see the Logcat error messages, which are generated by various application and system events (you can create your own using the android.util.Log library). Right now the only relevant log entry says “InetAddr Unknown host twitter.com,” which isn’t really helpful, but the execution has been paused to let us inspect the code behind that top-level error.

We can resume execution through the exception to the next line of code causing it. Usually this can get you a more detailed error message, and you can even inspect the code and variables at each step. Try it now (it’s the button that looks like “Play” on a tape deck — yes, I said tape deck; so I’m dating myself a bit), and notice the log messages scrolling at the bottom (you might have to click Resume a few times to get the right level of detail).

That's much more helpful.

That's much more helpful.

You can use the Logcat view’s controls to filter error messages by severity or tag if there’s a lot to sort through — in this case, though, a little reading makes the culprit fairly obvious. We never told the app that it needs to ask for Internet access permissions!

Let’s go back and add that to AndroidManifest.xml. Again, you can use the XML wizardy-view to go to the Permissions section and add Uses Permissions -> android.permission.INTERNET, but if you’re old-school or just prefer a good text edit, add this line to the <manifest> node (usually as the last thing before </manifest>):

1
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

Now when your users install this app, they’re warned once on installation that your application will access the Internet (but never again after that).

Go ahead and run one more time, filling in a message:

Now with 100% fewer Exceptions!

Now with 100% fewer Exceptions!

And check out our test Twitter account:

It worked!

It worked!

Hooray!

This concludes the tutorial – but hopefully just starts your Android development experience. Go ahead, start making an app of your own!

To get started (or in case you got lost during this tutorial) you can download the source of the application we’ve built. You can also comment away if you have any questions or feedback on the tutorial.

If you just want to bang around with some more advanced development techniques without starting from scratch, here are some ways you could improve the current app:

  • Use the AsyncTask class or a Service to make the updating happen in the background instead of locking the UI
  • prompt the user for a username/password on first use, using a Preferences activity (easy way: Preferences from XML)
  • Handle network failure gracefully.
  • Display a progress bar / loading spinner while tweeting.
  • Display updates from the users’ timeline in a ListView.
  • use an AlarmService to update the Timeline in the background, displaying a notification to the user
  • Cache tweets to an SQLite database or a flat file on the SD card
  • Use the Location services and the reverse-geocoder classes to tweet your location

I’ll also be posting a more advanced tutorial on AppWidgets (homescreen widgets) soon – so subscribe to the Active Frequency blog in your RSS reader.

Tags: ,

About Yoni Samlan

Yoni Samlan is a partner and developer at Active Frequency. He's been programming since he was yea tall, and has been a professional Python and Django developer since 2005.

  • Pingback: Ground-Up Android, Part 4: Writing the Code « Active Frequency

  • Matt J.

    Now the problem I am getting looks suspiciously like a typo in the tutorial: I typed in:

    public static final String TWITTER_USERNAME = “someusername”;
    public static final String TWITTER_PASSWORD = “somepassword”; //this is a very bad idea for a real product.

    and:

    Twitter twitter = new Twitter(TWITTER_USERNAME, TWITTER_PASSWORD);
    twitter.updateStatus(“twitterStatus”);

    in what are probably the right places. Everything resolves nicely except that the IDE flags “twitterStatus” as an unrecognized variable.

    Interestingly enough, when I look at the source for Twitter.updateStatus, I see that it expects a string, so just to get it to compile, I added quotes around it — even if that doesn't make a lot of sense.

    Now it builds. This actually might be good enough to get me to the point where your intentinal bug is, but after that…

  • Matt J.

    Oh, another thing: the button that looks like the 'Play' button on an eight-track (yes, that dates me even older than your “tape deck”) player does Resume, not Step. But surely 'Step Over' is what you mean. That is the button that looks like an arrow curved around the dot (not into).

    Now in fact, I pressed first on one, then on the other, repeated a few times until I finally saw the display you described, “Permission denied”. Please clarify which buttons you really mean.

  • ysamlan

    Good catch; there actually was a typo in Part 4 (it was correct in the code recap at the bottom and in the completed-code download, but not in the entry follow-along snippet). The onClick should have read:
    public void onClick(View v) {
    String twitterStatus = tweetEditText.getText().toString();
    Toast.makeText(TwitterPoster.this,
    twitterStatus,
    Toast.LENGTH_LONG).show();
    }
    })

    That way the twitterStatus variable refers to the contents of the EditText at the onClick event, not just a fixed string.

  • ysamlan

    I actually meant Resume, which steps deeper into the execution stack (not over) — I was referring to the function of the button and not its label. But since the label is actually Resume I've updated the post to be a little clearer about that.

  • Matt J.

    It is a “good catch” I expected some one of the many eyeballs of the Internet to catch before I did. Perhaps there aren't enough people using your tutorial? I put in a good word for it in Android Beginners, let's see if that attracts any more eyeballs.

  • David

    Thanks for taking the time to help educate! Each tutorial I read (yours and others) helps in unfolding the Android dev. process which for this 'old' programmer is a fun new journey. Appreciated.

  • http://www.dreamingisdigital.com/ Dan

    When I am clicking the tweet button in the application the emulator states a force close error. Any ideas what is causing that?

  • Peter

    Great tutorial, thank you! :)

  • ysamlan

    It's supposed to crash until you fix the permissions issue. Read the portion of the article about debugging and permissions first.

    If you're still getting errors after setting the permissions, make sure you've set the username and password in the code to a real Twitter login. If that doesn't do it, check the traceback from the emulator — run the app in Debug mode in Eclipse, and when it crashes it should prompt you to enter the debugger, where you can step through and find your error. Chances are the LogCat window output after a few steps should give you a fairly descriptive traceback to find your error.

  • http://www.dreamingisdigital.com/ Dan

    Well I figured out it was not the code at all by the jtwitter library throwing an exception. I switched to the twitter4j library and I had no problems.

  • http://www.dreamingisdigital.com/ Dan

    Well I figured out it was not the code at all by the jtwitter library throwing an exception. I switched to the twitter4j library and I had no problems.

  • Jeremiah Holder

    Good tutorial.

    It would be very helpful if you could add the steps for using OAuth as it is clearly a better practice. I know this is for beginners (which I am), but the transition to using the OAuth has some more advanced features that lead to confusion.

    Of course, not to look a gift horse in the mouth, I do appreciate the tutorial you've provided. If a more advanced continuation of it could be made, that would be really appreciated.

  • Maarten Kuiper

    It might be nice to mention that this tutorial no longer works, as Twitter no longer allows you to log in without oAuth.

  • Anonymous

    You’re totally right; I’ve added a disclaimer at the top of the post and at the top of Part 1. The overall ideas on Android coding and app workflow still apply, but the “OAuthocalypse” has rendered this part of this (quite old) tutorial obsolete.

  • Naveen

    Nice tutorial. But I’m stuck in the Part 5.. I also couldn’t download the source code. Can you please help me out?

  • Naveen

    When I try to download the source code it says,

    “Coming soon: Another fine website hosted by WebFaction.

    Site not configured”

    Can you help me to download the entire source code please?

    Thanks,
    Naveen. V