Skip to content

Commit

Permalink
Merge pull request #97 from proyecto26/96-add-maylaunchurl-and-warmup…
Browse files Browse the repository at this point in the history
…-methods-in-android

Add mayLaunchUrl and warmup methods in Android
  • Loading branch information
jdnichollsc committed Aug 1, 2022
2 parents 6fc92d6 + 80096cb commit 7a87cf6
Show file tree
Hide file tree
Showing 14 changed files with 465 additions and 53 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ 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)).
- 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)).
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion demo/App_Resources/Android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
android:launchMode="singleTask">

<activity
android:name="com.tns.NativeScriptActivity"
android:name="org.nativescript.demo.MainActivity"
android:label="@string/title_activity_kimera"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
android:theme="@style/LaunchScreenTheme"
Expand Down
98 changes: 98 additions & 0 deletions demo/app/activity.android.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
Application,
setActivityCallbacks,
AndroidActivityCallbacks,
} from "@nativescript/core";
import { InAppBrowser } from "nativescript-inappbrowser";

@NativeClass()
@JavaProxy("org.nativescript.demo.MainActivity")
export class Activity extends androidx.appcompat.app.AppCompatActivity {
public isNativeScriptActivity;

private _callbacks: AndroidActivityCallbacks;

public onCreate(savedInstanceState: android.os.Bundle): void {
Application.android.init(this.getApplication());
// Set the isNativeScriptActivity in onCreate (as done in the original NativeScript activity code)
// The JS constructor might not be called because the activity is created from Android.
this.isNativeScriptActivity = true;
if (!this._callbacks) {
setActivityCallbacks(this);
}

this._callbacks.onCreate(
this,
savedInstanceState,
this.getIntent(),
super.onCreate
);
}

public onNewIntent(intent: android.content.Intent): void {
this._callbacks.onNewIntent(
this,
intent,
super.setIntent,
super.onNewIntent
);
}

public onSaveInstanceState(outState: android.os.Bundle): void {
this._callbacks.onSaveInstanceState(
this,
outState,
super.onSaveInstanceState
);
}

public onStart(): void {
this._callbacks.onStart(this, super.onStart);
// InAppBrowser initialization (Connect to the Custom Tabs service)
InAppBrowser.onStart();
}

public onStop(): void {
this._callbacks.onStop(this, super.onStop);
}

public onDestroy(): void {
this._callbacks.onDestroy(this, super.onDestroy);
}

public onPostResume(): void {
this._callbacks.onPostResume(this, super.onPostResume);
}

public onBackPressed(): void {
this._callbacks.onBackPressed(this, super.onBackPressed);
}

public onRequestPermissionsResult(
requestCode: number,
permissions: Array<string>,
grantResults: Array<number>
): 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
);
}
}
10 changes: 10 additions & 0 deletions demo/app/home/home-view-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions demo/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
24 changes: 15 additions & 9 deletions src/ChromeTabsManagerActivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
Expand Down Expand Up @@ -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,
};
37 changes: 37 additions & 0 deletions src/CustomTabsServiceConnection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Context = android.content.Context;
import ComponentName = android.content.ComponentName;
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 {
private static readonly TAG = "CustomTabsController";
private readonly context: WeakRef<Context>;
public static customTabsClient: CustomTabsClient;
constructor(context: Context) {
super();
this.context = new WeakRef(context);

return global.__native(this);
}

onCustomTabsServiceConnected(_: ComponentName, client: CustomTabsClient) {
CustomTabsController.customTabsClient = client;
if (!client.warmup(long(0))) {
Log.e(CustomTabsController.TAG, "Couldn't warmup custom tabs client");
}
const context = this.context.get();
context.unbindService(this);
log("Custom tabs service connected");
}

onServiceDisconnected(_: ComponentName) {
CustomTabsController.customTabsClient = null;
log("Custom tabs service disconnected");
}
}

export { CustomTabsController };

0 comments on commit 7a87cf6

Please sign in to comment.