Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.browser.customtabs.*;
Expand Down Expand Up @@ -43,7 +44,10 @@ interface BrowserEventListener {
private CustomTabsClient customTabsClient;
private CustomTabsSession browserSession;
private boolean isInitialLoad = false;
private EventGroup group;

@Nullable
private ActivityResultLauncher<Intent> customTabLauncher;

private CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
@Override
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
Expand All @@ -61,7 +65,6 @@ public void onServiceDisconnected(ComponentName name) {}
*/
public Browser(@NonNull Context context) {
this.context = context;
this.group = new EventGroup(this::handleGroupCompletion);
}

/**
Expand All @@ -81,6 +84,16 @@ public BrowserEventListener getBrowserEventListenerListener() {
return browserEventListener;
}

/**
* Provide the ActivityResultLauncher used to open the Custom Tab. When
* set, the Custom Tab is launched via this launcher so that
* {@link #notifyBrowserFinished()} can be triggered from the launcher's
* result callback (only when the tab activity actually terminates).
*/
public void setCustomTabLauncher(@Nullable ActivityResultLauncher<Intent> launcher) {
this.customTabLauncher = launcher;
}

/**
* Open the browser to the specified URL.
* @param url
Expand Down Expand Up @@ -108,8 +121,12 @@ public void open(Uri url, @Nullable Integer toolbarColor) {
tabsIntent.intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + context.getPackageName()));

isInitialLoad = true;
group.reset();
tabsIntent.launchUrl(context, url);
if (customTabLauncher != null) {
tabsIntent.intent.setData(url);
customTabLauncher.launch(tabsIntent.intent);
} else {
tabsIntent.launchUrl(context, url);
}
}

/**
Expand All @@ -120,17 +137,14 @@ public boolean bindService() {
if (null == customTabPackageName) {
customTabPackageName = FALLBACK_CUSTOM_TAB_PACKAGE_NAME;
}
boolean result = CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
group.leave();
return result;
return CustomTabsClient.bindCustomTabsService(context, customTabPackageName, connection);
}

/**
* Unbind the custom tabs service, required to be called in the `onPause` lifecycle event.
*/
public void unbindService() {
context.unbindService(connection);
group.enter();
}

private void handledNavigationEvent(int navigationEvent) {
Expand All @@ -143,19 +157,13 @@ private void handledNavigationEvent(int navigationEvent) {
isInitialLoad = false;
}
break;
case CustomTabsCallback.TAB_HIDDEN:
group.leave();
break;
case CustomTabsCallback.TAB_SHOWN:
group.enter();
break;
}
}

private void handleGroupCompletion() {
// events such as TAB_HIDDEN and onPause can occur for multiple reasons and in
// different sequences so there is no single point to fire this. so we rely on the
// event group to track when it is safe to assume that the browser is done.
public void notifyBrowserFinished() {
// Notify listeners that the browser session has finished. Called by the
// host activity when the Custom Tab activity actually returns a result
// (i.e. the tab was truly dismissed, not just backgrounded or minimised).
if (browserEventListener != null) {
browserEventListener.onBrowserEvent(BROWSER_FINISHED);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package com.capacitorjs.plugins.browser;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;

public class BrowserControllerActivity extends Activity {
public class BrowserControllerActivity extends ComponentActivity {

private boolean isCustomTabsOpen = false;
private ActivityResultLauncher<Intent> customTabLauncher;
private Browser implementation;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isCustomTabsOpen = false;

customTabLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), (result) -> {
if (implementation != null) {
implementation.notifyBrowserFinished();
}
finish();
});

if (BrowserPlugin.browserControllerListener != null) {
BrowserPlugin.browserControllerListener.onControllerReady(this);
Expand All @@ -28,25 +37,15 @@ protected void onNewIntent(Intent intent) {
}
}

@Override
protected void onResume() {
super.onResume();
if (isCustomTabsOpen) {
isCustomTabsOpen = false;
finish();
} else {
isCustomTabsOpen = true;
}
}

public void open(Browser implementation, Uri url, Integer toolbarColor) {
this.implementation = implementation;
implementation.setCustomTabLauncher(customTabLauncher);
implementation.open(url, toolbarColor);
}

@Override
protected void onDestroy() {
super.onDestroy();
isCustomTabsOpen = false;
BrowserPlugin.setBrowserControllerListener(null);
}
}

This file was deleted.

Loading