An LSPosed (Xposed) module that spoofs telephony country/operator inside Google Play Services and Google Maps so that GMS Location History / Timeline can be enabled on devices whose SIM is registered in a region where Google has restricted the feature.
The module only loads in:
com.google.android.gmscom.google.android.gsfcom.google.android.apps.maps
In those processes it returns fake values for:
TelephonyManager.getSimCountryIso{,ForPhone}→usTelephonyManager.getNetworkCountryIso{,ForPhone}→usTelephonyManager.getSimOperator{,Numeric,ForPhone}→310030TelephonyManager.getNetworkOperator{,Numeric,ForPhone}→310030SubscriptionInfo.getCountryIso()→usSubscriptionInfo.getMcc{,String}()→310SubscriptionInfo.getMnc{,String}()→30/030SystemProperties.get(...)forgsm.(sim.)?operator.(numeric|iso-country)
Other property reads pass through unchanged.
./gradlew :xposed:assembleDebug
# output: xposed/build/outputs/apk/debug/xposed-debug.apkRelease builds never use the Android debug key. Configure all four environment variables to produce a signed release APK:
RELEASE_STORE_FILE
RELEASE_STORE_PASSWORD
RELEASE_KEY_ALIAS
RELEASE_KEY_PASSWORD
Without those variables, assembleRelease produces an unsigned APK suitable
for build verification only. Keep the release keystore and its passwords out
of the repository.
Pushing a v* tag runs the GitHub release job. Configure these repository
secrets first: RELEASE_KEYSTORE_BASE64, RELEASE_STORE_PASSWORD,
RELEASE_KEY_ALIAS, RELEASE_KEY_PASSWORD, and RELEASE_APK_CERT_SHA256.
The release job stops before building if any required secret is absent.
On Windows, create a new keystore and configure all five secrets interactively:
.\scripts\setup-release-signing.ps1The script requires keytool, an authenticated gh CLI, and a remote named
origin pointing to GitHub. It creates a PKCS12 keystore in the user profile
by default and never writes its passwords to the repository.
- Install the APK with
adb install(or any installer). - In LSPosed manager, enable Timeline Unlocker (Xposed).
- Confirm the scope includes the three Google packages above.
- Force-stop GMS, Maps, and GSF (or reboot). Open Maps → Timeline.
Spoofing country to us in com.google.android.apps.maps makes Maps stop
applying its built-in WGS-84 → GCJ-02 conversion, so the live location
dot drifts off the China map tiles by a few hundred meters.
To compensate, the Maps process additionally hooks
Location.getLatitude() / Location.getLongitude() and applies the public
WGS-84 → GCJ-02 transform when the coordinate falls inside the China
bounding box. The dot then realigns with the GCJ-02 tiles.
This compensation is only installed in com.google.android.apps.maps;
GMS / GSF still see the original WGS-84 values, which is what Location
History upload expects.