mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 02:36:12 -04:00
fix(upgrade): Add a persistent acknowledgement safety net for Play purchases
Play auto-refunds (and revokes) purchases not acknowledged within 3 days. The in-process ack machinery covers every case where the process lives long enough; what it cannot cover is a process death around the Play sheet (aggressive OEM task killers) followed by the user not reopening the app before the deadline. Add a gplay-only WorkManager safety net: - PurchaseAckWorker: self-completing sweep via a new bounded BillingManager.ensureAllAcknowledged() that refreshes and acknowledges in the same coroutine (the reactive ack collector is async, so a worker cannot prove its acks happened through it). Retries with exponential backoff until the purchase's refund deadline, then gives up visibly. - PurchaseAckScheduler: two unique work identities. A launch watch (REPLACE, armed and awaited before launchBillingFlow with a 30min delay so it cannot complete while the user is still in the sheet) and a discovered-purchase rescue (KEEP, 1min delay, armed directly from an ack pass that finds unacknowledged purchases, pre-attempt). Separate identities so a new purchase flow can never displace a pending rescue. Both triggers are fail-open: a broken WorkManager never blocks a purchase or an ack. WorkManager resolves via Provider at first arm so eager Application-time construction of the billing stack cannot trigger WorkManager's on-demand initialization prematurely. - Nothing cancels the work from the foreground path: an ack pass can see zero unacked purchases while the sheet is still open, so the worker completes itself after its own reconciliation instead. The ack pass now runs under a mutex (the worker sweep and the reactive collector would otherwise race the token bookkeeping) and reports per-outcome counts for the sweep result mapping. This is a port of d4rken-org/sdmaid-se#2685; the ported sources are byte-identical to the donor apart from the package rename. CAPod had no explicit WorkManager wiring at all (work-runtime only arrived transitively through Glance), so this also adds it: - addWorkerManager() pinning androidx.work 2.7.1, the version already resolved via Glance, plus androidx.hilt:hilt-work and its KSP compiler. work-runtime-ktx is required at 2.7.1: CoroutineWorker, Operation.await, OneTimeWorkRequestBuilder and workDataOf all still live in the ktx artifact at that version. androidx.hilt moves 1.0.0 -> 1.2.0 (by conflict resolution) because 1.0.0's hilt-compiler ships no KSP SymbolProcessorProvider, so @HiltWorker would generate nothing. - WorkManagerModule providing the singleton WorkManager. - App implements Configuration.Provider with the injected HiltWorkerFactory. WorkManager 2.7.1 still declares that interface as getWorkManagerConfiguration(), not the later property form. - The manifest removes androidx.work's startup initializer so the on-demand configuration is the one that takes effect. FOSS stays untouched behaviour-wise: all new billing types live in src/gplay, workers need no manifest entry, and the worker factory resolves the worker only in gplay variants.
This commit is contained in:
@@ -130,6 +130,22 @@ fun DependencyHandlerScope.addDataStore() {
|
||||
implementation("androidx.datastore:datastore-preferences:1.1.4")
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.addWorkerManager() {
|
||||
// Resolved transitively via Glance today; declared explicitly so the safety-net worker does not
|
||||
// depend on Glance's choice. work-runtime-ktx is NOT an empty shell at this version: at 2.7.1
|
||||
// CoroutineWorker, OperationKt.await, OneTimeWorkRequestBuilder and workDataOf all live in the
|
||||
// ktx artifact (they only moved into work-runtime on later releases).
|
||||
val version = "2.7.1"
|
||||
implementation("androidx.work:work-runtime:$version")
|
||||
implementation("androidx.work:work-runtime-ktx:$version")
|
||||
testImplementation("androidx.work:work-testing:$version")
|
||||
|
||||
// androidx.hilt 1.0.0's hilt-compiler ships no KSP SymbolProcessorProvider, so @HiltWorker
|
||||
// would silently generate nothing under this project's KSP setup.
|
||||
implementation("androidx.hilt:hilt-work:1.2.0")
|
||||
ksp("androidx.hilt:hilt-compiler:1.2.0")
|
||||
}
|
||||
|
||||
fun DependencyHandlerScope.addGlance() {
|
||||
implementation("androidx.glance:glance-appwidget:${Versions.Glance.core}")
|
||||
implementation("androidx.glance:glance-material3:${Versions.Glance.core}")
|
||||
|
||||
Reference in New Issue
Block a user