Skip to content

Commit 7a87cf6

Browse files
authored
Merge pull request #97 from proyecto26/96-add-maylaunchurl-and-warmup-methods-in-android
Add mayLaunchUrl and warmup methods in Android
2 parents 6fc92d6 + 80096cb commit 7a87cf6

14 files changed

+465
-53
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ in case of vulnerabilities.
2525
### Added
2626
- Add custom size option to iOS formSheet Modal by [@ShaneMckenna23](https://github.com/ShaneMckenna23) ([#91](https://github.com/proyecto26/nativescript-inappbrowser/pull/91)).
2727
- 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)).
28+
- 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)).
2829

2930
### Fixed
3031
- Complete migration to ns8 and fix build issues by [@rigor789](https://github.com/rigor789) ([#92](https://github.com/proyecto26/nativescript-inappbrowser/pull/92)).
31-
- Fix support `Metadata Filtering` for Android by [@jcassidyav](https://github.com/jcassidyav) ([#93](https://github.com/proyecto26/nativescript-inappbrowser/pull/93)).
32+
- Fix support for `Metadata Filtering` from Android by [@jcassidyav](https://github.com/jcassidyav) ([#93](https://github.com/proyecto26/nativescript-inappbrowser/pull/93)).
3233

3334
### Removed
3435
- Remove `QUERY_ALL_PACKAGES` permission by [@edusperoni](https://github.com/edusperoni) ([#87](https://github.com/proyecto26/nativescript-inappbrowser/pull/87)).

README.md

+33
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ Methods | Action
9292
`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)**.
9393
`closeAuth` | Dismisses the current authentication session.
9494
`isAvailable` | Detect if the device supports this plugin.
95+
`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.
96+
`warmup` | Warm up the browser process - Android Only.
97+
`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.
9598

9699
### iOS Options
97100

@@ -194,6 +197,36 @@ import { InAppBrowser } from 'nativescript-inappbrowser';
194197
...
195198
```
196199

200+
### Android Optimizations
201+
202+
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).
203+
204+
```ts
205+
import { InAppBrowser } from "nativescript-inappbrowser";
206+
@NativeClass()
207+
@JavaProxy("org.nativescript.demo.MainActivity")
208+
export class Activity extends androidx.appcompat.app.AppCompatActivity {
209+
public onCreate(): void {
210+
// InAppBrowser initialization for CustomTabsServiceConnection
211+
InAppBrowser.onStart();
212+
}
213+
}
214+
```
215+
216+
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).
217+
218+
```ts
219+
constructor() {
220+
super();
221+
// Do not call this every time the component render
222+
InAppBrowser.mayLaunchUrl(this._url, [
223+
"https://twitter.com/NativeScript",
224+
"https://github.com/NativeScript/NativeScript",
225+
"https://openjsf.org"
226+
]);
227+
}
228+
```
229+
197230
### Authentication Flow using Deep Linking
198231

199232
In order to redirect back to your application from a web browser, you must specify a unique URI to your app. To do this,

demo/App_Resources/Android/src/main/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
android:launchMode="singleTask">
2828

2929
<activity
30-
android:name="com.tns.NativeScriptActivity"
30+
android:name="org.nativescript.demo.MainActivity"
3131
android:label="@string/title_activity_kimera"
3232
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
3333
android:theme="@style/LaunchScreenTheme"

demo/app/activity.android.ts

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {
2+
Application,
3+
setActivityCallbacks,
4+
AndroidActivityCallbacks,
5+
} from "@nativescript/core";
6+
import { InAppBrowser } from "nativescript-inappbrowser";
7+
8+
@NativeClass()
9+
@JavaProxy("org.nativescript.demo.MainActivity")
10+
export class Activity extends androidx.appcompat.app.AppCompatActivity {
11+
public isNativeScriptActivity;
12+
13+
private _callbacks: AndroidActivityCallbacks;
14+
15+
public onCreate(savedInstanceState: android.os.Bundle): void {
16+
Application.android.init(this.getApplication());
17+
// Set the isNativeScriptActivity in onCreate (as done in the original NativeScript activity code)
18+
// The JS constructor might not be called because the activity is created from Android.
19+
this.isNativeScriptActivity = true;
20+
if (!this._callbacks) {
21+
setActivityCallbacks(this);
22+
}
23+
24+
this._callbacks.onCreate(
25+
this,
26+
savedInstanceState,
27+
this.getIntent(),
28+
super.onCreate
29+
);
30+
}
31+
32+
public onNewIntent(intent: android.content.Intent): void {
33+
this._callbacks.onNewIntent(
34+
this,
35+
intent,
36+
super.setIntent,
37+
super.onNewIntent
38+
);
39+
}
40+
41+
public onSaveInstanceState(outState: android.os.Bundle): void {
42+
this._callbacks.onSaveInstanceState(
43+
this,
44+
outState,
45+
super.onSaveInstanceState
46+
);
47+
}
48+
49+
public onStart(): void {
50+
this._callbacks.onStart(this, super.onStart);
51+
// InAppBrowser initialization (Connect to the Custom Tabs service)
52+
InAppBrowser.onStart();
53+
}
54+
55+
public onStop(): void {
56+
this._callbacks.onStop(this, super.onStop);
57+
}
58+
59+
public onDestroy(): void {
60+
this._callbacks.onDestroy(this, super.onDestroy);
61+
}
62+
63+
public onPostResume(): void {
64+
this._callbacks.onPostResume(this, super.onPostResume);
65+
}
66+
67+
public onBackPressed(): void {
68+
this._callbacks.onBackPressed(this, super.onBackPressed);
69+
}
70+
71+
public onRequestPermissionsResult(
72+
requestCode: number,
73+
permissions: Array<string>,
74+
grantResults: Array<number>
75+
): void {
76+
this._callbacks.onRequestPermissionsResult(
77+
this,
78+
requestCode,
79+
permissions,
80+
grantResults,
81+
undefined /*TODO: Enable if needed*/
82+
);
83+
}
84+
85+
public onActivityResult(
86+
requestCode: number,
87+
resultCode: number,
88+
data: android.content.Intent
89+
): void {
90+
this._callbacks.onActivityResult(
91+
this,
92+
requestCode,
93+
resultCode,
94+
data,
95+
super.onActivityResult
96+
);
97+
}
98+
}

demo/app/home/home-view-model.ts

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ export class HelloWorldModel extends Observable {
1111

1212
// Initialize default values.
1313
this._url = "https://nativescript.org";
14+
if (InAppBrowser.warmup()) {
15+
console.log("Warmup successful!");
16+
InAppBrowser.mayLaunchUrl(this._url, [
17+
"https://twitter.com/NativeScript",
18+
"https://github.com/NativeScript/NativeScript",
19+
"https://openjsf.org"
20+
]);
21+
} else {
22+
console.log("Warmup failed :(");
23+
}
1424
}
1525

1626
get url(): string {

demo/webpack.config.js

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ module.exports = (env) => {
55
webpack.init(env);
66
webpack.useConfig("typescript");
77

8+
env.appComponents = (env.appComponents || []).concat([
9+
"./app/activity.android",
10+
]);
11+
812
webpack.chainWebpack((config) => {
913
// shared demo code
1014
config.resolve.alias.set(

src/ChromeTabsManagerActivity.ts

+15-9
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { BROWSER_TYPES } from "./InAppBrowser.common";
77
import { DISMISSED_EVENT } from "./utils.android";
88
import { log } from "./utils.common";
99

10-
export class ChromeTabsEvent extends Observable {
10+
class ChromeTabsEvent extends Observable {
1111
public message: string;
1212
public resultType: string;
1313
public isError: boolean;
1414
}
1515

16-
export const BROWSER_ACTIVITY_EVENTS = new ChromeTabsEvent();
16+
const BROWSER_ACTIVITY_EVENTS = new ChromeTabsEvent();
1717

1818
const KEY_BROWSER_INTENT = "browserIntent";
1919
const BROWSER_RESULT_TYPE = "browserResultType";
@@ -39,7 +39,7 @@ const notifyMessage = (
3939
*/
4040
@NativeClass()
4141
@JavaProxy("com.proyecto26.inappbrowser.ChromeTabsManagerActivity")
42-
export class ChromeTabsManagerActivity extends android.app.Activity {
42+
class ChromeTabsManagerActivity extends android.app.Activity {
4343
private mOpened = false;
4444
private resultType = null;
4545
private isError = false;
@@ -131,21 +131,27 @@ export class ChromeTabsManagerActivity extends android.app.Activity {
131131
}
132132
}
133133

134-
export const createStartIntent = (
135-
context: Context,
136-
authIntent: Intent
137-
): Intent => {
134+
const createStartIntent = (context: Context, authIntent: Intent): Intent => {
138135
let intent = createBaseIntent(context);
139136
intent.putExtra(KEY_BROWSER_INTENT, authIntent);
140137
return intent;
141138
};
142139

143-
export const createDismissIntent = (context: Context): Intent => {
140+
const createDismissIntent = (context: Context): Intent => {
144141
let intent = createBaseIntent(context);
145142
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
146143
return intent;
147144
};
148145

149-
export const createBaseIntent = (context: Context): Intent => {
146+
const createBaseIntent = (context: Context): Intent => {
150147
return new Intent(context, ChromeTabsManagerActivity.class);
151148
};
149+
150+
export {
151+
BROWSER_ACTIVITY_EVENTS,
152+
ChromeTabsEvent,
153+
createStartIntent,
154+
createDismissIntent,
155+
createBaseIntent,
156+
ChromeTabsManagerActivity,
157+
};

src/CustomTabsServiceConnection.ts

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Context = android.content.Context;
2+
import ComponentName = android.content.ComponentName;
3+
import CustomTabsClient = androidx.browser.customtabs.CustomTabsClient;
4+
import Log = android.util.Log;
5+
6+
import { CustomTabsServiceConnection } from "./utils.android";
7+
import { log } from "./utils.common";
8+
9+
@NativeClass()
10+
class CustomTabsController extends CustomTabsServiceConnection {
11+
private static readonly TAG = "CustomTabsController";
12+
private readonly context: WeakRef<Context>;
13+
public static customTabsClient: CustomTabsClient;
14+
constructor(context: Context) {
15+
super();
16+
this.context = new WeakRef(context);
17+
18+
return global.__native(this);
19+
}
20+
21+
onCustomTabsServiceConnected(_: ComponentName, client: CustomTabsClient) {
22+
CustomTabsController.customTabsClient = client;
23+
if (!client.warmup(long(0))) {
24+
Log.e(CustomTabsController.TAG, "Couldn't warmup custom tabs client");
25+
}
26+
const context = this.context.get();
27+
context.unbindService(this);
28+
log("Custom tabs service connected");
29+
}
30+
31+
onServiceDisconnected(_: ComponentName) {
32+
CustomTabsController.customTabsClient = null;
33+
log("Custom tabs service disconnected");
34+
}
35+
}
36+
37+
export { CustomTabsController };

0 commit comments

Comments
 (0)