Blog

Generating a Facebook-style manifest

If you've spent any time with the Facebook Android app, you know that it requires a breathtaking number of permissions to install. The real genius of this is that the user's social connections are essentially held hostage in exchange for access to sensitive aspects of the user's device. Furthermore, most Facebook users are unaware that Facebook's mobile site actually performs better than their native Android app. In fact, if more people uninstalled the app and used the mobile site, they'd expose less of their sensitive data to Facebook and have much better battery life. The quality of their personal lives would likely also benefit from the loss of persistent interruptions in the form of inane push notifications.

If you're looking to follow in Facebook's footsteps, be careful not to put too many permission requirements in your Android app early on. Work hard to make your service ubiquitous to the point that it feels inevitable. Then and only then, the real harvest begins!

It's tough making sure you have access to all a user's data. A little clever scripting can go a long way here. Google conveniently lists all possible permissions on the Android Developer site, so why not automate the process? Well, you can do exactly that, just like this:

This script leverages the power of the Beautiful Soup python library to parse out every possible permission you could ask for. The script then outputs a manifest template that's a great starting point for your app. Keep in mind there are a handful of system permissions that the script picks up. Unfortunately, your app can't actually receive these permissions as a non-system app, so you'll have to manually remove them. I'm not going to fix this because I consider it a bug in the Android API that there are permissions that Facebook can't receive.

Generating a third-party license report in Android Studio

The Android development community is fantastic. There are a ton of extremely useful open source libraries and apps out there that can save you work and make you more productive. One thing to remember when you use someone else's code is to do so in a way that complies with their license. If there is not license, well you probably shouldn't use it for your own sake.

A while ago, I discovered a super handy script in the source for the Google I/O app that will walk the entire source tree and create an html report. I had been running it manually, but lately I've been migrating a lot of old build tasks to gradle, the super-powerful build system used by Android Studio. I decided to integrate my license generation step and here's how I did it:

 

Since we need to execute a python script, I've implemented an Exec task. Within the task I point the standardOutput property to a file (since the python script prints to the standard out). Then I assign the executable and all arguments to the commandLine property. The script can accept more than one source tree as demonstrated.

Now you can simply add a settings option that displays the license report with a WebView.

That's it. Have fun! 

Registering for and handling URLs

One of the extremely forward thinking features of Android is the ability register your app to handle URLs. It'a bit like setting the default application for a file type in Windows, but much more powerful. For one thing, the user isn't harassed immediately after installing your app; they can take your app for a spin before making a difficult-to-reverse decision.

Enabling this feature is very simple. You'll need to specify which types of URLs your app can handle and create an Activity to handle them. Registering for URLs happens in the manifest and there's a ton of flexibility here. You can do it by scheme, domain, port, filetype and path. Be as specific as you absolutely need to be, but no more. I wrote a micro app to handle Youtube short URLs and this is how I matched them:

Here I've specified that I would like to be able to handle any http URLs that begin with "www.youtu.be" or "youtu.be" . The next time the user tries to open one of these URLs, they'd see something like this:

"Redirect" is my app! 

"Redirect" is my app! 

If your app is selected, it will be launched and then it will receive the full URL. How you handle the URL depends entirely on your needs. I only want to expand the shortened URL and then send the expanded URL back out the operating system. This is what I do:

You can see that I get the full Uri that represents the URL by using getIntent().getData(). In my case, I'm only interested in the very last segment, so I grab that and build the full url with it. I then sent out an Intent to the operating system that any other app can try to handle. There's no reason for my app to stick around after that, so I close it.

With a little imagination, you can see how useful this is. You can handle someone else's URLs (as I did) or create an app that handles your own URLs. When your app is installed, you get the super-deluxe native experience, but you can always fall back on the web experience otherwise.

A significantly less useful system would be to use a custom URL scheme (hello, iOS). While you can go this route, keep in mind that clickable hyper-links passed around through email, social media, or messaging apps are now impossible. If you're interested in something like this, it's a better idea to look into defining your own custom Intents. It's a much more expressive system that involves less hackery as the scheme gets more elaborate.

Responsibility and Vaccines

Today I came across a post on the Harvard Bill of Health blog wherein Dr. Art Caplan makes the case for financial liability in the form of lawsuits for parents who fail to vaccinate their children. As a vocal advocate for vaccination, I share his belief that it is a parental responsibility of incredible importance. I have personal reasons for my position, which I will discuss later. Pursuing financial liability is the wrong direction for this issue. By creating a financial penalty, we risk transforming a very serious health problem into one strictly about money. Essentially, we would be creating a "price" for skipping vaccination, which could actually encourage it. If a person's actions have a direct negative affect on another's health, it is plainly a moral issue.

