bug: rotating the device while the photo picker is open relaunches it, stacking a second picker over the preview
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 68/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- android, typescript
- Lĩnh vực
- mobile
Hướng nghiên cứu
Xác định IONCAMROpenPhotoPickerActivity và khai báo của nó trong manifest của thư viện, sau đó kiểm tra cách onCreate sử dụng savedInstanceState trước khi khởi chạy picker. Tái hiện luồng xoay màn hình trên Android khi photo picker đang mở. Được xem là hoàn tất khi thao tác xoay giữ nguyên picker hiện có mà không xếp chồng thêm một instance; kiểm tra xem image editor và các loading activity được khai báo tương tự có cùng mẫu này hay không.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Bug Report
Plugin version: @capacitor/camera 8.2.0 — also reproduced against ioncamera-android 1.0.2 (shipped in 8.2.2)
Capacitor version: 8.4.0
Platform: Android 13, Samsung Galaxy Tab Active3 (SM-T570), com.google.android.photopicker versionName 17
Current behavior
Rotating the device while the system photo picker is open launches a second picker instance on top of the first one. It is most visible when the user has opened the picker's preview screen: after rotating, the selection grid reappears over the preview.
Expected behavior
A configuration change should not relaunch the picker. The already-open picker should simply handle the rotation itself.
Steps to reproduce
- Call
Camera.chooseFromGallery({ allowMultipleSelection: true }). - In the system photo picker, select a photo and open the preview.
- Rotate the device to landscape.
- A second picker opens on top.
The picker options are irrelevant — the same happens with default options and with allowMultipleSelection: false.
Root cause
IONCAMROpenPhotoPickerActivity is declared in the library manifest without android:configChanges:
<activity
android:name="io.ionic.libs.ioncameralib.view.IONCAMROpenPhotoPickerActivity"
android:exported="false"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
So a rotation destroys and recreates it. Its onCreate then passes savedInstanceState to super and never reads it again, calling launchSinglePicker / launchMultiplePicker unconditionally:
protected void onCreate(android.os.Bundle);
0: aload_0
1: aload_1
2: invokespecial // ComponentActivity.onCreate
... // reads intent extras only — savedInstanceState is never tested
110: invokespecial // launchMultiplePicker
119: invokespecial // launchSinglePicker
Every recreation therefore launches another picker. This is visible in the activity stack, captured while the bug was on screen:
#3 com.google.android.photopicker/MainActivity <- resumed, the one "on top"
#2 com.google.android.photopicker/MainActivity <- first instance, showing the preview
#1 <app>/io.ionic.libs.ioncameralib.view.IONCAMROpenPhotoPickerActivity
#0 <app>/MainActivity
Both picker instances have resultTo=IONCAMROpenPhotoPickerActivity.
Note that the host app's own MainActivity declares android:configChanges="orientation|screenSize|…" (the Capacitor default), which is why the rest of the app absorbs rotation without issue — the library's proxy activity does not inherit that.
Suggested fix
Either guard the launch in onCreate:
if (savedInstanceState == null) {
// launchSinglePicker / launchMultiplePicker
}
or declare android:configChanges on the activity in the library manifest.
IONCAMRImageEditorActivity and IONCAMRLoadingActivity are declared the same way and may be affected by the same pattern.
Workaround
Overriding the declaration in the app manifest stops the relaunch:
<activity
android:name="io.ionic.libs.ioncameralib.view.IONCAMROpenPhotoPickerActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
tools:node="merge" />
- Ngôn ngữ chính
- TypeScript
- Star
- 6
- Fork
- 3
- Merge trung bình
- 2 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 6
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của ionic-team/capacitor-camera
-
bug(android): NullPointerException on ActivityResultLauncher.unregister() in LegacyCameraFlowĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
ionic-team/capacitor-camera#75 · 1 reaction ·
-
[Bug]: Crash SecurityException: No persistable permission grants found in IONCAMROpenPhotoPickerActivityCó thể đã có người làm @ankit-edii đã nhận 24 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
ionic-team/capacitor-camera#58 · 1 bình luận ·
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 67/100
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
ionic-team/capacitor-camera#76 · 1 bình luận · 1 reaction ·
Tất cả issue của ionic-team/capacitor-camera
Issue tương tự
-
twilio.webhook() rejects valid requests when the query string has an encoded `?` and a `+` spaceĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
twilio/twilio-node#1232 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Tiling managers are not destroyed in disable(), so window-created handlers keep running (Gio.Settings constructed without schema)Có thể đã có người làm @gnacho đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
domferr/tilingshell#641 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
🐛 bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
LibreChat-AI/LibreChat#17887 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
`isCI` is `true` inside a running Google Cloud Run service (also Railway, Render, Deno Deploy)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100