Skip to content

Commit 49a3964

Browse files
fix(browser): only fire browserFinished when the Custom Tab actually terminates
1 parent 5b65292 commit 49a3964

3 files changed

Lines changed: 42 additions & 79 deletions

File tree

browser/android/src/main/java/com/capacitorjs/plugins/browser/Browser.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.content.Intent;
88
import android.net.Uri;
99
import android.os.Bundle;
10+
import androidx.activity.result.ActivityResultLauncher;
1011
import androidx.annotation.NonNull;
1112
import androidx.annotation.Nullable;
1213
import androidx.browser.customtabs.*;
@@ -43,7 +44,8 @@ interface BrowserEventListener {
4344
private CustomTabsClient customTabsClient;
4445
private CustomTabsSession browserSession;
4546
private boolean isInitialLoad = false;
46-
private EventGroup group;
47+
@Nullable
48+
private ActivityResultLauncher<Intent> customTabLauncher;
4749
private CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
4850
@Override
4951
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
@@ -61,7 +63,6 @@ public void onServiceDisconnected(ComponentName name) {}
6163
*/
6264
public Browser(@NonNull Context context) {
6365
this.context = context;
64-
this.group = new EventGroup(this::handleGroupCompletion);
6566
}
6667

6768
/**
@@ -81,6 +82,16 @@ public BrowserEventListener getBrowserEventListenerListener() {
8182
return browserEventListener;
8283
}
8384

85+
/**
86+
* Provide the ActivityResultLauncher used to open the Custom Tab. When
87+
* set, the Custom Tab is launched via this launcher so that
88+
* {@link #notifyBrowserFinished()} can be triggered from the launcher's
89+
* result callback (only when the tab activity actually terminates).
90+
*/
91+
public void setCustomTabLauncher(@Nullable ActivityResultLauncher<Intent> launcher) {
92+
this.customTabLauncher = launcher;
93+
}
94+
8495
/**
8596
* Open the browser to the specified URL.
8697
* @param url
@@ -108,8 +119,12 @@ public void open(Uri url, @Nullable Integer toolbarColor) {
108119
tabsIntent.intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + context.getPackageName()));
109120

110121
isInitialLoad = true;
111-
group.reset();
112-
tabsIntent.launchUrl(context, url);
122+
if (customTabLauncher != null) {
123+
tabsIntent.intent.setData(url);
124+
customTabLauncher.launch(tabsIntent.intent);
125+
} else {
126+
tabsIntent.launchUrl(context, url);
127+
}
113128
}
114129

115130
/**
@@ -120,17 +135,14 @@ public boolean bindService() {
120135
if (null == customTabPackageName) {
121136
customTabPackageName = FALLBACK_CUSTOM_TAB_PACKAGE_NAME;
122137
}
123-
boolean result = CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
124-
group.leave();
125-
return result;
138+
return CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
126139
}
127140

128141
/**
129142
* Unbind the custom tabs service, required to be called in the `onPause` lifecycle event.
130143
*/
131144
public void unbindService() {
132145
context.unbindService(connection);
133-
group.enter();
134146
}
135147

136148
private void handledNavigationEvent(int navigationEvent) {
@@ -143,19 +155,13 @@ private void handledNavigationEvent(int navigationEvent) {
143155
isInitialLoad = false;
144156
}
145157
break;
146-
case CustomTabsCallback.TAB_HIDDEN:
147-
group.leave();
148-
break;
149-
case CustomTabsCallback.TAB_SHOWN:
150-
group.enter();
151-
break;
152158
}
153159
}
154160

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.
161+
public void notifyBrowserFinished() {
162+
// Notify listeners that the browser session has finished. Called by the
163+
// host activity when the Custom Tab activity actually returns a result
164+
// (i.e. the tab was truly dismissed, not just backgrounded or minimised).
159165
if (browserEventListener != null) {
160166
browserEventListener.onBrowserEvent(BROWSER_FINISHED);
161167
}
Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
package com.capacitorjs.plugins.browser;
22

3-
import android.app.Activity;
43
import android.content.Intent;
54
import android.net.Uri;
65
import android.os.Bundle;
6+
import androidx.activity.ComponentActivity;
7+
import androidx.activity.result.ActivityResultLauncher;
8+
import androidx.activity.result.contract.ActivityResultContracts;
79
import androidx.annotation.Nullable;
810

9-
public class BrowserControllerActivity extends Activity {
11+
public class BrowserControllerActivity extends ComponentActivity {
1012

11-
private boolean isCustomTabsOpen = false;
13+
private ActivityResultLauncher<Intent> customTabLauncher;
14+
private Browser implementation;
1215

1316
@Override
1417
protected void onCreate(@Nullable Bundle savedInstanceState) {
1518
super.onCreate(savedInstanceState);
16-
isCustomTabsOpen = false;
19+
20+
customTabLauncher = registerForActivityResult(
21+
new ActivityResultContracts.StartActivityForResult(),
22+
result -> {
23+
if (implementation != null) {
24+
implementation.notifyBrowserFinished();
25+
}
26+
finish();
27+
}
28+
);
1729

1830
if (BrowserPlugin.browserControllerListener != null) {
1931
BrowserPlugin.browserControllerListener.onControllerReady(this);
@@ -28,25 +40,15 @@ protected void onNewIntent(Intent intent) {
2840
}
2941
}
3042

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-
4243
public void open(Browser implementation, Uri url, Integer toolbarColor) {
44+
this.implementation = implementation;
45+
implementation.setCustomTabLauncher(customTabLauncher);
4346
implementation.open(url, toolbarColor);
4447
}
4548

4649
@Override
4750
protected void onDestroy() {
4851
super.onDestroy();
49-
isCustomTabsOpen = false;
5052
BrowserPlugin.setBrowserControllerListener(null);
5153
}
5254
}

browser/android/src/main/java/com/capacitorjs/plugins/browser/EventGroup.java

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)