Library / SDK
bigsinger/AndroidIdChanger avatar
bigsinger/AndroidIdChanger

AndroidIdChanger is an Xposed module for scoping and rewriting Android device identifiers

Xposed Module for Changing Android Device Info

641 stars156 forksJavaApache-2.0

At a glance

What is it?
AndroidIdChanger is a Java-only Android project that works both as a plain device information viewer and as an Xposed module that replaces identifiers per package scope. The README is unusually explicit about boundaries: it refuses to fake values it cannot read, it does not touch the hardware trust chain, and it ships two mutually exclusive APK variants for legacy Xposed and modern libxposed.
Who is it for?
Adopt AndroidIdChanger if you need to verify how an app behaves with different device identifiers, on a device you own or have permission to test. Do not adopt it as a way to defeat integrity checks, since the README states it does not modify KeyMint, hardware attestation, Play Integrity or other hardware trust chains and makes no promise against integrity detection.
Can I use it commercially?
Yes. Apache-2.0 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 70 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 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two personalities in one APK family, one for legacy Xposed and one for libxposed

AndroidIdChanger is a Java-only Android project that can be used either as an ordinary device information viewer or as an Xposed module that operates with per application scope. The open source version is 2.2.1, and the source lives in a source/ subdirectory while the original doc, release and screenshot directories are kept in place.

The release choice is the first decision a user has to make, and the README makes it a table rather than prose. The legacy variant needs Android 4.2, API 17, and talks the original Xposed API 53, so it suits classic Xposed and frameworks that provide an original API compatibility layer. The modern variant needs Android 8.0, API 26, and uses libxposed API 102, so it suits frameworks that support the modern module format and RemotePreferences.

Both release APKs are in the repository as 2.2.1, one for each variant. The constraint that catches people out is stated directly: the two APKs use the same package name and signature, so they cannot be installed at the same time, and switching variants means an overwrite install. If you only want to view device information as a normal app, the rule is Android 4.2 to 7.1 means the legacy variant, while Android 8.0 and above can use either.

The README also separates two things that are easy to conflate. Framework support range is not the same as Android system support range, and any Xposed variant that has not actually been verified is marked as experimental, with the details in the compatibility document under doc/.

It shows what it can read and refuses to invent the rest

The read side is broad. The module reports system and build information, Android ID, phone and SIM data, Wi-Fi and Bluetooth, CPU and ABI, memory, storage, screen, battery, network, sensors, camera, app signatures and install sources.

What is interesting is the failure behaviour. Where a value is limited by permission or by a system privacy policy, the display says permission not granted, redacted by the system, not supported or unavailable, and the README stresses that it no longer passes off some other identifier as a stand-in for a missing value. That is a small design decision with a large effect on trust: a diagnostic screen that quietly substitutes a related value is worse than one that says it cannot see something.

The replacement side follows the same discipline. Values are generated per release variant, and they are non-empty, well formed and clearly marked as being for testing. Dimensions that are read-only keep the local display value and are not written into the replacement configuration at all, so a configuration file never contains a real identifier by accident.

For a developer testing compatibility, that is the difference between a tool that tells you what the app can see and one that quietly rewrites the world. The scope model is explicit too: the default scope is empty, the hook all apps option is off, and replacement only happens when both the in-app scope and the framework manager scope allow it.

Configuration is a validated UTF-8 properties file with field switches and package scope

The configuration is imported, exported and replaced wholesale, and the README describes strict validation on every path. The format is UTF-8 properties, and the configuration contains field switches, value sources and exact package name scopes.

The import is capped at 256 KiB and checked against a field whitelist, strict UTF-8, type, length, duplicate entries, package names and version. The important detail is the ordering: the configuration is only committed after the whole parse succeeds, so a malformed file leaves the previous configuration intact instead of half applying.

The authoritative copy of the configuration lives in a single SharedPreferences file and is committed in batches. In the normal app environment it uses private mode. The legacy entry point is the exception, because of the cross-process read restrictions in the original Xposed API, so it needs the framework to explicitly allow Xposed readable mode and otherwise falls back safely to private mode.

There is also a data minimisation rule that is easy to miss. The app does not persist a snapshot of the real device information of the machine it runs on, and a portable configuration contains only replaceable fields, so read-only device fields from older configurations are discarded on import. In other words, exporting a config and handing it to someone else does not leak your device's real identifiers.

Six steps from install to a scoped hook

The quick usage section is a numbered procedure and it is worth following in order, because the scoping model has two gates. You install the release APK that matches your system and framework. If you only want to view your own device information, you open the app and tap the environment check, and the README notes you can see the non-sensitive dimensions even if you refuse sensitive permissions.

For the Xposed path you first enable the module in the framework manager and tick only the target applications you intend to test. Then inside the app you tap the one-click random button or edit fields by hand, and tick the fields you want replaced. Greyed out fields are display-only and take no part in the replacement. In the Hook App screen you select the fully qualified target package name and save.

The last step differs between the two variants and is the main operational difference. The legacy entry point requires you to force stop and restart the target application, while the modern entry point receives configuration changes in real time, though a target application that has already cached its result still needs its process restarted. That is a meaningful difference when you are iterating: the modern path removes most of the restart wait, but it does not remove it entirely.

Full steps, permission purposes, the configuration format and troubleshooting are in the usage help document under doc/.

Android's own scoping rules are the real ceiling

