Skip to content

Commit 9680246

Browse files
Merge pull request #12 from torusresearch/feat/browser-android-updates
Updating react-native web-browser android code to latest code from expo.
2 parents 0905e9d + 229c3df commit 9680246

File tree

19 files changed

+3028
-3914
lines changed

19 files changed

+3028
-3914
lines changed

.husky/pre-commit

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#!/bin/sh
2-
. "$(dirname "$0")/_/husky.sh"
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
33

4-
yarn lint && yarn typescript
5-
swiftformat ios/
4+
npm test

android/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,9 @@ dependencies {
128128
api 'com.facebook.react:react-native:+'
129129
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
130130
api "androidx.browser:browser:1.4.0"
131+
// coroutine
132+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
133+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
134+
implementation 'androidx.core:core-ktx:1.0.0'
131135

132136
}
-285 Bytes
Binary file not shown.

android/gradlew

100755100644
File mode changed.

android/src/main/java/com/reactnativewebbrowser/InternalActicityProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.reactnativewebbrowser
33
import android.app.Activity
44
import com.facebook.react.bridge.ReactContext
55

6-
class InternalActicityProvider(val reactContext: ReactContext) :
6+
class InternalActivityProvider(private val reactContext: ReactContext) :
77
ActivityProvider {
88
override fun getCurrentActivity(): Activity? {
99
return reactContext.currentActivity

android/src/main/java/com/reactnativewebbrowser/InternalCustomTabsActivitiesHelper.kt

Lines changed: 81 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,99 +8,116 @@ import android.net.Uri
88
import androidx.browser.customtabs.CustomTabsClient
99
import androidx.browser.customtabs.CustomTabsIntent
1010
import androidx.browser.customtabs.CustomTabsService
11+
import com.reactnativewebbrowser.error.CurrentActivityNotFoundException
12+
import com.reactnativewebbrowser.error.PackageManagerNotFoundException
1113
import java.util.ArrayList
12-
import java.util.Collections
1314
import java.util.LinkedHashSet
1415

16+
private const val DUMMY_URL = "https://web3auth.io"
1517

16-
import androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION
17-
import com.reactnativewebbrowser.error.CurrentActivityNotFoundException
18-
import com.reactnativewebbrowser.error.PackageManagerNotFoundException
18+
class InternalCustomTabsActivitiesHelper(
19+
private val activityProvider: ActivityProvider?
20+
) {
1921

20-
class InternalCustomTabsActivitiesHelper(val activityProvider: ActivityProvider) :
21-
CustomTabsActivitiesHelper {
22+
// region Actual custom tabs activities helper methods
2223

23-
override val customTabsResolvingActivities: ArrayList<String>
24-
get() = mapCollectionToDistinctArrayList(
25-
getResolvingActivities(
26-
createDefaultCustomTabsIntent()
27-
)
28-
) { resolveInfo -> resolveInfo.activityInfo.packageName }
24+
/**
25+
* @throws CurrentActivityNotFoundException
26+
* @throws PackageManagerNotFoundException
27+
*/
28+
fun canResolveIntent(intent: Intent): Boolean = getResolvingActivities(intent).isNotEmpty()
2929

30-
override val customTabsResolvingServices: ArrayList<String>
31-
get() {
32-
return mapCollectionToDistinctArrayList(
33-
packageManager.queryIntentServices(
34-
createDefaultCustomTabsServiceIntent(),
35-
0
36-
)
37-
) { resolveInfo -> resolveInfo.serviceInfo.packageName }
38-
}
30+
/**
31+
* @throws PackageManagerNotFoundException
32+
* @throws CurrentActivityNotFoundException
33+
*/
34+
val customTabsResolvingActivities: ArrayList<String>
35+
get() = getResolvingActivities(createDefaultCustomTabsIntent())
36+
.mapToDistinctArrayList { resolveInfo: ResolveInfo ->
37+
resolveInfo.activityInfo.packageName
38+
}
39+
40+
/**
41+
* @throws PackageManagerNotFoundException
42+
* @throws CurrentActivityNotFoundException
43+
*/
44+
val customTabsResolvingServices: ArrayList<String>
45+
get() = packageManager.queryIntentServices(createDefaultCustomTabsServiceIntent(), 0)
46+
.mapToDistinctArrayList { resolveInfo: ResolveInfo ->
47+
resolveInfo.serviceInfo.packageName
48+
}
3949

40-
override fun getPreferredCustomTabsResolvingActivity(packages: List<String>?): String? {
41-
var packages: List<String>? = packages
42-
if (packages == null) packages = customTabsResolvingActivities
43-
return CustomTabsClient.getPackageName(currentActivity, packages)
50+
/**
51+
* @throws PackageManagerNotFoundException
52+
* @throws CurrentActivityNotFoundException
53+
*/
54+
fun getPreferredCustomTabsResolvingActivity(packages: List<String?>?): String? {
55+
val resolvedPackages = packages ?: customTabsResolvingActivities
56+
return CustomTabsClient.getPackageName(currentActivity, resolvedPackages)
4457
}
4558

46-
override val defaultCustomTabsResolvingActivity: String?
59+
/**
60+
* @throws PackageManagerNotFoundException
61+
* @throws CurrentActivityNotFoundException
62+
*/
63+
val defaultCustomTabsResolvingActivity: String?
4764
get() {
48-
val info: ResolveInfo? =
49-
packageManager.resolveActivity(createDefaultCustomTabsIntent(), 0)
65+
val info = packageManager.resolveActivity(createDefaultCustomTabsIntent(), 0)
5066
return info?.activityInfo?.packageName
5167
}
5268

53-
override fun canResolveIntent(intent: Intent): Boolean {
54-
return getResolvingActivities(intent).isNotEmpty()
55-
}
56-
57-
override fun startCustomTabs(intent: Intent) {
69+
/**
70+
* @throws CurrentActivityNotFoundException
71+
*/
72+
fun startCustomTabs(intent: Intent) {
5873
currentActivity.startActivity(intent)
5974
}
6075

76+
// endregion
77+
78+
// region Private helpers
79+
80+
/**
81+
* @throws CurrentActivityNotFoundException
82+
* @throws PackageManagerNotFoundException
83+
*/
6184
private fun getResolvingActivities(intent: Intent): List<ResolveInfo> {
6285
return packageManager.queryIntentActivities(intent, 0)
6386
}
6487

88+
/**
89+
* @throws CurrentActivityNotFoundException
90+
* @throws PackageManagerNotFoundException
91+
*/
6592
private val packageManager: PackageManager
66-
get() {
67-
val pm: PackageManager? = currentActivity.packageManager
68-
if (pm == null) throw PackageManagerNotFoundException() else return pm
69-
}
93+
get() = currentActivity.packageManager ?: throw PackageManagerNotFoundException()
7094

95+
/**
96+
* @throws CurrentActivityNotFoundException
97+
*/
7198
private val currentActivity: Activity
7299
get() {
73-
return activityProvider.getCurrentActivity()
74-
?: throw CurrentActivityNotFoundException()
100+
return activityProvider?.getCurrentActivity() ?: throw CurrentActivityNotFoundException()
75101
}
76102

77-
private fun createDefaultCustomTabsIntent(): Intent {
78-
val builder: CustomTabsIntent.Builder = CustomTabsIntent.Builder()
79-
val customTabsIntent: CustomTabsIntent = builder.build()
80-
val intent: Intent = customTabsIntent.intent
81-
intent.data = Uri.parse(DUMMY_URL)
82-
return intent
83-
}
103+
// endregion
104+
}
84105

85-
private fun createDefaultCustomTabsServiceIntent(): Intent {
86-
val serviceIntent: Intent = Intent()
87-
serviceIntent.action = CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION
88-
return serviceIntent
106+
private inline fun <T, R> Collection<T>.mapToDistinctArrayList(mapper: (T) -> R): ArrayList<R> {
107+
val resultSet = LinkedHashSet<R>()
108+
for (element in this) {
109+
resultSet.add(mapper.invoke(element))
89110
}
111+
return ArrayList(resultSet)
112+
}
90113

91-
fun onDestroy() {}
92-
93-
companion object {
94-
private val DUMMY_URL: String = "https://expo.io"
95-
fun <T, R> mapCollectionToDistinctArrayList(
96-
toMap: Collection<T>,
97-
mapper: (T) -> R
98-
): ArrayList<R> {
99-
val resultSet: LinkedHashSet<R> = LinkedHashSet()
100-
for (element: T in toMap) {
101-
resultSet.add(mapper(element))
102-
}
103-
return ArrayList(resultSet)
104-
}
114+
private fun createDefaultCustomTabsIntent(): Intent {
115+
val customTabsIntent = CustomTabsIntent.Builder().build()
116+
return customTabsIntent.intent.apply {
117+
data = Uri.parse(DUMMY_URL)
105118
}
106119
}
120+
121+
private fun createDefaultCustomTabsServiceIntent() = Intent().apply {
122+
action = CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION
123+
}

android/src/main/java/com/reactnativewebbrowser/InternalCustomTabsConnectionHelper.kt

Lines changed: 48 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,108 +6,92 @@ import android.net.Uri
66
import androidx.browser.customtabs.CustomTabsClient
77
import androidx.browser.customtabs.CustomTabsServiceConnection
88
import androidx.browser.customtabs.CustomTabsSession
9-
import com.facebook.react.bridge.LifecycleEventListener
109

11-
class InternalCustomTabsConnectionHelper internal constructor(private val context: Context) :
12-
CustomTabsServiceConnection(), LifecycleEventListener,
13-
CustomTabsConnectionHelper {
14-
private var mPackageName: String? = null
15-
private val clientActions: DeferredClientActionsQueue<CustomTabsClient> =
16-
DeferredClientActionsQueue()
17-
private val sessionActions: DeferredClientActionsQueue<CustomTabsSession> =
18-
DeferredClientActionsQueue()
10+
class InternalCustomTabsConnectionHelper(
11+
private val context: Context
12+
) : CustomTabsServiceConnection() {
13+
private var currentPackageName: String? = null
14+
private val clientActions = DeferredClientActionsQueue<CustomTabsClient>()
15+
private val sessionActions = DeferredClientActionsQueue<CustomTabsSession?>()
1916

20-
override fun warmUp(packageName: String) {
21-
clientActions.executeOrQueueAction { client -> client.warmup(0) }
17+
// region lifecycle methods
18+
fun destroy() = clearConnection()
19+
// endregion
20+
21+
// region Actual connection helper methods
22+
fun warmUp(packageName: String) {
23+
clientActions.executeOrQueueAction { client: CustomTabsClient -> client.warmup(0) }
2224
ensureConnection(packageName)
2325
}
2426

25-
override fun mayInitWithUrl(packageName: String, uri: Uri) {
26-
sessionActions.executeOrQueueAction { session ->
27-
session.mayLaunchUrl(
28-
uri,
29-
null,
30-
null
31-
)
27+
fun mayInitWithUrl(packageName: String, uri: Uri) {
28+
sessionActions.executeOrQueueAction { session: CustomTabsSession? ->
29+
session?.mayLaunchUrl(uri, null, null)
3230
}
3331
ensureConnection(packageName)
3432
ensureSession()
3533
}
3634

37-
private fun ensureSession() {
38-
if (!sessionActions.hasClient()) {
39-
clientActions.executeOrQueueAction { client ->
40-
sessionActions.setClient(
41-
client.newSession(null)
42-
)
43-
}
44-
}
45-
}
46-
47-
override fun coolDown(packageName: String): Boolean {
48-
if ((packageName == mPackageName)) {
49-
unbindService()
35+
fun coolDown(packageName: String): Boolean {
36+
if (isConnectionStarted(packageName)) {
37+
clearConnection()
5038
return true
5139
}
5240
return false
5341
}
42+
// endregion
5443

55-
private fun ensureConnection(packageName: String) {
56-
if (mPackageName != null && !(mPackageName == packageName)) {
57-
clearConnection()
58-
}
59-
if (!connectionStarted(packageName)) {
60-
CustomTabsClient.bindCustomTabsService(context, packageName, this)
61-
mPackageName = packageName
62-
}
63-
}
64-
65-
private fun connectionStarted(packageName: String): Boolean {
66-
return (packageName == mPackageName)
67-
}
68-
44+
// region CustomTabsServiceConnection implementation
6945
override fun onBindingDied(componentName: ComponentName) {
70-
if ((componentName.packageName == mPackageName)) {
46+
if (isConnectionStarted(componentName.packageName)) {
7147
clearConnection()
7248
}
7349
}
7450

75-
override fun onCustomTabsServiceConnected(
76-
componentName: ComponentName,
77-
client: CustomTabsClient
78-
) {
79-
if ((componentName.packageName == mPackageName)) {
51+
override fun onCustomTabsServiceConnected(componentName: ComponentName, client: CustomTabsClient) {
52+
if (isConnectionStarted(componentName.packageName)) {
8053
clientActions.setClient(client)
8154
}
8255
}
8356

8457
override fun onServiceDisconnected(componentName: ComponentName) {
85-
if ((componentName.packageName == mPackageName)) {
58+
if (isConnectionStarted(componentName.packageName)) {
8659
clearConnection()
8760
}
8861
}
62+
// endregion
8963

90-
override fun onHostResume() {
91-
// do nothing
92-
}
64+
private fun ensureSession() {
65+
if (sessionActions.hasClient()) {
66+
return
67+
}
9368

94-
override fun onHostPause() {
95-
// do nothing
69+
clientActions.executeOrQueueAction { client: CustomTabsClient ->
70+
sessionActions.setClient(client.newSession(null))
71+
}
9672
}
9773

98-
override fun onHostDestroy() {
99-
unbindService()
74+
private fun ensureConnection(packageName: String) {
75+
if (currentPackageName != null && currentPackageName != packageName) {
76+
clearConnection()
77+
}
78+
if (!isConnectionStarted(packageName)) {
79+
CustomTabsClient.bindCustomTabsService(context, packageName, this)
80+
currentPackageName = packageName
81+
}
10082
}
10183

102-
private fun unbindService() {
103-
context.unbindService(this)
104-
clearConnection()
84+
private fun isConnectionStarted(packageName: String): Boolean {
85+
return packageName == currentPackageName
10586
}
10687

10788
private fun clearConnection() {
108-
mPackageName = null
89+
if (currentPackageName != null) {
90+
context.unbindService(this)
91+
}
92+
93+
currentPackageName = null
10994
clientActions.clear()
11095
sessionActions.clear()
11196
}
112-
11397
}

0 commit comments

Comments
 (0)