Means again in 2018, Google launched Android Pie. Among the many UI adjustments and new options, there have been additionally some developer-side adjustments. These adjustments included new APIs, bugfixes for current APIs, and in addition restrictions on entry to hidden APIs.
Fortunately although, there are methods to get round these restrictions. Earlier than I get into methods to bypass the restrictions, I ought to clarify a bit about what hidden APIs are, why they had been restricted within the first place, and why you would possibly wish to entry them.
What are hidden APIs?
Hidden APIs are the APIs in Android that app builders usually cannot see. For those who check out AOSP’s code, you may see a complete bunch of courses, variables, and strategies which have a @disguise
annotation inside a remark block above them.
This annotation instructs no matter device Google makes use of when compiling the SDK to exclude the merchandise beneath it. That SDK is then distributed to builders contained in the SDKs downloaded via Android Studio. Except you utilize a modified SDK, Android Studio will assume any of these hidden gadgets simply do not exist. For those who attempt to use one instantly, it would present it in purple and refuse to compile.
Why are APIs hidden?
There are quite a lot of the reason why an API could be hidden. Some issues are solely meant for use by inner or system apps and will not work if utilized by a third-party app. Others are experimental or unstable, and could be eliminated or modified sooner or later. Some are even simply APIs Google simply does not wish to apple the traditional deprecation cycle to in the event that they’re ever eliminated.
Why use hidden APIs?
Whereas the usual Android SDK has a lot in it, generally it isn’t sufficient. Typically there’s one thing you wish to do this already exists in Android, however simply is not publicly uncovered.
For example, quite a lot of the apps I make, together with SystemUI Tuner and Lockscreen Widgets, make use of a bunch of various hidden APIs. SystemUI Tuner must entry some to correctly observe, change, and reset choices. Lockscreen Widgets makes use of some to indicate the wallpaper beneath it, amongst different issues.
Most builders needn’t entry hidden APIs, however generally they are often fairly helpful.
How are hidden APIs restricted?
With the discharge of Android 9 (Pie), Google launched the hidden API blacklist. Not each hidden API was included, and there have been totally different ranges of lists. Hidden APIs on the whitelist might be accessed by anybody. Hidden APIs on the light-greylist might be accessed by any app, however could be inaccessible in future variations of Android. Something on the dark-greylist may solely be accessed by apps concentrating on API ranges earlier than Pie (i.e., earlier than API stage 28). Apps concentrating on Pie and later could be denied entry. Lastly, hidden APIs on the blacklist could not be accessed by any non-system (or non-whitelisted) app, regardless of the goal API.
Android 10 modified how the lists had been organized, and simplified them barely, however the concept stayed the identical. Sure hidden APIs might be accessed by apps whereas others had been blocked. Android 11 strengthened the entry detection to dam a bypass used for Pie and 10.
In all Android variations, any time a third-party app makes an attempt to entry a blacklisted hidden API, Android will throw the suitable “not discovered” error.
The right way to bypass the hidden API blacklist
There are literally fairly a number of methods to get previous the hidden API blacklist. Relying in your wants, you’ll be able to select ones that work for all Android variations, ones that work for less than Android 9 and 10, ones that use native C++ code, and ones which are absolutely Java-based. There’s even a development-only workaround utilizing ADB.
ADB Workaround
In case your gadget is working Android Pie, run the next two ADB instructions to allow hidden API entry.
adb shell settings put international hidden_api_policy_pre_p_apps 1
adb shell settings put international hidden_api_policy_p_apps 1
In case your gadget is working Android 10 or later, run the next ADB command to allow hidden API entry.
adb shell settings put international hidden_api_policy 1
To revert to the default habits, simply substitute put
with delete
and take away the 1
.
Clearly, these instructions aren’t precisely helpful for a manufacturing app. I can let you know firsthand that correctly instructing customers on methods to use ADB is extremely troublesome. However they are often helpful if that you must replace an previous app to adjust to the brand new restrictions.
Native/JNI workaround
There are two methods you’ll be able to bypass the hidden API blacklist utilizing JNI in your Android app. One works for Android 9 and 10, and the opposite works for Android 9 and later.
Android 9 and 10
If you have already got a local portion of your app, this will probably be straightforward to implement. Simply use the JNI_OnLoad()
operate.
static artwork::Runtime* runtime = nullptr;
extern "C" jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  ...
  runtime = reinterpret_cast<artwork::JavaVMExt*>(vm)->GetRuntime();
  runtime->SetHiddenApiEnforcementPolicy(artwork::hiddenapi::EnforcementPolicy::kNoChecks);
  ...
}
Bear in mind that this technique solely works on Android 9 and 10.
Android 9 and later
For any model of Android, you could have your alternative of two libraries to bypass the hidden API restriction: FreeReflection and RestrictionBypass.
Each are straightforward to implement and use.
To implement FreeReflection, add the dependency to your module-level construct.gradle.
implementation 'me.weishu:free_reflection:3.0.1'
Then override attachBaseContext()
in your Utility class.
protected void attachBaseContext(Context base) {
  tremendous.attachBaseContext(base);
  Reflection.unseal(base);
}
If you do not have an Utility class, you’ll be able to add it fairly simply. Create a brand new class that extends Utility
after which level to it in your AndroidManifest.xml.
Instance:
public class App extends Utility {
  ...
 Â
  protected void attachBaseContext(Context base) {
    tremendous.attachBaseContext(base);
    Reflection.unseal(base);
  }
}
<manifest>
  ...
  <software
    ...
    identify=".App">
    ...
  </software>
