@capawesome/capacitor-in-app-browser 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +219 -51
  2. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/InAppBrowser.java +25 -5
  3. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/InAppBrowserPlugin.java +37 -10
  4. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/classes/WebViewDialog.java +40 -2
  5. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/classes/events/{MessageReceivedEvent.java → BrowserMessageReceivedEvent.java} +2 -2
  6. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/classes/events/{BrowserPageNavigationCompletedEvent.java → BrowserNavigationCompletedEvent.java} +2 -2
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/classes/events/BrowserUrlChangedEvent.java +23 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/inappbrowser/classes/options/OpenInWebViewOptions.java +7 -0
  9. package/dist/docs.json +114 -24
  10. package/dist/esm/definitions.d.ts +62 -12
  11. package/dist/esm/definitions.js.map +1 -1
  12. package/dist/esm/web.d.ts +1 -0
  13. package/dist/esm/web.js +3 -0
  14. package/dist/esm/web.js.map +1 -1
  15. package/dist/plugin.cjs.js +3 -0
  16. package/dist/plugin.cjs.js.map +1 -1
  17. package/dist/plugin.js +3 -0
  18. package/dist/plugin.js.map +1 -1
  19. package/ios/Plugin/Classes/Events/{MessageReceivedEvent.swift → BrowserMessageReceivedEvent.swift} +1 -1
  20. package/ios/Plugin/Classes/Events/{BrowserPageNavigationCompletedEvent.swift → BrowserNavigationCompletedEvent.swift} +1 -1
  21. package/ios/Plugin/Classes/Events/BrowserUrlChangedEvent.swift +16 -0
  22. package/ios/Plugin/Classes/Options/OpenInWebViewOptions.swift +2 -0
  23. package/ios/Plugin/Classes/WebViewController.swift +18 -2
  24. package/ios/Plugin/InAppBrowser.swift +45 -4
  25. package/ios/Plugin/InAppBrowserPlugin.swift +25 -9
  26. package/package.json +12 -4
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @capawesome/capacitor-in-app-browser
1
+ # Capacitor In-App Browser Plugin
2
2
 
3
3
  Capacitor plugin to open URLs in the external browser, the system browser or an embedded web view.
4
4
 
@@ -10,7 +10,7 @@ Capacitor plugin to open URLs in the external browser, the system browser or an
10
10
 
11
11
  ## Features
12
12
 
13
- We are proud to offer one of the most complete and feature-rich Capacitor plugins for in-app browsing. Here are some of the key features:
13
+ The Capacitor In-App Browser plugin is one of the most complete in-app browsing solutions for Capacitor apps. Here are some of the key features:
14
14
 
15
15
  - 🌐 **Three browser modes**: Open URLs in the external browser, the system browser (Custom Tabs on Android, `SFSafariViewController` on iOS) or an embedded web view.
16
16
  - 🧭 **Navigation events**: Get notified when the browser is closed, a page has been loaded or a navigation has been completed.
@@ -24,9 +24,15 @@ We are proud to offer one of the most complete and feature-rich Capacitor plugin
24
24
 
25
25
  Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!
26
26
 
27
- ## Newsletter
27
+ ## Use Cases
28
28
 
29
- Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).
29
+ The In-App Browser plugin is typically used whenever an app needs to display web content without losing the user, for example:
30
+
31
+ - **External links**: Open links, terms of service, or documentation in the system browser without leaving the app context.
32
+ - **Login and checkout flows**: Open a web-based flow in the embedded web view and watch for a redirect using the `browserUrlChanged` event.
33
+ - **Hybrid web content**: Embed a web page with a themed native toolbar and exchange messages between the app and the page.
34
+ - **Background loading**: Load a URL in a hidden web view with the `visible` option and present it once the page has loaded.
35
+ - **Session control**: Clear the cache and session data of the web view, or use an isolated data store on iOS.
30
36
 
31
37
  ## Compatibility
32
38
 
@@ -96,6 +102,12 @@ No configuration required for this plugin.
96
102
 
97
103
  ## Usage
98
104
 
