Skip to content

Android Scroll Freeze After Repeated Embedded Native Maps #167

@adworks

Description

@adworks

Bug Report

Plugin(s)

@capacitor/google-maps: 8.0.1
@capacitor/core: 8.1.0
@capacitor/android: 8.1.0
@capacitor/app: 8.0.1
@ionic/angular: 8.x
@angular/core: 20.x

Capacitor Version

💊   Capacitor Doctor  💊

Latest Dependencies:

  @capacitor/cli: 8.2.0
  @capacitor/core: 8.2.0
  @capacitor/android: 8.2.0
  @capacitor/ios: 8.2.0

Installed Dependencies:

  @capacitor/cli: 8.1.0
  @capacitor/ios: 8.1.0
  @capacitor/android: 8.1.0
  @capacitor/core: 8.1.0

[success] Android looking great! 👌
[error] Xcode is not installed

Platform(s)

Android
Samsung Galaxy S24 Ultra
Android 16

Current Behavior

On Android, repeated use of multiple scrollable Ionic pages that embed native @capacitor/google-maps views can leave the app in a state where manual drag scrolling stops working application-wide until the Android process is fully restarted.

The failure happens after moving quickly through several map-heavy screens, scrolling them, and sometimes presenting/dismissing an Ionic alert during the same session.

Once the bug appears:

  1. touchstart, touchmove, and pointerdown still reach the WebView.
  2. ion-content is still present, visible, and configured with overflowY: auto.
  3. Programmatic scroll still works.
  4. Only manual drag-to-scroll is broken.
  5. Navigating to a different page does not fix it.
  6. Backgrounding/foregrounding the app does not fix it.
  7. Resetting Angular/Ionic shell state does not fix it.
  8. Destroying all currently tracked native maps does not fix it.
  9. Remounting the affected ion-content does not fix it.
  10. Toggling scrollY on ion-content does not fix it.
  11. Killing the app process from Android recents and relaunching clears the issue immediately.

Expected Behavior

Repeated use of embedded native Google Maps inside ion-content should not break manual drag scrolling for the current app process.

Code Reproduction

I do not yet have a minimal public reproduction repo, but the issue is reproducible in a real Capacitor Android app with these conditions:

  1. Create at least 2-3 Ionic pages using ion-content.
  2. Embed native @capacitor/google-maps views in those pages.
  3. Navigate quickly between those pages multiple times.
  4. On each page:
    • interact with the native map
    • scroll the page down and back up
  5. Optionally present and dismiss an Ionic alert during the same session.
  6. Continue repeating until manual drag scrolling stops working.

The issue becomes easier to reproduce when:

  1. there are multiple map-bearing screens in the same flow
  2. pages are repeatedly created/destroyed in quick succession
  3. the user alternates between page scrolling and native map interaction

Other Technical Details

Framework stack:

  • Angular 20
  • Ionic 8
  • Capacitor 8

Android runtime:

  • native Capacitor Android build
  • physical device testing
  • Samsung Galaxy S24 Ultra
  • Android 16

Observed package versions:

  • @capacitor/google-maps: 8.0.1
  • @capacitor/core: 8.1.0
  • @capacitor/android: 8.1.0
  • @ionic/angular: ^8.0.0
  • @angular/core: ^20.0.0

Additional Context

Important findings from our diagnostic session:

  1. This does not look like a leftover HTML overlay:
    • activeOverlayCount = 0
    • backdropCount = 0
    • DOM hit-testing still returned normal HTML elements
  2. This does not look like a simple native-map transparency refcount leak:
    • transparency bookkeeping returned to zero correctly
  3. There was a real late-lifecycle race where map setup could continue after component destroy, but fixing that race did not remove the bug.
  4. When the bug is active:
    • touch events still enter the WebView
    • the blocked page still has a valid ion-content
    • scrollHeight > clientHeight
    • overflowY = auto
    • scrollTop can still be changed programmatically
  5. This narrows the remaining symptom:
    • the drag gesture -> scroll pipeline is broken
    • the page is still alive
    • the scroll container is still alive
    • only gesture-driven scrolling is lost
  6. With all embedded native maps temporarily disabled in the same test flow, the bug stopped reproducing.
  7. Re-enabling only one embedded native map screen was enough for the bug to return.

Representative log snippets from the session:

[native-map] gis-draw-map-bl2c4kfca1b ngOnDestroy
[native-map] gis-draw-map-bl2c4kfca1b destroy-start {"hasMap":true,"transparencyHeld":true}
[native-map] gis-draw-map-bl2c4kfca1b destroy-success
[native-map] gis-draw-map-bl2c4kfca1b late-setup-cleanup {"stage":"setup-after-initialFocus","destroyed":true,"attemptToken":1,"currentToken":2,"hasMap":false}

The race above was real, but after adding defensive cleanup for it, the scroll freeze still reproduced.

[native-map] registry destroy-all-start {"reason":"home-dashboard-test-button","activeMaps":0}
[native-map] registry destroy-all-finished {"reason":"home-dashboard-test-button","activeMaps":0}

The logs above show that, when the app was already frozen, the global native-map registry no longer knew about any active map instances.

[data-entry-input-debug] {"hasContent":true,"scrollTop":0,"scrollHeight":1849,"clientHeight":716,"overflowY":"auto"}
[input-debug] snapshot {"reason":"data-entry-page-dump","nativeMapActive":false,"ionContent":{"label":"visible:ion-content.md.content-ltr.hydrated","rect":{"top":85,"left":0,"width":384,"height":631},"scrollTop":0,"scrollHeight":1849,"clientHeight":716,"overflowY":"auto"},"recentEvents":[{"type":"touchmove"},{"type":"touchmove"},{"type":"touchmove"}]}

The logs above show that:

  1. touch input was still reaching the WebView
  2. the blocked page still had a normal scroll container
  3. manual drag scrolling was broken anyway

Current working hypothesis after elimination:

  1. something in Android runtime gesture arbitration between WebView scrolling and the native map surface remains corrupted after repeated embedded-map usage
  2. the problem appears lower than normal Angular/Ionic page lifecycle and lower than ordinary DOM overlays

A screen recording is available here: https://www.youtube.com/shorts/_kagfuN7VYk

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions