Wednesday, December 10, 2008

Reflection Continued

In addiction to being somewhat messy, reflection can be used in dangerous ways. Remember you are using code in which the programmer never intended. Sometimes this can result in humorous things (see Crashing an in flight entertainment system). Sometimes your great plans can go down in flames.

Looking through the source code of the Android platform (which can be downloaded very easily from here if you have a mac or linux computer), you can find out how to do things that are not in the standard source. In this case I was looking for how to enable/disable GPS for my ToggleGPS app.

You can see the code for the Security and Location settings screen here.

It's not for the faint of heart. I wouldn't suggest doing this except for experienced developers because a lot of times you encounter code and terminology that you haven't seen before.

All the magic of enabling GPS happens with this line

// Inform the location manager about the changes
mLocationManager.updateProviders();

However, if you check out the Android SDK reference for LocationManager you find out that there isn't an updateProviders() method.

It's private, it's hidden. How google is calling it here I'm not really sure. We can get the LocationManager in our code by

LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);

And as I showed in my last post you can access "hidden" methods using reflection.

Method updateProvidersMethod =
locationManager.getClass().getMethod("updateProviders");
updateProvidersMethod.setAccessible(true);
updateProvidersMethod.invoke(locationManager);

But...

Under the hood things are not as they seem. If you try to run this in code in the emulator you get a very strange exception. Buried in the stack trace you find:

...
W/System.err( 415): Caused by: java.lang.SecurityException: Permission Denial:
getIntentSender() from pid=415, uid=10023 is not allowed to send as package andr
oid
...

Now I didn't bother looking through the Android code to figure out what is going on under the hood, but the message "not allowed to send as package android" stopped me in my tracks. You can use reflection to trick java into doing what you want it to do but this you can't trick. I'm guessing, but the error message probably means that I was trying to access operating system protected code.

But there ARE apps in the Android Market that can do this. But how?

The answer to this is surprisingly simple. But that is for another post.

3 comments:

Dan said...

I like your apps. Efficient at doing what they do.

I understand the logic behind having several small apps in case people only care about toggling 1-3 things, but I think there could be a need for a graphical toggle program.

There are three on Android Market that I can think of, but none are that great. Perhaps you could make one that works better/just as well and more intuitively designed.

Dave said...

I've downloaded your other two apps and was happy today to see the GPS toggle. Unfortunately, this one isn't so good. At install it turned on; but, it doesn't turn off. Do love the others though.

BlackEel said...

Great apps, I have all three on my desktop and they work great for me. I was wondering if you could make one to toggle the data roaming setting?

Home Screen > Menu > Settings > Wireless Controls > Mobile Networks > Data Roaming