105
+ The following examples show how to open URLs in the external, system, and in-app browsers, control the embedded web view, exchange messages with the loaded page, clear browsing data, and listen for browser events.
106
+
107
+ ### Open a URL in the external browser
108
+
109
+ Open a URL in the default browser app of the device. Since the browser is opened in a separate app, no events are emitted in this mode:
110
+
99
111
  ```typescript
100
112
  import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
101
113
 
@@ -104,6 +116,14 @@ const openInExternalBrowser = async () => {
104
116
  url: 'https://capawesome.io',
105
117
  });
106
118
  };
119
+ ```
120
+
121
+ ### Open a URL in the system browser
122
+
123
+ Open a URL in the system browser (Custom Tabs on Android, `SFSafariViewController` on iOS) and customize the toolbar with platform-specific options. Only available on Android and iOS:
124
+
125
+ ```typescript
126
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
107
127
 
108
128
  const openInSystemBrowser = async () => {
109
129
  await InAppBrowser.openInSystemBrowser({
@@ -118,6 +138,14 @@ const openInSystemBrowser = async () => {
118
138
  },
119
139
  });
120
140
  };
141
+ ```
142
+
143
+ ### Open a URL in an embedded web view
144
+
145
+ Open a URL in an embedded web view with a native toolbar whose color, title, and buttons can be customized. Only available on Android and iOS:
146
+
147
+ ```typescript
148
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
121
149
 
122
150
  const openInWebView = async () => {
123
151
  await InAppBrowser.openInWebView({
@@ -129,10 +157,26 @@ const openInWebView = async () => {
129
157
  },
130
158
  });
131
159
  };
160
+ ```
161
+
162
+ ### Close the browser
163
+
164
+ Close the currently open browser. This closes browsers opened with `openInWebView(...)` or `openInSystemBrowser(...)`. Only available on Android and iOS:
165
+
166
+ ```typescript
167
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
132
168
 
133
169
  const close = async () => {
134
170
  await InAppBrowser.close();
135
171
  };
172
+ ```
173
+
174
+ ### Execute JavaScript in the web view
175
+
176
+ Execute any JavaScript code in the currently open web view. This method is only available for browsers opened with `openInWebView(...)` on Android and iOS:
177
+
178
+ ```typescript
179
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
136
180
 
137
181
  const executeScript = async () => {
138
182
  const { result } = await InAppBrowser.executeScript({
@@ -140,12 +184,28 @@ const executeScript = async () => {
140
184
  });
141
185
  return result;
142
186
  };
187
+ ```
188
+
189
+ ### Post a message to the web page
190
+
191
+ Post a message to the currently open web view. The web page receives the message by listening for the `capacitorInAppBrowserMessage` window event, see [Messaging](#messaging). This method is only available for browsers opened with `openInWebView(...)` on Android and iOS:
192
+
193
+ ```typescript
194
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
143
195
 
144
196
  const postMessage = async () => {
145
197
  await InAppBrowser.postMessage({
146
198
  data: { name: 'Capawesome' },
147
199
  });
148
200
  };
201
+ ```
202
+
203
+ ### Clear the cache and session data
204
+
205
+ Clear the cache or the session data (cookies and web storage) of the web view. Only available on Android and iOS:
206
+
207
+ ```typescript
208
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
149
209
 
150
210
  const clearCache = async () => {
151
211
  await InAppBrowser.clearCache();
@@ -154,19 +214,30 @@ const clearCache = async () => {
154
214
  const clearSessionData = async () => {
155
215
  await InAppBrowser.clearSessionData();
156
216
  };
217
+ ```
218
+
219
+ ### Listen for browser events
220
+
221
+ Get notified when the browser is closed, a message is received, a navigation has been completed, a page has been loaded, or the URL has changed:
222
+
223
+ ```typescript
224
+ import { InAppBrowser } from '@capawesome/capacitor-in-app-browser';
157
225
 
158
226
  const addListeners = async () => {
159
227
  await InAppBrowser.addListener('browserClosed', () => {
160
228
  console.log('Browser closed');
161
229
  });
162
- await InAppBrowser.addListener('browserPageLoaded', () => {
163
- console.log('Browser page loaded');
230
+ await InAppBrowser.addListener('browserMessageReceived', event => {
231
+ console.log('Message received', event.data);
164
232
  });
165
- await InAppBrowser.addListener('browserPageNavigationCompleted', event => {
233
+ await InAppBrowser.addListener('browserNavigationCompleted', event => {
166
234
  console.log('Navigation completed', event.url);
167
235
  });
168
- await InAppBrowser.addListener('messageReceived', event => {
169
- console.log('Message received', event.data);
236
+ await InAppBrowser.addListener('browserPageLoaded', () => {
237
+ console.log('Browser page loaded');
238
+ });
239
+ await InAppBrowser.addListener('browserUrlChanged', event => {
240
+ console.log('URL changed', event.url);
170
241
  });
171
242
  };
172
243
  ```
@@ -184,10 +255,12 @@ const addListeners = async () => {
184
255
  * [`openInSystemBrowser(...)`](#openinsystembrowser)
185
256
  * [`openInWebView(...)`](#openinwebview)
186
257
  * [`postMessage(...)`](#postmessage)
258
+ * [`show()`](#show)
187
259
  * [`addListener('browserClosed', ...)`](#addlistenerbrowserclosed-)
260
+ * [`addListener('browserMessageReceived', ...)`](#addlistenerbrowsermessagereceived-)
261
+ * [`addListener('browserNavigationCompleted', ...)`](#addlistenerbrowsernavigationcompleted-)
188
262
  * [`addListener('browserPageLoaded', ...)`](#addlistenerbrowserpageloaded-)
189
- * [`addListener('browserPageNavigationCompleted', ...)`](#addlistenerbrowserpagenavigationcompleted-)
190
- * [`addListener('messageReceived', ...)`](#addlistenermessagereceived-)
263
+ * [`addListener('browserUrlChanged', ...)`](#addlistenerbrowserurlchanged-)
191
264
  * [`removeAllListeners()`](#removealllisteners)
192
265
  * [Interfaces](#interfaces)
193
266
  * [Type Aliases](#type-aliases)
@@ -375,6 +448,24 @@ Only available on Android and iOS.
375
448
  --------------------
376
449
 
377
450
 
451
+ ### show()
452
+
453
+ ```typescript
454
+ show() => Promise<void>
455
+ ```
456
+
457
+ Show the web view if it was opened with `visible: false`.
458
+
459
+ This method is only available for browsers opened with
460
+ `openInWebView(...)`.
461
+
462
+ Only available on Android and iOS.
463
+
464
+ **Since:** 0.1.0
465
+
466
+ --------------------
467
+
468
+
378
469
  ### addListener('browserClosed', ...)
379
470
 
380
471
  ```typescript
@@ -397,23 +488,23 @@ Only available on Android and iOS.
397
488
  --------------------
398
489
 
399
490
 
400
- ### addListener('browserPageLoaded', ...)
491
+ ### addListener('browserMessageReceived', ...)
401
492
 
402
493
  ```typescript
403
- addListener(eventName: 'browserPageLoaded', listenerFunc: () => void) => Promise<PluginListenerHandle>
494
+ addListener(eventName: 'browserMessageReceived', listenerFunc: (event: BrowserMessageReceivedEvent) => void) => Promise<PluginListenerHandle>
404
495
  ```
405
496
 
406
- Called when the initial page of the browser has finished loading.
497
+ Called when the web page posts a message to the app using the injected
498
+ `window.CapacitorInAppBrowser.postMessage(...)` function.
407
499
 
408
- On Android, this event is only emitted for browsers opened with
409
- `openInWebView(...)`.
500
+ This event is only emitted for browsers opened with `openInWebView(...)`.
410
501
 
411
502
  Only available on Android and iOS.
412
503
 
413
- | Param | Type |
414
- | ------------------ | -------------------------------- |
415
- | **`eventName`** | <code>'browserPageLoaded'</code> |
416
- | **`listenerFunc`** | <code>() =&gt; void</code> |
504
+ | Param | Type |
505
+ | ------------------ | ------------------------------------------------------------------------------------------------------- |
506
+ | **`eventName`** | <code>'browserMessageReceived'</code> |
507
+ | **`listenerFunc`** | <code>(event: <a href="#browsermessagereceivedevent">BrowserMessageReceivedEvent</a>) =&gt; void</code> |
417
508
 
418
509
  **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
419
510
 
@@ -422,10 +513,10 @@ Only available on Android and iOS.
422
513
  --------------------
423
514
 
424
515
 
425
- ### addListener('browserPageNavigationCompleted', ...)
516
+ ### addListener('browserNavigationCompleted', ...)
426
517
 
427
518
  ```typescript
428
- addListener(eventName: 'browserPageNavigationCompleted', listenerFunc: (event: BrowserPageNavigationCompletedEvent) => void) => Promise<PluginListenerHandle>
519
+ addListener(eventName: 'browserNavigationCompleted', listenerFunc: (event: BrowserNavigationCompletedEvent) => void) => Promise<PluginListenerHandle>
429
520
  ```
430
521
 
431
522
  Called when a page navigation has been completed in the web view.
@@ -434,10 +525,10 @@ This event is only emitted for browsers opened with `openInWebView(...)`.
434
525
 
435
526
  Only available on Android and iOS.
436
527
 
437
- | Param | Type |
438
- | ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
439
- | **`eventName`** | <code>'browserPageNavigationCompleted'</code> |
440
- | **`listenerFunc`** | <code>(event: <a href="#browserpagenavigationcompletedevent">BrowserPageNavigationCompletedEvent</a>) =&gt; void</code> |
528
+ | Param | Type |
529
+ | ------------------ | --------------------------------------------------------------------------------------------------------------- |
530
+ | **`eventName`** | <code>'browserNavigationCompleted'</code> |
531
+ | **`listenerFunc`** | <code>(event: <a href="#browsernavigationcompletedevent">BrowserNavigationCompletedEvent</a>) =&gt; void</code> |
441
532
 
442
533
  **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
443
534
 
@@ -446,23 +537,52 @@ Only available on Android and iOS.
446
537
  --------------------
447
538
 
448
539
 
449
- ### addListener('messageReceived', ...)
540
+ ### addListener('browserPageLoaded', ...)
450
541
 
451
542
  ```typescript
452
- addListener(eventName: 'messageReceived', listenerFunc: (event: MessageReceivedEvent) => void) => Promise<PluginListenerHandle>
543
+ addListener(eventName: 'browserPageLoaded', listenerFunc: () => void) => Promise<PluginListenerHandle>
453
544
  ```
454
545
 
455
- Called when the web page posts a message to the app using the injected
456
- `window.CapacitorInAppBrowser.postMessage(...)` function.
546
+ Called when the initial page of the browser has finished loading.
547
+
548
+ On Android, this event is only emitted for browsers opened with
549
+ `openInWebView(...)`.
550
+
551
+ Only available on Android and iOS.
552
+
553
+ | Param | Type |
554
+ | ------------------ | -------------------------------- |
555
+ | **`eventName`** | <code>'browserPageLoaded'</code> |
556
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
557
+
558
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
559
+
560
+ **Since:** 0.1.0
561
+
562
+ --------------------
563
+
564
+
565
+ ### addListener('browserUrlChanged', ...)
566
+
567
+ ```typescript
568
+ addListener(eventName: 'browserUrlChanged', listenerFunc: (event: BrowserUrlChangedEvent) => void) => Promise<PluginListenerHandle>
569
+ ```
570
+
571
+ Called when the current URL of the web view changes, e.g. when the user
572
+ navigates to a new page, a server redirect occurs, or a single-page
573
+ application updates the browser history.
574
+
575
+ This event is also emitted for the initial URL and fires earlier than
576
+ `browserNavigationCompleted`.
457
577
 
458
578
  This event is only emitted for browsers opened with `openInWebView(...)`.
459
579
 
460
580
  Only available on Android and iOS.
461
581
 
462
- | Param | Type |
463
- | ------------------ | ----------------------------------------------------------------------------------------- |
464
- | **`eventName`** | <code>'messageReceived'</code> |
465
- | **`listenerFunc`** | <code>(event: <a href="#messagereceivedevent">MessageReceivedEvent</a>) =&gt; void</code> |
582
+ | Param | Type |
583
+ | ------------------ | --------------------------------------------------------------------------------------------- |
584
+ | **`eventName`** | <code>'browserUrlChanged'</code> |
585
+ | **`listenerFunc`** | <code>(event: <a href="#browserurlchangedevent">BrowserUrlChangedEvent</a>) =&gt; void</code> |
466
586
 
467
587
  **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
468
588
 
@@ -552,16 +672,17 @@ Remove all listeners for this plugin.
552
672
 
553
673
  #### OpenInWebViewOptions
554
674
 
555
- | Prop | Type | Description | Default | Since |
556
- | ------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ----- |
557
- | **`android`** | <code><a href="#openinwebviewandroidoptions">OpenInWebViewAndroidOptions</a></code> | Options that are only applied on Android. Only available on Android. | | 0.1.0 |
558
- | **`dataStore`** | <code><a href="#webviewdatastore">WebViewDataStore</a></code> | The data store to use for the web view. On Android, this option is ignored. The web view always uses the app-global (`shared`) data store. Only available on iOS. | <code>'shared'</code> | 0.1.0 |
559
- | **`headers`** | <code>{ [key: string]: string; }</code> | Additional HTTP headers to send with the initial request. | | 0.1.0 |
560
- | **`ios`** | <code><a href="#openinwebviewiosoptions">OpenInWebViewIosOptions</a></code> | Options that are only applied on iOS. Only available on iOS. | | 0.1.0 |
561
- | **`mediaPlaybackRequiresUserAction`** | <code>boolean</code> | Whether or not media playback requires user action. | <code>false</code> | 0.1.0 |
562
- | **`toolbar`** | <code><a href="#webviewtoolbaroptions">WebViewToolbarOptions</a></code> | Options for the toolbar of the web view. | | 0.1.0 |
563
- | **`url`** | <code>string</code> | The URL to open in the web view. | | 0.1.0 |
564
- | **`userAgent`** | <code>string</code> | The custom user agent to use for the web view. | | 0.1.0 |
675
+ | Prop | Type | Description | Default | Since |
676
+ | ------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | ----- |
677
+ | **`android`** | <code><a href="#openinwebviewandroidoptions">OpenInWebViewAndroidOptions</a></code> | Options that are only applied on Android. Only available on Android. | | 0.1.0 |
678
+ | **`dataStore`** | <code><a href="#webviewdatastore">WebViewDataStore</a></code> | The data store to use for the web view. On Android, this option is ignored. The web view always uses the app-global (`shared`) data store. Only available on iOS. | <code>'shared'</code> | 0.1.0 |
679
+ | **`headers`** | <code>{ [key: string]: string; }</code> | Additional HTTP headers to send with the initial request. | | 0.1.0 |
680
+ | **`ios`** | <code><a href="#openinwebviewiosoptions">OpenInWebViewIosOptions</a></code> | Options that are only applied on iOS. Only available on iOS. | | 0.1.0 |
681
+ | **`mediaPlaybackRequiresUserAction`** | <code>boolean</code> | Whether or not media playback requires user action. | <code>false</code> | 0.1.0 |
682
+ | **`toolbar`** | <code><a href="#webviewtoolbaroptions">WebViewToolbarOptions</a></code> | Options for the toolbar of the web view. | | 0.1.0 |
683
+ | **`url`** | <code>string</code> | The URL to open in the web view. | | 0.1.0 |
684
+ | **`userAgent`** | <code>string</code> | The custom user agent to use for the web view. | | 0.1.0 |
685
+ | **`visible`** | <code>boolean</code> | Whether or not the web view is presented when opened. If `false`, the web view loads the URL in the background and stays hidden until `show()` is called. The `browserPageLoaded` event is still emitted and `close()` can be called while the web view is hidden. | <code>true</code> | 0.1.0 |
565
686
 
566
687
 
567
688
  #### OpenInWebViewAndroidOptions
@@ -608,18 +729,25 @@ Remove all listeners for this plugin.
608
729
  | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
609
730
 
610
731
 
611
- #### BrowserPageNavigationCompletedEvent
732
+ #### BrowserMessageReceivedEvent
733
+
734
+ | Prop | Type | Description | Since |
735
+ | ---------- | -------------------- | ---------------------------------------- | ----- |
736
+ | **`data`** | <code>unknown</code> | The message data posted by the web page. | 0.1.0 |
737
+
738
+
739
+ #### BrowserNavigationCompletedEvent
612
740
 
613
741
  | Prop | Type | Description | Since |
614
742
  | --------- | ------------------- | ------------------------------------------ | ----- |
615
743
  | **`url`** | <code>string</code> | The URL of the page that was navigated to. | 0.1.0 |
616
744
 
617
745
 
618
- #### MessageReceivedEvent
746
+ #### BrowserUrlChangedEvent
619
747
 
620
- | Prop | Type | Description | Since |
621
- | ---------- | -------------------- | ---------------------------------------- | ----- |
622
- | **`data`** | <code>unknown</code> | The message data posted by the web page. | 0.1.0 |
748
+ | Prop | Type | Description | Since |
749
+ | --------- | ------------------- | ---------------------------- | ----- |
750
+ | **`url`** | <code>string</code> | The new URL of the web view. | 0.1.0 |
623
751
 
624
752
 
625
753
  ### Type Aliases
@@ -661,7 +789,7 @@ The web page can post a message to the app using the injected `window.CapacitorI
661
789
  window.CapacitorInAppBrowser.postMessage({ name: 'Capawesome' });
662
790
  ```
663
791
 
664
- The app receives the message via the `messageReceived` event.
792
+ The app receives the message via the `browserMessageReceived` event.
665
793
 
666
794
  ### From the app to the web page
667
795
 
@@ -677,10 +805,50 @@ window.addEventListener('capacitorInAppBrowserMessage', event => {
677
805
 
678
806
  The three browser modes behave differently on each platform. Keep the following differences in mind:
679
807
 
680
- - **System browser**: Tracking the visited URLs is not possible by design. If you need the `browserPageNavigationCompleted` event, use the `openInWebView(...)` method instead. On Android, the `browserPageLoaded` event is not emitted for the system browser and the `browserClosed` event is emitted when the user returns to the app.
808
+ - **System browser**: Tracking the visited URLs is not possible by design. If you need the `browserNavigationCompleted` or `browserUrlChanged` event, use the `openInWebView(...)` method instead. On Android, the `browserPageLoaded` event is not emitted for the system browser and the `browserClosed` event is emitted when the user returns to the app.
681
809
  - **Embedded web view**: The web view always uses the app-global (`shared`) data store on Android. The `dataStore` option is only supported on iOS. On iOS, hiding the toolbar removes the close button, so the browser can then only be closed using the `close(...)` method.
682
810
  - **External browser**: The browser is opened in a separate app. For this reason, no events are emitted and the `close(...)` method has no effect.
683
811
 
812
+ ## FAQ
813
+
814
+ ### How is this plugin different from other similar plugins?
815
+
816
+ It covers three browsing modes in one fully typed API — the external browser, the system browser (Custom Tabs on Android, `SFSafariViewController` on iOS), and an embedded web view with a themed native toolbar, JavaScript execution, two-way messaging, navigation events, and session control. Camera and microphone requests from web pages are forwarded to the app, and you can even load a URL hidden in the background and present it once it's ready. If you only need to open a link, the external mode is a simple one-liner; if you need to embed, theme, and communicate with web content, this plugin is designed for exactly that.
817
+
818
+ ### What is the difference between the external browser, the system browser and the embedded web view?
819
+
820
+ The `openInExternalBrowser(...)` method opens the URL in the default browser app of the device, so no events are emitted and the `close()` method has no effect. The `openInSystemBrowser(...)` method presents the system browser (Custom Tabs on Android, `SFSafariViewController` on iOS) inside your app with a customizable toolbar. The `openInWebView(...)` method opens an embedded web view with a native toolbar and offers the most control, including JavaScript execution, messaging, and navigation events. See [Platform Behavior](#platform-behavior) for the differences between the modes.
821
+
822
+ ### How can I track which URLs the user visits?
823
+
824
+ Tracking the visited URLs is only possible in the embedded web view. Open the URL with `openInWebView(...)` and listen for the `browserUrlChanged` or `browserNavigationCompleted` event. In the system browser, tracking the visited URLs is not possible by design, and in the external browser no events are emitted at all.
825
+
826
+ ### How can I exchange data between my app and the opened web page?
827
+
828
+ The embedded web view injects a small message bridge into every web page. The web page can post messages to the app using the injected `window.CapacitorInAppBrowser.postMessage(...)` function, which the app receives via the `browserMessageReceived` event. The app can post messages to the web page using the `postMessage(...)` method, which the web page receives via the `capacitorInAppBrowserMessage` window event. See [Messaging](#messaging) for more details.
829
+
830
+ ### Can web pages access the camera or microphone?
831
+
832
+ Yes, camera and microphone permission requests from web pages opened in the embedded web view are forwarded to the app. On Android, the corresponding permissions must be declared in your `AndroidManifest.xml` and granted before a web page requests access. On iOS, the `NSCameraUsageDescription` and `NSMicrophoneUsageDescription` keys must be added to your `Info.plist` file. See [Installation](#installation) for details.
833
+
834
+ ### Can I load a URL in the background before showing it?
835
+
836
+ Yes, open the URL with `openInWebView(...)` and set the `visible` option to `false`. The web view then loads the URL in the background and stays hidden until you call the `show()` method. The `browserPageLoaded` event is still emitted and `close()` can be called while the web view is hidden.
837
+
838
+ ### Can I use this plugin with Ionic, React, Vue or Angular?
839
+
840
+ Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.
841
+
842
+ ## Related Plugins
843
+
844
+ - [App Launcher](https://capawesome.io/docs/sdks/capacitor/app-launcher/): Check if an app can be opened and open it.
845
+ - [OAuth](https://capawesome.io/docs/sdks/capacitor/oauth/): Communicate with OAuth 2.0 and OpenID Connect providers.
846
+ - [System WebView](https://capawesome.io/docs/sdks/capacitor/system-webview/): Detect an outdated Android System WebView and guide users to update it.
847
+
848
+ ## Newsletter
849
+
850
+ Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).
851
+
684
852
  ## Changelog
685
853
 
686
854
  See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/in-app-browser/CHANGELOG.md).
@@ -11,8 +11,9 @@ import androidx.browser.customtabs.CustomTabColorSchemeParams;
11
11
  import androidx.browser.customtabs.CustomTabsIntent;
12
12
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.CustomExceptions;
13
13
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.WebViewDialog;
14
- import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserPageNavigationCompletedEvent;
15
- import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.MessageReceivedEvent;
14
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserMessageReceivedEvent;
15
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserNavigationCompletedEvent;
16
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserUrlChangedEvent;
16
17
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.ExecuteScriptOptions;
17
18
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.GetCookiesOptions;
18
19
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.OpenInExternalBrowserOptions;
@@ -199,14 +200,19 @@ public class InAppBrowser {
199
200
  handleMessageReceived(data);
200
201
  }
201
202
 
203
+ @Override
204
+ public void onNavigationCompleted(@NonNull String url) {
205
+ plugin.notifyBrowserNavigationCompletedListeners(new BrowserNavigationCompletedEvent(url));
206
+ }
207
+
202
208
  @Override
203
209
  public void onPageLoaded() {
204
210
  plugin.notifyBrowserPageLoadedListeners();
205
211
  }
206
212
 
207
213
  @Override
208
- public void onPageNavigationCompleted(@NonNull String url) {
209
- plugin.notifyBrowserPageNavigationCompletedListeners(new BrowserPageNavigationCompletedEvent(url));
214
+ public void onUrlChanged(@NonNull String url) {
215
+ plugin.notifyBrowserUrlChangedListeners(new BrowserUrlChangedEvent(url));
210
216
  }
211
217
  }
212
218
  );
@@ -230,6 +236,20 @@ public class InAppBrowser {
230
236
  });
231
237
  }
232
238
 
239
+ public void show(@NonNull EmptyCallback callback) {
240
+ plugin
241
+ .getActivity()
242
+ .runOnUiThread(() -> {
243
+ WebViewDialog webViewDialog = this.webViewDialog;
244
+ if (webViewDialog == null) {
245
+ callback.error(CustomExceptions.NO_BROWSER_OPEN);
246
+ return;
247
+ }
248
+ webViewDialog.showWebView();
249
+ callback.success();
250
+ });
251
+ }
252
+
233
253
  private void handleMessageReceived(@NonNull String data) {
234
254
  Object value;
235
255
  try {
@@ -237,6 +257,6 @@ public class InAppBrowser {
237
257
  } catch (JSONException exception) {
238
258
  value = data;
239
259
  }
240
- plugin.notifyMessageReceivedListeners(new MessageReceivedEvent(value));
260
+ plugin.notifyBrowserMessageReceivedListeners(new BrowserMessageReceivedEvent(value));
241
261
  }
242
262
  }
@@ -9,8 +9,9 @@ import com.getcapacitor.PluginCall;
9
9
  import com.getcapacitor.PluginMethod;
10
10
  import com.getcapacitor.annotation.CapacitorPlugin;
11
11
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.CustomException;
12
- import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserPageNavigationCompletedEvent;
13
- import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.MessageReceivedEvent;
12
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserMessageReceivedEvent;
13
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserNavigationCompletedEvent;
14
+ import io.capawesome.capacitorjs.plugins.inappbrowser.classes.events.BrowserUrlChangedEvent;
14
15
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.ExecuteScriptOptions;
15
16
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.GetCookiesOptions;
16
17
  import io.capawesome.capacitorjs.plugins.inappbrowser.classes.options.OpenInExternalBrowserOptions;
@@ -27,9 +28,10 @@ import io.capawesome.capacitorjs.plugins.inappbrowser.interfaces.Result;
27
28
  public class InAppBrowserPlugin extends Plugin {
28
29
 
29
30
  public static final String EVENT_BROWSER_CLOSED = "browserClosed";
31
+ public static final String EVENT_BROWSER_MESSAGE_RECEIVED = "browserMessageReceived";
32
+ public static final String EVENT_BROWSER_NAVIGATION_COMPLETED = "browserNavigationCompleted";
30
33
  public static final String EVENT_BROWSER_PAGE_LOADED = "browserPageLoaded";
31
- public static final String EVENT_BROWSER_PAGE_NAVIGATION_COMPLETED = "browserPageNavigationCompleted";
32
- public static final String EVENT_MESSAGE_RECEIVED = "messageReceived";
34
+ public static final String EVENT_BROWSER_URL_CHANGED = "browserUrlChanged";
33
35
  public static final String TAG = "InAppBrowserPlugin";
34
36
 
35
37
  private static final String ERROR_UNKNOWN_ERROR = "An unknown error occurred.";
@@ -152,16 +154,20 @@ public class InAppBrowserPlugin extends Plugin {
152
154
  notifyListeners(EVENT_BROWSER_CLOSED, new JSObject());
153
155
  }
154
156
 
155
- public void notifyBrowserPageLoadedListeners() {
156
- notifyListeners(EVENT_BROWSER_PAGE_LOADED, new JSObject());
157
+ public void notifyBrowserMessageReceivedListeners(@NonNull BrowserMessageReceivedEvent event) {
158
+ notifyListeners(EVENT_BROWSER_MESSAGE_RECEIVED, event.toJSObject());
157
159
  }
158
160
 
159
- public void notifyBrowserPageNavigationCompletedListeners(@NonNull BrowserPageNavigationCompletedEvent event) {
160
- notifyListeners(EVENT_BROWSER_PAGE_NAVIGATION_COMPLETED, event.toJSObject());
161
+ public void notifyBrowserNavigationCompletedListeners(@NonNull BrowserNavigationCompletedEvent event) {
162
+ notifyListeners(EVENT_BROWSER_NAVIGATION_COMPLETED, event.toJSObject());
161
163
  }
162
164
 
163
- public void notifyMessageReceivedListeners(@NonNull MessageReceivedEvent event) {
164
- notifyListeners(EVENT_MESSAGE_RECEIVED, event.toJSObject());
165
+ public void notifyBrowserPageLoadedListeners() {
166
+ notifyListeners(EVENT_BROWSER_PAGE_LOADED, new JSObject());
167
+ }
168
+
169
+ public void notifyBrowserUrlChangedListeners(@NonNull BrowserUrlChangedEvent event) {
170
+ notifyListeners(EVENT_BROWSER_URL_CHANGED, event.toJSObject());
165
171
  }
166
172
 
167
173
  @PluginMethod
@@ -252,6 +258,27 @@ public class InAppBrowserPlugin extends Plugin {
252
258
  }
253
259
  }
254
260
 
261
+ @PluginMethod
262
+ public void show(PluginCall call) {
263
+ try {
264
+ EmptyCallback callback = new EmptyCallback() {
265
+ @Override
266
+ public void success() {
267
+ resolveCall(call);
268
+ }
269
+
270
+ @Override
271
+ public void error(@NonNull Exception exception) {
272
+ rejectCall(call, exception);
273
+ }
274
+ };
275
+
276
+ implementation.show(callback);
277
+ } catch (Exception exception) {
278
+ rejectCall(call, exception);
279
+ }
280
+ }
281
+
255
282
  @Override
256
283
  protected void handleOnPause() {
257
284
  implementation.handleOnPause();