From cf30ac392ae854fbdfdf2e5d7ea7c9f6b01c600b Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 12 Sep 2023 12:54:17 +0200 Subject: [PATCH 1/2] MOBILE-4410 core: Fix return param in timeoutPromise --- src/core/services/utils/utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index 3a487888c..84b033fd3 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -260,7 +260,7 @@ export class CoreUtilsProvider { try { const response = await this.timeoutPromise(window.fetch(url, initOptions), CoreWS.getRequestTimeout()); - return !!response && response.redirected; + return response.redirected; } catch (error) { if (error.timeout && controller) { // Timeout, abort the request. @@ -1547,14 +1547,14 @@ export class CoreUtilsProvider { * @param time Number of milliseconds of the timeout. * @returns Promise with the timeout. */ - timeoutPromise(promise: Promise, time: number): Promise { + timeoutPromise(promise: Promise, time: number): Promise { return new Promise((resolve, reject): void => { let timedOut = false; - const resolveBeforeTimeout = () => { + const resolveBeforeTimeout = (value: T) => { if (timedOut) { return; } - resolve(); + resolve(value); }; const timeout = setTimeout( () => { From 47b17987ef1d60873cb7ae480fe553ea464e043b Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 8 Sep 2023 15:19:01 +0200 Subject: [PATCH 2/2] MOBILE-4410 login: Use install referrer URL in android --- cordova-plugin-moodleapp/plugin.xml | 5 + .../src/android/InstallReferrer.java | 148 ++++++++++++++++++ cordova-plugin-moodleapp/src/ts/index.ts | 2 + .../src/ts/plugins/InstallReferrer.ts | 39 +++++ cordova-plugin-moodleapp/types/index.d.ts | 2 + src/core/features/login/pages/site/site.html | 6 +- src/core/features/login/pages/site/site.ts | 48 +++++- src/core/features/native/services/native.ts | 8 +- src/core/services/referrer.ts | 61 ++++++++ src/core/services/sites.ts | 6 +- 10 files changed, 310 insertions(+), 15 deletions(-) create mode 100644 cordova-plugin-moodleapp/src/android/InstallReferrer.java create mode 100644 cordova-plugin-moodleapp/src/ts/plugins/InstallReferrer.ts create mode 100644 src/core/services/referrer.ts diff --git a/cordova-plugin-moodleapp/plugin.xml b/cordova-plugin-moodleapp/plugin.xml index ddc3cf863..f25baf041 100644 --- a/cordova-plugin-moodleapp/plugin.xml +++ b/cordova-plugin-moodleapp/plugin.xml @@ -6,12 +6,17 @@ + + + + + diff --git a/cordova-plugin-moodleapp/src/android/InstallReferrer.java b/cordova-plugin-moodleapp/src/android/InstallReferrer.java new file mode 100644 index 000000000..f1b0dbba0 --- /dev/null +++ b/cordova-plugin-moodleapp/src/android/InstallReferrer.java @@ -0,0 +1,148 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.moodle.moodlemobile; + +import android.util.Log; +import android.os.RemoteException; +import org.json.JSONArray; +import org.json.JSONObject; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.PluginResult; + +import com.android.installreferrer.api.InstallReferrerClient; +import com.android.installreferrer.api.InstallReferrerStateListener; +import com.android.installreferrer.api.ReferrerDetails; + +public class InstallReferrer extends CordovaPlugin implements InstallReferrerStateListener { + + private static final String TAG = "InstallReferrer"; + private static final int UNKNOWN_ERROR = 1; + private static final int FEATURE_NOT_SUPPORTED = 2; + private static final int SERVICE_UNAVAILABLE = 3; + + private InstallReferrerClient referrerClient; + private CallbackContext callbackContext; + private JSONObject referrerResult; + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) { + try { + switch (action) { + case "getReferrer": + this.getReferrer(callbackContext); + + return true; + } + } catch (Throwable e) { + Log.e(TAG, "Failed executing action: " + action, e); + callbackContext.error(e.getMessage()); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR)); + } + + return false; + } + + /** + * Connect to the referrer client and obtain the referrer data when connected. + * + * @param callbackContext The callback context used when calling back into JavaScript. + */ + private void getReferrer(CallbackContext callbackContext) { + if (this.referrerResult != null) { + callbackContext.success(this.referrerResult); + + return; + } + + this.callbackContext = callbackContext; + + try { + if (this.referrerClient == null) { + this.referrerClient = InstallReferrerClient.newBuilder(this.cordova.getActivity().getApplicationContext()).build(); + } + + this.referrerClient.startConnection(this); + } catch (Exception exception) { + Log.e(TAG, "startConnection error: " + exception.getMessage()); + callbackContext.error(exception.getMessage()); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR)); + } + } + + /** + * Get referral data from an already established connection and pass it to current callback context. + */ + private void getReferralData() { + try { + ReferrerDetails response = referrerClient.getInstallReferrer(); + JSONObject referrerResult = new JSONObject(); + + referrerResult.put("referrer", response.getInstallReferrer()); + referrerResult.put("clickTime", response.getReferrerClickTimestampSeconds()); + referrerResult.put("appInstallTime", response.getInstallBeginTimestampSeconds()); + referrerResult.put("instantExperienceLaunched", response.getGooglePlayInstantParam()); + this.referrerResult = referrerResult; + + if (this.callbackContext != null) { + this.callbackContext.success(this.referrerResult); + } + } catch (Exception exception) { + Log.e(TAG, "getReferralData error: " + exception.getMessage()); + if (this.callbackContext != null) { + this.callbackContext.error(exception.getMessage()); + this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR)); + } + + this.referrerClient.endConnection(); + } + + try { + this.referrerClient.endConnection(); + } catch (Exception exception) { + // Ignore errors. + } + } + + @Override + public void onInstallReferrerSetupFinished(int responseCode) { + switch (responseCode) { + case InstallReferrerClient.InstallReferrerResponse.OK: + // Connection established. + this.getReferralData(); + break; + case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED: + // API not available on the current Play Store app. + if (this.callbackContext != null) { + this.callbackContext.error("Referrer feature not supported."); + this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FEATURE_NOT_SUPPORTED)); + } + break; + case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE: + // Connection couldn't be established. + if (this.callbackContext != null) { + this.callbackContext.error("Referrer service unavailable."); + this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SERVICE_UNAVAILABLE)); + } + break; + } + } + + @Override + public void onInstallReferrerServiceDisconnected() { + // Nothing to do. + } + +} diff --git a/cordova-plugin-moodleapp/src/ts/index.ts b/cordova-plugin-moodleapp/src/ts/index.ts index a11c3eba9..79542caa0 100644 --- a/cordova-plugin-moodleapp/src/ts/index.ts +++ b/cordova-plugin-moodleapp/src/ts/index.ts @@ -12,10 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { InstallReferrer } from './plugins/InstallReferrer'; import { SecureStorage } from './plugins/SecureStorage'; const api: MoodleAppPlugins = { secureStorage: new SecureStorage(), + installReferrer: new InstallReferrer(), }; // This is necessary to work around the default transpilation behavior, diff --git a/cordova-plugin-moodleapp/src/ts/plugins/InstallReferrer.ts b/cordova-plugin-moodleapp/src/ts/plugins/InstallReferrer.ts new file mode 100644 index 000000000..83c9ecc5e --- /dev/null +++ b/cordova-plugin-moodleapp/src/ts/plugins/InstallReferrer.ts @@ -0,0 +1,39 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Allows retrieving install referrer data. + * https://developer.android.com/google/play/installreferrer + */ +export class InstallReferrer { + + /** + * Get referrer data. + * + * @returns Referrer data. + */ + async getReferrer(): Promise { + return new Promise((resolve, reject) => { + cordova.exec(resolve, reject, 'InstallReferrer', 'getReferrer', []); + }); + } + +} + +export type InstallReferrerResult = { + referrer: string; + clickTime: number; + appInstallTime: number; + instantExperienceLaunched: boolean; +}; diff --git a/cordova-plugin-moodleapp/types/index.d.ts b/cordova-plugin-moodleapp/types/index.d.ts index 59ed28d30..9e7c3c6f2 100644 --- a/cordova-plugin-moodleapp/types/index.d.ts +++ b/cordova-plugin-moodleapp/types/index.d.ts @@ -12,12 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { InstallReferrer } from '../src/ts/plugins/InstallReferrer'; import { SecureStorage as SecureStorageImpl } from '../src/ts/plugins/SecureStorage'; declare global { interface MoodleAppPlugins { secureStorage: SecureStorageImpl; + installReferrer: InstallReferrer; } interface Cordova { diff --git a/src/core/features/login/pages/site/site.html b/src/core/features/login/pages/site/site.html index 2f2e443d4..ae1a62c8b 100644 --- a/src/core/features/login/pages/site/site.html +++ b/src/core/features/login/pages/site/site.html @@ -20,7 +20,7 @@ -
+ @@ -48,7 +48,7 @@

{{ 'core.login.selectsite' | translate }}

-