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
9 changes: 4 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [2.1.0]

### Fixes

- Fire `browserClosed` only when the Custom Tab actually terminates, using `ActivityResultLauncher` instead of inferring closure from `TAB_HIDDEN`. Prevents the event from firing prematurely when the tab is minimized to Picture-in-Picture or the app is backgrounded. This fix applies to Android 14 and higher, on older versions the previous behavior is preserved because the `ActivityResult` callback is not reliably delivered when the tab is dismissed from Picture-in-Picture.
### Features

## [2.0.4]
- Add `successUrlPatterns` WebView option: a list of regex patterns checked against each finished page load, closing the browser natively as soon as one matches, independent of whether the host app's WebView is able to react to the completion event ([RMET-5394](https://outsystemsrd.atlassian.net/browse/RMET-5394)).

### Fixes

- Keep the main app process active while the WebView is in the foreground, by binding it to the WebView's process. Without this, Android can freeze the main process during a browser session, so browser events stop being processed and the app never reacts to the page finishing ([RMET-5394](https://outsystemsrd.atlassian.net/browse/RMET-5394)).
- Fire `browserClosed` only when the Custom Tab actually terminates, using `ActivityResultLauncher` instead of inferring closure from `TAB_HIDDEN`. Prevents the event from firing prematurely when the tab is minimized to Picture-in-Picture or the app is backgrounded. This fix applies to Android 14 and higher, on older versions the previous behavior is preserved because the `ActivityResult` callback is not reliably delivered when the tab is dismissed from Picture-in-Picture.

## [2.0.3]

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.ionic.libs</groupId>
<artifactId>ioninappbrowser-android</artifactId>
<version>2.0.3</version>
<version>2.1.0</version>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ data class OSIABWebViewOptions(
@SerializedName("hardwareBack") val hardwareBack: Boolean = true,
@SerializedName("pauseMedia") val pauseMedia: Boolean = true,
@SerializedName("customUserAgent") val customUserAgent: String? = null,
@SerializedName("isIsolated") val isIsolated: Boolean = true
@SerializedName("isIsolated") val isIsolated: Boolean = true,
// RMET-5394: regex patterns checked against each finished page load; a match closes the
// browser natively (no dependency on MainActivity's WebView JS being able to react).
@SerializedName("successUrlPatterns") val successUrlPatterns: List<String>? = null
) : OSIABOptions, Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import java.io.IOException
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
import java.util.regex.PatternSyntaxException

open class OSIABWebViewActivity : AppCompatActivity() {

Expand Down Expand Up @@ -548,6 +549,22 @@ open class OSIABWebViewActivity : AppCompatActivity() {
sendWebViewEvent(OSIABEvents.BrowserPageNavigationCompleted(browserId, resolvedUrl))
}

// RMET-5394: close natively the moment an app-configured "done" pattern matches,
// independent of whether MainActivity's WebView JS is able to react to the event
// above - sendWebViewEvent() above is synchronous (see #59), so the broadcast is
// already in flight by the time finish() runs below.
val matchesSuccessPattern = resolvedUrl != null && options.successUrlPatterns?.any { pattern ->
try {
Regex(pattern).containsMatchIn(resolvedUrl)
} catch (e: PatternSyntaxException) {
Log.d(LOG_TAG, "Invalid successUrlPatterns regex '$pattern': ${e.message}")
false
}
} == true
if (matchesSuccessPattern) {
finish()
}

if (url?.startsWith(PDF_VIEWER_URL_PREFIX) == true && options.clearCache) {
webView.evaluateJavascript(
"localStorage.clear(); sessionStorage.clear();", null
Expand Down
Loading