Home > Android, hacks > Using internal (com.android.internal) and hidden (@hide) APIs [Part 1, Introduction]

Using internal (com.android.internal) and hidden (@hide) APIs [Part 1, Introduction]

(Parts 1, 2, 3, 4, 5)

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).

image_thumb13_thumb

And another example of hidden setWifiApEnabled function from WifiManager (source code of API Level 10).

image_thumb15_thumb

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 ).

image_thumb30_thumb

image_thumb29_thumb

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:

  1. Enable both internal and hidden APIs (scenario A)
  2. Enable only hidden API (scenario B)
  3. 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).

Scenario A: read parts 1, 2, 3, 4, 5

Scenario B: read parts 1, 2, 3, 5

Scenario C: read parts 1, 2, 3, 4, 5

(Next post)

Categories: Android, hacks
  1. August 31, 2011 at 04:27

    Hi, your distinction of “hidden” vs. “internal” is wrong. There is no such distinction. A function that is not in the SDK is hidden and internal and not to be used by apps. There are many things outside of com.android.internal that are hidden without any intention of ever being placed in the SDK. For example, there are functions that other parts of the framework need for their implementation but are not intended for use by applications and never will be.

    And functionally there is no difference between these. They both use @hide to prevent the functions from being included in the stub library you link against. In the case of com.android.internal, @hide is used for the entire package so we don’t need to do it for every class. But this is no different than using @hide on a method of a public class. It just prevents that symbol from being included in the stub library, so developers know they should not use it and do not accidentally do so.

    • August 31, 2011 at 09:27

      The only reason why I needed to introduce this distinction is because “hidden” and “internal” cases needed different handling in order to be accessed. The “internal” part needs one extra step of modifying ADT plugin. But when I started digging deeper it turned out to be used in some places that looked like they will be uncovered later to developers. Which actually happened with BluetoothHeadset in 3.0 for example. Hence my conclusions.

      But since then I saw many places that used @hidden in places that had no reason to be uncovered to developers. So you are totally right on that @hidden doesn’t mean “work in progress”, it just that @hidden part *might* get released or might not, or maybe there were no intent to release that piece whatsoever.

      By the way, I’ve updated the post. Thanks for the correction.

  2. December 19, 2011 at 19:42

    Thank you very much, was of great help. Trying to work with hidden VPN classes.

  3. January 30, 2013 at 08:36

    I’m an avid Intellij IDEA android app developer and I, too, was looking for how to use the android source methods to do some things that can’t be done unless your app is of system privelage, or otherwise. I really like this tutorial..but for those who use Intellij IDEA like I do, I just found out what to do instead of using the above Eclipse method… this is it ->

    http://www.jetbrains.com/idea/webhelp/sharing-android-source-code-and-resources-using-library-projects.html

    Enjoy ;)

    mDK

  4. alexhkleung
    April 24, 2013 at 11:57

    4.0.3 (API 15) emulator does not contain classes.dex in framework.jar. What should I do then?

  5. ismail
    May 19, 2013 at 19:18

    Good job!
    Let me warn. You have a mistake. In part 2, “dev2jar” should be “dex2jar”, is that so?

  1. January 18, 2011 at 20:53
  2. January 18, 2011 at 22:33
  3. June 15, 2011 at 08:28
  4. November 10, 2011 at 14:01
  5. December 21, 2011 at 23:28
  6. May 25, 2012 at 12:04
  7. September 29, 2012 at 15:02
  8. April 9, 2013 at 09:02

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 35 other followers