The framing of this issue should be based on the idea that there is  portion of our population for whom vaccines are ineffective or simple not possible to receive. Their only hope is to avoid exposure to these dangerous diseases altogether. A suitably high vaccination rate is akin to a forest with firebreaks. If disease is introduced, there is not enough "fuel" for it to survive and it will simply die off completely. This is how we stopped Smallpox.

I won't go very deep into the vaccine debate except to say that there is none. A debate indicates that there is worthwhile discourse, which is simply not true. The side of vaccination has the plurality of the medical community and centuries of evidence. The other side has vague aspersions, conspiracies, a few celebrities and a handful of disgraced doctors. The problem is some very nice people whom I personally like assert that I "must respect" them whether I share their opinion or not.

It's now time for me to tip my hand. I have a very real personal interest in ubiquitous vaccination. His name is Isaiah and he is my son. He has an incredibly rare disease called atypical Hemolytic Uremic Syndrome (aHUS). His immune system attacks his own body and causes a condition that, untreated, would destroy his internal organs and end his life. He is fortunate enough to live in a time of advanced medical treatment. He receives a miraculous medicine called Soliris, which fully contains the disease's symptoms and allows him to be a normal 3-year-old.

The only problem is that he is now immunocompromised, meaning he is at the mercy of herd immunity. He and others like him are what the falling vaccination rates are about. If you choose to not vaccinate, you are risking my son's life. This is your choice. I do not respect you, even if I like you. You are dangerous. You are irresponsible. You should be ashamed.

Please be reconsider. Please vaccinate.

A Builder for ContentValues

If you're working with databases in Android, you'll wind up familiar with the ContentValues class. This class very simple and it's fine to work with, but I find it strange that there is no Builder for it -- especially when Builders are so prevalent in other parts of the Android API. It turns out that a Builder is incredibly easy to implement:

I spent even less work on this class than it looks. Much of the code was directly lifted from the ContentProviderOperation source code.

A better way to find Views in a layout

When dealing with Activities and Fragments in Android, it's not very convenient to get a reference to an existing View in a layout. The return type of the findViewById method is View, which usually isn't useful. Typically, you want to do something like set the text of a TextView or set the bitmap of an ImageView, but you'll need to perform a cast in order to do so. This causes the Activity.onCreate() and Fragment.onCreateView() method to be bloated with casts and the accompanying parentheses parade. It really should be much simpler to perform a task that is so frequently necessary.

Generic methods in Java can understand something about what you're trying to get by what you're assigning the return value to, so use that to your advantage. Here's a convenience method that makes my life easier:

Keep in mind that this won't do any extra compile-time checking. That is, you're still subject to a ClassCastException if the View with the specified id is of a different type than what you're assigning it to.

No ifs ifs or ifs

I don't come across it very often, but there's piece of code that I find so jarring as to be offensive. It seems like a very simple thing, but it drives me up a wall. Here is the basic snippet that irks me so:

if ( condition ) {
    return true;
} else {
    return false;
}

You should never return the exact same value that your conditional clause evaluates to; just return the conditional clause! Failing to do so leads to useless clutter and it screams "amateur". I suspect that experienced programmers fall into this trap when the conditional statement is complex enough to distract the eyes. It could also crop up during a refactor session. Whatever the reason the code got this way, it shouldn't ever be checked in like this.

Properly checking Android version

If you're doing Android development, you have to support multiple versions of the operating system. It's pretty foolish not to and, for all the mellodramatic cries of "alas, fragmentation!", it's really not that hard. The basic idea is that you want to execute one piece of code for one version of Android (and higher usually) and another piece of code for everything else:

if ( version >= gingerbread) {

    do it the new way

} else {

    do it the old way

}

I've seen many ways that people will attempt to check the version of Android. It's usually something along these lines:

 

if (android.os.Build.VERSION.RELEASE.startsWith("1.") ||
        android.os.Build.VERSION.RELEASE.startsWith("2.0") ||
        android.os.Build.VERSION.RELEASE.startsWith("2.1")){
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
}

 

This code is needlessly complex and it's doing several wastefull string comparisons every time you perform the check. Don't do this. Instead, rely on the Build.VERSION.SDK_INT value. The previous comparison becomes:

if (android.os.Build.VERSION.SDK_INT >=

        android.os.Build.VERSION_CODES.FROYO) {

    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

}

This is an integer comparison and it's much more readable. You may be thinking that this comparison will explode when the current operating system is being compared to a newer one. For instance, how would a froyo phone be aware of gingerbread? Shouldn't that cause a runtime error? The operating system doesn't need to be aware of newer versions of Android because the Build.VERSION_CODES values are injected by the compiler. This is why you should always compile against the highest version of Android available.

Hey, LogCat, shhhhhhhh.

