[BUG] [MicroG] DynamiteContextFactory bug breaks paid/verified app license checks
- /e/OS version(s):
3.4-a15-20260114569178-official-FP6
3.5-a15-20260211580868-official-FP6 - Device model(s): Fairphone 6
- Impacted Application:
- MicroG
- (example app, BusinessCalendar2)
- Affected application/URL:
- microG: 0.3.11.250932-15
Summary:
Apps fail to verify Play Store licenses due to MicroG's incomplete emulation of DynamiteContextFactory API. E.g., Business Calendar 2 ("BC2" ; com.appgenix.bizcal) fails to see its valid license -- verified and purchased on the same Google account -- and incorrectly shows it's "pay to go pro" upgrade screen.
Expected:
Apps using the Play Billing Library should find existing purchases & unlock their pro features.
Observed:
BC2 launches & shows its GoProActivity screen, asking for a new purchase even though one's already been made.
Analysis:
Logcat shows the clear sequence pointing to an incompatibility with MicroG.
-
OK Initial Billing comm:
BC2 successfully connects to MicroG's billing service & confirms support for in-app purchases + subscriptions.02-13 11:18:13.355 D Billing : isBillingSupported(...type=subs)=Bundle[{...RESPONSE_CODE=0}] 02-13 11:18:13.362 D Billing : isBillingSupported(...type=inapp)=Bundle[{...RESPONSE_CODE=0}] -
License Query init:
App correctly queries for existing purchases for license verification02-13 11:18:13.379 D Billing : getPurchasesExtraParams(...type=inapp,...) 02-13 11:18:13.392 D Billing : getPurchasesExtraParams(...type=subs,...) -
DynamiteContextFactory Emulation FAIL:
The problem's here. BC2 attempts to useDynamiteContextFactory, but fails with "Unsupported class loader" warnings. This appears to be the core incompatibility in MicroG's GMS emulation.02-13 11:18:13.124 D DynamiteContextFactory: Created and cached a new DynamiteContext for cacheKey: com.google.android.gms.measurement.dynamite-com.appgenix.bizcal 02-13 11:18:13.125 W appgenix.bizcal: Unsupported class loader 02-13 11:18:13.191 D DynamiteContextFactory: Created and cached a new DynamiteContext for cacheKey: com.google.android.gms.maps_dynamite-com.appgenix.bizcal 02-13 11:18:13.191 W appgenix.bizcal: Unsupported class loader 02-13 11:18:13.307 W appgenix.bizcal: Unsupported class loader 02-13 11:18:13.307 D DynamiteContextFactory: Created and cached a new ClassLoader for cacheKey: com.google.android.gms.measurement.dynamite-com.appgenix.bizcal ClassLoader: 70308833 02-13 11:18:13.377 W appgenix.bizcal: Unsupported class loader 02-13 11:18:13.377 D DynamiteContextFactory: Created and cached a new ClassLoader for cacheKey: com.google.android.gms.maps_dynamite-com.appgenix.bizcal ClassLoader: 207065700 -
Logic continues with bad Data:
Because theDynamiteContextFactorycall FAILs,getPurchasesExtraParamscall returns an empty list. Looks like BC2's logic sees this empty list & determines -- correctly in this case -- there's no license. -
Incorrect App Behavior Triggered:
BC2 then launches itsGoProActivitylicensing screen -- and there's the problem. This isn't an app bug; it's just the correct response to the bad data it received from MicroG.02-13 11:18:17.392 I ActivityTaskManager: START u0 {cmp=com.appgenix.bizcal/.ui.GoProActivity} ...
Root Cause:
The DynamiteContextFactory implementation in MicroG fails to provide a compatible ClassLoader for dynamically loaded GMS modules (e.g., com.google.android.gms.measurement.dynamite). When the Google Play Billing library (or one/more of its deps?) attempts to use this ClassLoader, it fails, logged as an "Unsupported class loader" warning. The silent fail prevents a getPurchasesExtraParams call from correctly querying Google's servers & parsing the response.
This results in an empty purchase list being returned to the application.
Conclusion:
This is a specific implementation defect in MicroG's DynamiteContextFactory.
A likely fix requires modifying it to return a ClassLoader that's' fully compatible with the GMS client libraries. The new ClassLoader should correctly resolve and load resources and classes from both the dynamically loaded module's APK and the host app's context. Once the "Unsupported class loader" failure is remedied, it should allow the license verification process to complete successfully.