Intents

App Crashers!

When I was a little kid, I had a great-uncle whom the family called "George With The Hat", to distinguish him from another (hat-less) great-uncle also called George.  George With The Hat was a farmer, and raised sheep.  I remember that when visiting him, he would go out to the pasture to feed the sheep, and as he approached, he would call out "baaa!", and the sheep would all reply in unison and come running over to him.  I thought that was cool, but when I tried it, they ignored me. What does this have to do with software?  Bear with me.

I've integrated my Android app with a crash reporting mechanism, so that I can find out about problems my users encounter.  I use ACRA, which I've tied in with BugSense, but there are others like Crittercism, Flurry, HockeyApp, etc.

I wanted to have an easy way to test that the crash-reporting mechanism was working in release builds of my app, but I didn't want to have to put some obscure UI affordance into the app to trigger a crash.

So, I built a separate little "App Crasher" app.  All it does it show a button that, when pressed, sends out an intent with a custom action.  Then, in my app that contains the crash reporting logic, I implemented a simple activity that intentionally causes a crash in its onCreate() method.  In the manifest, that activity registers an intent filter to receive the intent sent by the App Crasher. As an extra precaution (here's where George With The Hat comes in), I implemented a custom permission that the "crash-ee" requires of the "crash-er" as part of the intent filtering.

It's all pretty simple, but handy, and it demonstrates how to use intents with custom verbs and permissions to communicate between apps.

Without further ado, the code:

In the App Crasher app, the main activity does a setContentView() on a layout containing a button with the ID "boom", looks up that button via findViewById(), and sets an onClickListener on it that calls startActivity(), specifying the custom action.


public class MainActivity extends Activity {

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button button = (Button) findViewById(R.id.boom);
        button.setOnClickListener(new View.OnClickListener() { 
            @Override public void onClick(View v) { 
                try { 
                    startActivity(new Intent("com.fizzbuzz.appcrasher.CRASH"));
                } catch (ActivityNotFoundException e) {
                    Toast.makeText(MainActivity.this, "No apps found that want to crash :-(", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

The App Crasher manifest declares a custom permission that the receiving app's intent filter will require of intent senders:

 

In the app where I want to receive the intent and produce a crash, I added a simple activity:


public class CrashActivity extends Activity { 
    @Override protected void onCreate(Bundle savedInstanceState) { 
        int i = 1 / 0; // boom! 
    }
} 

... and in that app's manifest, I declared the activity and an intent filter for it, specifying the custom permission and the custom action: