aosp-android-jar: swapping the SDK android.jar for AOSP builds
AOSP编译出的android.jar,sdk里面以前反射调用的方法,现在可以直接调用了。
At a glance
- What is it?
- aosp-android-jar publishes android.jar files compiled from AOSP source, one per API level, so hidden platform APIs can be called directly instead of through reflection. The trade is a compile-time break whenever AOSP signatures drift from the public SDK.
- Who is it for?
- Teams that must touch non-SDK platform APIs, such as device management or package installation code, get real compile-time type checking and a working method list from aosp-android-jar, and the swap costs only a file replacement plus a project sync. Applications that stay inside the public SDK gain nothing and take on the risk of an undocumented AOSP signature change.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 121 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Reaching AOSP platform APIs without writing reflection wrappers
The problem this project solves is narrow and concrete. The android.jar shipped inside the Android SDK exposes only the public API surface, so a developer who needs a platform method that the SDK hides has no compile-time symbol for it. The usual answer is reflection: look the method up by name and string, cast the result, and hope the signature is stable. The project description states the intent plainly, saying that methods which previously had to be invoked reflectively inside the SDK can now be called directly. aosp-android-jar is therefore not a library that ends up in your application. It is a replacement for one file that the build toolchain already loads, and it targets developers working on system-adjacent features, device policy tooling, and package installation flows where the public SDK stops short. Nothing in the repository adds runtime behaviour, and the Sample project is a consumer of the file rather than part of it. That distinction matters for review, because the risk sits in the compiled contract of your code, not in a new dependency tree.
A file swap under platforms, followed by a sync
The whole installation path is a replacement operation. The usage notes tell you to replace the android.jar under the platform directory of your Android SDK, where the path is written as `${Android Sdk}/platforms/andorid-api/`, and then sync the project. Two screenshots in the repository document the same procedure from both ends, one showing the current SDK path and version and one showing the same-named file being replaced in that directory. Because the path in the notes is spelled with the letters transposed, check the actual folder name on your machine before copying anything into it. The repository layout is a set of API level directories, from android-28 through android-37, each holding a jar for that level, plus a Sample directory, a picture directory, a LICENSE file and a README. Releases follow the same numbering, with tags named 37 (API37), 36.1 (API36-1) and 36 (API36), so the directory name and the release label tell you which Android version a given jar was built from. Syncing after the swap forces the IDE and the build to re-resolve the platform jar against the new bytecode.
Calling a hidden API does not make the call permitted
The project links to the platform documentation on non-SDK interface restrictions and then states the boundary in blunt terms: being able to call something does not mean you are allowed to call it, and blacklisted APIs remain subject to those restrictions. Two exceptions are named, system applications and anything running with root permission, since neither falls under the ordinary app restrictions. This is the part that is easy to misread. The jar removes a compiler barrier, not a policy barrier. An application distributed through an app store that calls a non-SDK interface through reflection already faces enforcement on real devices, and the same enforcement applies when the call site is a plain typed invocation. What changes with aosp-android-jar is the moment of discovery. Instead of a reflective lookup that silently returns null or throws at runtime, a method that does not exist in the AOSP build of your chosen API level fails as a compile error. The value of the project sits in that shift, and the risk of shipping a restricted call sits exactly where it already was.
AOSP signatures force a compatibility branch at every call site
The AOSP interfaces do not always match the public SDK interfaces, and the project takes a deliberate position on that gap. The android.jar interfaces are kept in line with current AOSP interfaces, but some classes are modified so that older system interfaces are added back, and those modifications are described in the notes for the corresponding jar directory, which means a short adaptation is expected in your code. The example given is the package installer path, where the constructor of PackageInstaller takes an extra argument on Android 12 and later, and the code branches on the SDK level.
final IPackageInstaller iPackageInstaller = AppGlobals.getPackageManager().getPackageInstaller();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
packageInstaller = new PackageInstaller(iPackageInstaller, null, null, UserHandle.myUserId());
} else {
packageInstaller = new PackageInstaller(iPackageInstaller, null, UserHandle.myUserId());
}The adaptation is exactly the kind of thing a typed API makes visible instead of hiding. There is a practical consequence to the design that the notes do not spell out: the branch is now your responsibility in source code, and it has to be maintained across every API level your application supports, not just the newest one you build against. Where you used to hide differences behind a reflective call, you now carry an explicit compatibility layer in every affected method.
Return value drift still pushes some calls back into reflection
Adding symbols does not remove every problem that reflection was hiding. The project notes that some newer SDK interfaces return a different value than their older counterparts, and that if you do not consume the return value, the code may compile without complaint and then fail at runtime. In that situation the guidance is to fall back to a reflective call. The example offered is a lock pattern save call whose signature differs across the API 28 and API 29 boundaries, passing a null argument, a password quality constant and the current user id:
lockPatternUtils.saveLockPassword(it, null, DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, UserHandle.myUserId())This is the honest limit of the whole approach. The jar converts missing symbols into compile errors, but it cannot convert a changed return contract into a compile error, because a compatible-looking call site still type checks. A team that reads this project as a blanket replacement for reflection wrappers will find that a subset of call sites still needs the old style, and the split between the two styles has to be a decision rather than an accident.
The bundled Sample project and a keystore worth inspecting
The repository includes a Sample directory that shows how the swapped jar is consumed: an app module, a build.gradle, a settings.gradle, a gradle.properties, a buildSrc directory, a gradle directory, the gradlew and gradlew.bat wrappers, an impl directory, an .idea directory, a .gitignore, a keystore directory and its own README. Two entries in that listing deserve attention before you copy the sample into your own tree. The keystore directory means signing keys travel with the repository, and you should confirm what it holds and who can use it rather than assuming it is a throwaway debug key. The committed .idea directory is project noise that adds merge conflicts for anyone on a different IDE. The useful part of the sample is the structure it demonstrates, a multi-module Gradle build that compiles against the replaced platform jar, which is the smallest working example of the swap described in the usage notes.
Release labels, the last push date, and the licence question
The published releases are labelled 37 (API37) dated 2026-06-24, 36.1 (API36-1) dated 2025-07-02 and 36 (API36) dated 2025-06-12, and the last push to the repository was on 2026-06-24. The newest directory in the tree, android-37, matches the newest release, so the jar set tracks the platform versions that Android tooling is shipping. The point release label on 36.1 shows that the numbering can carry a patch suffix, so matching a directory to a target platform is a matter of reading the release name rather than assuming one tag per API level. The repository is published under the MIT licence, with a 2020 copyright notice, which allows modification and redistribution of the repository contents provided the notice travels with copies. The licence of the AOSP sources that these jars are compiled from is a separate question, and the repository documentation does not address it. If you intend to redistribute a jar inside a product rather than only use it on a developer machine, resolve that licence question first.
Editorial conclusion
Teams that must touch non-SDK platform APIs, such as device management or package installation code, get real compile-time type checking and a working method list from aosp-android-jar, and the swap costs only a file replacement plus a project sync. Applications that stay inside the public SDK gain nothing and take on the risk of an undocumented AOSP signature change. Before adopting, confirm the android-3x directory matches your compileSdk, read the modification notes shipped with that jar, and check the licence of the AOSP sources behind the file, which the repository does not address.
Frequently asked questions
How do I install aosp-android-jar in an Android project?
Replace the android.jar in your Android SDK platform directory, using the path shown in the screenshots in the repository, and then sync the project so the build resolves the new file. The jar is picked up from the SDK platform folder rather than added as a Gradle dependency.
Which Android API levels does aosp-android-jar provide?
The repository holds one directory per API level, running from android-28 up to android-37. Releases are named after those levels, including 37 (API37), 36.1 (API36-1) and 36 (API36).
Does using aosp-android-jar let me bypass the non-SDK interface restrictions?
No. The project states that being able to call an API does not mean the call is permitted, and that blacklisted APIs remain subject to the platform restrictions on non-SDK interfaces. It names system applications and processes running with root permission as the cases where those restrictions do not apply.
When do I still need reflection after switching to aosp-android-jar?
Where a newer SDK interface returns a different value than its older counterpart and your code does not consume the return value, the call may compile and then fail at runtime. For those call sites the project recommends keeping a reflective form, as in the lock pattern save example it shows.
What licence is aosp-android-jar released under?
The repository is published under the MIT licence with a 2020 copyright notice. The licence covering the AOSP sources compiled into the jars is not addressed in the repository documentation, so check it separately if you plan to redistribute the file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/reginer-aosp-android-jar)Was this useful?