Before I start this blog entry you might see that I’m now writing in English. (Yes, Queens English that is ;))
This is not to be a pretentious dick, it’s because I’ve receieved quite a few questions regarding Android and Google translate Swedish->English is somewhat “less than perfect”… Also English is my main writing language anyway and I spent nearly 10 years of my life there so there you go! 😛 And on that bombshell…
…the innards of Android not (?) available to us public non-vendor developers! (well, I’m a Vendor as well but not for my private projects…)
It all started a few weeks ago whilst developing Tim(mer) Stock™ and I needed a way to secure the reset function for the countdown timer. I love the LockPatternView component in Android and for someone who perhaps can’t read it would be the perfect unlock solution. I created a new view called unlock.xml and entered this:
<?xml version="1.0" encoding="utf-8"?> <com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/patternView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#00000000" android:orientation="horizontal" > <LinearLayout android:layout_width="0.0dip" android:layout_height="fill_parent" android:layout_marginLeft="0.0dip" android:layout_weight="1.0" android:gravity="left" android:orientation="vertical" > <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
Switched to Graphical layout and there it was – my own LockPatternView!
I was really happy that I was now able to provide a system-friendly and autism-friendly “password” input method to my app.
The next thing I did was to create a class that extended Activity and was going to handle the view and the action and started with the imports…
No, nop, nicht, no f-ing way was the only reply from Eclipse :/ (well, not exactly but you get the point…)
Quickly jumped into the Android 4.0.3 source and Yes, it was there but why couldn’t I import it? (I’m still a beginner when it comes to apps development and I heavily rely on what I think should work way before actually checking documentation… hehe…)
After some digging I realised that com.android.internal pretty much only consists of internal classes which aren’t supposed to be used by us app-developers 🙁
Internal and hidden classes are so because they might be removed soon, they are undocumented or they will pose a security threat. (which is my case I think…)
Ok, so I wasn’t supposed to do this but… hmm… a challenge?
I looked in the android.jar from the SDK and sure, internals weren’t there, but was that the only thing holding me back?
Of course not! In order for Android to function this needs to exist on the device so with a bit of wizardry I decided to create a new Android.jar which fulfilled my needs!
I plugged in my phone which runs ICS 4.0.3 and did the following:
adb pull /system/framework/framework.jar unzip framework.jar cd framework dex2jar classes.dex
Now I had all the classes I needed so I just copied all that I’d just extracted into the android.jar from the SDK!
Restarted Eclipse and my new android.jar loaded just fine and all the internal classes were there! Great I though and tried to import LockPatternView again but all I got was a backhand-bitchslap in my face from Eclipse…
MOFO I though and started digging and pretty soon I found the evil culprit… Android ADT!
The guys at Google must’ve figured this out and decided to hinder (stop would be impossible) us from doing this and added a small gift in the ADT plugin to Eclipse (AndroidClasspathContainerInitializer.class) to always deny com.android.internal by hardcoding the path.
Not exactly rocket science this so I just changed
and updated the android.jar with the new and modified AndroidClasspathContainerInitializer.class and yet again restarted Eclipse just to be sure…
The import worked fine and the code compiled – Bob’s your uncle! 🙂
There are also classes which are declared with @hide and my best guess is that this allows Google to hide API’s/classes that doesn’t reside in com.android.internal but has the same effect.
Sadly I can’t use this in my app since I’ve gained access to a hidden API by hacking the SDK and if Google says I can’t use it, I can’t… I’m sure they’d pick up on this as soon as I uploaded it to Google Play anyway but I learned a lot from doing this. I ended up with copying the files from the source and included them in my project instead but that ment NOT using the already available resources in the platform, thus creating a bigger apk and no longer being fully system friendly.
However, if you want to play around with internal API’s and you don’t want to build complete cookies – this is one way to do so, but don’t upload the apk to Google Play because you might get banned for breaking the EULA. In fact, only use it yourself for educational purposes because your app might break when you update your phone next time…
There are some security aspects to this as well but I’ll keep those findings to myself because the purpose of this post was to describe how I took a detour around the problem, not what I found on the way that we shouldn’t do 😉
Happy coding – I’m having fun for sure!
p.s This type of “hacking” isn’t illegal or bad, it’s educational, and as long as you stick to the EULA for the Android SDK you’re not doing anything wrong.