@capacitor/browser 8.0.4 → 8.0.5-dev-2561-20260716T164713.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.
@@ -7,6 +7,7 @@ import android.content.Context;
7
7
  import android.content.Intent;
8
8
  import android.net.Uri;
9
9
  import android.os.Bundle;
10
+ import androidx.activity.result.ActivityResultLauncher;
10
11
  import androidx.annotation.NonNull;
11
12
  import androidx.annotation.Nullable;
12
13
  import androidx.browser.customtabs.*;
@@ -43,7 +44,10 @@ public class Browser {
43
44
  private CustomTabsClient customTabsClient;
44
45
  private CustomTabsSession browserSession;
45
46
  private boolean isInitialLoad = false;
46
- private EventGroup group;
47
+
48
+ @Nullable
49
+ private ActivityResultLauncher<Intent> customTabLauncher;
50
+
47
51
  private CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
48
52
  @Override
49
53
  public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
@@ -61,7 +65,6 @@ public class Browser {
61
65
  */
62
66
  public Browser(@NonNull Context context) {
63
67
  this.context = context;
64
- this.group = new EventGroup(this::handleGroupCompletion);
65
68
  }
66
69
 
67
70
  /**
@@ -81,6 +84,16 @@ public class Browser {
81
84
  return browserEventListener;
82
85
  }
83
86
 
87
+ /**
88
+ * Provide the ActivityResultLauncher used to open the Custom Tab. When
89
+ * set, the Custom Tab is launched via this launcher so that
90
+ * {@link #notifyBrowserFinished()} can be triggered from the launcher's
91
+ * result callback (only when the tab activity actually terminates).
92
+ */
93
+ public void setCustomTabLauncher(@Nullable ActivityResultLauncher<Intent> launcher) {
94
+ this.customTabLauncher = launcher;
95
+ }
96
+
84
97
  /**
85
98
  * Open the browser to the specified URL.
86
99
  * @param url
@@ -108,8 +121,12 @@ public class Browser {
108
121
  tabsIntent.intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + context.getPackageName()));
109
122
 
110
123
  isInitialLoad = true;
111
- group.reset();
112
- tabsIntent.launchUrl(context, url);
124
+ if (customTabLauncher != null) {
125
+ tabsIntent.intent.setData(url);
126
+ customTabLauncher.launch(tabsIntent.intent);
127
+ } else {
128
+ tabsIntent.launchUrl(context, url);
129
+ }
113
130
  }
114
131
 
115
132
  /**
@@ -120,9 +137,7 @@ public class Browser {
120
137
  if (null == customTabPackageName) {
121
138
  customTabPackageName = FALLBACK_CUSTOM_TAB_PACKAGE_NAME;
122
139
  }
123
- boolean result = CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
124
- group.leave();
125
- return result;
140
+ return CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
126
141
  }
127
142
 
128
143
  /**
@@ -130,7 +145,6 @@ public class Browser {
130
145
  */
131
146
  public void unbindService() {
132
147
  context.unbindService(connection);
133
- group.enter();
134
148
  }
135
149
 
136
150
  private void handledNavigationEvent(int navigationEvent) {
@@ -143,19 +157,13 @@ public class Browser {
143
157
  isInitialLoad = false;
144
158
  }
145
159
  break;
146
- case CustomTabsCallback.TAB_HIDDEN:
147
- group.leave();
148
- break;
149
- case CustomTabsCallback.TAB_SHOWN:
150
- group.enter();
151
- break;
152
160
  }
153
161
  }
154
162
 
155
- private void handleGroupCompletion() {
156
- // events such as TAB_HIDDEN and onPause can occur for multiple reasons and in
157
- // different sequences so there is no single point to fire this. so we rely on the
158
- // event group to track when it is safe to assume that the browser is done.
163
+ public void notifyBrowserFinished() {
164
+ // Notify listeners that the browser session has finished. Called by the
165
+ // host activity when the Custom Tab activity actually returns a result
166
+ // (i.e. the tab was truly dismissed, not just backgrounded or minimised).
159
167
  if (browserEventListener != null) {
160
168
  browserEventListener.onBrowserEvent(BROWSER_FINISHED);
161
169
  }
@@ -1,19 +1,28 @@
1
1
  package com.capacitorjs.plugins.browser;
2
2
 
3
- import android.app.Activity;
4
3
  import android.content.Intent;
5
4
  import android.net.Uri;
6
5
  import android.os.Bundle;
6
+ import androidx.activity.ComponentActivity;
7
+ import androidx.activity.result.ActivityResultLauncher;
8
+ import androidx.activity.result.contract.ActivityResultContracts;
7
9
  import androidx.annotation.Nullable;
8
10
 
9
- public class BrowserControllerActivity extends Activity {
11
+ public class BrowserControllerActivity extends ComponentActivity {
10
12
 
11
- private boolean isCustomTabsOpen = false;
13
+ private ActivityResultLauncher<Intent> customTabLauncher;
14
+ private Browser implementation;
12
15
 
13
16
  @Override
14
17
  protected void onCreate(@Nullable Bundle savedInstanceState) {
15
18
  super.onCreate(savedInstanceState);
16
- isCustomTabsOpen = false;
19
+
20
+ customTabLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), (result) -> {
21
+ if (implementation != null) {
22
+ implementation.notifyBrowserFinished();
23
+ }
24
+ finish();
25
+ });
17
26
 
18
27
  if (BrowserPlugin.browserControllerListener != null) {
19
28
  BrowserPlugin.browserControllerListener.onControllerReady(this);
@@ -28,25 +37,15 @@ public class BrowserControllerActivity extends Activity {
28
37
  }
29
38
  }
30
39
 
31
- @Override
32
- protected void onResume() {
33
- super.onResume();
34
- if (isCustomTabsOpen) {
35
- isCustomTabsOpen = false;
36
- finish();
37
- } else {
38
- isCustomTabsOpen = true;
39
- }
40
- }
41
-
42
40
  public void open(Browser implementation, Uri url, Integer toolbarColor) {
41
+ this.implementation = implementation;
42
+ implementation.setCustomTabLauncher(customTabLauncher);
43
43
  implementation.open(url, toolbarColor);
44
44
  }
45
45
 
46
46
  @Override
47
47
  protected void onDestroy() {
48
48
  super.onDestroy();
49
- isCustomTabsOpen = false;
50
49
  BrowserPlugin.setBrowserControllerListener(null);
51
50
  }
52
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/browser",
3
- "version": "8.0.4",
3
+ "version": "8.0.5-dev-2561-20260716T164713.0",
4
4
  "description": "The Browser API provides the ability to open an in-app browser and subscribe to browser events.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -80,6 +80,5 @@
80
80
  },
81
81
  "publishConfig": {
82
82
  "access": "public"
83
- },
84
- "gitHead": "0bfde98313dbd0312224c0a4896648b9fa6d57c3"
83
+ }
85
84
  }
@@ -1,45 +0,0 @@
1
- package com.capacitorjs.plugins.browser;
2
-
3
- /**
4
- * Simple class to handle indeterminate sequence of events. Not thread safe.
5
- */
6
- class EventGroup {
7
-
8
- interface EventGroupCompletion {
9
- void onGroupCompletion();
10
- }
11
-
12
- private int count;
13
- private boolean isComplete;
14
- private EventGroupCompletion completion;
15
-
16
- public EventGroup(EventGroupCompletion onCompletion) {
17
- super();
18
- count = 0;
19
- isComplete = false;
20
- completion = onCompletion;
21
- }
22
-
23
- public void enter() {
24
- count++;
25
- }
26
-
27
- public void leave() {
28
- count--;
29
- checkForCompletion();
30
- }
31
-
32
- public void reset() {
33
- count = 0;
34
- isComplete = false;
35
- }
36
-
37
- private void checkForCompletion() {
38
- if (count <= 0) {
39
- if (isComplete == false && completion != null) {
40
- completion.onGroupCompletion();
41
- }
42
- isComplete = true;
43
- }
44
- }
45
- }