From d36515f93d1a1c0f3fff0413b9d59b9f1e904c16 Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Sun, 31 Jul 2022 21:59:42 -0500 Subject: [PATCH 01/10] Add mayLaunchUrl and warmup methods in Android --- .../Android/src/main/AndroidManifest.xml | 2 +- demo/app/activity.android.ts | 98 +++++++++++++++++ demo/webpack.config.js | 4 + src/CustomTabsServiceConnection.ts | 32 ++++++ src/InAppBrowser.android.ts | 85 +++++++++++--- src/InAppBrowser.common.ts | 4 + src/InAppBrowser.ios.ts | 9 ++ src/platforms/android/AndroidManifest.xml | 4 + .../android/nativescript_inappbrowser.aar | Bin 4522 -> 4538 bytes src/types/android.d.ts | 104 +++++++++++++++--- src/utils.android.ts | 37 +++++-- 11 files changed, 337 insertions(+), 42 deletions(-) create mode 100644 demo/app/activity.android.ts create mode 100644 src/CustomTabsServiceConnection.ts diff --git a/demo/App_Resources/Android/src/main/AndroidManifest.xml b/demo/App_Resources/Android/src/main/AndroidManifest.xml index 8b4b9c8..ab63746 100644 --- a/demo/App_Resources/Android/src/main/AndroidManifest.xml +++ b/demo/App_Resources/Android/src/main/AndroidManifest.xml @@ -27,7 +27,7 @@ android:launchMode="singleTask"> , + grantResults: Array + ): void { + this._callbacks.onRequestPermissionsResult( + this, + requestCode, + permissions, + grantResults, + undefined /*TODO: Enable if needed*/ + ); + } + + public onActivityResult( + requestCode: number, + resultCode: number, + data: android.content.Intent + ): void { + this._callbacks.onActivityResult( + this, + requestCode, + resultCode, + data, + super.onActivityResult + ); + } +} diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 67fb28f..29f3fda 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -5,6 +5,10 @@ module.exports = (env) => { webpack.init(env); webpack.useConfig("typescript"); + env.appComponents = (env.appComponents || []).concat([ + "./app/activity.android", + ]); + webpack.chainWebpack((config) => { // shared demo code config.resolve.alias.set( diff --git a/src/CustomTabsServiceConnection.ts b/src/CustomTabsServiceConnection.ts new file mode 100644 index 0000000..872be61 --- /dev/null +++ b/src/CustomTabsServiceConnection.ts @@ -0,0 +1,32 @@ +import ComponentName = android.content.ComponentName; +import CustomTabsClient = androidx.browser.customtabs.CustomTabsClient; + +import { Utils } from "@nativescript/core"; +import { + setCustomTabsClient, + CustomTabsServiceConnection, +} from "./utils.android"; +import { log } from "./utils.common"; + +@NativeClass() +@JavaProxy("com.proyecto26.inappbrowser.CustomTabsServiceConnection") +export class InAppBrowserCustomTabsServiceConnection extends CustomTabsServiceConnection { + constructor() { + super(); + return global.__native(this); + } + + onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) { + setCustomTabsClient(client); + if (!client.warmup(long(0))) { + console.error(`Couldn't warmup custom tabs client for ${name}`); + } + const context = Utils.android.getApplicationContext(); + context.unbindService(this); + } + + onServiceDisconnected(name: ComponentName) { + setCustomTabsClient(null); + log(`Custom tabs service disconnected for ${name}`); + } +} diff --git a/src/InAppBrowser.android.ts b/src/InAppBrowser.android.ts index b51bea9..e4bebab 100644 --- a/src/InAppBrowser.android.ts +++ b/src/InAppBrowser.android.ts @@ -7,42 +7,46 @@ import Context = android.content.Context; import BitmapFactory = android.graphics.BitmapFactory; import Browser = android.provider.Browser; import Pattern = java.util.regex.Pattern; +import ArrayList = java.util.ArrayList; import { Application, EventData, Utils } from "@nativescript/core"; import { - ChromeTabsEvent, BROWSER_ACTIVITY_EVENTS, - createStartIntent, + ChromeTabsEvent, createDismissIntent, + createStartIntent, } from "./ChromeTabsManagerActivity"; import { Animations, BrowserResult, + BROWSER_TYPES, getDefaultOptions, - InAppBrowserOptions, InAppBrowserClassMethods, - RedirectResolve, + InAppBrowserOptions, RedirectReject, - BROWSER_TYPES, + RedirectResolve, } from "./InAppBrowser.common"; import { + ARROW_BACK_BLACK, + ARROW_BACK_WHITE, Builder, - getDrawableId, - toolbarIsLight, + closeAuthSessionPolyfillAsync, + CustomTabsCallback, + CustomTabsClient, CustomTabsIntent, + CustomTabsService, DISMISSED_EVENT, - ARROW_BACK_WHITE, - ARROW_BACK_BLACK, + getDefaultBrowser, + getDrawableId, getPreferredPackages, openAuthSessionPolyfillAsync, - closeAuthSessionPolyfillAsync, + toolbarIsLight, + getCustomTabsClient, } from "./utils.android"; - import { tryParseColor } from "./utils.common"; +import { InAppBrowserCustomTabsServiceConnection } from "./CustomTabsServiceConnection"; -declare let global: any; - -let InAppBrowserModuleInstance: InAppBrowserClassMethods; +let InAppBrowserModuleInstance: any; function setup() { @NativeClass() @@ -223,8 +227,7 @@ function setup() { intent.setPackage(packageName); } } else { - const packageName = - inAppBrowserOptions[InAppBrowserModule.KEY_BROWSER_PACKAGE]; + const packageName = getDefaultBrowser(context); intent.setPackage(packageName); } } catch (error) { @@ -412,6 +415,56 @@ function setup() { InAppBrowserModule.redirectResolve = null; InAppBrowserModule.redirectReject = null; } + + public onStart(): void { + const context = Utils.android.getApplicationContext() as Context; + const connection = new InAppBrowserCustomTabsServiceConnection(); + const packageName = getDefaultBrowser(context); + if (packageName) { + CustomTabsClient.bindCustomTabsService( + context, + packageName, + connection + ); + } else { + console.error("No browser supported to bind custom tab service"); + } + } + + public warmup(): boolean { + const customTabsClient = getCustomTabsClient(); + if (customTabsClient?.warmup) { + return customTabsClient.warmup(long(0)); + } + return false; + } + + public mayLaunchUrl(mostLikelyUrl: string, otherUrls: Array): void { + const customTabsClient = getCustomTabsClient(); + if (customTabsClient?.newSession) { + const customTabsSession = customTabsClient.newSession( + new CustomTabsCallback() + ); + if (customTabsSession != null) { + const otherUrlBundles = new ArrayList(otherUrls.length); + + for (let index = 0; index < otherUrls.length; index++) { + const link = otherUrls[index]; + if (link != null) { + const bundle = new Bundle(); + bundle.putParcelable(CustomTabsService.KEY_URL, Uri.parse(link)); + otherUrlBundles.add(bundle); + } + } + + customTabsSession.mayLaunchUrl( + Uri.parse(mostLikelyUrl), + null, + otherUrlBundles + ); + } + } + } } return new InAppBrowserModule(); diff --git a/src/InAppBrowser.common.ts b/src/InAppBrowser.common.ts index ee3473a..0523983 100644 --- a/src/InAppBrowser.common.ts +++ b/src/InAppBrowser.common.ts @@ -86,6 +86,10 @@ export interface InAppBrowserClassMethods { ) => Promise; closeAuth: () => void; isAvailable: () => Promise; + // Android only + onStart(): void; + warmup: () => boolean; + mayLaunchUrl: (mostLikelyUrl: string, otherUrls: Array) => void; } export type RedirectResolve = ( diff --git a/src/InAppBrowser.ios.ts b/src/InAppBrowser.ios.ts index e3aa018..229a72b 100644 --- a/src/InAppBrowser.ios.ts +++ b/src/InAppBrowser.ios.ts @@ -303,6 +303,15 @@ function setup() { this.redirectResolve = null; this.redirectReject = null; } + onStart() { + log("onStart is not supported on iOS"); + } + warmup() { + return false; + } + mayLaunchUrl(url: string, otherUrls: Array) { + log(`mayLaunchUrl is not supported on iOS. url: ${url}, otherUrls: ${otherUrls}`); + } } return InAppBrowserModule.new(); diff --git a/src/platforms/android/AndroidManifest.xml b/src/platforms/android/AndroidManifest.xml index 967a7f5..003b65d 100644 --- a/src/platforms/android/AndroidManifest.xml +++ b/src/platforms/android/AndroidManifest.xml @@ -8,6 +8,10 @@ android:name="com.proyecto26.inappbrowser.ChromeTabsManagerActivity" android:exported="true"> + + diff --git a/src/platforms/android/nativescript_inappbrowser.aar b/src/platforms/android/nativescript_inappbrowser.aar index ae35297f39a8aae4cf3dc397ed39a78ba7a991ed..d848bd0f07b9405c8ac1ce9b9a0cdbf455523433 100644 GIT binary patch delta 575 zcmZ3byi0jPBG(d&>VQy21_ll0iP@6%OM`s<4;%38{T?2&Q$JBb(PZn~3tO1k%Mygc zr!0*VFa4=dc>3FWPw(qnnfW;G|4Fj9w^yGje^qha!OF}MuVr7_jx1}lllYv(-&K9DPqX*4{tRop zBie9y(QeJon;kcsf-jk`ubur&E5kOwRC9s<>a(9xx8C8gxTjqpRCDdT-x9YA6^v06 zxc}5PtzToxw{nGzRBMg2PVVcMi(JhZBb!$*Z73@`AAYKBv(UBdpQoB^yjrx|n9v&EJ!{kPw1 z-QGxvwF|$#^^X!VGt%<9@$+{2{LLpBpKu}t_2li`fs8jNbMjbla4|736r~pHPd4P2 znH7i={@V@->mvzgP!q8Fazg;%7gM*ma-o9x%`$N|IfY$WvXq^bx_LsuZ zX_K#btmYTc=q!uuM_^_L@$=s=O_CpFOR%XZ?Ltp_BE( zgf9lkof4YW4vU>X-#NfaT;k1eT>0WZ z-@;G#6bnOHi`t&pt=sbSb7=P)rA@4Bwl-}mUa!@**FETB_0N-!jr^ldx@81h*0?@P zPq{uh{$t;r#k(7n%Kx8ePk*>t*^0S$ad_rq-;X;lC)aZw+BuWw(R{@VqhXQunCleyXS!3KTflVUtRS&%=9an + ): boolean; } - export class CustomTabsIntent { + export class CustomTabsClient extends java.lang.Object { + static getPackageName( + context: android.content.Context, + list: java.util.List + ): string; + static bindCustomTabsService( + context: android.content.Context, + packageName: string, + connection: CustomTabsServiceConnection + ): CustomTabsClient; + warmup(flags: java.lang.Long): boolean; + newSession(callback: CustomTabsCallback): CustomTabsSession; + } + export class CustomTabsIntent extends java.lang.Object { launchUrl(context: android.content.Context, url: android.net.Uri): void; intent: android.content.Intent; static NO_TITLE: number; @@ -13,9 +31,8 @@ declare namespace android { startAnimationBundle: android.os.Bundle; } namespace CustomTabsIntent { - export class Builder { - constructor(); - build(): android.support.customtabs.CustomTabsIntent; + export class Builder extends java.lang.Object { + build(): CustomTabsIntent; setShowTitle(showTitle: boolean): this; setToolbarColor(color: number): this; setSecondaryToolbarColor(color: number): this; @@ -23,11 +40,29 @@ declare namespace android { setNavigationBarDividerColor(color: number): this; addDefaultShareMenuItem(): this; enableUrlBarHiding(): this; - setStartAnimations(context: android.content.Context, enterResId: number, exitResId: number): this; - setExitAnimations(context: android.content.Context, enterResId: number, exitResId: number): this; + setStartAnimations( + context: android.content.Context, + enterResId: number, + exitResId: number + ): this; + setExitAnimations( + context: android.content.Context, + enterResId: number, + exitResId: number + ): this; setCloseButtonIcon(icon: android.graphics.Bitmap): this; } } + export class CustomTabsService extends android.app.Service { + static KEY_URL: string; + } + export class CustomTabsServiceConnection extends android.content + .ServiceConnection { + onCustomTabsServiceConnected( + name: android.content.ComponentName, + client: CustomTabsClient + ): void; + } } } } @@ -35,10 +70,28 @@ declare namespace android { declare namespace androidx { export namespace browser { export namespace customtabs { - export class CustomTabsClient { - static getPackageName(context: android.content.Context, list: java.util.List): string; + export class CustomTabsCallback extends java.lang.Object {} + export class CustomTabsSession extends java.lang.Object { + mayLaunchUrl( + url: android.net.Uri, + extras: android.os.Bundle, + otherLikelyBundles: java.util.List + ): boolean; + } + export class CustomTabsClient extends java.lang.Object { + static getPackageName( + context: android.content.Context, + list: java.util.List + ): string; + static bindCustomTabsService( + context: android.content.Context, + packageName: string, + connection: CustomTabsServiceConnection + ): void; + warmup(flags: java.lang.Long): boolean; + newSession(callback: CustomTabsCallback): CustomTabsSession; } - export class CustomTabsIntent { + export class CustomTabsIntent extends java.lang.Object { launchUrl(context: android.content.Context, url: android.net.Uri): void; intent: android.content.Intent; static NO_TITLE: number; @@ -47,9 +100,8 @@ declare namespace androidx { startAnimationBundle: android.os.Bundle; } namespace CustomTabsIntent { - export class Builder { - constructor(); - build(): android.support.customtabs.CustomTabsIntent; + export class Builder extends java.lang.Object { + build(): CustomTabsIntent; setShowTitle(showTitle: boolean): this; setToolbarColor(color: number): this; setSecondaryToolbarColor(color: number): this; @@ -57,11 +109,29 @@ declare namespace androidx { setNavigationBarDividerColor(color: number): this; addDefaultShareMenuItem(): this; enableUrlBarHiding(): this; - setStartAnimations(context: android.content.Context, enterResId: number, exitResId: number): this; - setExitAnimations(context: android.content.Context, enterResId: number, exitResId: number): this; + setStartAnimations( + context: android.content.Context, + enterResId: number, + exitResId: number + ): this; + setExitAnimations( + context: android.content.Context, + enterResId: number, + exitResId: number + ): this; setCloseButtonIcon(icon: android.graphics.Bitmap): this; } } + export class CustomTabsService extends android.app.Service { + static KEY_URL: string; + } + export class CustomTabsServiceConnection extends android.content + .ServiceConnection { + onCustomTabsServiceConnected( + name: android.content.ComponentName, + client: CustomTabsClient + ): void; + } } } -} \ No newline at end of file +} diff --git a/src/utils.android.ts b/src/utils.android.ts index d525bde..b9d6574 100644 --- a/src/utils.android.ts +++ b/src/utils.android.ts @@ -8,20 +8,24 @@ import List = java.util.List; import Arrays = java.util.Arrays; import { - Utils, + AndroidActivityEventData, + AndroidApplication, Application, ApplicationEventData, - AndroidApplication, - AndroidActivityEventData, + Utils, } from "@nativescript/core"; import { - RedirectResult, - OpenBrowserAsync, AuthSessionResult, BROWSER_TYPES, InAppBrowserOptions, + OpenBrowserAsync, + RedirectResult, } from "./InAppBrowser.common"; +export function useAndroidX() { + return global.androidx && global.androidx.browser; +} + export type Builder = androidx.browser.customtabs.CustomTabsIntent.Builder; export const CustomTabsIntent = ( useAndroidX() ? androidx.browser : android.support @@ -29,9 +33,20 @@ export const CustomTabsIntent = ( export const CustomTabsClient = ( useAndroidX() ? androidx.browser : android.support ).customtabs.CustomTabsClient; +export const CustomTabsServiceConnection = ( + useAndroidX() ? androidx.browser : android.support +).customtabs.CustomTabsServiceConnection; +export const CustomTabsService = ( + useAndroidX() ? androidx.browser : android.support +).customtabs.CustomTabsService; +export const CustomTabsCallback = ( + useAndroidX() ? androidx.browser : android.support +).customtabs.CustomTabsCallback; + export const ColorUtils: typeof androidx.core.graphics.ColorUtils = ( useAndroidX() ? androidx.core.graphics : (android.support.v4.graphics as any) ).ColorUtils; + export const CHROME_PACKAGE_STABLE = "com.android.chrome"; export const CHROME_PACKAGE_BETA = "com.chrome.beta"; export const CHROME_PACKAGE_DEV = "com.chrome.dev"; @@ -51,12 +66,18 @@ let _redirectHandler: (args: ApplicationEventData) => void; */ let initialUrl = ""; -export const getDrawableId = Utils.ad.resources.getDrawableId; +let customTabsClient: androidx.browser.customtabs.CustomTabsClient; -export function useAndroidX() { - return global.androidx && global.androidx.browser; +export function getCustomTabsClient () { + return customTabsClient; +} + +export function setCustomTabsClient (client: androidx.browser.customtabs.CustomTabsClient) { + customTabsClient = client; } +export const getDrawableId = Utils.ad.resources.getDrawableId; + /** * Get the url when the app is opened and clear the data for security concerns. * @param activity - Current Android Activity. From fe5973390e8a99eeb5766cb15401f1f61e50b0c7 Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 00:28:56 -0500 Subject: [PATCH 02/10] Code review --- .../Android/native-api-usage.json | 5 +++- src/ChromeTabsManagerActivity.ts | 24 ++++++++++++------- src/CustomTabsServiceConnection.ts | 17 ++++++++----- src/InAppBrowser.android.ts | 5 ++-- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/demo/App_Resources/Android/native-api-usage.json b/demo/App_Resources/Android/native-api-usage.json index 7668b99..1d19a3a 100644 --- a/demo/App_Resources/Android/native-api-usage.json +++ b/demo/App_Resources/Android/native-api-usage.json @@ -1,3 +1,6 @@ { - "whitelist-plugins-usages": true + "whitelist-plugins-usages": true, + "whitelist": [ + "org.nativescript*:*" + ] } diff --git a/src/ChromeTabsManagerActivity.ts b/src/ChromeTabsManagerActivity.ts index 7cbfc9e..9c203a6 100644 --- a/src/ChromeTabsManagerActivity.ts +++ b/src/ChromeTabsManagerActivity.ts @@ -7,13 +7,13 @@ import { BROWSER_TYPES } from "./InAppBrowser.common"; import { DISMISSED_EVENT } from "./utils.android"; import { log } from "./utils.common"; -export class ChromeTabsEvent extends Observable { +class ChromeTabsEvent extends Observable { public message: string; public resultType: string; public isError: boolean; } -export const BROWSER_ACTIVITY_EVENTS = new ChromeTabsEvent(); +const BROWSER_ACTIVITY_EVENTS = new ChromeTabsEvent(); const KEY_BROWSER_INTENT = "browserIntent"; const BROWSER_RESULT_TYPE = "browserResultType"; @@ -39,7 +39,7 @@ const notifyMessage = ( */ @NativeClass() @JavaProxy("com.proyecto26.inappbrowser.ChromeTabsManagerActivity") -export class ChromeTabsManagerActivity extends android.app.Activity { +class ChromeTabsManagerActivity extends android.app.Activity { private mOpened = false; private resultType = null; private isError = false; @@ -131,21 +131,27 @@ export class ChromeTabsManagerActivity extends android.app.Activity { } } -export const createStartIntent = ( - context: Context, - authIntent: Intent -): Intent => { +const createStartIntent = (context: Context, authIntent: Intent): Intent => { let intent = createBaseIntent(context); intent.putExtra(KEY_BROWSER_INTENT, authIntent); return intent; }; -export const createDismissIntent = (context: Context): Intent => { +const createDismissIntent = (context: Context): Intent => { let intent = createBaseIntent(context); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); return intent; }; -export const createBaseIntent = (context: Context): Intent => { +const createBaseIntent = (context: Context): Intent => { return new Intent(context, ChromeTabsManagerActivity.class); }; + +export { + BROWSER_ACTIVITY_EVENTS, + ChromeTabsEvent, + createStartIntent, + createDismissIntent, + createBaseIntent, + ChromeTabsManagerActivity, +}; diff --git a/src/CustomTabsServiceConnection.ts b/src/CustomTabsServiceConnection.ts index 872be61..d92f0da 100644 --- a/src/CustomTabsServiceConnection.ts +++ b/src/CustomTabsServiceConnection.ts @@ -1,3 +1,4 @@ +import Context = android.content.Context; import ComponentName = android.content.ComponentName; import CustomTabsClient = androidx.browser.customtabs.CustomTabsClient; @@ -9,24 +10,28 @@ import { import { log } from "./utils.common"; @NativeClass() -@JavaProxy("com.proyecto26.inappbrowser.CustomTabsServiceConnection") -export class InAppBrowserCustomTabsServiceConnection extends CustomTabsServiceConnection { - constructor() { +class CustomTabsController extends CustomTabsServiceConnection { + private readonly context: WeakRef; + constructor(context: Context) { super(); + this.context = new WeakRef(context); + return global.__native(this); } onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) { setCustomTabsClient(client); if (!client.warmup(long(0))) { - console.error(`Couldn't warmup custom tabs client for ${name}`); + console.error(`Couldn't warmup custom tabs client for ${name.getClassName()}`); } - const context = Utils.android.getApplicationContext(); + const context = this.context.get(); context.unbindService(this); } onServiceDisconnected(name: ComponentName) { setCustomTabsClient(null); - log(`Custom tabs service disconnected for ${name}`); + log(`Custom tabs service disconnected for ${name.getClassName()}`); } } + +export { CustomTabsController } \ No newline at end of file diff --git a/src/InAppBrowser.android.ts b/src/InAppBrowser.android.ts index e4bebab..53f9031 100644 --- a/src/InAppBrowser.android.ts +++ b/src/InAppBrowser.android.ts @@ -16,6 +16,7 @@ import { createDismissIntent, createStartIntent, } from "./ChromeTabsManagerActivity"; +import { CustomTabsController } from "./CustomTabsServiceConnection"; import { Animations, BrowserResult, @@ -35,6 +36,7 @@ import { CustomTabsClient, CustomTabsIntent, CustomTabsService, + CustomTabsServiceConnection, DISMISSED_EVENT, getDefaultBrowser, getDrawableId, @@ -44,7 +46,6 @@ import { getCustomTabsClient, } from "./utils.android"; import { tryParseColor } from "./utils.common"; -import { InAppBrowserCustomTabsServiceConnection } from "./CustomTabsServiceConnection"; let InAppBrowserModuleInstance: any; @@ -418,7 +419,7 @@ function setup() { public onStart(): void { const context = Utils.android.getApplicationContext() as Context; - const connection = new InAppBrowserCustomTabsServiceConnection(); + const connection = new CustomTabsController(context); const packageName = getDefaultBrowser(context); if (packageName) { CustomTabsClient.bindCustomTabsService( From c23bcde4fd1b2284c57708466108508264baf39b Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 00:32:00 -0500 Subject: [PATCH 03/10] Code review --- src/platforms/android/AndroidManifest.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/platforms/android/AndroidManifest.xml b/src/platforms/android/AndroidManifest.xml index 003b65d..967a7f5 100644 --- a/src/platforms/android/AndroidManifest.xml +++ b/src/platforms/android/AndroidManifest.xml @@ -8,10 +8,6 @@ android:name="com.proyecto26.inappbrowser.ChromeTabsManagerActivity" android:exported="true"> - - From fc78c765880de85da434122c47667bba1a85f11c Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 00:47:01 -0500 Subject: [PATCH 04/10] Update native usage --- src/platforms/android/native-api-usage.json | 6 ++++++ .../android/nativescript_inappbrowser.aar | Bin 4538 -> 4522 bytes src/types/android.d.ts | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/platforms/android/native-api-usage.json b/src/platforms/android/native-api-usage.json index 8bd939a..16c8a6a 100644 --- a/src/platforms/android/native-api-usage.json +++ b/src/platforms/android/native-api-usage.json @@ -2,13 +2,17 @@ "uses": [ "com.proyecto26*:*", "android.app:Activity*", + "android.app:Service*", "android.content:Context*", + "android.content:ComponentName*", "android.content:Intent*", + "android.content:ServiceConnection*", "android.content.pm:ResolveInfo*", "android.content.pm:PackageManager*", "android.content.res:Resources*", "android.graphics:BitmapFactory*", "android.graphics:Color*", + "android.graphics:Bitmap*", "android.net:Uri*", "android.os:Build*", "android.os:Bundle*", @@ -25,9 +29,11 @@ "android.support.customtabs.action:CustomTabsService*", "android.support.v4.graphics:ColorUtils*", "java.lang:Object*", + "java.lang:Long*", "java.lang.reflect:Method*", "java.util:List*", "java.util:Arrays*", + "java.util:ArrayList*", "java.util.regex:Pattern*", "java.util.regex:Matcher*" ] diff --git a/src/platforms/android/nativescript_inappbrowser.aar b/src/platforms/android/nativescript_inappbrowser.aar index d848bd0f07b9405c8ac1ce9b9a0cdbf455523433..ae35297f39a8aae4cf3dc397ed39a78ba7a991ed 100644 GIT binary patch delta 560 zcmdm`yh?dOB3E9azg;%7gM*ma-o9x%`$N|IfY$WvXq^bx_LsuZ zX_K#btmYTc=q!uuM_^_L@$=s=O_CpFOR%XZ?Ltp_BE( zgf9lkof4YW4vU>X-#NfaT;k1eT>0WZ z-@;G#6bnOHi`t&pt=sbSb7=P)rA@4Bwl-}mUa!@**FETB_0N-!jr^ldx@81h*0?@P zPq{uh{$t;r#k(7n%Kx8ePk*>t*^0S$ad_rq-;X;lC)aZw+BuWw(R{@VqhXQunCleyXS!3KTflVUtRS&%=9anVQy21_ll0iP@6%OM`s<4;%38{T?2&Q$JBb(PZn~3tO1k%Mygc zr!0*VFa4=dc>3FWPw(qnnfW;G|4Fj9w^yGje^qha!OF}MuVr7_jx1}lllYv(-&K9DPqX*4{tRop zBie9y(QeJon;kcsf-jk`ubur&E5kOwRC9s<>a(9xx8C8gxTjqpRCDdT-x9YA6^v06 zxc}5PtzToxw{nGzRBMg2PVVcMi(JhZBb!$*Z73@`AAYKBv(UBdpQoB^yjrx|n9v&EJ!{kPw1 z-QGxvwF|$#^^X!VGt%<9@$+{2{LLpBpKu}t_2li`fs8jNbMjbla4|736r~pHPd4P2 znH7i={@V@->mvzgP!q8F ): string; static bindCustomTabsService( context: android.content.Context, @@ -81,7 +81,7 @@ declare namespace androidx { export class CustomTabsClient extends java.lang.Object { static getPackageName( context: android.content.Context, - list: java.util.List + packages: java.util.List ): string; static bindCustomTabsService( context: android.content.Context, From 3e15256be081189ce6d588ca071a053c0e281b79 Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 01:13:13 -0500 Subject: [PATCH 05/10] Code review --- src/CustomTabsServiceConnection.ts | 24 ++++++++++----------- src/InAppBrowser.android.ts | 10 ++++----- src/platforms/android/native-api-usage.json | 1 + src/utils.android.ts | 10 --------- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/CustomTabsServiceConnection.ts b/src/CustomTabsServiceConnection.ts index d92f0da..574d59d 100644 --- a/src/CustomTabsServiceConnection.ts +++ b/src/CustomTabsServiceConnection.ts @@ -1,17 +1,15 @@ import Context = android.content.Context; import ComponentName = android.content.ComponentName; import CustomTabsClient = androidx.browser.customtabs.CustomTabsClient; +import Log = android.util.Log; -import { Utils } from "@nativescript/core"; -import { - setCustomTabsClient, - CustomTabsServiceConnection, -} from "./utils.android"; -import { log } from "./utils.common"; +import { CustomTabsServiceConnection } from "./utils.android"; @NativeClass() class CustomTabsController extends CustomTabsServiceConnection { + private static readonly TAG = "CustomTabsController"; private readonly context: WeakRef; + public static customTabsClient: CustomTabsClient; constructor(context: Context) { super(); this.context = new WeakRef(context); @@ -19,19 +17,19 @@ class CustomTabsController extends CustomTabsServiceConnection { return global.__native(this); } - onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) { - setCustomTabsClient(client); + onCustomTabsServiceConnected(_: ComponentName, client: CustomTabsClient) { + CustomTabsController.customTabsClient = client; if (!client.warmup(long(0))) { - console.error(`Couldn't warmup custom tabs client for ${name.getClassName()}`); + Log.e(CustomTabsController.TAG, "Couldn't warmup custom tabs client"); } const context = this.context.get(); context.unbindService(this); } - onServiceDisconnected(name: ComponentName) { - setCustomTabsClient(null); - log(`Custom tabs service disconnected for ${name.getClassName()}`); + onServiceDisconnected(_: ComponentName) { + CustomTabsController.customTabsClient = null; + Log.d(CustomTabsController.TAG, "Custom tabs service disconnected"); } } -export { CustomTabsController } \ No newline at end of file +export { CustomTabsController }; diff --git a/src/InAppBrowser.android.ts b/src/InAppBrowser.android.ts index 53f9031..a7a915a 100644 --- a/src/InAppBrowser.android.ts +++ b/src/InAppBrowser.android.ts @@ -36,14 +36,12 @@ import { CustomTabsClient, CustomTabsIntent, CustomTabsService, - CustomTabsServiceConnection, DISMISSED_EVENT, getDefaultBrowser, getDrawableId, getPreferredPackages, openAuthSessionPolyfillAsync, toolbarIsLight, - getCustomTabsClient, } from "./utils.android"; import { tryParseColor } from "./utils.common"; @@ -433,16 +431,16 @@ function setup() { } public warmup(): boolean { - const customTabsClient = getCustomTabsClient(); - if (customTabsClient?.warmup) { + const customTabsClient = CustomTabsController.customTabsClient; + if (customTabsClient) { return customTabsClient.warmup(long(0)); } return false; } public mayLaunchUrl(mostLikelyUrl: string, otherUrls: Array): void { - const customTabsClient = getCustomTabsClient(); - if (customTabsClient?.newSession) { + const customTabsClient = CustomTabsController.customTabsClient; + if (customTabsClient) { const customTabsSession = customTabsClient.newSession( new CustomTabsCallback() ); diff --git a/src/platforms/android/native-api-usage.json b/src/platforms/android/native-api-usage.json index 16c8a6a..b3a16f8 100644 --- a/src/platforms/android/native-api-usage.json +++ b/src/platforms/android/native-api-usage.json @@ -13,6 +13,7 @@ "android.graphics:BitmapFactory*", "android.graphics:Color*", "android.graphics:Bitmap*", + "android.util:Log*", "android.net:Uri*", "android.os:Build*", "android.os:Bundle*", diff --git a/src/utils.android.ts b/src/utils.android.ts index b9d6574..55910dc 100644 --- a/src/utils.android.ts +++ b/src/utils.android.ts @@ -66,16 +66,6 @@ let _redirectHandler: (args: ApplicationEventData) => void; */ let initialUrl = ""; -let customTabsClient: androidx.browser.customtabs.CustomTabsClient; - -export function getCustomTabsClient () { - return customTabsClient; -} - -export function setCustomTabsClient (client: androidx.browser.customtabs.CustomTabsClient) { - customTabsClient = client; -} - export const getDrawableId = Utils.ad.resources.getDrawableId; /** From 27fe8f34d68bf04d74817155663fede52267dfef Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 01:55:36 -0500 Subject: [PATCH 06/10] Code Review --- demo/App_Resources/Android/native-api-usage.json | 5 +---- demo/App_Resources/Android/src/main/AndroidManifest.xml | 2 +- demo/app/activity.android.ts | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/demo/App_Resources/Android/native-api-usage.json b/demo/App_Resources/Android/native-api-usage.json index 1d19a3a..7668b99 100644 --- a/demo/App_Resources/Android/native-api-usage.json +++ b/demo/App_Resources/Android/native-api-usage.json @@ -1,6 +1,3 @@ { - "whitelist-plugins-usages": true, - "whitelist": [ - "org.nativescript*:*" - ] + "whitelist-plugins-usages": true } diff --git a/demo/App_Resources/Android/src/main/AndroidManifest.xml b/demo/App_Resources/Android/src/main/AndroidManifest.xml index ab63746..9e9b2a6 100644 --- a/demo/App_Resources/Android/src/main/AndroidManifest.xml +++ b/demo/App_Resources/Android/src/main/AndroidManifest.xml @@ -27,7 +27,7 @@ android:launchMode="singleTask"> Date: Mon, 1 Aug 2022 16:19:50 -0500 Subject: [PATCH 07/10] Fix Metadata filtering and include Android Optimizations from README --- CHANGELOG.md | 2 +- README.md | 33 +++++++++++ demo/app/activity.android.ts | 6 +- demo/app/home/home-view-model.ts | 10 ++++ src/CustomTabsServiceConnection.ts | 4 +- src/InAppBrowser.android.ts | 6 +- src/InAppBrowser.common.ts | 64 ++++++++++++++++++++- src/InAppBrowser.ios.ts | 4 +- src/platforms/android/native-api-usage.json | 10 ++++ 9 files changed, 127 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79915a8..394f14f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ in case of vulnerabilities. ### Fixed - Complete migration to ns8 and fix build issues by [@rigor789](https://github.com/rigor789) ([#92](https://github.com/proyecto26/nativescript-inappbrowser/pull/92)). -- Fix support `Metadata Filtering` for Android by [@jcassidyav](https://github.com/jcassidyav) ([#93](https://github.com/proyecto26/nativescript-inappbrowser/pull/93)). +- Fix support for `Metadata Filtering` from Android by [@jcassidyav](https://github.com/jcassidyav) ([#93](https://github.com/proyecto26/nativescript-inappbrowser/pull/93)). ### Removed - Remove `QUERY_ALL_PACKAGES` permission by [@edusperoni](https://github.com/edusperoni) ([#87](https://github.com/proyecto26/nativescript-inappbrowser/pull/87)). diff --git a/README.md b/README.md index 3b6796b..8263c91 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,9 @@ Methods | Action `openAuth` | Opens the url with Safari in a modal on iOS using **SFAuthenticationSession/ASWebAuthenticationSession**, and Chrome in a new custom tab on Android. On iOS, the user will be asked whether to allow the app to authenticate using the given url **(OAuth flow with deep linking redirection)**. `closeAuth` | Dismisses the current authentication session. `isAvailable` | Detect if the device supports this plugin. +`onStart` | Initialize a bound background service so the application can communicate its intention to the browser. After the service is connected, the client can be used to Warms up the browser to make navigation faster and indicates that a given URL may be loaded in the future. - Android Only. +`warmup` | Warm up the browser process - Android Only. +`mayLaunchUrl` | Tells the browser of a likely future navigation to a URL. The most likely URL has to be specified first. Optionally, a list of other likely URLs can be provided. They are treated as less likely than the first one, and have to be sorted in decreasing priority order. These additional URLs may be ignored. All previous calls to this method will be deprioritized - Android Only. ### iOS Options @@ -194,6 +197,36 @@ import { InAppBrowser } from 'nativescript-inappbrowser'; ... ``` +### Android Optimizations + +On Android, you can warmup the in app browser client to make it launch siginificantly faster. To do so, add the following to your [Custom Android Activity](https://docs.nativescript.org/advanced-concepts.html#extending-android-activity). + +```ts +import { InAppBrowser } from "nativescript-inappbrowser"; +@NativeClass() +@JavaProxy("org.nativescript.demo.MainActivity") +export class Activity extends androidx.appcompat.app.AppCompatActivity { + public onCreate(): void { + // InAppBrowser initialization for CustomTabsServiceConnection + InAppBrowser.onStart(); + } +} +``` + +You can further optimize performance and pre-render pages [by providing the urls that the user is likely to open](https://developer.chrome.com/docs/android/custom-tabs/best-practices/#pre-render-content). + +```ts +constructor() { + super(); + // Do not call this every time the component render + InAppBrowser.mayLaunchUrl(this._url, [ + "https://twitter.com/NativeScript", + "https://github.com/NativeScript/NativeScript", + "https://openjsf.org" + ]); +} +``` + ### Authentication Flow using Deep Linking In order to redirect back to your application from a web browser, you must specify a unique URI to your app. To do this, diff --git a/demo/app/activity.android.ts b/demo/app/activity.android.ts index cdb6881..5ab847c 100644 --- a/demo/app/activity.android.ts +++ b/demo/app/activity.android.ts @@ -3,7 +3,7 @@ import { setActivityCallbacks, AndroidActivityCallbacks, } from "@nativescript/core"; -// import { InAppBrowser } from "nativescript-inappbrowser"; +import { InAppBrowser } from "nativescript-inappbrowser"; @NativeClass() @JavaProxy("org.nativescript.demo.MainActivity") @@ -27,6 +27,8 @@ export class Activity extends androidx.appcompat.app.AppCompatActivity { this.getIntent(), super.onCreate ); + // InAppBrowser initialization for CustomTabsServiceConnection + InAppBrowser.onStart(); } public onNewIntent(intent: android.content.Intent): void { @@ -48,8 +50,6 @@ export class Activity extends androidx.appcompat.app.AppCompatActivity { public onStart(): void { this._callbacks.onStart(this, super.onStart); - // InAppBrowser initialization for CustomTabsServiceConnection - // InAppBrowser.onStart(); } public onStop(): void { diff --git a/demo/app/home/home-view-model.ts b/demo/app/home/home-view-model.ts index d8d524a..cf2a448 100644 --- a/demo/app/home/home-view-model.ts +++ b/demo/app/home/home-view-model.ts @@ -11,6 +11,16 @@ export class HelloWorldModel extends Observable { // Initialize default values. this._url = "https://nativescript.org"; + if (InAppBrowser.warmup()) { + console.log("Warmup successful"); + InAppBrowser.mayLaunchUrl(this._url, [ + "https://twitter.com/NativeScript", + "https://github.com/NativeScript/NativeScript", + "https://openjsf.org" + ]); + } else { + console.log("Warmup failed"); + } } get url(): string { diff --git a/src/CustomTabsServiceConnection.ts b/src/CustomTabsServiceConnection.ts index 574d59d..faeee3f 100644 --- a/src/CustomTabsServiceConnection.ts +++ b/src/CustomTabsServiceConnection.ts @@ -4,6 +4,7 @@ import CustomTabsClient = androidx.browser.customtabs.CustomTabsClient; import Log = android.util.Log; import { CustomTabsServiceConnection } from "./utils.android"; +import { log } from "./utils.common"; @NativeClass() class CustomTabsController extends CustomTabsServiceConnection { @@ -24,11 +25,12 @@ class CustomTabsController extends CustomTabsServiceConnection { } const context = this.context.get(); context.unbindService(this); + log("Custom tabs service connected"); } onServiceDisconnected(_: ComponentName) { CustomTabsController.customTabsClient = null; - Log.d(CustomTabsController.TAG, "Custom tabs service disconnected"); + log("Custom tabs service disconnected"); } } diff --git a/src/InAppBrowser.android.ts b/src/InAppBrowser.android.ts index a7a915a..97cd2ef 100644 --- a/src/InAppBrowser.android.ts +++ b/src/InAppBrowser.android.ts @@ -8,6 +8,7 @@ import BitmapFactory = android.graphics.BitmapFactory; import Browser = android.provider.Browser; import Pattern = java.util.regex.Pattern; import ArrayList = java.util.ArrayList; +import Log = android.util.Log; import { Application, EventData, Utils } from "@nativescript/core"; import { @@ -426,7 +427,7 @@ function setup() { connection ); } else { - console.error("No browser supported to bind custom tab service"); + Log.e(InAppBrowserModule.ERROR_CODE, "No browser supported to bind custom tab service"); } } @@ -446,10 +447,9 @@ function setup() { ); if (customTabsSession != null) { const otherUrlBundles = new ArrayList(otherUrls.length); - for (let index = 0; index < otherUrls.length; index++) { const link = otherUrls[index]; - if (link != null) { + if (link) { const bundle = new Bundle(); bundle.putParcelable(CustomTabsService.KEY_URL, Uri.parse(link)); otherUrlBundles.add(bundle); diff --git a/src/InAppBrowser.common.ts b/src/InAppBrowser.common.ts index 0523983..da6ad21 100644 --- a/src/InAppBrowser.common.ts +++ b/src/InAppBrowser.common.ts @@ -77,18 +77,80 @@ export type OpenBrowserAsync = ( ) => Promise; export interface InAppBrowserClassMethods { + /** + * Opens the url with Safari in a modal on iOS using [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller), + * or Chrome in a new [custom tab](https://developer.chrome.com/multidevice/android/customtabs) on Android. + * + * @param url The url to open in the web browser. + * @param options A dictionary of key-value pairs. + * + * @return The promise behaves differently based on the platform: + * - If the user closed the web browser, the Promise resolves with `{ type: 'cancel' }`. + * - If the browser is closed using `close`, the Promise resolves with `{ type: 'dismiss' }`. + */ open: OpenBrowserAsync; + /** + * Dismisses the presented web browser. + */ close: () => void; + /** + * # On iOS: + * Opens the url with Safari in a modal using `ASWebAuthenticationSession`. The user will be asked + * whether to allow the app to authenticate using the given url. + * + * # On Android: + * This will be done using a "custom Chrome tabs" browser and [activityResumedEvent](https://docs.nativescript.org/api-reference/classes/androidapplication#activityresumedevent), + * + * @param url The url to open in the web browser. This should be a login page. + * @param redirectUrl _Optional_ - The url to deep link back into your app. + * @param options _Optional_ - An object extending the InAppBrowser Options. + * + * @return + * - If the user does not permit the application to authenticate with the given url, the Promise fulfills with `{ type: 'cancel' }` object. + * - If the user closed the web browser, the Promise fulfills with `{ type: 'cancel' }` object. + * - If the browser is closed using `dismissBrowser`, the Promise fulfills with `{ type: 'dismiss' }` object. + */ openAuth: ( url: string, redirectUrl: string, options?: InAppBrowserOptions ) => Promise; + /** + * Dismisses the current authentication session + */ closeAuth: () => void; + /** + * Detect if the device supports this plugin. + */ isAvailable: () => Promise; - // Android only + /** + * Initialize a bound background service so the application can communicate its intention to the browser. + * After the service is connected, the client can be used to warms up the browser to make navigation faster and indicates that a given URL may be loaded in the future. + * + * @platform android + */ onStart(): void; + /** + * Warm up the browser process. + * Allows the browser application to pre-initialize itself in the background. + * Significantly speeds up URL opening in the browser. + * This is synchronous and can be called several times. + * + * @platform android + */ warmup: () => boolean; + /** + * Tells the browser of a likely future navigation to a URL. + * The most likely URL has to be specified first. + * Optionally, a list of other likely URLs can be provided. + * They are treated as less likely than the first one, and have to be sorted in decreasing priority order. + * These additional URLs may be ignored. + * + * @param mostLikelyUrl Most likely URL, may be null if otherUrls is provided. + * @param otherUrls Other likely destinations, sorted in decreasing likelihood order. + * + * @platform android + */ mayLaunchUrl: (mostLikelyUrl: string, otherUrls: Array) => void; } diff --git a/src/InAppBrowser.ios.ts b/src/InAppBrowser.ios.ts index 229a72b..f138869 100644 --- a/src/InAppBrowser.ios.ts +++ b/src/InAppBrowser.ios.ts @@ -303,9 +303,7 @@ function setup() { this.redirectResolve = null; this.redirectReject = null; } - onStart() { - log("onStart is not supported on iOS"); - } + onStart() {} warmup() { return false; } diff --git a/src/platforms/android/native-api-usage.json b/src/platforms/android/native-api-usage.json index b3a16f8..caf0225 100644 --- a/src/platforms/android/native-api-usage.json +++ b/src/platforms/android/native-api-usage.json @@ -4,6 +4,7 @@ "android.app:Activity*", "android.app:Service*", "android.content:Context*", + "android.content:ComponentCallbacks2*", "android.content:ComponentName*", "android.content:Intent*", "android.content:ServiceConnection*", @@ -17,16 +18,25 @@ "android.net:Uri*", "android.os:Build*", "android.os:Bundle*", + "android.os:Parcelable*", "android.provider:Browser*", "android.text:TextUtils*", "android.nfc:NfcAdapter*", + "androidx.browser.customtabs:CustomTabsCallback*", "androidx.browser.customtabs:CustomTabsClient*", "androidx.browser.customtabs:CustomTabsIntent*", "androidx.browser.customtabs.CustomTabsIntent:Builder*", + "androidx.browser.customtabs:CustomTabsService*", + "androidx.browser.customtabs:CustomTabsServiceConnection*", + "androidx.browser.customtabs:CustomTabsSession*", "androidx.core.graphics:ColorUtils*", + "android.support.customtabs:CustomTabsCallback*", "android.support.customtabs:CustomTabsClient*", "android.support.customtabs:CustomTabsIntent*", "android.support.customtabs.CustomTabsIntent:Builder*", + "android.support.customtabs:CustomTabsService*", + "android.support.customtabs:CustomTabsServiceConnection*", + "android.support.customtabs:CustomTabsSession*", "android.support.customtabs.action:CustomTabsService*", "android.support.v4.graphics:ColorUtils*", "java.lang:Object*", From 08a40c1ce14fd4b9b80c755bbaade6057dd1770d Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 16:27:59 -0500 Subject: [PATCH 08/10] Update README --- demo/app/activity.android.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/app/activity.android.ts b/demo/app/activity.android.ts index 5ab847c..cb681c9 100644 --- a/demo/app/activity.android.ts +++ b/demo/app/activity.android.ts @@ -27,7 +27,7 @@ export class Activity extends androidx.appcompat.app.AppCompatActivity { this.getIntent(), super.onCreate ); - // InAppBrowser initialization for CustomTabsServiceConnection + // InAppBrowser initialization (Connect to the Custom Tabs service) InAppBrowser.onStart(); } From 85f3207682451e80a296cb82c6a90492c6d64685 Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 16:30:17 -0500 Subject: [PATCH 09/10] Code review --- demo/app/activity.android.ts | 4 ++-- demo/app/home/home-view-model.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/app/activity.android.ts b/demo/app/activity.android.ts index cb681c9..09c8d1b 100644 --- a/demo/app/activity.android.ts +++ b/demo/app/activity.android.ts @@ -27,8 +27,6 @@ export class Activity extends androidx.appcompat.app.AppCompatActivity { this.getIntent(), super.onCreate ); - // InAppBrowser initialization (Connect to the Custom Tabs service) - InAppBrowser.onStart(); } public onNewIntent(intent: android.content.Intent): void { @@ -50,6 +48,8 @@ export class Activity extends androidx.appcompat.app.AppCompatActivity { public onStart(): void { this._callbacks.onStart(this, super.onStart); + // InAppBrowser initialization (Connect to the Custom Tabs service) + InAppBrowser.onStart(); } public onStop(): void { diff --git a/demo/app/home/home-view-model.ts b/demo/app/home/home-view-model.ts index cf2a448..7b5f8cc 100644 --- a/demo/app/home/home-view-model.ts +++ b/demo/app/home/home-view-model.ts @@ -12,14 +12,14 @@ export class HelloWorldModel extends Observable { // Initialize default values. this._url = "https://nativescript.org"; if (InAppBrowser.warmup()) { - console.log("Warmup successful"); + console.log("Warmup successful!"); InAppBrowser.mayLaunchUrl(this._url, [ "https://twitter.com/NativeScript", "https://github.com/NativeScript/NativeScript", "https://openjsf.org" ]); } else { - console.log("Warmup failed"); + console.log("Warmup failed :("); } } From 80096cbca575e0e77d9dd940aa855e5a2dd910f2 Mon Sep 17 00:00:00 2001 From: Juan David Nicholls Cardona Date: Mon, 1 Aug 2022 16:34:47 -0500 Subject: [PATCH 10/10] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 394f14f..fc8142b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ in case of vulnerabilities. ### Added - Add custom size option to iOS formSheet Modal by [@ShaneMckenna23](https://github.com/ShaneMckenna23) ([#91](https://github.com/proyecto26/nativescript-inappbrowser/pull/91)). - Add `includeReferrer` to allow adding android package name as referrer for website to track by [@vincent-paing](https://github.com/vincent-paing) ([#95](https://github.com/proyecto26/nativescript-inappbrowser/pull/95)). +- Add `warmup` and `mayLaunchUrl` functions for optimization in Android by [@vincent-paing](https://github.com/vincent-paing) ([#97](https://github.com/proyecto26/nativescript-inappbrowser/pull/97)). ### Fixed - Complete migration to ns8 and fix build issues by [@rigor789](https://github.com/rigor789) ([#92](https://github.com/proyecto26/nativescript-inappbrowser/pull/92)).