Using internal (com.android.internal) and hidden (@hide) APIs [Part 1, Introduction]
Android has two types of APIs that are not accessible via SDK.
The first one is located in package com.android.internal. I will refer to this API as to internal API. The second API type is collection of classes and functions that are marked with @hide javadoc attribute. Even though this strictly is not a single API but a collection of small hidden APIs, I still going to assume this is one API and will refer to it as to hidden API.
Hidden API examples
You can look into android’s source code and find that some constants, functions and classes are marked with javadoc’s attribute @hide.
Here is an example of hidden constant from WifiManager (source code of API Level 10).
And another example of hidden setWifiApEnabled function from WifiManager (source code of API Level 10).
So whenever you see @hide attribute, you are looking at hidden API.
Difference between internal and hidden APIs.
Hidden API is hidden in order to prevent developers from using unfinished or unstable (in terms of interface and architecture) parts of SDK . For example, Bluetooth API was in Android before API Level 5 (Android 2.0), but it was hidden in API Level 3 and 4 (Android 1.5 and 1.6 ) using @hide attributes. When this API was stabilized and cleaned up Google’s developers removed @hide attribute and made Bluetooth API official in API Level 5. Lots of things were changed between 4th and 5th API levels. If you were relying on something from hidden API you could be in trouble when your application was launched on newer version of Android OS. At the same time any part of internal API is not planned to be opened to the public. This is internal kitchen of Android that should be treated as black box by developers. Things can change here as well. And if you rely on something from internal API you can get upset when new update of Android is released. To summarize the difference:
Hidden API = work in progress; Internal API = black box;
It turns out there is no semantical difference between Hidden and Internal APIs. It just was my observation that some parts of Hidden API were released later (like bluetooth in 2.0 and BluetoothHeadset in 3.0). But this doesn’t mean that if you see @hide somewhere, then there are some plans to release that thing later. Its just a convenience thing that can be used to hide API that is not located in `com.android.internal` package (for any reason).
The distinction of these APIs still matters for the sake of this post, as there is difference between how to uncover Hidden vs. Internal API. Internal API require one more step. But more on this later.
Compile time vs. Runtime for internal and hidden APIs
When you are developing using Android SDK you reference one very important jar file called android.jar. It’s located in Android SDK platform directory SDK_DIR/platforms/platform-X/android.jar (where X is API level, it can be 5 or 10 or any other number). This android.jar has all classes from com.android.internal removed, and all classes, enums, fields and methods marked with @hide removed as well.
But when you launch your application on device it loads framework.jar (roughly this is equivalent of android.jar on the device) which is uncut and has all the internal API classes and all hidden API components. So you can use reflection to access both hidden and internal APIs. (but this is not very developer friendly approach, and I’ll show how you can use these APIs without need for reflection later).
Here is the one extra thing about internal API. ADT plugin for Eclipse adds one extra rule that prohibits usage of anything from com.android.internal package. So even if we could restore original (uncut) android.jar there would be no easy way to use internal API from eclipse.
You can check this yourself. Create new Android project in eclipse (or use existing one). Look at its referenced Libraries ( right click on project Properties –> Java Build Path –> Libraries ).
Important summary: internal and hidden APIs are handled in exactly the same way in SDK (they are both removed from android.jar), but internal API is additionally explicitly prohibited by Eclipse ADT plugin.
Using internal and hidden APIs without reflection
The ultimate target of these articles is to give developers the power of Internal and Hidden APIs without using reflection. If you complete all the steps described in next several parts you will be able to use Internal and Hidden APIs as if they were public open APIs. There will be no need for reflection.
But if you’re using these non-public APIs then you should be aware that your application is at great risk. Basically there are no guarantees that APIs will not be broken with next update to Android OS. There are even no guarantees about consistent behavior across devices from different vendors. You are completely on your own.
There are three scenarios you may want to follow:
- Enable both internal and hidden APIs (scenario A)
- Enable only hidden API (scenario B)
- Enable only internal API (scenario C)
- Scenario A is a sum of B and C. Scenario B is the easiest one (requires no eclipse ADT plugin modifications).