One of the most frustrating things about using LogCat from the Android Developer Tools is that it can be really noisy. The situation seems to be particularly bad with manufacturers who use heavy customizations. The problem is the way too many logging statements were left in and your one-liner can scroll right off the screen before you notice it. Of course you can filter by a single tag if you're looking for a particular statement, but if you want to monitor the situation overall, you'll need to be a quick draw on that pause button. If you're dealing with camera hardware, the log is useless. For some reason, the developers decided to create 4-5 log statements per frame.

Well, you can fix this by creating a new filter and using a regex to ommit the noisy tags. Here's what made my log readable:

^(?!.*(CameraHal|MotOverlay|DOMX_RPC)).*$

The most important thing to take out of this is that you, as a developer, need to be sensible about what you leave in the final build. Your logging statements create new String Objects, so you're negatively impacting the performance for every logging statement. Worse still, you may be exposing information that puts you or your user at risk. It's a hassle to try to comment all of them out before generating the final build, and this is where Proguard is your friend. Use it to take out some or all of your logging statements:

 

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** e(...);
}

 

Abe Clone Attack (learning OpenGL)

I wanted to learn OpenGL, so I threw together a game using libgdx. Below is the text from the market page for the app.

This isn't meant to be a serious game. I threw this together in my spare time over the course of a week to learn OpenGL basics on Android. I wrote a rudimentary game engine including animation, collision detection and score keeping.

Why Abe Lincoln? When I needed an image to represent a sprite, his face popped into my mind. Maybe it's his striking facial features or the fact that he's a person that I respect deeply that made me think of him in that moment.

The sprite class holds an array of animations and the state of the sprite (position, dead, type). For each call to the renderer, the engine passes the number of frames (calculated by time since last render) to the sprite, which then advances that many frames into its current animation.

Upon completing a "death" animation, the sprite marks itself as "dead". Upon the next call to render, the engine removes the sprite from those to be rendered.

I wrote a texture library to reuse textures among sprites and animations. Animations as for a texture (by resource name) from the texture library. The library either returns the texture from a map, or loads it into the map and then returns it. This is an easy way to share a single texture for all identical animation frames.
I know this is ugly. I know it's simple. It was fun to make and I'm happy to say that I learned something in the process.

Android Market Link

PAX 2011 Unofficial Guide

Sorry, I never followed through on my series of guides. I got so involved in learning the Android API that I actually started and completed a full app.

I went to the Penny Arcade Expo for the first time this year. I was planning on traveling with three buddies, but they all had to back out due to uncontrollable events. I saw it as a chance to create an app organizing all of the maps, schedules, and twitter feeds for PAX. There were nearly 70,000 attendees this year, so playing it by ear sounded daunting.

The biggest feature I was not able to implement was syncing events with Google Calendar. I finished it at nearly the last minute and wasn't able to promote it properly. Even so, I had about 300 downloads at peak. That number is dropping like a rock now that the convention is over, but I'm planning on updating it for the next convention in spring.

I think I'm in love with mobile development and I'm hatching an idea for my next app.

Though I went alone, I did connect with several friends from Gamers With Jobs and the weekend was great success.

 Android Market Link

Android For Absolute Beginners, Part 1

If you've successfully completed part 0, your computer is set up and read to write Android apps. The final part of that guide had you launching an app that was generated automatically. In this guide you'll take a peak at the guts of this app and, hopefully, learn just a little bit about Android.

Problem: I don't know anything

Okay, you know plenty. In fact, you might even know some of what is in this lesson. To make this as helpful as possible for absolute newbies, let's pretend that you don't know anything yet.

Read More

Android for Absolute Beginners, Part 0

I decided to write a beginner's programming guide for Android. My intention is to be as basic as possible for people who have the interest, but no experience. The requirements are low, but there are a few and they are:

  • You do not know how to program
  • You want to learn how to program
  • You're interested in making Android apps
  • You know how to install software on your computer

The fact that you found this guide means you have interest, but let me help out those who are on the fence. First, let's talk about what programming is.

Read More

vacation.finish()

Now that the family vacation is over, It's time to get back to work on my first Android app.  It's time to knuckle down and churn out a basic but fully functional alpha.  My first app is tentatively called "Scoreo", by me at least.  It will be a basic score keeper / stat tracker for board and card games.  I'll try to put out basic tutorials as I make progress.  I always feel that I have the strongest grasp on something when I can teach it to someone else.  I don't really have anyone to teach directly so tutorials will have to suffice.  My first tutorial will handle Activities.

Paint.NET

When I was eighteen I thought it was amazing that every popular piece of software was free for the taking.  I didn't need to decide between Fireworks and Photoshop, I could have both.  Actually, I could have the entire suites of software offered by Macromedia and Adobe.  I'm not interested in lecturing anyone, but suffice it to say I've turned to free alternatives when I can't afford the software I want.

The Gimp has matured as a powerful free image editor, but the startup time and awkward interface make it frustrating to use.  I use Picasa as my photo organizer and it has taken over basic cropping and color adjustment duties.

Read More