ionic-team / ionic-team/capacitor-google-maps

Android Scroll Freeze After Repeated Embedded Native Maps

Open
#167 1 comment 1 reaction 0 assignees View on GitHub
triage
Dominant language
TypeScript
Stars
32
Forks
47
PR merge metrics
No merged PRs in 30d

Description

## 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.