@@ -46,6 +46,17 @@ private interface ActivityResultListener {
4646 void onActivityResult (ActivityResult result );
4747 }
4848
49+ // Static variables to store pending file chooser state to survive activity recreation
50+ private static ValueCallback <Uri []> pendingFilePathCallback ;
51+ private static Uri pendingImageFileUri ;
52+ private static FileChooserType pendingFileChooserType ;
53+
54+ private enum FileChooserType {
55+ IMAGE_CAPTURE ,
56+ VIDEO_CAPTURE ,
57+ FILE_PICKER
58+ }
59+
4960 private ActivityResultLauncher permissionLauncher ;
5061 private ActivityResultLauncher activityLauncher ;
5162 private PermissionListener permissionListener ;
@@ -70,10 +81,70 @@ public BridgeWebChromeClient(Bridge bridge) {
7081 activityLauncher = bridge .registerForActivityResult (new ActivityResultContracts .StartActivityForResult (), (result ) -> {
7182 if (activityListener != null ) {
7283 activityListener .onActivityResult (result );
84+ } else if (pendingFilePathCallback != null ) {
85+ // Handle case where activity was recreated and instance callback is null
86+ // Use the static callback instead
87+ handlePendingFileChooserResult (result );
7388 }
7489 });
7590 }
7691
92+ /**
93+ * Handle file chooser result when the activity was recreated and instance callbacks were lost.
94+ * This uses the static pending callback to deliver the result.
95+ */
96+ private void handlePendingFileChooserResult (ActivityResult result ) {
97+ if (pendingFilePathCallback == null ) {
98+ return ;
99+ }
100+
101+ try {
102+ Uri [] uriResult = null ;
103+ if (result .getResultCode () == Activity .RESULT_OK ) {
104+ switch (pendingFileChooserType ) {
105+ case IMAGE_CAPTURE :
106+ if (pendingImageFileUri != null ) {
107+ uriResult = new Uri [] { pendingImageFileUri };
108+ }
109+ break ;
110+ case VIDEO_CAPTURE :
111+ Intent videoData = result .getData ();
112+ if (videoData != null && videoData .getData () != null ) {
113+ uriResult = new Uri [] { videoData .getData () };
114+ }
115+ break ;
116+ case FILE_PICKER :
117+ Intent fileData = result .getData ();
118+ if (fileData != null ) {
119+ if (fileData .getClipData () != null ) {
120+ final int numFiles = fileData .getClipData ().getItemCount ();
121+ uriResult = new Uri [numFiles ];
122+ for (int i = 0 ; i < numFiles ; i ++) {
123+ uriResult [i ] = fileData .getClipData ().getItemAt (i ).getUri ();
124+ }
125+ } else {
126+ uriResult = WebChromeClient .FileChooserParams .parseResult (result .getResultCode (), fileData );
127+ }
128+ }
129+ break ;
130+ }
131+ }
132+ pendingFilePathCallback .onReceiveValue (uriResult );
133+ } finally {
134+ // Clear the static state after handling
135+ clearPendingFileChooserState ();
136+ }
137+ }
138+
139+ /**
140+ * Clear the static pending file chooser state.
141+ */
142+ private static void clearPendingFileChooserState () {
143+ pendingFilePathCallback = null ;
144+ pendingImageFileUri = null ;
145+ pendingFileChooserType = null ;
146+ }
147+
77148 /**
78149 * Render web content in `view`.
79150 *
@@ -340,12 +411,19 @@ private boolean showImageCapturePicker(final ValueCallback<Uri[]> filePathCallba
340411 return false ;
341412 }
342413 takePictureIntent .putExtra (MediaStore .EXTRA_OUTPUT , imageFileUri );
414+
415+ // Store in static variables to survive activity recreation
416+ pendingFilePathCallback = filePathCallback ;
417+ pendingImageFileUri = imageFileUri ;
418+ pendingFileChooserType = FileChooserType .IMAGE_CAPTURE ;
419+
343420 activityListener = (activityResult ) -> {
344421 Uri [] result = null ;
345422 if (activityResult .getResultCode () == Activity .RESULT_OK ) {
346423 result = new Uri [] { imageFileUri };
347424 }
348425 filePathCallback .onReceiveValue (result );
426+ clearPendingFileChooserState ();
349427 };
350428 activityLauncher .launch (takePictureIntent );
351429
@@ -359,12 +437,18 @@ private boolean showVideoCapturePicker(final ValueCallback<Uri[]> filePathCallba
359437 return false ;
360438 }
361439
440+ // Store in static variables to survive activity recreation
441+ pendingFilePathCallback = filePathCallback ;
442+ pendingImageFileUri = null ;
443+ pendingFileChooserType = FileChooserType .VIDEO_CAPTURE ;
444+
362445 activityListener = (activityResult ) -> {
363446 Uri [] result = null ;
364447 if (activityResult .getResultCode () == Activity .RESULT_OK ) {
365448 result = new Uri [] { activityResult .getData ().getData () };
366449 }
367450 filePathCallback .onReceiveValue (result );
451+ clearPendingFileChooserState ();
368452 };
369453 activityLauncher .launch (takeVideoIntent );
370454
@@ -383,6 +467,12 @@ private void showFilePicker(final ValueCallback<Uri[]> filePathCallback, FileCho
383467 intent .setType (validTypes [0 ]);
384468 }
385469 }
470+
471+ // Store in static variables to survive activity recreation
472+ pendingFilePathCallback = filePathCallback ;
473+ pendingImageFileUri = null ;
474+ pendingFileChooserType = FileChooserType .FILE_PICKER ;
475+
386476 try {
387477 activityListener = (activityResult ) -> {
388478 Uri [] result ;
@@ -397,10 +487,12 @@ private void showFilePicker(final ValueCallback<Uri[]> filePathCallback, FileCho
397487 result = WebChromeClient .FileChooserParams .parseResult (activityResult .getResultCode (), resultIntent );
398488 }
399489 filePathCallback .onReceiveValue (result );
490+ clearPendingFileChooserState ();
400491 };
401492 activityLauncher .launch (intent );
402493 } catch (ActivityNotFoundException e ) {
403494 filePathCallback .onReceiveValue (null );
495+ clearPendingFileChooserState ();
404496 }
405497 }
406498
0 commit comments