The boundaries section is the most technically useful part of the README, because it describes the platform rather than the tool. From Android 8, ANDROID_ID is scoped by application signature, user and device, and it is not a permanent hardware identifier. From Android 10, identifiers such as IMEI, MEID, serial number, IMSI and ICCID are generally no longer exposed to ordinary applications.

Android 17 tightens things further by applying stricter limits to modification of static final fields, which is why the modern entry point hooks only public methods, while the legacy entry point makes a best effort on Build.* fields. The README is explicit about the consequence: direct field reads, native reads and inlined constants may still return the true value.

That is the honest technical floor for any tool in this category, and it is the reason a module like this cannot deliver a uniform promise across devices. What remains variable per device is exactly what a hook cannot reach.

Two further limits are worth naming. The project does not modify KeyMint, hardware attestation, Play Integrity or any other hardware trust chain, and it makes no promise to work against integrity detection. And the environment's own restrictions still apply, which is why the module asks for elevated permissions and why the README warns to use it only on devices and applications you own or have clearly been authorised to test, since using Xposed changes the runtime behaviour of the target process.

A pure Java build with no native code and no network permission

The build section lists the toolchain precisely: AGP 9.2.1, Gradle 9.4.1, JDK 17, compileSdk and targetSdk 37, Java 11, and the Android Support Library 28. There is no Kotlin, no AndroidX, no NDK, no CMake and no .so files at all. A pure Java APK is CPU ABI independent, so it runs on both arm32 and arm64 devices.

The three Gradle commands in the README cover unit tests for both variants, lint for both release variants, and assembling both release APKs:

bash
cd source
./gradlew.bat testLegacyDebugUnitTest testModernDebugUnitTest
./gradlew.bat lintLegacyRelease lintModernRelease
./gradlew.bat assembleLegacyRelease assembleModernRelease

Running the test, lint and assemble tasks for both variants in one command is the point of the layout. A change that breaks only the modern path still fails the build, which is what you want from a project that ships two flavours of the same code.

The project also states that Gradle and Maven mirrors are already written into the project with the official repositories only as a fallback, and that the full toolchain, source layering and signing notes are in source/README.md. On the privacy side the README states there is no Bugly, no advertising SDK and no custom telemetry, and the app does not request network permission. Logs do not record target package names or the replaced IMEI, IMSI, ICCID and serial values. The README also notes that telemetry, root deletion, target sandbox copying, chmod 777, module hiding, native environment detection and real style identifier datasets from an older private project did not make it into the new source.

Maintenance, licence and what a reviewer should actually read

The last push was on 2026-08-14 and the repository is not archived, so work is ongoing, and the repository has no GitHub releases, so the version to track is the one in the README, 2.2.1, with the prebuilt APKs linked from the repository itself.

The licence is Apache 2.0, with the LICENSE file at the root. Third party components and their licences are listed separately in THIRD_PARTY_NOTICES.md, and the README asks you to read the disclaimer document as well. Those are points for your own review to pick up rather than conclusions for this article to draw, since a licence note is not legal advice.

The structure of the repository is itself informative. Alongside the source, doc, release and screenshot directories, the top level holds SECURITY.md and CONTRIBUTING.md, which the README points to for security reporting and contribution rules. The compatibility document under doc/ is the file to consult when a framework behaves unexpectedly, since unverified Xposed variants are marked as experimental there.

The related platform behaviour is anchored to external references rather than to the project itself: the Android 17 behaviour changes page, the Android identifier best practices page and the libxposed API repository. That is a sensible choice for a module in this category, because the rules it works within are set by the platform and the framework, and those change more often than this code does.

Editorial conclusion

Adopt AndroidIdChanger if you need to verify how an app behaves with different device identifiers, on a device you own or have permission to test. Do not adopt it as a way to defeat integrity checks, since the README states it does not modify KeyMint, hardware attestation, Play Integrity or other hardware trust chains and makes no promise against integrity detection. Verify first which Xposed variant your framework supports, since the legacy and modern APKs share a package name and signature and cannot be installed side by side, and note that on Android 17 only public methods are hooked in the modern entry point, so some static fields may still read as their real values.

Frequently asked questions

How do I install AndroidIdChanger on my device?

Pick the release APK that matches your setup, legacy for classic Xposed on Android 4.2 and later, or modern for libxposed on Android 8.0 and later. The two APKs share a package name and signature, so they cannot be installed at the same time and switching means an overwrite install.

Does AndroidIdChanger need internet permission?

No. The README states there is no Bugly, no advertising SDK and no custom telemetry, and the app does not request network permission. Device information exports mask sensitive identifiers by default.

Why does the app still show my real identifier on some devices?

From Android 10, identifiers such as IMEI, serial number, IMSI and ICCID are generally no longer exposed to ordinary apps, and from Android 17 stricter limits apply to modifying static final fields, so the modern entry point hooks only public methods. The README notes that direct field reads, native reads and inlined constants may still be the true value.

Can AndroidIdChanger replace identifiers in every app on my device?

No. The default scope is empty, the hook all apps option is off, and replacement only happens when both the in-app scope and the framework manager scope allow it. You select the exact target package name in the Hook App screen before saving.

What licence is AndroidIdChanger released under?

It is open source under the Apache License 2.0, with the LICENSE file at the repository root. Third party component licences are listed in THIRD_PARTY_NOTICES.md, and the README also asks you to read the disclaimer document before use.

Official sources

  1. bigsinger/AndroidIdChanger on GitHub
  2. Issues
  3. License: Apache-2.0
  4. Project website
  5. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bigsinger-androididchanger.svg)](https://hysenlabs.com/projects/bigsinger-androididchanger)

Was this useful?