Added support for Android TWA (Trusted Web Activity)
This commit is contained in:
parent
c61019058c
commit
5510fd342f
@ -6,6 +6,7 @@
|
||||
- Added `singleInstance` option for Android `ChromeSafariBrowser` implementation
|
||||
- Added `onDownloadStartRequest` event and deprecated old `onDownloadStart` event
|
||||
- Added `shareState` Android option for `ChromeSafariBrowser` class
|
||||
- Added support for Android TWA (Trusted Web Activity)
|
||||
- Fixed missing `onZoomScaleChanged` call for `InAppBrowser` class
|
||||
- Fixed `requestImageRef` method always `null` on iOS
|
||||
- Fixed "applicationNameForUserAgent is not work in ios" [#525](https://github.com/pichillilorenzo/flutter_inappwebview/issues/525)
|
||||
|
@ -46,8 +46,8 @@ android {
|
||||
}
|
||||
dependencies {
|
||||
implementation 'androidx.webkit:webkit:1.4.0'
|
||||
implementation 'androidx.browser:browser:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.browser:browser:1.4.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
}
|
||||
|
@ -11,11 +11,20 @@
|
||||
android:theme="@style/ThemeTransparent"
|
||||
android:exported="true"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeCustomTabsActivity" />
|
||||
<activity
|
||||
android:theme="@style/ThemeTransparent"
|
||||
android:exported="true"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.TrustedWebActivity" />
|
||||
<activity
|
||||
android:theme="@style/ThemeTransparent"
|
||||
android:exported="true"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeCustomTabsActivitySingleInstance"
|
||||
android:launchMode="singleInstance"/>
|
||||
<activity
|
||||
android:theme="@style/ThemeTransparent"
|
||||
android:exported="true"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.TrustedWebActivitySingleInstance"
|
||||
android:launchMode="singleInstance"/>
|
||||
<receiver android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ActionBroadcastReceiver" />
|
||||
<meta-data
|
||||
android:name="io.flutter.embedded_views_preview"
|
||||
|
@ -67,17 +67,7 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
||||
customTabActivityHelper.setConnectionCallback(new CustomTabActivityHelper.ConnectionCallback() {
|
||||
@Override
|
||||
public void onCustomTabsConnected() {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
Uri uri = Uri.parse(url);
|
||||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
|
||||
builder = new CustomTabsIntent.Builder(customTabsSession);
|
||||
prepareCustomTabs(menuItemList);
|
||||
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
prepareCustomTabsIntent(customTabsIntent);
|
||||
|
||||
CustomTabActivityHelper.openCustomTab(chromeCustomTabsActivity, customTabsIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
customTabsConnected(url, menuItemList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,6 +139,20 @@ public class ChromeCustomTabsActivity extends Activity implements MethodChannel.
|
||||
}
|
||||
}
|
||||
|
||||
public void customTabsConnected (String url, List<HashMap<String, Object>> menuItemList) {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
Uri uri = Uri.parse(url);
|
||||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
|
||||
builder = new CustomTabsIntent.Builder(customTabsSession);
|
||||
prepareCustomTabs(menuItemList);
|
||||
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
prepareCustomTabsIntent(customTabsIntent);
|
||||
|
||||
CustomTabActivityHelper.openCustomTab(this, customTabsIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
}
|
||||
|
||||
private void prepareCustomTabs(List<HashMap<String, Object>> menuItemList) {
|
||||
if (options.addDefaultShareMenuItem != null) {
|
||||
builder.setShareState(options.addDefaultShareMenuItem ?
|
||||
|
@ -4,10 +4,14 @@ import android.content.Intent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.trusted.ScreenOrientation;
|
||||
import androidx.browser.trusted.TrustedWebActivityDisplayMode;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Options;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChromeCustomTabsOptions implements Options<ChromeCustomTabsActivity> {
|
||||
@ -24,8 +28,12 @@ public class ChromeCustomTabsOptions implements Options<ChromeCustomTabsActivity
|
||||
public Boolean instantAppsEnabled = false;
|
||||
public String packageName;
|
||||
public Boolean keepAliveEnabled = false;
|
||||
public Boolean singleInstance = false;
|
||||
public Boolean isSingleInstance = false;
|
||||
public Boolean noHistory = false;
|
||||
public Boolean isTrustedWebActivity = false;
|
||||
public List<String> additionalTrustedOrigins = new ArrayList<>();
|
||||
public TrustedWebActivityDisplayMode displayMode = null;
|
||||
public Integer screenOrientation = ScreenOrientation.DEFAULT;
|
||||
|
||||
@Override
|
||||
public ChromeCustomTabsOptions parse(Map<String, Object> options) {
|
||||
@ -61,12 +69,35 @@ public class ChromeCustomTabsOptions implements Options<ChromeCustomTabsActivity
|
||||
case "keepAliveEnabled":
|
||||
keepAliveEnabled = (Boolean) value;
|
||||
break;
|
||||
case "singleInstance":
|
||||
singleInstance = (Boolean) value;
|
||||
case "isSingleInstance":
|
||||
isSingleInstance = (Boolean) value;
|
||||
break;
|
||||
case "noHistory":
|
||||
noHistory = (Boolean) value;
|
||||
break;
|
||||
case "isTrustedWebActivity":
|
||||
isTrustedWebActivity = (Boolean) value;
|
||||
break;
|
||||
case "additionalTrustedOrigins":
|
||||
additionalTrustedOrigins = (List<String>) value;
|
||||
break;
|
||||
case "displayMode":
|
||||
Map<String, Object> displayModeMap = (Map<String, Object>) value;
|
||||
String displayModeType = (String) displayModeMap.get("type");
|
||||
if (displayModeType != null) {
|
||||
switch (displayModeType) {
|
||||
case "IMMERSIVE_MODE":
|
||||
boolean isSticky = (boolean) displayModeMap.get("isSticky");
|
||||
int layoutInDisplayCutoutMode = (int) displayModeMap.get("layoutInDisplayCutoutMode");
|
||||
displayMode = new TrustedWebActivityDisplayMode.ImmersiveMode(isSticky, layoutInDisplayCutoutMode);
|
||||
case "DEFAULT_MODE":
|
||||
displayMode = new TrustedWebActivityDisplayMode.DefaultMode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "screenOrientation":
|
||||
screenOrientation = (Integer) value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,8 +114,11 @@ public class ChromeCustomTabsOptions implements Options<ChromeCustomTabsActivity
|
||||
options.put("instantAppsEnabled", instantAppsEnabled);
|
||||
options.put("packageName", packageName);
|
||||
options.put("keepAliveEnabled", keepAliveEnabled);
|
||||
options.put("singleInstance", singleInstance);
|
||||
options.put("isSingleInstance", isSingleInstance);
|
||||
options.put("noHistory", noHistory);
|
||||
options.put("isTrustedWebActivity", isTrustedWebActivity);
|
||||
options.put("additionalTrustedOrigins", additionalTrustedOrigins);
|
||||
options.put("screenOrientation", screenOrientation);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -68,11 +68,15 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
||||
extras.putSerializable("options", options);
|
||||
extras.putSerializable("menuItemList", (Serializable) menuItemList);
|
||||
|
||||
Boolean isSingleInstance = (Boolean) options.get("singleInstance");
|
||||
Boolean isSingleInstance = (Boolean) Util.getOrDefault(options, "isSingleInstance", false);
|
||||
Boolean isTrustedWebActivity = (Boolean) Util.getOrDefault(options, "isTrustedWebActivity", false);
|
||||
if (CustomTabActivityHelper.isAvailable(activity)) {
|
||||
intent = new Intent(activity, !isSingleInstance ? ChromeCustomTabsActivity.class : ChromeCustomTabsActivitySingleInstance.class);
|
||||
intent = new Intent(activity, !isSingleInstance ?
|
||||
(!isTrustedWebActivity ? ChromeCustomTabsActivity.class : TrustedWebActivity.class) :
|
||||
(!isTrustedWebActivity ? ChromeCustomTabsActivitySingleInstance.class : TrustedWebActivitySingleInstance.class));
|
||||
intent.putExtras(extras);
|
||||
if ((Boolean) options.get("noHistory")) {
|
||||
Boolean noHistory = (Boolean) Util.getOrDefault(options, "noHistory", false);
|
||||
if (noHistory) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
}
|
||||
activity.startActivity(intent);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
@ -9,6 +10,7 @@ import androidx.browser.customtabs.CustomTabsClient;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
||||
import androidx.browser.customtabs.CustomTabsSession;
|
||||
import androidx.browser.trusted.TrustedWebActivityIntent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -37,6 +39,14 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
activity.startActivityForResult(customTabsIntent.intent, requestCode);
|
||||
}
|
||||
|
||||
public static void openCustomTab(Activity activity,
|
||||
TrustedWebActivityIntent trustedWebActivityIntent,
|
||||
Uri uri,
|
||||
int requestCode) {
|
||||
trustedWebActivityIntent.getIntent().setData(uri);
|
||||
activity.startActivityForResult(trustedWebActivityIntent.getIntent(), requestCode);
|
||||
}
|
||||
|
||||
public static boolean isAvailable(Activity activity) {
|
||||
return CustomTabsHelper.getPackageNameToUse(activity) != null;
|
||||
}
|
||||
@ -135,5 +145,4 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||
*/
|
||||
void onCustomTabsDisconnected();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
||||
import androidx.browser.trusted.TrustedWebActivityIntent;
|
||||
import androidx.browser.trusted.TrustedWebActivityIntentBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class TrustedWebActivity extends ChromeCustomTabsActivity {
|
||||
|
||||
protected static final String LOG_TAG = "TrustedWebActivity";
|
||||
|
||||
public TrustedWebActivityIntentBuilder builder;
|
||||
|
||||
@Override
|
||||
public void customTabsConnected (String url, List<HashMap<String, Object>> menuItemList) {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
Uri uri = Uri.parse(url);
|
||||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
|
||||
builder = new TrustedWebActivityIntentBuilder(uri);
|
||||
prepareCustomTabs();
|
||||
|
||||
TrustedWebActivityIntent trustedWebActivityIntent = builder.build(customTabsSession);
|
||||
prepareCustomTabsIntent(trustedWebActivityIntent);
|
||||
|
||||
CustomTabActivityHelper.openCustomTab(this, trustedWebActivityIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
}
|
||||
|
||||
private void prepareCustomTabs() {
|
||||
if (options.toolbarBackgroundColor != null && !options.toolbarBackgroundColor.isEmpty()) {
|
||||
CustomTabColorSchemeParams.Builder defaultColorSchemeBuilder = new CustomTabColorSchemeParams.Builder();
|
||||
builder.setDefaultColorSchemeParams(defaultColorSchemeBuilder
|
||||
.setToolbarColor(Color.parseColor(options.toolbarBackgroundColor))
|
||||
.build());
|
||||
}
|
||||
|
||||
if (options.additionalTrustedOrigins != null && !options.additionalTrustedOrigins.isEmpty()) {
|
||||
builder.setAdditionalTrustedOrigins(options.additionalTrustedOrigins);
|
||||
}
|
||||
|
||||
if (options.displayMode != null) {
|
||||
builder.setDisplayMode(options.displayMode);
|
||||
}
|
||||
|
||||
builder.setScreenOrientation(options.screenOrientation);
|
||||
}
|
||||
|
||||
private void prepareCustomTabsIntent(TrustedWebActivityIntent trustedWebActivityIntent) {
|
||||
Intent intent = trustedWebActivityIntent.getIntent();
|
||||
if (options.packageName != null)
|
||||
intent.setPackage(options.packageName);
|
||||
else
|
||||
intent.setPackage(CustomTabsHelper.getPackageNameToUse(this));
|
||||
|
||||
if (options.keepAliveEnabled)
|
||||
CustomTabsHelper.addKeepAliveExtra(this, intent);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
||||
|
||||
public class TrustedWebActivitySingleInstance extends TrustedWebActivity {
|
||||
|
||||
protected static final String LOG_TAG = "TrustedWebActivitySingleInstance";
|
||||
|
||||
}
|
@ -30,6 +30,10 @@
|
||||
android:label="flutter_inappwebview_example"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<meta-data
|
||||
android:name="asset_statements"
|
||||
android:resource="@string/asset_statements" />
|
||||
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
|
11
example/android/app/src/main/res/values/strings.xml
Executable file
11
example/android/app/src/main/res/values/strings.xml
Executable file
@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
<string name="app_name">Flutter Trusted Web Activity</string>
|
||||
<string name="asset_statements">
|
||||
[{
|
||||
\"relation\": [\"delegate_permission/common.handle_all_urls\"],
|
||||
\"target\": {
|
||||
\"namespace\": \"web\",
|
||||
\"site\": \"https://flutter.dev\"}
|
||||
}]
|
||||
</string>
|
||||
</resources>
|
@ -67,7 +67,8 @@ class _ChromeSafariBrowserExampleScreenState
|
||||
options: ChromeSafariBrowserClassOptions(
|
||||
android: AndroidChromeCustomTabsOptions(
|
||||
shareState: CustomTabsShareState.SHARE_STATE_OFF,
|
||||
singleInstance: false,
|
||||
isSingleInstance: false,
|
||||
isTrustedWebActivity: false,
|
||||
keepAliveEnabled: true),
|
||||
ios: IOSSafariOptions(
|
||||
dismissButtonStyle:
|
||||
|
@ -11,23 +11,31 @@ import '../../in_app_webview/android/in_app_webview_options.dart';
|
||||
///This class represents all the Android-only [ChromeSafariBrowser] options available.
|
||||
class AndroidChromeCustomTabsOptions
|
||||
implements ChromeSafariBrowserOptions, AndroidOptions {
|
||||
///Set to `false` if you don't want the default share item to the menu. The default value is `true`.
|
||||
///Use `shareState` instead.
|
||||
@Deprecated('Use `shareState` instead')
|
||||
bool? addDefaultShareMenuItem;
|
||||
|
||||
///The share state that should be applied to the custom tab. The default value is [CustomTabsShareState.SHARE_STATE_DEFAULT].
|
||||
///
|
||||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
CustomTabsShareState shareState;
|
||||
|
||||
///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
|
||||
///
|
||||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
bool showTitle;
|
||||
|
||||
///Set the custom background color of the toolbar.
|
||||
Color? toolbarBackgroundColor;
|
||||
|
||||
///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`.
|
||||
///
|
||||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
bool enableUrlBarHiding;
|
||||
|
||||
///Set to `true` to enable Instant Apps. The default value is `false`.
|
||||
///
|
||||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
bool instantAppsEnabled;
|
||||
|
||||
///Set an explicit application package name that limits
|
||||
@ -41,11 +49,29 @@ class AndroidChromeCustomTabsOptions
|
||||
bool keepAliveEnabled;
|
||||
|
||||
///Set to `true` to launch the Android activity in `singleInstance` mode. The default value is `false`.
|
||||
bool singleInstance;
|
||||
bool isSingleInstance;
|
||||
|
||||
///Set to `true` to launch the Android intent with the flag `FLAG_ACTIVITY_NO_HISTORY`. The default value is `false`.
|
||||
bool noHistory;
|
||||
|
||||
///Set to `true` to launch the Custom Tab as a Trusted Web Activity. The default value is `false`.
|
||||
bool isTrustedWebActivity;
|
||||
|
||||
///Sets a list of additional trusted origins that the user may navigate or be redirected to from the starting uri.
|
||||
///
|
||||
///**NOTE**: Available only in a Trusted Web Activity.
|
||||
List<String> additionalTrustedOrigins;
|
||||
|
||||
///Sets a display mode of a Trusted Web Activity.
|
||||
///
|
||||
///**NOTE**: Available only in a Trusted Web Activity.
|
||||
TrustedWebActivityDisplayMode? displayMode;
|
||||
|
||||
///Sets a screen orientation. This can be used e.g. to enable the locking of an orientation lock type.
|
||||
///
|
||||
///**NOTE**: Available only in a Trusted Web Activity.
|
||||
TrustedWebActivityScreenOrientation screenOrientation;
|
||||
|
||||
AndroidChromeCustomTabsOptions(
|
||||
{@Deprecated('Use `shareState` instead') this.addDefaultShareMenuItem,
|
||||
this.shareState = CustomTabsShareState.SHARE_STATE_DEFAULT,
|
||||
@ -55,8 +81,12 @@ class AndroidChromeCustomTabsOptions
|
||||
this.instantAppsEnabled = false,
|
||||
this.packageName,
|
||||
this.keepAliveEnabled = false,
|
||||
this.singleInstance = false,
|
||||
this.noHistory = false});
|
||||
this.isSingleInstance = false,
|
||||
this.noHistory = false,
|
||||
this.isTrustedWebActivity = false,
|
||||
this.additionalTrustedOrigins = const [],
|
||||
this.displayMode,
|
||||
this.screenOrientation = TrustedWebActivityScreenOrientation.DEFAULT});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
@ -70,8 +100,12 @@ class AndroidChromeCustomTabsOptions
|
||||
"instantAppsEnabled": instantAppsEnabled,
|
||||
"packageName": packageName,
|
||||
"keepAliveEnabled": keepAliveEnabled,
|
||||
"singleInstance": singleInstance,
|
||||
"noHistory": noHistory
|
||||
"isSingleInstance": isSingleInstance,
|
||||
"noHistory": noHistory,
|
||||
"isTrustedWebActivity": isTrustedWebActivity,
|
||||
"additionalTrustedOrigins": additionalTrustedOrigins,
|
||||
"displayMode": displayMode?.toMap(),
|
||||
"screenOrientation": screenOrientation.toValue()
|
||||
};
|
||||
}
|
||||
|
||||
@ -88,8 +122,20 @@ class AndroidChromeCustomTabsOptions
|
||||
options.instantAppsEnabled = map["instantAppsEnabled"];
|
||||
options.packageName = map["packageName"];
|
||||
options.keepAliveEnabled = map["keepAliveEnabled"];
|
||||
options.singleInstance = map["singleInstance"];
|
||||
options.isSingleInstance = map["isSingleInstance"];
|
||||
options.noHistory = map["noHistory"];
|
||||
options.isTrustedWebActivity = map["isTrustedWebActivity"];
|
||||
options.additionalTrustedOrigins = map["additionalTrustedOrigins"];
|
||||
switch(map["displayMode"]["type"]) {
|
||||
case "IMMERSIVE_MODE":
|
||||
options.displayMode = TrustedWebActivityImmersiveDisplayMode.fromMap(map["displayMode"]);
|
||||
break;
|
||||
case "DEFAULT_MODE":
|
||||
default:
|
||||
options.displayMode = TrustedWebActivityDefaultDisplayMode();
|
||||
break;
|
||||
}
|
||||
options.screenOrientation = map["screenOrientation"];
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -7012,6 +7012,264 @@ class CustomTabsShareState {
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Android-class that represents display mode of a Trusted Web Activity.
|
||||
abstract class TrustedWebActivityDisplayMode {
|
||||
Map<String, dynamic> toMap() {
|
||||
return {};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Android-class that represents the default display mode of a Trusted Web Activity.
|
||||
///The system UI (status bar, navigation bar) is shown, and the browser toolbar is hidden while the user is on a verified origin.
|
||||
class TrustedWebActivityDefaultDisplayMode implements TrustedWebActivityDisplayMode {
|
||||
|
||||
String _type = "DEFAULT_MODE";
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"type": _type
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Android-class that represents the default display mode of a Trusted Web Activity.
|
||||
///The system UI (status bar, navigation bar) is shown, and the browser toolbar is hidden while the user is on a verified origin.
|
||||
class TrustedWebActivityImmersiveDisplayMode implements TrustedWebActivityDisplayMode {
|
||||
///Whether the Trusted Web Activity should be in sticky immersive mode.
|
||||
bool isSticky;
|
||||
|
||||
///The constant defining how to deal with display cutouts.
|
||||
AndroidLayoutInDisplayCutoutMode layoutInDisplayCutoutMode;
|
||||
|
||||
String _type = "IMMERSIVE_MODE";
|
||||
|
||||
TrustedWebActivityImmersiveDisplayMode(
|
||||
{required this.isSticky,
|
||||
required this.layoutInDisplayCutoutMode});
|
||||
|
||||
static TrustedWebActivityImmersiveDisplayMode? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return TrustedWebActivityImmersiveDisplayMode(
|
||||
isSticky: map["isSticky"],
|
||||
layoutInDisplayCutoutMode: map["layoutInDisplayCutoutMode"]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"isSticky": isSticky,
|
||||
"layoutInDisplayCutoutMode": layoutInDisplayCutoutMode.toValue(),
|
||||
"type": _type
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
///Android-specific class representing the share state that should be applied to the custom tab.
|
||||
///
|
||||
///**NOTE**: available on Android 28+.
|
||||
class AndroidLayoutInDisplayCutoutMode {
|
||||
final int _value;
|
||||
|
||||
const AndroidLayoutInDisplayCutoutMode._internal(this._value);
|
||||
|
||||
static final Set<AndroidLayoutInDisplayCutoutMode> values = [
|
||||
AndroidLayoutInDisplayCutoutMode.DEFAULT,
|
||||
AndroidLayoutInDisplayCutoutMode.SHORT_EDGES,
|
||||
AndroidLayoutInDisplayCutoutMode.NEVER,
|
||||
AndroidLayoutInDisplayCutoutMode.ALWAYS
|
||||
].toSet();
|
||||
|
||||
static AndroidLayoutInDisplayCutoutMode? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return AndroidLayoutInDisplayCutoutMode.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "SHORT_EDGES";
|
||||
case 2:
|
||||
return "NEVER";
|
||||
case 3:
|
||||
return "ALWAYS";
|
||||
case 0:
|
||||
default:
|
||||
return "DEFAULT";
|
||||
}
|
||||
}
|
||||
|
||||
///With this default setting, content renders into the cutout area when displayed in portrait mode, but content is letterboxed when displayed in landscape mode.
|
||||
///
|
||||
///**NOTE**: available on Android 28+.
|
||||
static const DEFAULT = const AndroidLayoutInDisplayCutoutMode._internal(0);
|
||||
|
||||
///Content renders into the cutout area in both portrait and landscape modes.
|
||||
///
|
||||
///**NOTE**: available on Android 28+.
|
||||
static const SHORT_EDGES = const AndroidLayoutInDisplayCutoutMode._internal(1);
|
||||
|
||||
///Content never renders into the cutout area.
|
||||
///
|
||||
///**NOTE**: available on Android 28+.
|
||||
static const NEVER = const AndroidLayoutInDisplayCutoutMode._internal(2);
|
||||
|
||||
///The window is always allowed to extend into the DisplayCutout areas on the all edges of the screen.
|
||||
///
|
||||
///**NOTE**: available on Android 30+.
|
||||
static const ALWAYS = const AndroidLayoutInDisplayCutoutMode._internal(3);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
/// Android-specific class representing Screen Orientation Lock type value of a Trusted Web Activity:
|
||||
/// https://www.w3.org/TR/screen-orientation/#screenorientation-interface
|
||||
class TrustedWebActivityScreenOrientation {
|
||||
final int _value;
|
||||
|
||||
const TrustedWebActivityScreenOrientation._internal(this._value);
|
||||
|
||||
static final Set<TrustedWebActivityScreenOrientation> values = [
|
||||
TrustedWebActivityScreenOrientation.DEFAULT,
|
||||
TrustedWebActivityScreenOrientation.PORTRAIT_PRIMARY,
|
||||
TrustedWebActivityScreenOrientation.PORTRAIT_SECONDARY,
|
||||
TrustedWebActivityScreenOrientation.LANDSCAPE_PRIMARY,
|
||||
TrustedWebActivityScreenOrientation.LANDSCAPE_SECONDARY,
|
||||
TrustedWebActivityScreenOrientation.ANY,
|
||||
TrustedWebActivityScreenOrientation.LANDSCAPE,
|
||||
TrustedWebActivityScreenOrientation.PORTRAIT,
|
||||
TrustedWebActivityScreenOrientation.NATURAL,
|
||||
].toSet();
|
||||
|
||||
static TrustedWebActivityScreenOrientation? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return TrustedWebActivityScreenOrientation.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "PORTRAIT_PRIMARY";
|
||||
case 2:
|
||||
return "PORTRAIT_SECONDARY";
|
||||
case 3:
|
||||
return "LANDSCAPE_PRIMARY";
|
||||
case 4:
|
||||
return "LANDSCAPE_SECONDARY";
|
||||
case 5:
|
||||
return "ANY";
|
||||
case 6:
|
||||
return "LANDSCAPE";
|
||||
case 7:
|
||||
return "PORTRAIT";
|
||||
case 8:
|
||||
return "NATURAL";
|
||||
case 0:
|
||||
default:
|
||||
return "DEFAULT";
|
||||
}
|
||||
}
|
||||
|
||||
/// The default screen orientation is the set of orientations to which the screen is locked when
|
||||
/// there is no current orientation lock.
|
||||
static const DEFAULT = const TrustedWebActivityScreenOrientation._internal(0);
|
||||
|
||||
/// Portrait-primary is an orientation where the screen width is less than or equal to the
|
||||
/// screen height. If the device's natural orientation is portrait, then it is in
|
||||
/// portrait-primary when held in that position.
|
||||
static const PORTRAIT_PRIMARY = const TrustedWebActivityScreenOrientation._internal(1);
|
||||
|
||||
/// Portrait-secondary is an orientation where the screen width is less than or equal to the
|
||||
/// screen height. If the device's natural orientation is portrait, then it is in
|
||||
/// portrait-secondary when rotated 180° from its natural position.
|
||||
static const PORTRAIT_SECONDARY = const TrustedWebActivityScreenOrientation._internal(2);
|
||||
|
||||
/// Landscape-primary is an orientation where the screen width is greater than the screen height.
|
||||
/// If the device's natural orientation is landscape, then it is in landscape-primary when held
|
||||
/// in that position.
|
||||
static const LANDSCAPE_PRIMARY = const TrustedWebActivityScreenOrientation._internal(3);
|
||||
|
||||
/// Landscape-secondary is an orientation where the screen width is greater than the
|
||||
/// screen height. If the device's natural orientation is landscape, it is in
|
||||
/// landscape-secondary when rotated 180° from its natural orientation.
|
||||
static const LANDSCAPE_SECONDARY = const TrustedWebActivityScreenOrientation._internal(4);
|
||||
|
||||
/// Any is an orientation that means the screen can be locked to any one of portrait-primary,
|
||||
/// portrait-secondary, landscape-primary and landscape-secondary.
|
||||
static const ANY = const TrustedWebActivityScreenOrientation._internal(5);
|
||||
|
||||
/// Landscape is an orientation where the screen width is greater than the screen height and
|
||||
/// depending on platform convention locking the screen to landscape can represent
|
||||
/// landscape-primary, landscape-secondary or both.
|
||||
static const LANDSCAPE = const TrustedWebActivityScreenOrientation._internal(6);
|
||||
|
||||
/// Portrait is an orientation where the screen width is less than or equal to the screen height
|
||||
/// and depending on platform convention locking the screen to portrait can represent
|
||||
/// portrait-primary, portrait-secondary or both.
|
||||
static const PORTRAIT = const TrustedWebActivityScreenOrientation._internal(7);
|
||||
|
||||
/// Natural is an orientation that refers to either portrait-primary or landscape-primary
|
||||
/// depending on the device's usual orientation. This orientation is usually provided by
|
||||
/// the underlying operating system.
|
||||
static const NATURAL = const TrustedWebActivityScreenOrientation._internal(8);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user