Root Cause Analysis of Automatic Coupon Redemption Caused by Android Activity Rebirth
This article analyzes a puzzling case where coupons appeared to be redeemed automatically in a mobile app, tracing the issue to Android's activity rebirth mechanism, explaining the lifecycle, memory reclamation, state saving, and presenting a robust fix to prevent the bug.
Background – In a local‑life group‑buying scenario, merchants reported that coupons were being marked as redeemed without the consumer scanning the QR code, leading to the suspicion of an "automatic" redemption bug.
Investigation Process – The team collected information from consumers A and B, the merchant, and logs from the front‑end, back‑end, and client. They ruled out business‑logic errors, delayed notifications, and QR‑code duplication, focusing on the runtime environment.
Key Findings – Log analysis showed that during the second redemption there was no scan request on the server side, and the client logs contained a cold‑start event. This indicated that the app was being revived from the background directly into the redemption page.
Android Activity Lifecycle – Android activities have six core callbacks: onCreate() , onStart() , onResume() , onPause() , onStop() , and onDestroy() . When the system reclaims memory, it may destroy a background activity and later recreate it, invoking onSaveInstanceState() to store the initial UI state and onRestoreInstanceState() to restore it.
Memory Reclamation – Android keeps background apps in a cache, but under low‑memory conditions it terminates processes based on priority (foreground > visible > service > cached). An activity that is stopped can be killed, causing its UI state to be saved as the initial page rather than the final state.
Root Cause – After the first coupon redemption, the merchant’s app was sent to the background. The system reclaimed memory, saved the WebView’s initial state (the redemption page), and later recreated the activity when the app was brought forward for the second consumer. The merchant mistakenly operated on the previous consumer’s page, making it appear as if the coupon was auto‑redeemed.
Solution – Separate the operation page and the result page into two distinct WebView containers and use an open‑schema navigation to close the operation activity after a successful redemption. This prevents the previous page from being restored after a memory‑reclaim event. Additionally, enable the developer option "Don’t keep activities" for testing the rebirth scenario.
Conclusion – Activity rebirth is an Android‑level mechanism that affects any WebView‑based front‑end. Developers must understand both the UI code and the underlying runtime environment to safeguard against similar issues.
ByteDance ADFE Team
Official account of ByteDance Advertising Frontend Team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.