</manifest>
To implement RestrictionBypass, add the JitPack repository to your project-level construct.gradle.
allprojects {
  repositories {
    ...
    maven { url " }
  }
}
Then add the dependency to your module-level construct.gradle.
implementation 'com.github.ChickenHook:RestrictionBypass:2.2'
And that is it. This library routinely removes the blacklist restrictions.
Java workaround
Whereas the JNI options are efficient, there are occasions you won’t wish to use native code. For those who aren’t already doing issues in C++, it could possibly add pointless measurement, together with platform restrictions, to your app. Fortunately, there are methods to bypass the hidden API blacklist utilizing solely Java.
Android 9 and 10
In Android 9 and 10, you need to use what could be referred to as double-reflection or meta-reflection to bypass the hidden API blacklist. As a result of the system solely checks what third-party apps are calling, double-reflection methods it into pondering the system is making the hidden API calls.
This trick can be utilized to name a technique to present your app hidden API exemptions, aptly named setHiddenApiExemptions()
. Merely add the next code someplace early on in your app’s lifecycle (akin to Utility’s onCreate()
technique), and it will deal with bypassing the blacklist.
Technique forName = Class.class.getDeclaredMethod("forName", String.class);
Technique getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
Class vmRuntimeClass = (Class) forName.invoke(null, "dalvik.system.VMRuntime");
Technique getRuntime = (Technique) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
Technique setHiddenApiExemptions = (Technique) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[] { String[].class} );
Object vmRuntime = getRuntime.invoke(null);
setHiddenApiExemptions.invoke(vmRuntime, new String[][] { new String[] { "L" } });
In case your app is suitable with variations of Android decrease than 9, bear in mind to wrap this in a model examine.
Android 9 and later
To bypass the hidden API blacklist on Android 9 and any later model, you need to use LSPosed’s library. This library makes use of Java’s Unsafe API, so it is unlikely to ever break.
To implement it, simply add the dependency to your module-level construct.gradle.
implementation 'org.lsposed.hiddenapibypass:hiddenapibypass:2.0'
Then use it to bypass the blacklist.
HiddenApiBypass.addHiddenApiExemptions("L");
In case your app is suitable with variations of Android decrease than 9, bear in mind to wrap this in a model examine.
Conclusion and Extra Information
There are many choices for bypassing the hidden API blacklist on Android, regardless of which platform model you goal or use. For those who’re curious to study extra about how these strategies and libraries work, you’ll want to try the next hyperlinks.