Merge branch 'develop' into issue_location/build_on_and_support_android_12_sdk_31
This commit is contained in:
commit
489b115038
|
@ -0,0 +1 @@
|
|||
/Users/lorenzopichilli/fvm/versions/2.10.4
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"flutterSdkVersion": "2.10.4",
|
||||
"flavors": {}
|
||||
}
|
|
@ -1,11 +1,29 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
|
||||
.vscode/
|
||||
.packages
|
||||
.pub/
|
||||
pubspec.lock
|
||||
|
||||
build/
|
||||
|
||||
.idea/workspace.xml
|
|
@ -1,122 +0,0 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="OTHER_INDENT_OPTIONS">
|
||||
<value>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</value>
|
||||
</option>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -1,5 +0,0 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
|
@ -1,420 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Dart Packages" type="DartPackagesLibraryType">
|
||||
<properties>
|
||||
<option name="packageNameToDirsMap">
|
||||
<entry key="archive">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/archive-3.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="async">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="boolean_selector">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="characters">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="charcode">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="clock">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="collection">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="crypto">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="cupertino_icons">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/cupertino_icons-1.0.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="fake_async">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ffi">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/ffi-1.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="file">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/file-6.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="flutter">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="flutter_downloader">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="flutter_driver">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter_driver/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="flutter_test">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter_test/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="fuchsia_remote_debug_protocol">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/fuchsia_remote_debug_protocol/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="integration_test">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/integration_test/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="matcher">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="meta">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path_provider">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path_provider_linux">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path_provider_macos">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path_provider_platform_interface">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_platform_interface-2.0.0-nullsafety/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path_provider_windows">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pedantic">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="permission_handler">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="permission_handler_platform_interface">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/permission_handler_platform_interface-2.0.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="platform">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="plugin_platform_interface">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/plugin_platform_interface-1.1.0-nullsafety.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="process">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/process-4.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="sky_engine">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/fvm/versions/2.1.0-10.0.pre/bin/cache/pkg/sky_engine/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="source_span">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="stack_trace">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="stream_channel">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="string_scanner">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="sync_http">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="term_glyph">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="test_api">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="typed_data">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher_linux">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher_macos">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher_platform_interface">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_platform_interface-2.0.0-nullsafety.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="url_launcher_windows">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="vector_math">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="vm_service">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/vm_service-6.0.1-nullsafety.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="webdriver">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/webdriver-3.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="win32">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/win32-2.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="xdg_directories">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/xdg_directories-0.2.0-nullsafety.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
</option>
|
||||
</properties>
|
||||
<CLASSES>
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/archive-3.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/cupertino_icons-1.0.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/ffi-1.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/file-6.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_platform_interface-2.0.0-nullsafety/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/permission_handler_platform_interface-2.0.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/plugin_platform_interface-1.1.0-nullsafety.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/process-4.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_platform_interface-2.0.0-nullsafety.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/vm_service-6.0.1-nullsafety.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/webdriver-3.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/win32-2.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/xdg_directories-0.2.0-nullsafety.1/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/bin/cache/pkg/sky_engine/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter_driver/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/flutter_test/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/fuchsia_remote_debug_protocol/lib" />
|
||||
<root url="file://$USER_HOME$/fvm/versions/2.1.0-10.0.pre/packages/integration_test/lib" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
|
@ -1,28 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Dart SDK">
|
||||
<CLASSES>
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/async" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/cli" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/collection" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/convert" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/core" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/developer" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/ffi" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/html" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/io" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/isolate" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/js" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/js_util" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/math" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/svg" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
||||
<root url="file://$USER_HOME$/flutter/bin/cache/dart-sdk/lib/web_sql" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
|
@ -1,7 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Flutter Plugins">
|
||||
<CLASSES />
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
|
@ -1,9 +0,0 @@
|
|||
<component name="libraryTable">
|
||||
<library name="Flutter for Android">
|
||||
<CLASSES>
|
||||
<root url="jar:///Users/lorenzo/flutter/bin/cache/artifacts/engine/android-arm/flutter.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownEnhProjectSettings">
|
||||
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imagePathType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
<component name="MarkdownNavigatorHistory">
|
||||
<PasteImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
|
||||
<highlightList />
|
||||
<directories />
|
||||
<filenames />
|
||||
</PasteImageHistory>
|
||||
<CopyImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
|
||||
<highlightList />
|
||||
<directories />
|
||||
<filenames />
|
||||
</CopyImageHistory>
|
||||
<PasteLinkHistory onPasteImageTargetRef="3" onPasteTargetRef="1" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteWikiElement="2" onPasteReferenceElement="2" hideInapplicableOperations="false" preserveLinkFormat="false" useHeadingForLinkText="false" linkFormat="0" saveAsDefaultOnOK="false" />
|
||||
<TableToJsonHistory>
|
||||
<entries />
|
||||
</TableToJsonHistory>
|
||||
<TableSortHistory>
|
||||
<entries />
|
||||
</TableSortHistory>
|
||||
</component>
|
||||
</project>
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="FlexmarkProjectSettings">
|
||||
<FlexmarkHtmlSettings flexmarkSpecExampleRendering="0" flexmarkSpecExampleRenderHtml="false">
|
||||
<flexmarkSectionLanguages>
|
||||
<option name="1" value="Markdown" />
|
||||
<option name="2" value="HTML" />
|
||||
<option name="3" value="flexmark-ast:1" />
|
||||
</flexmarkSectionLanguages>
|
||||
</FlexmarkHtmlSettings>
|
||||
</component>
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" lastLayoutSetsDefault="false">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
|
||||
<PegdownExtensions>
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="INTELLIJ_DUMMY_IDENTIFIER" value="true" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="WIKILINKS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||
<option name="PRODUCTION_SPEC_PARSER" value="true" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="true" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.md.nav.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
<cssUriHistory />
|
||||
</CssSettings>
|
||||
</component>
|
||||
</project>
|
|
@ -1,42 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="10">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 28 Platform" project-jdk-type="Android SDK" />
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="io.flutter" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/flutter_inappwebview.iml" filepath="$PROJECT_DIR$/flutter_inappwebview.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/flutter_inappwebview_android.iml" filepath="$PROJECT_DIR$/flutter_inappwebview_android.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false">
|
||||
<option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
120
CHANGELOG.md
120
CHANGELOG.md
|
@ -1,3 +1,41 @@
|
|||
## 5.4.0
|
||||
|
||||
- `getOriginalUrl` method is cross-platform now
|
||||
- Updated Android `compileSdkVersion` to 31
|
||||
- Updated Flutter environment: sdk to `>=2.14.0 <3.0.0` and flutter version to `>=2.5.0`
|
||||
- Added `singleInstance` option for Android `ChromeSafariBrowser` implementation
|
||||
- Added `onDownloadStartRequest` event and deprecated old `onDownloadStart` event
|
||||
- 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)
|
||||
- Fixed "Crash when try select file from webview input on Android" [#867](https://github.com/pichillilorenzo/flutter_inappwebview/issues/867)
|
||||
- Fixed "NavigationAction.request should use toMap method" [#878](https://github.com/pichillilorenzo/flutter_inappwebview/issues/878)
|
||||
- Fixed "Missing body field in URLRequest toMap method" [#990](https://github.com/pichillilorenzo/flutter_inappwebview/issues/990)
|
||||
- Fixed "iOS : createWindowAction.request.body in onCreateWindow() is NULL" [#994](https://github.com/pichillilorenzo/flutter_inappwebview/issues/994)
|
||||
- Fixed "Crash at HeadlessInAppWebView dispose" [#881](https://github.com/pichillilorenzo/flutter_inappwebview/issues/881)
|
||||
- Fixed "Crash happens when HeadlessInAppWebView's dispose function is called in iOS" [#972](https://github.com/pichillilorenzo/flutter_inappwebview/issues/972)
|
||||
- Fixed "In android, when click a href with img returns img src on onCreateWindow" [#951](https://github.com/pichillilorenzo/flutter_inappwebview/issues/951)
|
||||
- Fixed "crash at com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView$11.run (InAppWebView.java:1307)" [#1040](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1040)
|
||||
- Fixed "Unexpected behavior when using a null initialUrlRequest" [#1063](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1063)
|
||||
- Fixed "Local storage & cookie didn't persist when sharedCookie and cache both enabled" [#1092](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1092)
|
||||
- Fixed "ios zoomBy crash: Foundation/NSNumber.swift:467: Fatal error: Unable to bridge NSNumber to Float" [#873](https://github.com/pichillilorenzo/flutter_inappwebview/issues/873)
|
||||
- Merged "Update Options.swift" [#889](https://github.com/pichillilorenzo/flutter_inappwebview/pull/889) (thanks to [cloudygeek](https://github.com/cloudygeek))
|
||||
- Merged "fix: Applicatio nNameForUserAgent is not working in iOS" [#1095](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1095) (thanks to [sunalwaysknows](https://github.com/sunalwaysknows))
|
||||
- Merged "Make sure we open a new instance of a custom chrome chrome tab" [#812](https://github.com/pichillilorenzo/flutter_inappwebview/pull/812) (thanks to [savy-91](https://github.com/savy-91))
|
||||
- Merged "fix bug when in String[] array come null" [#868](https://github.com/pichillilorenzo/flutter_inappwebview/pull/868) (thanks to [Ser1ous](https://github.com/Ser1ous))
|
||||
- Merged "fix: use in NavigationAction request toMap method" [#879](https://github.com/pichillilorenzo/flutter_inappwebview/pull/879) (thanks to [chreck](https://github.com/chreck))
|
||||
- Merged "switch android mockserver dependency with okhttp" [#946](https://github.com/pichillilorenzo/flutter_inappwebview/pull/946) (thanks to [randysecrist](https://github.com/randysecrist))
|
||||
- Merged "Adds missing body to URLRequest mapping." [#991](https://github.com/pichillilorenzo/flutter_inappwebview/pull/991) (thanks to [Miiha](https://github.com/Miiha))
|
||||
- Merged "fix. Crash happens when HeadlessInAppWebView's dispose function is called in iOS" [#1017](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1017) (thanks to [hoanglm4](https://github.com/hoanglm4))
|
||||
- Merged "Fixes URL returned when taping image with href in onCreateWindow [Android]" [#1042](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1042) (thanks to [Manuito83](https://github.com/Manuito83))
|
||||
- Merged "Fix Android Sometimes crash after close webpage and return to platform code." [#1050](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1050) (thanks to [rsydor](https://github.com/rsydor))
|
||||
- Merged "Add application/wasm MimeType with InAppLocalhostServer" [#1054](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1054) (thanks to [foxstream528](https://github.com/foxstream528))
|
||||
- Merged "Fixed the unexpected behavior of InAppWebView and HeadlessInAppWebView when initialUrlRequest was set as null." [#1064](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1064) (thanks to [RodXander](https://github.com/RodXander))
|
||||
- Merged "updated com.android.tools.build:gradle" [#1066](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1066) (thanks to [chownation](https://github.com/chownation))
|
||||
- Merged "WIP - expose content-disposition and content-length from android" [#1088](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1088) (thanks to [ashank96](https://github.com/ashank96))
|
||||
- Merged "Fix ios persistance when using sharedCookie" [#1093](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1093) (thanks to [EA-YOUHOU](https://github.com/EA-YOUHOU))
|
||||
- Merged "Fixes zoomBy with floats (iOS)" [#1109](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1109) (thanks to [Manuito83](https://github.com/Manuito83))
|
||||
|
||||
## 5.3.2
|
||||
|
||||
- Added `onLoad` and `onError` callbacks in `ScriptHtmlTagAttributes` class used by `InAppWebViewController.injectJavascriptFileFromUrl`
|
||||
|
@ -63,7 +101,7 @@
|
|||
- Fixed iOS sometimes `scrollView.contentSize` doesn't fit all the `frame.size` available
|
||||
- Fixed ajax and fetch interceptor when the data/body sent is not a string
|
||||
- Fixed "InAppLocalhostServer - Error: type 'List<dynamic>' is not a subtype of type 'List<int>' in type cast" [#724](https://github.com/pichillilorenzo/flutter_inappwebview/issues/724)
|
||||
- Merge "fix proguard" [#737](https://github.com/pichillilorenzo/flutter_inappwebview/pull/737) (thanks to [myroid](https://github.com/myroid))
|
||||
- Merged "fix proguard" [#737](https://github.com/pichillilorenzo/flutter_inappwebview/pull/737) (thanks to [myroid](https://github.com/myroid))
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
|
@ -149,19 +187,19 @@
|
|||
- Added new iOS-specific attributes to `ShouldOverrideUrlLoadingRequest` and `CreateWindowRequest` classes
|
||||
- Added `toolbarTopTranslucent`, `toolbarTopTintColor`, `toolbarBottomTintColor`, `toolbarTopBarTintColor` ios-specific InAppBrowser options
|
||||
- Updated integration tests
|
||||
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
|
||||
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
|
||||
- Merge "Fix: added iOS fallback module import" [#466](https://github.com/pichillilorenzo/flutter_inappwebview/pull/466) (thanks to [Eddayy](https://github.com/Eddayy))
|
||||
- Merge "Fix NullPointerException after taking a photo by a camera app on Android" [#492](https://github.com/pichillilorenzo/flutter_inappwebview/pull/492) (thanks to [AAkira](https://github.com/AAkira))
|
||||
- Merge "iOS CookieManager.getCookies - Check that URL has suffix of cookie do…" [#658](https://github.com/pichillilorenzo/flutter_inappwebview/pull/658) (thanks to [arneke](https://github.com/arneke))
|
||||
- Merge "Add NTLM Auth" [#634](https://github.com/pichillilorenzo/flutter_inappwebview/pull/634) (thanks to [albatrosify](https://github.com/albatrosify))
|
||||
- Merge "iOS ChromeSafariBrowserManager - Fixing unnecessary casting of rootViewController to FlutterViewController" [#567](https://github.com/pichillilorenzo/flutter_inappwebview/pull/567) (thanks to [gunantosteven](https://github.com/gunantosteven))
|
||||
- Merge "Fix _channel.invokeMethod name for injectCSSFileFromUrl method" [#645](https://github.com/pichillilorenzo/flutter_inappwebview/pull/645) (thanks to [omralcrt](https://github.com/omralcrt))
|
||||
- Merge "Add android media intents on wildcard input accept" [#620](https://github.com/pichillilorenzo/flutter_inappwebview/pull/620) (thanks to [cbodin](https://github.com/cbodin))
|
||||
- Merge "Add ChromeSafariBrowser support for Android 11" [#538](https://github.com/pichillilorenzo/flutter_inappwebview/pull/538) (thanks to [DRSchlaubi](https://github.com/DRSchlaubi))
|
||||
- Merge "fix(iOS): missing implementation of method zoomBy" [#670](https://github.com/pichillilorenzo/flutter_inappwebview/pull/670) (thanks to [pcqpcq](https://github.com/pcqpcq))
|
||||
- Merge "[mod] Fix all issues relate to long click in Android version 7.0 (#657, #527)" [#671](https://github.com/pichillilorenzo/flutter_inappwebview/pull/671) (thanks to [MrNinja](https://github.com/MrNinja))
|
||||
- Merge "Fix ViewGroup.removeView NullPointerException (#450)" [#683](https://github.com/pichillilorenzo/flutter_inappwebview/pull/683) (thanks to [toda-bps](https://github.com/toda-bps))
|
||||
- Merged "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
|
||||
- Merged "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
|
||||
- Merged "Fix: added iOS fallback module import" [#466](https://github.com/pichillilorenzo/flutter_inappwebview/pull/466) (thanks to [Eddayy](https://github.com/Eddayy))
|
||||
- Merged "Fix NullPointerException after taking a photo by a camera app on Android" [#492](https://github.com/pichillilorenzo/flutter_inappwebview/pull/492) (thanks to [AAkira](https://github.com/AAkira))
|
||||
- Merged "iOS CookieManager.getCookies - Check that URL has suffix of cookie do…" [#658](https://github.com/pichillilorenzo/flutter_inappwebview/pull/658) (thanks to [arneke](https://github.com/arneke))
|
||||
- Merged "Add NTLM Auth" [#634](https://github.com/pichillilorenzo/flutter_inappwebview/pull/634) (thanks to [albatrosify](https://github.com/albatrosify))
|
||||
- Merged "iOS ChromeSafariBrowserManager - Fixing unnecessary casting of rootViewController to FlutterViewController" [#567](https://github.com/pichillilorenzo/flutter_inappwebview/pull/567) (thanks to [gunantosteven](https://github.com/gunantosteven))
|
||||
- Merged "Fix _channel.invokeMethod name for injectCSSFileFromUrl method" [#645](https://github.com/pichillilorenzo/flutter_inappwebview/pull/645) (thanks to [omralcrt](https://github.com/omralcrt))
|
||||
- Merged "Add android media intents on wildcard input accept" [#620](https://github.com/pichillilorenzo/flutter_inappwebview/pull/620) (thanks to [cbodin](https://github.com/cbodin))
|
||||
- Merged "Add ChromeSafariBrowser support for Android 11" [#538](https://github.com/pichillilorenzo/flutter_inappwebview/pull/538) (thanks to [DRSchlaubi](https://github.com/DRSchlaubi))
|
||||
- Merged "fix(iOS): missing implementation of method zoomBy" [#670](https://github.com/pichillilorenzo/flutter_inappwebview/pull/670) (thanks to [pcqpcq](https://github.com/pcqpcq))
|
||||
- Merged "[mod] Fix all issues relate to long click in Android version 7.0 (#657, #527)" [#671](https://github.com/pichillilorenzo/flutter_inappwebview/pull/671) (thanks to [MrNinja](https://github.com/MrNinja))
|
||||
- Merged "Fix ViewGroup.removeView NullPointerException (#450)" [#683](https://github.com/pichillilorenzo/flutter_inappwebview/pull/683) (thanks to [toda-bps](https://github.com/toda-bps))
|
||||
- Fixed missing properties initialization when using InAppWebViewController.fromInAppBrowser
|
||||
- Fixed "Issue in Flutter web: 'Unsupported operation: Platform._operatingSystem'" [#507](https://github.com/pichillilorenzo/flutter_inappwebview/issues/507)
|
||||
- Fixed "window.flutter_inappwebview.callHandler is not a function" [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218)
|
||||
|
@ -363,13 +401,13 @@
|
|||
- Updated for Flutter 1.12 new Java Embedding API (Android)
|
||||
- Updated `clearCache` for Android
|
||||
- Updated default value for `domStorageEnabled` and `databaseEnabled` options to `true` for Android
|
||||
- Merge "Fixes null error when calling getOptions for InAppBrowser class" [#214](https://github.com/pichillilorenzo/flutter_inappwebview/pull/214) (thanks to [panndoraBoo](https://github.com/panndoraBoo))
|
||||
- Merge "Fixes crash onConsoleMessage iOS forced unwrapping" [#228](https://github.com/pichillilorenzo/flutter_inappwebview/pull/228) (thanks to [tokonu](https://github.com/tokonu))
|
||||
- Merge "Fix HTTPCookie.secure" [#311](https://github.com/pichillilorenzo/flutter_inappwebview/pull/311) (thanks to [xtyxtyx](https://github.com/xtyxtyx))
|
||||
- Merge "Fix config options for Android release builds" [#295](https://github.com/pichillilorenzo/flutter_inappwebview/pull/295) (thanks to [wwwdata](https://github.com/wwwdata))
|
||||
- Merge "fix scrollbar on iOS always show if not disable scroll" [#256](https://github.com/pichillilorenzo/flutter_inappwebview/pull/256) (thanks to [phamnhuvu-dev](https://github.com/phamnhuvu-dev))
|
||||
- Merge "Fix crash on nil/invalid URL (iOS)" [#262](https://github.com/pichillilorenzo/flutter_inappwebview/pull/262) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Merge "Fix crash when `prompt` was called on Android Q." [#262](https://github.com/pichillilorenzo/flutter_inappwebview/pull/263) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Merged "Fixes null error when calling getOptions for InAppBrowser class" [#214](https://github.com/pichillilorenzo/flutter_inappwebview/pull/214) (thanks to [panndoraBoo](https://github.com/panndoraBoo))
|
||||
- Merged "Fixes crash onConsoleMessage iOS forced unwrapping" [#228](https://github.com/pichillilorenzo/flutter_inappwebview/pull/228) (thanks to [tokonu](https://github.com/tokonu))
|
||||
- Merged "Fix HTTPCookie.secure" [#311](https://github.com/pichillilorenzo/flutter_inappwebview/pull/311) (thanks to [xtyxtyx](https://github.com/xtyxtyx))
|
||||
- Merged "Fix config options for Android release builds" [#295](https://github.com/pichillilorenzo/flutter_inappwebview/pull/295) (thanks to [wwwdata](https://github.com/wwwdata))
|
||||
- Merged "fix scrollbar on iOS always show if not disable scroll" [#256](https://github.com/pichillilorenzo/flutter_inappwebview/pull/256) (thanks to [phamnhuvu-dev](https://github.com/phamnhuvu-dev))
|
||||
- Merged "Fix crash on nil/invalid URL (iOS)" [#262](https://github.com/pichillilorenzo/flutter_inappwebview/pull/262) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Merged "Fix crash when `prompt` was called on Android Q." [#262](https://github.com/pichillilorenzo/flutter_inappwebview/pull/263) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Fix for Android and iOS `InAppBrowser` for some controller methods not exposed.
|
||||
- Fixed "App Crashes after clicking on dropdown (Using inappwebview)" [#182](https://github.com/pichillilorenzo/flutter_inappwebview/issues/182)
|
||||
- Fixed "webview can not be released when in ios" [#225](https://github.com/pichillilorenzo/flutter_inappwebview/issues/225). Now the iOS WebView is released from memory when it is disposed from Flutter.
|
||||
|
@ -416,16 +454,16 @@
|
|||
|
||||
## 2.0.0
|
||||
|
||||
- Merge "Avoid null pointer exception after webview is disposed" [#116](https://github.com/pichillilorenzo/flutter_inappwebview/pull/116) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Merge "Remove async call in close" [#119](https://github.com/pichillilorenzo/flutter_inappwebview/pull/119) (thanks to [benfingo](https://github.com/benfingo))
|
||||
- Merge "Android takeScreenshot does not work properly." [#122](https://github.com/pichillilorenzo/flutter_inappwebview/pull/122) (thanks to [PauloMelo](https://github.com/PauloMelo))
|
||||
- Merge "Resolving gradle error." [#144](https://github.com/pichillilorenzo/flutter_inappwebview/pull/144) (thanks to [Klingens13](https://github.com/Klingens13))
|
||||
- Merge "Create issue and pull request templates" [#150](https://github.com/pichillilorenzo/flutter_inappwebview/pull/150) (thanks to [deandreamatias](https://github.com/deandreamatias))
|
||||
- Merge "Fix abstract method error && swift version error" [#155](https://github.com/pichillilorenzo/flutter_inappwebview/pull/155) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Merge "migrating to swift 5.0" [#162](https://github.com/pichillilorenzo/flutter_inappwebview/pull/162) (thanks to [fattiger00](https://github.com/fattiger00))
|
||||
- Merge "Update readme example" [#178](https://github.com/pichillilorenzo/flutter_inappwebview/pull/178) (thanks to [SebastienBtr](https://github.com/SebastienBtr))
|
||||
- Merge "handle choose file callback in android" [#183](https://github.com/pichillilorenzo/flutter_inappwebview/pull/183) (thanks to [crazecoder](https://github.com/crazecoder))
|
||||
- Merge "add initialScale in android" [#186](https://github.com/pichillilorenzo/flutter_inappwebview/pull/186) (thanks to [crazecoder](https://github.com/crazecoder))
|
||||
- Merged "Avoid null pointer exception after webview is disposed" [#116](https://github.com/pichillilorenzo/flutter_inappwebview/pull/116) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Merged "Remove async call in close" [#119](https://github.com/pichillilorenzo/flutter_inappwebview/pull/119) (thanks to [benfingo](https://github.com/benfingo))
|
||||
- Merged "Android takeScreenshot does not work properly." [#122](https://github.com/pichillilorenzo/flutter_inappwebview/pull/122) (thanks to [PauloMelo](https://github.com/PauloMelo))
|
||||
- Merged "Resolving gradle error." [#144](https://github.com/pichillilorenzo/flutter_inappwebview/pull/144) (thanks to [Klingens13](https://github.com/Klingens13))
|
||||
- Merged "Create issue and pull request templates" [#150](https://github.com/pichillilorenzo/flutter_inappwebview/pull/150) (thanks to [deandreamatias](https://github.com/deandreamatias))
|
||||
- Merged "Fix abstract method error && swift version error" [#155](https://github.com/pichillilorenzo/flutter_inappwebview/pull/155) (thanks to [AlexVincent525](https://github.com/AlexVincent525))
|
||||
- Merged "migrating to swift 5.0" [#162](https://github.com/pichillilorenzo/flutter_inappwebview/pull/162) (thanks to [fattiger00](https://github.com/fattiger00))
|
||||
- Merged "Update readme example" [#178](https://github.com/pichillilorenzo/flutter_inappwebview/pull/178) (thanks to [SebastienBtr](https://github.com/SebastienBtr))
|
||||
- Merged "handle choose file callback in android" [#183](https://github.com/pichillilorenzo/flutter_inappwebview/pull/183) (thanks to [crazecoder](https://github.com/crazecoder))
|
||||
- Merged "add initialScale in android" [#186](https://github.com/pichillilorenzo/flutter_inappwebview/pull/186) (thanks to [crazecoder](https://github.com/crazecoder))
|
||||
- Added `horizontalScrollBarEnabled` and `verticalScrollBarEnabled` options to enable/disable the corresponding scrollbar of the WebView [#165](https://github.com/pichillilorenzo/flutter_inappwebview/issues/165)
|
||||
- Added `onDownloadStart` event and `useOnDownloadStart` option: event fires when the WebView recognizes and starts a downloadable file.
|
||||
- Added `onLoadResourceCustomScheme` event and `resourceCustomSchemes` option to set custom schemes that WebView must handle to load resources
|
||||
|
@ -464,22 +502,22 @@
|
|||
|
||||
## 1.2.2
|
||||
|
||||
- Merge "added a shared WKProcessPool for webview instances" [#198](https://github.com/pichillilorenzo/flutter_inappwebview/pull/198) (thanks to [robertcnst](https://github.com/robertcnst))
|
||||
- Merged "added a shared WKProcessPool for webview instances" [#198](https://github.com/pichillilorenzo/flutter_inappwebview/pull/198) (thanks to [robertcnst](https://github.com/robertcnst))
|
||||
- Fixed iOS setCookie.
|
||||
|
||||
## 1.2.1
|
||||
|
||||
- Merge "Add new option to control the contentMode in Android platform" [#101](https://github.com/pichillilorenzo/flutter_inappwebview/pull/101) (thanks to [DreamBuddy](https://github.com/DreamBuddy))
|
||||
- Merge "Fix crash on xcode 10.2" [#107](https://github.com/pichillilorenzo/flutter_inappwebview/pull/107) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Merge "Remove headers_build_phase from example's Podfile" [#108](https://github.com/pichillilorenzo/flutter_inappwebview/pull/108) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Merged "Add new option to control the contentMode in Android platform" [#101](https://github.com/pichillilorenzo/flutter_inappwebview/pull/101) (thanks to [DreamBuddy](https://github.com/DreamBuddy))
|
||||
- Merged "Fix crash on xcode 10.2" [#107](https://github.com/pichillilorenzo/flutter_inappwebview/pull/107) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Merged "Remove headers_build_phase from example's Podfile" [#108](https://github.com/pichillilorenzo/flutter_inappwebview/pull/108) (thanks to [robsonfingo](https://github.com/robsonfingo))
|
||||
- Fixed "Make html5 video fullscreen" for Android [#43](https://github.com/pichillilorenzo/flutter_inappwebview/issues/43)
|
||||
- Fixed "AllowsInlineMediaPlayback not working" for iOS [#73](https://github.com/pichillilorenzo/flutter_inappwebview/issues/73)
|
||||
|
||||
## 1.2.0
|
||||
|
||||
- Merge "Adds a transparentBackground option for iOS and Android" [#86](https://github.com/pichillilorenzo/flutter_inappwebview/pull/86) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merge "The 'open' method requires an options dictionary" [#87](https://github.com/pichillilorenzo/flutter_inappwebview/pull/87) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merge "iOS: Call setNeedsLayout() in scrollViewDidScroll()" [#88](https://github.com/pichillilorenzo/flutter_inappwebview/pull/88) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merged "Adds a transparentBackground option for iOS and Android" [#86](https://github.com/pichillilorenzo/flutter_inappwebview/pull/86) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merged "The 'open' method requires an options dictionary" [#87](https://github.com/pichillilorenzo/flutter_inappwebview/pull/87) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merged "iOS: Call setNeedsLayout() in scrollViewDidScroll()" [#88](https://github.com/pichillilorenzo/flutter_inappwebview/pull/88) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Fixed "java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread." [#98](https://github.com/pichillilorenzo/flutter_inappwebview/issues/98) (thanks to [DreamBuddy](https://github.com/DreamBuddy))
|
||||
- Fixed "app force close/crash when enabling zoom and repeatedly changing orientation and zoomin zoomout" [#93](https://github.com/pichillilorenzo/flutter_inappwebview/issues/93)
|
||||
- Added `displayZoomControls` webview option for Android
|
||||
|
@ -487,14 +525,14 @@
|
|||
|
||||
## 1.1.3
|
||||
|
||||
- Merge "Add null checks around calls to InAppWebView callbacks" [#85](https://github.com/pichillilorenzo/flutter_inappwebview/pull/85) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
- Merged "Add null checks around calls to InAppWebView callbacks" [#85](https://github.com/pichillilorenzo/flutter_inappwebview/pull/85) (thanks to [matthewlloyd](https://github.com/matthewlloyd))
|
||||
|
||||
## 1.1.2
|
||||
|
||||
- Fix InAppBrowser crashes the app when i change the page "Lost connection" [#74](https://github.com/pichillilorenzo/flutter_inappwebview/issues/74)
|
||||
- Fix javascript `...args` parameter of `window.flutter_inappwebview.callHandler()`
|
||||
- Merge Enable setTextZoom function of Android WebViewSetting [#81](https://github.com/pichillilorenzo/flutter_inappwebview/pull/81) (thanks to [YouCii](https://github.com/YouCii))
|
||||
- Merge bug fix for android build: Android dependency 'androidx.core:core' has different version for the compile (1.0.0) and runtime (1.0.1) classpath [#83](https://github.com/pichillilorenzo/flutter_inappwebview/pull/83) (thanks to [cinos1](https://github.com/cinos1))
|
||||
- Merged Enable setTextZoom function of Android WebViewSetting [#81](https://github.com/pichillilorenzo/flutter_inappwebview/pull/81) (thanks to [YouCii](https://github.com/YouCii))
|
||||
- Merged bug fix for android build: Android dependency 'androidx.core:core' has different version for the compile (1.0.0) and runtime (1.0.1) classpath [#83](https://github.com/pichillilorenzo/flutter_inappwebview/pull/83) (thanks to [cinos1](https://github.com/cinos1))
|
||||
|
||||
## 1.1.1
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
*.iml
|
||||
.gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
gradle-wrapper.jar
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
local.properties
|
||||
keystore.properties
|
|
@ -8,7 +8,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.4'
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ android {
|
|||
implementation 'androidx.webkit:webkit:1.4.0'
|
||||
implementation 'androidx.browser:browser:1.3.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.squareup.okhttp3:mockwebserver:3.14.7'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,5 +0,0 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
|
@ -11,6 +11,10 @@
|
|||
android:theme="@style/ThemeTransparent"
|
||||
android:exported="false"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeCustomTabsActivity" />
|
||||
<activity
|
||||
android:theme="@style/ThemeTransparent"
|
||||
android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeCustomTabsActivitySingleInstance"
|
||||
android:launchMode="singleInstance"/>
|
||||
<receiver android:name="com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ActionBroadcastReceiver" />
|
||||
<meta-data
|
||||
android:name="io.flutter.embedded_views_preview"
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.in_app_webview;
|
||||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.PlatformWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.WebViewImplementation;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.StandardMessageCodec;
|
||||
import io.flutter.plugin.platform.PlatformView;
|
||||
import io.flutter.plugin.platform.PlatformViewFactory;
|
||||
|
@ -23,8 +23,16 @@ public class FlutterWebViewFactory extends PlatformViewFactory {
|
|||
@Override
|
||||
public PlatformView create(Context context, int id, Object args) {
|
||||
HashMap<String, Object> params = (HashMap<String, Object>) args;
|
||||
FlutterWebView flutterWebView = new FlutterWebView(plugin, context, id, params);
|
||||
|
||||
PlatformWebView flutterWebView;
|
||||
WebViewImplementation implementation = WebViewImplementation.fromValue((Integer) params.get("implementation"));
|
||||
switch (implementation) {
|
||||
case NATIVE:
|
||||
default:
|
||||
flutterWebView = new FlutterWebView(plugin, context, id, params);
|
||||
}
|
||||
flutterWebView.makeInitialLoad(params);
|
||||
|
||||
return flutterWebView;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import android.webkit.ValueCallback;
|
|||
import com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeSafariBrowserManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.credential_database.CredentialDatabaseHandler;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.FlutterWebViewFactory;
|
||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebViewManager;
|
||||
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
|
|
|
@ -16,11 +16,15 @@ import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserOptio
|
|||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewOptions;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ContentWorld;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.HitTestResult;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.InAppWebViewInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.SslCertificateExt;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.URLRequest;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.UserScript;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.WebMessage;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.WebMessageChannel;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.WebMessageListener;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.WebMessagePort;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -34,9 +38,9 @@ import io.flutter.plugin.common.MethodChannel;
|
|||
public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandler {
|
||||
static final String LOG_TAG = "IAWMethodHandler";
|
||||
|
||||
public InAppWebView webView;
|
||||
public InAppWebViewInterface webView;
|
||||
|
||||
public InAppWebViewMethodHandler(InAppWebView webView) {
|
||||
public InAppWebViewMethodHandler(InAppWebViewInterface webView) {
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
|
@ -176,8 +180,8 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
result.success(null);
|
||||
break;
|
||||
case "setOptions":
|
||||
if (webView != null && webView.inAppBrowserDelegate != null && webView.inAppBrowserDelegate instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.inAppBrowserDelegate;
|
||||
if (webView != null && webView.getInAppBrowserDelegate() != null && webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.getInAppBrowserDelegate();
|
||||
InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions();
|
||||
HashMap<String, Object> inAppBrowserOptionsMap = (HashMap<String, Object>) call.argument("options");
|
||||
inAppBrowserOptions.parse(inAppBrowserOptionsMap);
|
||||
|
@ -191,24 +195,24 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
result.success(true);
|
||||
break;
|
||||
case "getOptions":
|
||||
if (webView != null && webView.inAppBrowserDelegate != null && webView.inAppBrowserDelegate instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.inAppBrowserDelegate;
|
||||
if (webView != null && webView.getInAppBrowserDelegate() != null && webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.getInAppBrowserDelegate();
|
||||
result.success(inAppBrowserActivity.getOptions());
|
||||
} else {
|
||||
result.success((webView != null) ? webView.getOptions() : null);
|
||||
}
|
||||
break;
|
||||
case "close":
|
||||
if (webView != null && webView.inAppBrowserDelegate != null && webView.inAppBrowserDelegate instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.inAppBrowserDelegate;
|
||||
if (webView != null && webView.getInAppBrowserDelegate() != null && webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.getInAppBrowserDelegate();
|
||||
inAppBrowserActivity.close(result);
|
||||
} else {
|
||||
result.notImplemented();
|
||||
}
|
||||
break;
|
||||
case "show":
|
||||
if (webView != null && webView.inAppBrowserDelegate != null && webView.inAppBrowserDelegate instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.inAppBrowserDelegate;
|
||||
if (webView != null && webView.getInAppBrowserDelegate() != null && webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.getInAppBrowserDelegate();
|
||||
inAppBrowserActivity.show();
|
||||
result.success(true);
|
||||
} else {
|
||||
|
@ -216,8 +220,8 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
}
|
||||
break;
|
||||
case "hide":
|
||||
if (webView != null && webView.inAppBrowserDelegate != null && webView.inAppBrowserDelegate instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.inAppBrowserDelegate;
|
||||
if (webView != null && webView.getInAppBrowserDelegate() != null && webView.getInAppBrowserDelegate() instanceof InAppBrowserActivity) {
|
||||
InAppBrowserActivity inAppBrowserActivity = (InAppBrowserActivity) webView.getInAppBrowserDelegate();
|
||||
inAppBrowserActivity.hide();
|
||||
result.success(true);
|
||||
} else {
|
||||
|
@ -319,7 +323,11 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
result.success(true);
|
||||
break;
|
||||
case "getContentHeight":
|
||||
result.success((webView != null) ? webView.getContentHeight() : null);
|
||||
if (webView instanceof InAppWebView) {
|
||||
result.success(webView.getContentHeight());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "zoomBy":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
@ -332,22 +340,27 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
result.success((webView != null) ? webView.getOriginalUrl() : null);
|
||||
break;
|
||||
case "getZoomScale":
|
||||
result.success((webView != null) ? webView.zoomScale : null);
|
||||
if (webView instanceof InAppWebView) {
|
||||
result.success(webView.getZoomScale());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "getSelectedText":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webView.getSelectedText(result);
|
||||
if ((webView instanceof InAppWebView && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)) {
|
||||
webView.getSelectedText(new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "getHitTestResult":
|
||||
if (webView != null) {
|
||||
WebView.HitTestResult hitTestResult = webView.getHitTestResult();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", hitTestResult.getType());
|
||||
obj.put("extra", hitTestResult.getExtra());
|
||||
result.success(obj);
|
||||
if (webView instanceof InAppWebView) {
|
||||
result.success(HitTestResult.fromWebViewHitTestResult(webView.getHitTestResult()).toMap());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
|
@ -405,7 +418,7 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
case "setContextMenu":
|
||||
if (webView != null) {
|
||||
Map<String, Object> contextMenu = (Map<String, Object>) call.argument("contextMenu");
|
||||
webView.contextMenu = contextMenu;
|
||||
webView.setContextMenu(contextMenu);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -451,34 +464,34 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
result.success(true);
|
||||
break;
|
||||
case "addUserScript":
|
||||
if (webView != null && webView.userContentController != null) {
|
||||
if (webView != null && webView.getUserContentController() != null) {
|
||||
Map<String, Object> userScriptMap = (Map<String, Object>) call.argument("userScript");
|
||||
UserScript userScript = UserScript.fromMap(userScriptMap);
|
||||
result.success(webView.userContentController.addUserOnlyScript(userScript));
|
||||
result.success(webView.getUserContentController().addUserOnlyScript(userScript));
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "removeUserScript":
|
||||
if (webView != null && webView.userContentController != null) {
|
||||
if (webView != null && webView.getUserContentController() != null) {
|
||||
Integer index = (Integer) call.argument("index");
|
||||
Map<String, Object> userScriptMap = (Map<String, Object>) call.argument("userScript");
|
||||
UserScript userScript = UserScript.fromMap(userScriptMap);
|
||||
result.success(webView.userContentController.removeUserOnlyScriptAt(index, userScript.getInjectionTime()));
|
||||
result.success(webView.getUserContentController().removeUserOnlyScriptAt(index, userScript.getInjectionTime()));
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "removeUserScriptsByGroupName":
|
||||
if (webView != null && webView.userContentController != null) {
|
||||
if (webView != null && webView.getUserContentController() != null) {
|
||||
String groupName = (String) call.argument("groupName");
|
||||
webView.userContentController.removeUserOnlyScriptsByGroupName(groupName);
|
||||
webView.getUserContentController().removeUserOnlyScriptsByGroupName(groupName);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
case "removeAllUserScripts":
|
||||
if (webView != null && webView.userContentController != null) {
|
||||
webView.userContentController.removeAllUserOnlyScripts();
|
||||
if (webView != null && webView.getUserContentController() != null) {
|
||||
webView.getUserContentController().removeAllUserOnlyScripts();
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -512,8 +525,12 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
}
|
||||
break;
|
||||
case "createWebMessageChannel":
|
||||
if (webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL)) {
|
||||
result.success(webView.createCompatWebMessageChannel().toMap());
|
||||
if (webView != null) {
|
||||
if (webView instanceof InAppWebView && WebViewFeature.isFeatureSupported(WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL)) {
|
||||
result.success(webView.createCompatWebMessageChannel().toMap());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
|
@ -522,38 +539,47 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
|
|||
if (webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.POST_WEB_MESSAGE)) {
|
||||
Map<String, Object> message = (Map<String, Object>) call.argument("message");
|
||||
String targetOrigin = (String) call.argument("targetOrigin");
|
||||
List<WebMessagePortCompat> ports = new ArrayList<>();
|
||||
List<WebMessagePortCompat> compatPorts = new ArrayList<>();
|
||||
List<WebMessagePort> ports = new ArrayList<>();
|
||||
List<Map<String, Object>> portsMap = (List<Map<String, Object>>) message.get("ports");
|
||||
if (portsMap != null) {
|
||||
for (Map<String, Object> portMap : portsMap) {
|
||||
String webMessageChannelId = (String) portMap.get("webMessageChannelId");
|
||||
Integer index = (Integer) portMap.get("index");
|
||||
WebMessageChannel webMessageChannel = webView.webMessageChannels.get(webMessageChannelId);
|
||||
WebMessageChannel webMessageChannel = webView.getWebMessageChannels().get(webMessageChannelId);
|
||||
if (webMessageChannel != null) {
|
||||
ports.add(webMessageChannel.ports.get(index));
|
||||
if (webView instanceof InAppWebView) {
|
||||
compatPorts.add(webMessageChannel.compatPorts.get(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WebMessageCompat webMessage = new WebMessageCompat((String) message.get("data"), ports.toArray(new WebMessagePortCompat[0]));
|
||||
try {
|
||||
WebViewCompat.postWebMessage(webView, webMessage, Uri.parse(targetOrigin));
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
if (webView instanceof InAppWebView) {
|
||||
WebMessageCompat webMessage = new WebMessageCompat((String) message.get("data"), compatPorts.toArray(new WebMessagePortCompat[0]));
|
||||
try {
|
||||
WebViewCompat.postWebMessage((WebView) webView, webMessage, Uri.parse(targetOrigin));
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
break;
|
||||
case "addWebMessageListener":
|
||||
if (webView != null && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
|
||||
if (webView != null) {
|
||||
Map<String, Object> webMessageListenerMap = (Map<String, Object>) call.argument("webMessageListener");
|
||||
WebMessageListener webMessageListener = WebMessageListener.fromMap(webView.plugin.messenger, webMessageListenerMap);
|
||||
try {
|
||||
webView.addWebMessageListener(webMessageListener);
|
||||
WebMessageListener webMessageListener = WebMessageListener.fromMap(webView, webView.getPlugin().messenger, webMessageListenerMap);
|
||||
if (webView instanceof InAppWebView && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
|
||||
try {
|
||||
webView.addWebMessageListener(webMessageListener);
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
|
|
|
@ -99,9 +99,11 @@ public class InAppWebViewStatic implements MethodChannel.MethodCallHandler {
|
|||
}
|
||||
break;
|
||||
case "setWebContentsDebuggingEnabled":
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
{
|
||||
boolean debuggingEnabled = (boolean) call.argument("debuggingEnabled");
|
||||
WebView.setWebContentsDebuggingEnabled(debuggingEnabled);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
WebView.setWebContentsDebuggingEnabled(debuggingEnabled);
|
||||
}
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
|
|
@ -19,6 +19,9 @@ import org.json.JSONObject;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
|
@ -26,6 +29,7 @@ import java.security.cert.Certificate;
|
|||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -33,6 +37,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
|
@ -77,7 +82,7 @@ public class Util {
|
|||
return ANDROID_ASSET_URL + key;
|
||||
}
|
||||
|
||||
public static InputStream getFileAsset(InAppWebViewFlutterPlugin plugin,String assetFilePath) throws IOException {
|
||||
public static InputStream getFileAsset(InAppWebViewFlutterPlugin plugin, String assetFilePath) throws IOException {
|
||||
String key = (plugin.registrar != null) ? plugin.registrar.lookupKeyForAsset(assetFilePath) : plugin.flutterAssets.getAssetFilePathByName(assetFilePath);
|
||||
AssetManager mg = plugin.applicationContext.getResources().getAssets();
|
||||
return mg.open(key);
|
||||
|
@ -287,4 +292,33 @@ public class Util {
|
|||
public static float getPixelDensity(Context context) {
|
||||
return context.getResources().getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
public static boolean isClass(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isIPv6(String address) {
|
||||
try {
|
||||
Inet6Address.getByName(address);
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String normalizeIPv6(String address) throws Exception {
|
||||
if (!Util.isIPv6(address)) {
|
||||
throw new Exception("Invalid address: " + address);
|
||||
}
|
||||
return InetAddress.getByName(address).getCanonicalHostName();
|
||||
}
|
||||
|
||||
public static Object getOrDefault(Map map, String key, Object defaultValue) {
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
||||
|
||||
public class ChromeCustomTabsActivitySingleInstance extends ChromeCustomTabsActivity {
|
||||
|
||||
protected static final String LOG_TAG = "ChromeCustomTabsActivitySingleInstance";
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ import android.os.Bundle;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
@ -67,9 +68,13 @@ public class ChromeSafariBrowserManager implements MethodChannel.MethodCallHandl
|
|||
extras.putSerializable("options", options);
|
||||
extras.putSerializable("menuItemList", (Serializable) menuItemList);
|
||||
|
||||
Boolean isSingleInstance = (Boolean) options.get("singleInstance");
|
||||
if (CustomTabActivityHelper.isAvailable(activity)) {
|
||||
intent = new Intent(activity, ChromeCustomTabsActivity.class);
|
||||
intent = new Intent(activity, !isSingleInstance ? ChromeCustomTabsActivity.class : ChromeCustomTabsActivitySingleInstance.class);
|
||||
intent.putExtras(extras);
|
||||
if ((Boolean) options.get("noHistory")) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
}
|
||||
activity.startActivity(intent);
|
||||
result.success(true);
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.pichillilorenzo.flutter_inappwebview.InAppWebViewMethodHandler;
|
|||
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
|
||||
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout;
|
||||
import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshOptions;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.PlatformWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.URLRequest;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.UserScript;
|
||||
|
||||
|
@ -32,9 +33,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.platform.PlatformView;
|
||||
|
||||
public class FlutterWebView implements PlatformView {
|
||||
public class FlutterWebView implements PlatformWebView {
|
||||
|
||||
static final String LOG_TAG = "IAWFlutterWebView";
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -22,7 +23,6 @@ import android.util.AttributeSet;
|
|||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.DragEvent;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
@ -37,9 +37,11 @@ import android.view.inputmethod.InputConnection;
|
|||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.DownloadListener;
|
||||
import android.webkit.URLUtil;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebBackForwardList;
|
||||
import android.webkit.WebHistoryItem;
|
||||
import android.webkit.WebMessage;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebStorage;
|
||||
import android.widget.HorizontalScrollView;
|
||||
|
@ -53,6 +55,8 @@ import androidx.webkit.WebViewCompat;
|
|||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.DownloadStartRequest;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.InAppWebViewInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
@ -99,7 +103,7 @@ import okhttp3.OkHttpClient;
|
|||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
import static com.pichillilorenzo.flutter_inappwebview.types.PreferredContentModeOptionType.fromValue;
|
||||
|
||||
final public class InAppWebView extends InputAwareWebView {
|
||||
final public class InAppWebView extends InputAwareWebView implements InAppWebViewInterface {
|
||||
|
||||
static final String LOG_TAG = "InAppWebView";
|
||||
|
||||
|
@ -129,7 +133,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public LinearLayout floatingContextMenu = null;
|
||||
@Nullable
|
||||
public Map<String, Object> contextMenu = null;
|
||||
public Handler headlessHandler = new Handler(Looper.getMainLooper());
|
||||
public Handler mainLooperHandler = new Handler(Looper.getMainLooper());
|
||||
static Handler mHandler = new Handler();
|
||||
|
||||
public Runnable checkScrollStoppedTask;
|
||||
|
@ -145,6 +149,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public Map<String, ValueCallback<String>> evaluateJavaScriptContentWorldCallbacks = new HashMap<>();
|
||||
|
||||
public Map<String, WebMessageChannel> webMessageChannels = new HashMap<>();
|
||||
public List<WebMessageListener> webMessageListeners = new ArrayList<>();
|
||||
|
||||
public InAppWebView(Context context) {
|
||||
super(context);
|
||||
|
@ -174,11 +179,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
plugin.activity.registerForContextMenu(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
|
||||
httpClient = new OkHttpClient().newBuilder().build();
|
||||
|
@ -400,7 +400,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
onScrollStopped();
|
||||
} else {
|
||||
initialPositionScrollStoppedTask = getScrollY();
|
||||
headlessHandler.postDelayed(checkScrollStoppedTask, newCheckScrollStoppedTask);
|
||||
mainLooperHandler.postDelayed(checkScrollStoppedTask, newCheckScrollStoppedTask);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -418,7 +418,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
hideContextMenu();
|
||||
}
|
||||
} else {
|
||||
headlessHandler.postDelayed(checkContextMenuShouldBeClosedTask, newCheckContextMenuShouldBeClosedTaskTask);
|
||||
mainLooperHandler.postDelayed(checkContextMenuShouldBeClosedTask, newCheckContextMenuShouldBeClosedTaskTask);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -471,11 +471,9 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
setOnLongClickListener(new OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
HitTestResult hitTestResult = getHitTestResult();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", hitTestResult.getType());
|
||||
obj.put("extra", hitTestResult.getExtra());
|
||||
channel.invokeMethod("onLongPressHitTestResult", obj);
|
||||
com.pichillilorenzo.flutter_inappwebview.types.HitTestResult hitTestResult =
|
||||
com.pichillilorenzo.flutter_inappwebview.types.HitTestResult.fromWebViewHitTestResult(getHitTestResult());
|
||||
channel.invokeMethod("onLongPressHitTestResult", hitTestResult.toMap());
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
@ -540,6 +538,10 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
|
||||
public void loadFile(String assetFilePath) throws IOException {
|
||||
if (plugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadUrl(Util.getUrlAsset(plugin, assetFilePath));
|
||||
}
|
||||
|
||||
|
@ -570,12 +572,12 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public void takeScreenshot(final @Nullable Map<String, Object> screenshotConfiguration, final MethodChannel.Result result) {
|
||||
final float pixelDensity = Util.getPixelDensity(getContext());
|
||||
|
||||
headlessHandler.post(new Runnable() {
|
||||
mainLooperHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Bitmap resized = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(resized);
|
||||
Bitmap screenshotBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(screenshotBitmap);
|
||||
c.translate(-getScrollX(), -getScrollY());
|
||||
draw(c);
|
||||
|
||||
|
@ -588,10 +590,10 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
if (rect != null) {
|
||||
int rectX = (int) Math.floor(rect.get("x") * pixelDensity + 0.5);
|
||||
int rectY = (int) Math.floor(rect.get("y") * pixelDensity + 0.5);
|
||||
int rectWidth = Math.min(resized.getWidth(), (int) Math.floor(rect.get("width") * pixelDensity + 0.5));
|
||||
int rectHeight = Math.min(resized.getHeight(), (int) Math.floor(rect.get("height") * pixelDensity + 0.5));
|
||||
resized = Bitmap.createBitmap(
|
||||
resized,
|
||||
int rectWidth = Math.min(screenshotBitmap.getWidth(), (int) Math.floor(rect.get("width") * pixelDensity + 0.5));
|
||||
int rectHeight = Math.min(screenshotBitmap.getHeight(), (int) Math.floor(rect.get("height") * pixelDensity + 0.5));
|
||||
screenshotBitmap = Bitmap.createBitmap(
|
||||
screenshotBitmap,
|
||||
rectX,
|
||||
rectY,
|
||||
rectWidth,
|
||||
|
@ -601,9 +603,9 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
Double snapshotWidth = (Double) screenshotConfiguration.get("snapshotWidth");
|
||||
if (snapshotWidth != null) {
|
||||
int dstWidth = (int) Math.floor(snapshotWidth * pixelDensity + 0.5);
|
||||
float ratioBitmap = (float) resized.getWidth() / (float) resized.getHeight();
|
||||
float ratioBitmap = (float) screenshotBitmap.getWidth() / (float) screenshotBitmap.getHeight();
|
||||
int dstHeight = (int) ((float) dstWidth / ratioBitmap);
|
||||
resized = Bitmap.createScaledBitmap(resized, dstWidth, dstHeight, true);
|
||||
screenshotBitmap = Bitmap.createScaledBitmap(screenshotBitmap, dstWidth, dstHeight, true);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -615,7 +617,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
quality = (Integer) screenshotConfiguration.get("quality");
|
||||
}
|
||||
|
||||
resized.compress(
|
||||
screenshotBitmap.compress(
|
||||
compressFormat,
|
||||
quality,
|
||||
byteArrayOutputStream);
|
||||
|
@ -625,7 +627,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
resized.recycle();
|
||||
screenshotBitmap.recycle();
|
||||
result.success(byteArrayOutputStream.toByteArray());
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -982,7 +984,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
.replace(PluginScriptsUtil.VAR_RESULT_UUID, resultUuid);
|
||||
}
|
||||
final String finalScriptToInject = scriptToInject;
|
||||
headlessHandler.post(new Runnable() {
|
||||
mainLooperHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String scriptToInject = userContentController.generateCodeForScriptEvaluation(finalScriptToInject, contentWorld);
|
||||
|
@ -1181,10 +1183,17 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
|
||||
class DownloadStartListener implements DownloadListener {
|
||||
@Override
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("url", url);
|
||||
channel.invokeMethod("onDownloadStart", obj);
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
|
||||
DownloadStartRequest downloadStartRequest = new DownloadStartRequest(
|
||||
url,
|
||||
userAgent,
|
||||
contentDisposition,
|
||||
mimeType,
|
||||
contentLength,
|
||||
URLUtil.guessFileName(url, contentDisposition, mimeType),
|
||||
null
|
||||
);
|
||||
channel.invokeMethod("onDownloadStartRequest", downloadStartRequest.toMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1231,11 +1240,9 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
}
|
||||
|
||||
private void sendOnCreateContextMenuEvent() {
|
||||
HitTestResult hitTestResult = getHitTestResult();
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", hitTestResult.getType());
|
||||
obj.put("extra", hitTestResult.getExtra());
|
||||
channel.invokeMethod("onCreateContextMenu", obj);
|
||||
com.pichillilorenzo.flutter_inappwebview.types.HitTestResult hitTestResult =
|
||||
com.pichillilorenzo.flutter_inappwebview.types.HitTestResult.fromWebViewHitTestResult(getHitTestResult());
|
||||
channel.invokeMethod("onCreateContextMenu", hitTestResult.toMap());
|
||||
}
|
||||
|
||||
private Point contextMenuPoint = new Point(0, 0);
|
||||
|
@ -1302,8 +1309,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
public void run() {
|
||||
InputMethodManager imm =
|
||||
(InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
|
||||
if (imm != null && !imm.isAcceptingText()) {
|
||||
|
||||
if (containerView != null && imm != null && !imm.isAcceptingText()) {
|
||||
imm.hideSoftInputFromWindow(
|
||||
containerView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
}
|
||||
|
@ -1477,7 +1483,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, curx, ((int) cury) + getScrollY())
|
||||
);
|
||||
|
||||
headlessHandler.post(new Runnable() {
|
||||
mainLooperHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (floatingContextMenu != null) {
|
||||
|
@ -1551,16 +1557,6 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
});
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public void getSelectedText(final MethodChannel.Result result) {
|
||||
getSelectedText(new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
result.success(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, Object> requestFocusNodeHref() {
|
||||
Message msg = InAppWebView.mHandler.obtainMessage();
|
||||
requestFocusNodeHref(msg);
|
||||
|
@ -1649,8 +1645,16 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
return webMessageChannel;
|
||||
}
|
||||
|
||||
public void addWebMessageListener(@NonNull WebMessageListener webMessageListener) {
|
||||
@Override
|
||||
public WebMessageChannel createWebMessageChannel(ValueCallback<WebMessageChannel> callback) {
|
||||
WebMessageChannel webMessageChannel = createCompatWebMessageChannel();
|
||||
callback.onReceiveValue(webMessageChannel);
|
||||
return webMessageChannel;
|
||||
}
|
||||
|
||||
public void addWebMessageListener(@NonNull WebMessageListener webMessageListener) throws Exception {
|
||||
WebViewCompat.addWebMessageListener(this, webMessageListener.jsObjectName, webMessageListener.allowedOriginRules, webMessageListener.listener);
|
||||
webMessageListeners.add(webMessageListener);
|
||||
}
|
||||
|
||||
public void disposeWebMessageChannels() {
|
||||
|
@ -1660,19 +1664,94 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
webMessageChannels.clear();
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void disposeWebMessageListeners() {
|
||||
for (WebMessageListener webMessageListener : webMessageListeners) {
|
||||
webMessageListener.dispose();
|
||||
}
|
||||
webMessageListeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postWebMessage(com.pichillilorenzo.flutter_inappwebview.types.WebMessage message, Uri targetOrigin, ValueCallback<String> callback) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected void onWindowVisibilityChanged(int visibility) {
|
||||
// if (visibility != View.GONE) super.onWindowVisibilityChanged(View.VISIBLE);
|
||||
// }
|
||||
|
||||
public float getZoomScale() {
|
||||
return zoomScale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getZoomScale(final ValueCallback<Float> callback) {
|
||||
callback.onReceiveValue(zoomScale);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, Object> getContextMenu() {
|
||||
return contextMenu;
|
||||
}
|
||||
|
||||
public void setContextMenu(@Nullable Map<String, Object> contextMenu) {
|
||||
this.contextMenu = contextMenu;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InAppWebViewFlutterPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public void setPlugin(@Nullable InAppWebViewFlutterPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InAppBrowserDelegate getInAppBrowserDelegate() {
|
||||
return inAppBrowserDelegate;
|
||||
}
|
||||
|
||||
public void setInAppBrowserDelegate(@Nullable InAppBrowserDelegate inAppBrowserDelegate) {
|
||||
this.inAppBrowserDelegate = inAppBrowserDelegate;
|
||||
}
|
||||
|
||||
public UserContentController getUserContentController() {
|
||||
return userContentController;
|
||||
}
|
||||
|
||||
public void setUserContentController(UserContentController userContentController) {
|
||||
this.userContentController = userContentController;
|
||||
}
|
||||
|
||||
public Map<String, WebMessageChannel> getWebMessageChannels() {
|
||||
return webMessageChannels;
|
||||
}
|
||||
|
||||
public void setWebMessageChannels(Map<String, WebMessageChannel> webMessageChannels) {
|
||||
this.webMessageChannels = webMessageChannels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getContentHeight(ValueCallback<Integer> callback) {
|
||||
callback.onReceiveValue(getContentHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getHitTestResult(ValueCallback<com.pichillilorenzo.flutter_inappwebview.types.HitTestResult> callback) {
|
||||
callback.onReceiveValue(com.pichillilorenzo.flutter_inappwebview.types.HitTestResult.fromWebViewHitTestResult(getHitTestResult()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (windowId != null) {
|
||||
InAppWebViewChromeClient.windowWebViewMessages.remove(windowId);
|
||||
}
|
||||
headlessHandler.removeCallbacksAndMessages(null);
|
||||
mainLooperHandler.removeCallbacksAndMessages(null);
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
disposeWebMessageChannels();
|
||||
disposeWebMessageListeners();
|
||||
removeAllViews();
|
||||
if (checkContextMenuShouldBeClosedTask != null)
|
||||
removeCallbacks(checkContextMenuShouldBeClosedTask);
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
|
@ -573,6 +574,19 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
WebView.HitTestResult result = view.getHitTestResult();
|
||||
String url = result.getExtra();
|
||||
|
||||
// Ensure that images with hyperlink return the correct URL, not the image source
|
||||
if(result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||
Message href = view.getHandler().obtainMessage();
|
||||
view.requestFocusNodeHref(href);
|
||||
Bundle data = href.getData();
|
||||
if (data != null) {
|
||||
String imageUrl = data.getString("url");
|
||||
if(imageUrl != null && !imageUrl.isEmpty()) {
|
||||
url = imageUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
URLRequest request = new URLRequest(url, "GET", null, null);
|
||||
CreateWindowAction createWindowAction = new CreateWindowAction(
|
||||
request,
|
||||
|
@ -1004,7 +1018,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
|
|||
|
||||
private Boolean arrayContainsString(String[] array, String pattern) {
|
||||
for (String content : array) {
|
||||
if (content.contains(pattern)) {
|
||||
if (content != null && content.contains(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.webkit.WebSettings;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Options;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.InAppWebViewInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.PreferredContentModeOptionType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -17,7 +18,7 @@ import java.util.Map;
|
|||
import static android.webkit.WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
|
||||
import static android.webkit.WebSettings.LayoutAlgorithm.NORMAL;
|
||||
|
||||
public class InAppWebViewOptions implements Options<InAppWebView> {
|
||||
public class InAppWebViewOptions implements Options<InAppWebViewInterface> {
|
||||
|
||||
public static final String LOG_TAG = "InAppWebViewOptions";
|
||||
|
||||
|
@ -455,9 +456,10 @@ public class InAppWebViewOptions implements Options<InAppWebView> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getRealOptions(InAppWebView webView) {
|
||||
public Map<String, Object> getRealOptions(InAppWebViewInterface inAppWebView) {
|
||||
Map<String, Object> realOptions = toMap();
|
||||
if (webView != null) {
|
||||
if (inAppWebView instanceof InAppWebView) {
|
||||
InAppWebView webView = (InAppWebView) inAppWebView;
|
||||
WebSettings settings = webView.getSettings();
|
||||
realOptions.put("userAgent", settings.getUserAgentString());
|
||||
realOptions.put("javaScriptEnabled", settings.getJavaScriptEnabled());
|
||||
|
|
|
@ -15,6 +15,7 @@ public class JavaScriptBridgeJS {
|
|||
);
|
||||
|
||||
public static final String JAVASCRIPT_UTIL_VAR_NAME = "window." + JAVASCRIPT_BRIDGE_NAME + "._Util";
|
||||
public static final String WEB_MESSAGE_CHANNELS_VARIABLE_NAME = "window." + JAVASCRIPT_BRIDGE_NAME + "._webMessageChannels";
|
||||
|
||||
public static final String UTIL_JS_SOURCE = JAVASCRIPT_UTIL_VAR_NAME + " = {" +
|
||||
" support: {" +
|
||||
|
@ -131,10 +132,10 @@ public class JavaScriptBridgeJS {
|
|||
" }," +
|
||||
" convertBodyRequest: function(body) {" +
|
||||
" if (body == null) {" +
|
||||
" return new Promise((resolve, reject) => resolve(null));" +
|
||||
" return new Promise(function(resolve, reject) { resolve(null); });" +
|
||||
" }" +
|
||||
" if (" + JAVASCRIPT_UTIL_VAR_NAME + ".isString(body) || (" + JAVASCRIPT_UTIL_VAR_NAME + ".support.searchParams && body instanceof URLSearchParams)) {" +
|
||||
" return new Promise((resolve, reject) => resolve(body.toString()));" +
|
||||
" return new Promise(function(resolve, reject) { resolve(body.toString()); });" +
|
||||
" }" +
|
||||
" if (window.Response != null) {" +
|
||||
" return new Response(body).arrayBuffer().then(function(arrayBuffer) {" +
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DownloadStartRequest {
|
||||
|
||||
@NonNull
|
||||
private String url;
|
||||
@NonNull
|
||||
private String userAgent;
|
||||
@NonNull
|
||||
private String contentDisposition;
|
||||
@NonNull
|
||||
private String mimeType;
|
||||
private long contentLength;
|
||||
@Nullable
|
||||
private String suggestedFilename;
|
||||
@Nullable
|
||||
private String textEncodingName;
|
||||
|
||||
public DownloadStartRequest(@NonNull String url, @NonNull String userAgent, @NonNull String contentDisposition, @NonNull String mimeType, long contentLength, @Nullable String suggestedFilename, @Nullable String textEncodingName) {
|
||||
this.url = url;
|
||||
this.userAgent = userAgent;
|
||||
this.contentDisposition = contentDisposition;
|
||||
this.mimeType = mimeType;
|
||||
this.contentLength = contentLength;
|
||||
this.suggestedFilename = suggestedFilename;
|
||||
this.textEncodingName = textEncodingName;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("url", url);
|
||||
obj.put("userAgent", userAgent);
|
||||
obj.put("contentDisposition", contentDisposition);
|
||||
obj.put("mimeType", mimeType);
|
||||
obj.put("contentLength", contentLength);
|
||||
obj.put("suggestedFilename", suggestedFilename);
|
||||
obj.put("textEncodingName", textEncodingName);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(@NonNull String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(@NonNull String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getContentDisposition() {
|
||||
return contentDisposition;
|
||||
}
|
||||
|
||||
public void setContentDisposition(@NonNull String contentDisposition) {
|
||||
this.contentDisposition = contentDisposition;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public void setMimeType(@NonNull String mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
public long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSuggestedFilename() {
|
||||
return suggestedFilename;
|
||||
}
|
||||
|
||||
public void setSuggestedFilename(@Nullable String suggestedFilename) {
|
||||
this.suggestedFilename = suggestedFilename;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextEncodingName() {
|
||||
return textEncodingName;
|
||||
}
|
||||
|
||||
public void setTextEncodingName(@Nullable String textEncodingName) {
|
||||
this.textEncodingName = textEncodingName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DownloadStartRequest that = (DownloadStartRequest) o;
|
||||
|
||||
if (contentLength != that.contentLength) return false;
|
||||
if (!url.equals(that.url)) return false;
|
||||
if (!userAgent.equals(that.userAgent)) return false;
|
||||
if (!contentDisposition.equals(that.contentDisposition)) return false;
|
||||
if (!mimeType.equals(that.mimeType)) return false;
|
||||
if (suggestedFilename != null ? !suggestedFilename.equals(that.suggestedFilename) : that.suggestedFilename != null)
|
||||
return false;
|
||||
return textEncodingName != null ? textEncodingName.equals(that.textEncodingName) : that.textEncodingName == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = url.hashCode();
|
||||
result = 31 * result + userAgent.hashCode();
|
||||
result = 31 * result + contentDisposition.hashCode();
|
||||
result = 31 * result + mimeType.hashCode();
|
||||
result = 31 * result + (int) (contentLength ^ (contentLength >>> 32));
|
||||
result = 31 * result + (suggestedFilename != null ? suggestedFilename.hashCode() : 0);
|
||||
result = 31 * result + (textEncodingName != null ? textEncodingName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DownloadStartRequest{" +
|
||||
"url='" + url + '\'' +
|
||||
", userAgent='" + userAgent + '\'' +
|
||||
", contentDisposition='" + contentDisposition + '\'' +
|
||||
", mimeType='" + mimeType + '\'' +
|
||||
", contentLength=" + contentLength +
|
||||
", suggestedFilename='" + suggestedFilename + '\'' +
|
||||
", textEncodingName='" + textEncodingName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class HitTestResult {
|
||||
private int type;
|
||||
@Nullable
|
||||
private String extra;
|
||||
|
||||
public HitTestResult(int type, @Nullable String extra) {
|
||||
this.type = type;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static public HitTestResult fromWebViewHitTestResult(@Nullable WebView.HitTestResult hitTestResult) {
|
||||
if (hitTestResult == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new HitTestResult(hitTestResult.getType(), hitTestResult.getExtra());
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getExtra() {
|
||||
return extra;
|
||||
}
|
||||
|
||||
public void setExtra(@Nullable String extra) {
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> hitTestResultMap = new HashMap<>();
|
||||
hitTestResultMap.put("type", type);
|
||||
hitTestResultMap.put("extra", extra);
|
||||
return hitTestResultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
HitTestResult that = (HitTestResult) o;
|
||||
|
||||
if (type != that.type) return false;
|
||||
return extra != null ? extra.equals(that.extra) : that.extra == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type;
|
||||
result = 31 * result + (extra != null ? extra.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HitTestResultMap{" +
|
||||
"type=" + type +
|
||||
", extra='" + extra + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.net.http.SslCertificate;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebMessage;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebViewOptions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public interface InAppWebViewInterface {
|
||||
Context getContext();
|
||||
String getUrl();
|
||||
String getTitle();
|
||||
int getProgress();
|
||||
void loadUrl(URLRequest urlRequest);
|
||||
void postUrl(String url, byte[] postData);
|
||||
void loadDataWithBaseURL(String baseUrl, String data,
|
||||
String mimeType, String encoding, String historyUrl);
|
||||
void loadFile(String assetFilePath) throws IOException;
|
||||
void evaluateJavascript(String source, ContentWorld contentWorld, ValueCallback<String> resultCallback);
|
||||
void injectJavascriptFileFromUrl(String urlFile, Map<String, Object> scriptHtmlTagAttributes);
|
||||
void injectCSSCode(String source);
|
||||
void injectCSSFileFromUrl(String urlFile, Map<String, Object> cssLinkHtmlTagAttributes);
|
||||
void reload();
|
||||
void goBack();
|
||||
boolean canGoBack();
|
||||
void goForward();
|
||||
boolean canGoForward();
|
||||
void goBackOrForward(int steps);
|
||||
boolean canGoBackOrForward(int steps);
|
||||
void stopLoading();
|
||||
boolean isLoading();
|
||||
void takeScreenshot(Map<String, Object> screenshotConfiguration, MethodChannel.Result result);
|
||||
void setOptions(InAppWebViewOptions newOptions, HashMap<String, Object> newOptionsMap);
|
||||
Map<String, Object> getOptions();
|
||||
HashMap<String, Object> getCopyBackForwardList();
|
||||
void clearAllCache();
|
||||
void clearSslPreferences();
|
||||
void findAllAsync(String find);
|
||||
void findNext(boolean forward);
|
||||
void clearMatches();
|
||||
void scrollTo(Integer x, Integer y, Boolean animated);
|
||||
void scrollBy(Integer x, Integer y, Boolean animated);
|
||||
void onPause();
|
||||
void onResume();
|
||||
void pauseTimers();
|
||||
void resumeTimers();
|
||||
void printCurrentPage();
|
||||
int getContentHeight();
|
||||
void getContentHeight(ValueCallback<Integer> callback);
|
||||
void zoomBy(float zoomFactor);
|
||||
String getOriginalUrl();
|
||||
void getSelectedText(ValueCallback<String> callback);
|
||||
WebView.HitTestResult getHitTestResult();
|
||||
void getHitTestResult(ValueCallback<HitTestResult> callback);
|
||||
boolean pageDown(boolean bottom);
|
||||
boolean pageUp(boolean top);
|
||||
void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback);
|
||||
boolean zoomIn();
|
||||
boolean zoomOut();
|
||||
void clearFocus();
|
||||
Map<String, Object> requestFocusNodeHref();
|
||||
Map<String, Object> requestImageRef();
|
||||
int getScrollX();
|
||||
int getScrollY();
|
||||
SslCertificate getCertificate();
|
||||
void clearHistory();
|
||||
void callAsyncJavaScript(String functionBody, Map<String, Object> arguments, ContentWorld contentWorld, ValueCallback<String> resultCallback);
|
||||
void isSecureContext(final ValueCallback<Boolean> resultCallback);
|
||||
WebMessageChannel createCompatWebMessageChannel();
|
||||
WebMessageChannel createWebMessageChannel(ValueCallback<WebMessageChannel> callback);
|
||||
void postWebMessage(WebMessage message, Uri targetOrigin);
|
||||
void postWebMessage(com.pichillilorenzo.flutter_inappwebview.types.WebMessage message, Uri targetOrigin, ValueCallback<String> callback) throws Exception;
|
||||
void addWebMessageListener(WebMessageListener webMessageListener) throws Exception;
|
||||
boolean canScrollVertically();
|
||||
boolean canScrollHorizontally();
|
||||
float getZoomScale();
|
||||
void getZoomScale(ValueCallback<Float> callback);
|
||||
Map<String, Object> getContextMenu();
|
||||
void setContextMenu(Map<String, Object> contextMenu);
|
||||
InAppWebViewFlutterPlugin getPlugin();
|
||||
void setPlugin(InAppWebViewFlutterPlugin plugin);
|
||||
InAppBrowserDelegate getInAppBrowserDelegate();
|
||||
void setInAppBrowserDelegate(InAppBrowserDelegate inAppBrowserDelegate);
|
||||
UserContentController getUserContentController();
|
||||
void setUserContentController(UserContentController userContentController);
|
||||
Map<String, WebMessageChannel> getWebMessageChannels();
|
||||
void setWebMessageChannels(Map<String, WebMessageChannel> webMessageChannels);
|
||||
void disposeWebMessageChannels();
|
||||
void disposeWebMessageListeners();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.flutter.plugin.platform.PlatformView;
|
||||
|
||||
public interface PlatformWebView extends PlatformView {
|
||||
void makeInitialLoad(HashMap<String, Object> params);
|
||||
}
|
|
@ -60,7 +60,7 @@ public class UserContentController {
|
|||
return js;
|
||||
}
|
||||
|
||||
private String generateCodeForDocumentStart() {
|
||||
public String generateCodeForDocumentStart() {
|
||||
UserScriptInjectionTime injectionTime = UserScriptInjectionTime.AT_DOCUMENT_START;
|
||||
String js = "";
|
||||
js += generatePluginScriptsCodeAt(injectionTime);
|
||||
|
@ -70,7 +70,7 @@ public class UserContentController {
|
|||
return js;
|
||||
}
|
||||
|
||||
private String generateContentWorldsCreatorCode() {
|
||||
public String generateContentWorldsCreatorCode() {
|
||||
if (this.contentWorlds.size() == 1) {
|
||||
return "";
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public class UserContentController {
|
|||
|
||||
}
|
||||
|
||||
private String generatePluginScriptsCodeAt(UserScriptInjectionTime injectionTime) {
|
||||
public String generatePluginScriptsCodeAt(UserScriptInjectionTime injectionTime) {
|
||||
StringBuilder js = new StringBuilder();
|
||||
LinkedHashSet<PluginScript> scripts = this.getPluginScriptsAt(injectionTime);
|
||||
for (PluginScript script : scripts) {
|
||||
|
@ -105,7 +105,7 @@ public class UserContentController {
|
|||
return js.toString();
|
||||
}
|
||||
|
||||
private String generateUserOnlyScriptsCodeAt(UserScriptInjectionTime injectionTime) {
|
||||
public String generateUserOnlyScriptsCodeAt(UserScriptInjectionTime injectionTime) {
|
||||
StringBuilder js = new StringBuilder();
|
||||
LinkedHashSet<UserScript> scripts = this.getUserOnlyScriptsAt(injectionTime);
|
||||
for (UserScript script : scripts) {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WebMessage {
|
||||
@Nullable
|
||||
public String data;
|
||||
@Nullable
|
||||
public List<WebMessagePort> ports;
|
||||
|
||||
public WebMessage(@Nullable String data, @Nullable List<WebMessagePort> ports) {
|
||||
this.data = data;
|
||||
this.ports = ports;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (ports != null) {
|
||||
ports.clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.webkit.WebMessageCompat;
|
||||
|
@ -8,6 +10,7 @@ import androidx.webkit.WebViewCompat;
|
|||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -23,85 +26,64 @@ public class WebMessageChannel implements MethodChannel.MethodCallHandler {
|
|||
|
||||
public String id;
|
||||
public MethodChannel channel;
|
||||
public final List<WebMessagePortCompat> ports;
|
||||
private InAppWebView webView;
|
||||
public final List<WebMessagePortCompat> compatPorts;
|
||||
public final List<WebMessagePort> ports;
|
||||
public InAppWebViewInterface webView;
|
||||
|
||||
public WebMessageChannel(@NonNull String id, @NonNull InAppWebView webView) {
|
||||
public WebMessageChannel(@NonNull String id, @NonNull InAppWebViewInterface webView) {
|
||||
this.id = id;
|
||||
this.channel = new MethodChannel(webView.plugin.messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_channel_" + id);
|
||||
this.channel = new MethodChannel(webView.getPlugin().messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_channel_" + id);
|
||||
this.channel.setMethodCallHandler(this);
|
||||
this.ports = new ArrayList<>(Arrays.asList(WebViewCompat.createWebMessageChannel(webView)));
|
||||
if (webView instanceof InAppWebView) {
|
||||
this.compatPorts = new ArrayList<>(Arrays.asList(WebViewCompat.createWebMessageChannel((InAppWebView) webView)));
|
||||
this.ports = new ArrayList<>();
|
||||
} else {
|
||||
this.ports = Arrays.asList(new WebMessagePort("port1", this), new WebMessagePort("port2", this));
|
||||
this.compatPorts = new ArrayList<>();
|
||||
}
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
public void initJsInstance(InAppWebViewInterface webView, final ValueCallback<WebMessageChannel> callback) {
|
||||
if (webView != null) {
|
||||
final WebMessageChannel webMessageChannel = this;
|
||||
webView.evaluateJavascript("(function() {" +
|
||||
JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'] = new MessageChannel();" +
|
||||
"})();", null, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
callback.onReceiveValue(webMessageChannel);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.onReceiveValue(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "setWebMessageCallback":
|
||||
if (webView != null && ports.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK)) {
|
||||
if (webView instanceof InAppWebView) {
|
||||
final Integer index = (Integer) call.argument("index");
|
||||
final WebMessagePortCompat webMessagePort = ports.get(index);
|
||||
try {
|
||||
webMessagePort.setWebMessageCallback(new WebMessagePortCompat.WebMessageCallbackCompat() {
|
||||
@Override
|
||||
public void onMessage(@NonNull WebMessagePortCompat port, @Nullable WebMessageCompat message) {
|
||||
super.onMessage(port, message);
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("index", index);
|
||||
obj.put("message", message != null ? message.getData() : null);
|
||||
channel.invokeMethod("onMessage", obj);
|
||||
}
|
||||
});
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
setWebMessageCallbackForInAppWebView(index, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
break;
|
||||
case "postMessage":
|
||||
if (webView != null && ports.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE)) {
|
||||
if (webView instanceof InAppWebView) {
|
||||
final Integer index = (Integer) call.argument("index");
|
||||
WebMessagePortCompat port = ports.get(index);
|
||||
Map<String, Object> message = (Map<String, Object>) call.argument("message");
|
||||
List<WebMessagePortCompat> webMessagePorts = new ArrayList<>();
|
||||
List<Map<String, Object>> portsMap = (List<Map<String, Object>>) message.get("ports");
|
||||
if (portsMap != null) {
|
||||
for (Map<String, Object> portMap : portsMap) {
|
||||
String webMessageChannelId = (String) portMap.get("webMessageChannelId");
|
||||
Integer portIndex = (Integer) portMap.get("index");
|
||||
WebMessageChannel webMessageChannel = webView.webMessageChannels.get(webMessageChannelId);
|
||||
if (webMessageChannel != null) {
|
||||
webMessagePorts.add(webMessageChannel.ports.get(portIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
WebMessageCompat webMessage = new WebMessageCompat((String) message.get("data"), webMessagePorts.toArray(new WebMessagePortCompat[0]));
|
||||
try {
|
||||
port.postMessage(webMessage);
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
postMessageForInAppWebView(index, message, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
break;
|
||||
case "close":
|
||||
if (webView != null && ports.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_CLOSE)) {
|
||||
if (webView instanceof InAppWebView) {
|
||||
Integer index = (Integer) call.argument("index");
|
||||
WebMessagePortCompat port = ports.get(index);
|
||||
try {
|
||||
port.close();
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
closeForInAppWebView(index, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
|
@ -110,6 +92,81 @@ public class WebMessageChannel implements MethodChannel.MethodCallHandler {
|
|||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
private void setWebMessageCallbackForInAppWebView(final Integer index, @NonNull MethodChannel.Result result) {
|
||||
if (webView != null && compatPorts.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK)) {
|
||||
final WebMessagePortCompat webMessagePort = compatPorts.get(index);
|
||||
try {
|
||||
webMessagePort.setWebMessageCallback(new WebMessagePortCompat.WebMessageCallbackCompat() {
|
||||
@Override
|
||||
public void onMessage(@NonNull WebMessagePortCompat port, @Nullable WebMessageCompat message) {
|
||||
super.onMessage(port, message);
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("index", index);
|
||||
obj.put("message", message != null ? message.getData() : null);
|
||||
channel.invokeMethod("onMessage", obj);
|
||||
}
|
||||
});
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void postMessageForInAppWebView(final Integer index, Map<String, Object> message, @NonNull MethodChannel.Result result) {
|
||||
if (webView != null && compatPorts.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE)) {
|
||||
WebMessagePortCompat port = compatPorts.get(index);
|
||||
List<WebMessagePortCompat> webMessagePorts = new ArrayList<>();
|
||||
List<Map<String, Object>> portsMap = (List<Map<String, Object>>) message.get("ports");
|
||||
if (portsMap != null) {
|
||||
for (Map<String, Object> portMap : portsMap) {
|
||||
String webMessageChannelId = (String) portMap.get("webMessageChannelId");
|
||||
Integer portIndex = (Integer) portMap.get("index");
|
||||
WebMessageChannel webMessageChannel = webView.getWebMessageChannels().get(webMessageChannelId);
|
||||
if (webMessageChannel != null) {
|
||||
webMessagePorts.add(webMessageChannel.compatPorts.get(portIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
WebMessageCompat webMessage = new WebMessageCompat((String) message.get("data"), webMessagePorts.toArray(new WebMessagePortCompat[0]));
|
||||
try {
|
||||
port.postMessage(webMessage);
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void closeForInAppWebView(Integer index, @NonNull MethodChannel.Result result) {
|
||||
if (webView != null && compatPorts.size() > 0 &&
|
||||
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_CLOSE)) {
|
||||
WebMessagePortCompat port = compatPorts.get(index);
|
||||
try {
|
||||
port.close();
|
||||
result.success(true);
|
||||
} catch (Exception e) {
|
||||
result.error(LOG_TAG, e.getMessage(), null);
|
||||
}
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onMessage(Integer index, String message) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("index", index);
|
||||
obj.put("message", message );
|
||||
channel.invokeMethod("onMessage", obj);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> webMessageChannelMap = new HashMap<>();
|
||||
|
@ -119,14 +176,14 @@ public class WebMessageChannel implements MethodChannel.MethodCallHandler {
|
|||
|
||||
public void dispose() {
|
||||
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_PORT_CLOSE)) {
|
||||
for (WebMessagePortCompat port : ports) {
|
||||
for (WebMessagePortCompat port : compatPorts) {
|
||||
try {
|
||||
port.close();
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
this.channel.setMethodCallHandler(null);
|
||||
this.ports.clear();
|
||||
this.compatPorts.clear();
|
||||
this.webView = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -10,6 +12,11 @@ import androidx.webkit.WebMessageCompat;
|
|||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_webview.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -28,27 +35,63 @@ public class WebMessageListener implements MethodChannel.MethodCallHandler {
|
|||
public WebViewCompat.WebMessageListener listener;
|
||||
public JavaScriptReplyProxy replyProxy;
|
||||
public MethodChannel channel;
|
||||
public InAppWebViewInterface webView;
|
||||
|
||||
public WebMessageListener(@NonNull BinaryMessenger messenger, @NonNull String jsObjectName, @NonNull Set<String> allowedOriginRules) {
|
||||
public WebMessageListener(@NonNull InAppWebViewInterface webView, @NonNull BinaryMessenger messenger, @NonNull String jsObjectName, @NonNull Set<String> allowedOriginRules) {
|
||||
this.webView = webView;
|
||||
this.jsObjectName = jsObjectName;
|
||||
this.allowedOriginRules = allowedOriginRules;
|
||||
this.channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_web_message_listener_" + this.jsObjectName);
|
||||
this.channel.setMethodCallHandler(this);
|
||||
this.listener = new WebViewCompat.WebMessageListener() {
|
||||
@Override
|
||||
public void onPostMessage(@NonNull WebView view, @NonNull WebMessageCompat message, @NonNull Uri sourceOrigin, boolean isMainFrame, @NonNull JavaScriptReplyProxy javaScriptReplyProxy) {
|
||||
replyProxy = javaScriptReplyProxy;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("message", message.getData());
|
||||
obj.put("sourceOrigin", sourceOrigin.toString().equals("null") ? null : sourceOrigin.toString());
|
||||
obj.put("isMainFrame", isMainFrame);
|
||||
channel.invokeMethod("onPostMessage", obj);
|
||||
if (this.webView instanceof InAppWebView) {
|
||||
final WebMessageListener self = this;
|
||||
this.listener = new WebViewCompat.WebMessageListener() {
|
||||
@Override
|
||||
public void onPostMessage(@NonNull WebView view, @NonNull WebMessageCompat message, @NonNull Uri sourceOrigin, boolean isMainFrame, @NonNull JavaScriptReplyProxy javaScriptReplyProxy) {
|
||||
replyProxy = javaScriptReplyProxy;
|
||||
self.onPostMessage(message.getData(), sourceOrigin, isMainFrame);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void initJsInstance() {
|
||||
if (webView != null) {
|
||||
String jsObjectNameEscaped = Util.replaceAll(jsObjectName, "\'", "\\'");
|
||||
List<String> allowedOriginRulesStringList = new ArrayList<>();
|
||||
for (String allowedOriginRule : allowedOriginRules) {
|
||||
if ("*".equals(allowedOriginRule)) {
|
||||
allowedOriginRulesStringList.add("'*'");
|
||||
} else {
|
||||
Uri rule = Uri.parse(allowedOriginRule);
|
||||
String host = rule.getHost() != null ? "'" + Util.replaceAll(rule.getHost(), "\'", "\\'") + "'" : "null";
|
||||
allowedOriginRulesStringList.add("{scheme: '" + rule.getScheme() + "', host: " + host + ", port: " + (rule.getPort() != -1 ? rule.getPort() : "null") + "}");
|
||||
}
|
||||
}
|
||||
};
|
||||
String allowedOriginRulesString = TextUtils.join(", ", allowedOriginRulesStringList);
|
||||
|
||||
String source = "(function() {" +
|
||||
" var allowedOriginRules = [" + allowedOriginRulesString + "];" +
|
||||
" var isPageBlank = window.location.href === 'about:blank';" +
|
||||
" var scheme = !isPageBlank ? window.location.protocol.replace(':', '') : null;" +
|
||||
" var host = !isPageBlank ? window.location.hostname : null;" +
|
||||
" var port = !isPageBlank ? window.location.port : null;" +
|
||||
" if (window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "._isOriginAllowed(allowedOriginRules, scheme, host, port)) {" +
|
||||
" window['" + jsObjectNameEscaped + "'] = new FlutterInAppWebViewWebMessageListener('" + jsObjectNameEscaped + "');" +
|
||||
" }" +
|
||||
"})();";
|
||||
webView.getUserContentController().addPluginScript(new PluginScript(
|
||||
"WebMessageListener-" + jsObjectName,
|
||||
source,
|
||||
UserScriptInjectionTime.AT_DOCUMENT_START,
|
||||
null,
|
||||
false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static WebMessageListener fromMap(@NonNull BinaryMessenger messenger, @Nullable Map<String, Object> map) {
|
||||
public static WebMessageListener fromMap(@NonNull InAppWebViewInterface webView, @NonNull BinaryMessenger messenger, @Nullable Map<String, Object> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -57,27 +100,137 @@ public class WebMessageListener implements MethodChannel.MethodCallHandler {
|
|||
List<String> allowedOriginRuleList = (List<String>) map.get("allowedOriginRules");
|
||||
assert allowedOriginRuleList != null;
|
||||
Set<String> allowedOriginRules = new HashSet<>(allowedOriginRuleList);
|
||||
return new WebMessageListener(messenger, jsObjectName, allowedOriginRules);
|
||||
return new WebMessageListener(webView, messenger, jsObjectName, allowedOriginRules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "postMessage":
|
||||
if (replyProxy != null && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
|
||||
if (webView instanceof InAppWebView) {
|
||||
String message = (String) call.argument("message");
|
||||
replyProxy.postMessage(message);
|
||||
postMessageForInAppWebView(message, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
public void assertOriginRulesValid() throws Exception {
|
||||
int index = 0;
|
||||
for (String originRule : allowedOriginRules) {
|
||||
if (originRule == null) {
|
||||
throw new Exception("allowedOriginRules[" + index + "] is null");
|
||||
}
|
||||
if (originRule.isEmpty()) {
|
||||
throw new Exception("allowedOriginRules[" + index + "] is empty");
|
||||
}
|
||||
if ("*".equals(originRule)) {
|
||||
continue;
|
||||
}
|
||||
Uri url = Uri.parse(originRule);
|
||||
String scheme = url.getScheme();
|
||||
String host = url.getHost();
|
||||
String path = url.getPath();
|
||||
int port = url.getPort();
|
||||
if (scheme == null) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if (("http".equals(scheme) || "https".equals(scheme)) && (host == null || host.isEmpty())) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if (!"http".equals(scheme) && !"https".equals(scheme) && (host != null || port != -1)) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if ((host == null || host.isEmpty()) && port != -1) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if (!path.isEmpty()) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if (host != null) {
|
||||
int distance = host.indexOf("*");
|
||||
if (distance != 0 || (distance == 0 && !host.startsWith("*."))) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
if (host.startsWith("[")) {
|
||||
if (!host.endsWith("]")) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
String ipv6 = host.substring(1, host.length() - 1);
|
||||
if (!Util.isIPv6(ipv6)) {
|
||||
throw new Exception("allowedOriginRules " + originRule + " is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
private void postMessageForInAppWebView(String message, @NonNull MethodChannel.Result result) {
|
||||
if (replyProxy != null && WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
|
||||
replyProxy.postMessage(message);
|
||||
}
|
||||
result.success(true);
|
||||
}
|
||||
|
||||
public boolean isOriginAllowed(String scheme, String host, int port) {
|
||||
for (String allowedOriginRule : allowedOriginRules) {
|
||||
if ("*".equals(allowedOriginRule)) {
|
||||
return true;
|
||||
}
|
||||
if (scheme == null || scheme.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if ((scheme == null || scheme.isEmpty()) && (host == null || host.isEmpty()) && (port == 0 || port == -1)) {
|
||||
continue;
|
||||
}
|
||||
Uri rule = Uri.parse(allowedOriginRule);
|
||||
int rulePort = rule.getPort() == -1 || rule.getPort() == 0 ? ("https".equals(rule.getScheme()) ? 443 : 80) : rule.getPort();
|
||||
int currentPort = port == 0 || port == -1 ? ("https".equals(scheme) ? 443 : 80) : port;
|
||||
String IPv6 = null;
|
||||
if (rule.getHost() != null && rule.getHost().startsWith("[")) {
|
||||
try {
|
||||
IPv6 = Util.normalizeIPv6(rule.getHost().substring(1, rule.getHost().length() - 1));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
String hostIPv6 = null;
|
||||
try {
|
||||
hostIPv6 = Util.normalizeIPv6(host);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
boolean schemeAllowed = rule.getScheme().equals(scheme);
|
||||
|
||||
boolean hostAllowed = rule.getHost() == null ||
|
||||
rule.getHost().isEmpty() ||
|
||||
rule.getHost().equals(host) ||
|
||||
(rule.getHost().startsWith("*") && host != null && host.contains(rule.getHost().split("\\*")[1])) ||
|
||||
(hostIPv6 != null && IPv6 != null && hostIPv6.equals(IPv6));
|
||||
|
||||
boolean portAllowed = rulePort == currentPort;
|
||||
|
||||
if (schemeAllowed && hostAllowed && portAllowed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("message", message);
|
||||
obj.put("sourceOrigin", sourceOrigin.toString().equals("null") ? null : sourceOrigin.toString());
|
||||
obj.put("isMainFrame", isMainFrame);
|
||||
channel.invokeMethod("onPostMessage", obj);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
this.channel.setMethodCallHandler(null);
|
||||
this.listener = null;
|
||||
this.replyProxy = null;
|
||||
this.webView = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WebMessagePort {
|
||||
public String name;
|
||||
public WebMessageChannel webMessageChannel;
|
||||
public boolean isClosed = false;
|
||||
public boolean isTransferred = false;
|
||||
public boolean isStarted = false;
|
||||
|
||||
public WebMessagePort(String name, WebMessageChannel webMessageChannel) {
|
||||
this.name = name;
|
||||
this.webMessageChannel = webMessageChannel;
|
||||
}
|
||||
|
||||
public void setWebMessageCallback(final ValueCallback<Void> callback) throws Exception {
|
||||
if (isClosed || isTransferred) {
|
||||
throw new Exception("Port is already closed or transferred");
|
||||
}
|
||||
this.isStarted = true;
|
||||
InAppWebViewInterface webView = webMessageChannel != null && webMessageChannel.webView != null ? webMessageChannel.webView : null;
|
||||
if (webView != null) {
|
||||
int index = name.equals("port1") ? 0 : 1;
|
||||
webView.evaluateJavascript("(function() {" +
|
||||
" var webMessageChannel = " + JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'];" +
|
||||
" if (webMessageChannel != null) {" +
|
||||
" webMessageChannel." + this.name + ".onmessage = function (event) {" +
|
||||
" window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onWebMessagePortMessageReceived', {" +
|
||||
" 'webMessageChannelId': '" + webMessageChannel.id + "'," +
|
||||
" 'index': " + index + "," +
|
||||
" 'message': event.data" +
|
||||
" });" +
|
||||
" }" +
|
||||
" }" +
|
||||
"})();", null, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
if (callback != null) {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (callback != null) {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void postMessage(WebMessage message, final ValueCallback<Void> callback) throws Exception {
|
||||
if (isClosed || isTransferred) {
|
||||
throw new Exception("Port is already closed or transferred");
|
||||
}
|
||||
InAppWebViewInterface webView = webMessageChannel != null && webMessageChannel.webView != null ? webMessageChannel.webView : null;
|
||||
if (webView != null) {
|
||||
String portsString = "null";
|
||||
List<WebMessagePort> ports = message.ports;
|
||||
if (ports != null) {
|
||||
List<String> portArrayString = new ArrayList<>();
|
||||
for (WebMessagePort port : ports) {
|
||||
if (port == this) {
|
||||
throw new Exception("Source port cannot be transferred");
|
||||
}
|
||||
if (port.isStarted) {
|
||||
throw new Exception("Port is already started");
|
||||
}
|
||||
if (port.isClosed || port.isTransferred) {
|
||||
throw new Exception("Port is already closed or transferred");
|
||||
}
|
||||
port.isTransferred = true;
|
||||
portArrayString.add(JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "']." + port.name);
|
||||
}
|
||||
portsString = "[" + TextUtils.join(", ", portArrayString) + "]";
|
||||
}
|
||||
String data = message.data != null ? Util.replaceAll(message.data, "\'", "\\'") : "null";
|
||||
String source = "(function() {" +
|
||||
" var webMessageChannel = " + JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'];" +
|
||||
" if (webMessageChannel != null) {" +
|
||||
" webMessageChannel." + this.name + ".postMessage('" + data + "', " + portsString + ");" +
|
||||
" }" +
|
||||
"})();";
|
||||
webView.evaluateJavascript(source, null, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
message.dispose();
|
||||
}
|
||||
|
||||
public void close(final ValueCallback<Void> callback) throws Exception {
|
||||
if (isTransferred) {
|
||||
throw new Exception("Port is already transferred");
|
||||
}
|
||||
isClosed = true;
|
||||
InAppWebViewInterface webView = webMessageChannel != null && webMessageChannel.webView != null ? webMessageChannel.webView : null;
|
||||
if (webView != null) {
|
||||
String source = "(function() {" +
|
||||
" var webMessageChannel = " + JavaScriptBridgeJS.WEB_MESSAGE_CHANNELS_VARIABLE_NAME + "['" + webMessageChannel.id + "'];" +
|
||||
" if (webMessageChannel != null) {" +
|
||||
" webMessageChannel." + this.name + ".close();" +
|
||||
" }" +
|
||||
"})();";
|
||||
webView.evaluateJavascript(source, null, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback.onReceiveValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
isClosed = true;
|
||||
webMessageChannel = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
public enum WebViewImplementation {
|
||||
NATIVE(0);
|
||||
|
||||
private final int value;
|
||||
|
||||
private WebViewImplementation(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean equalsValue(int otherValue) {
|
||||
return value == otherValue;
|
||||
}
|
||||
|
||||
public static WebViewImplementation fromValue(int value) {
|
||||
for( WebViewImplementation type : WebViewImplementation.values()) {
|
||||
if(value == type.value)
|
||||
return type;
|
||||
}
|
||||
throw new IllegalArgumentException("No enum constant: " + value);
|
||||
}
|
||||
|
||||
public int rawValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(this.value);
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-04-07 18:05:10.935076","version":"2.1.0-10.0.pre"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2022-04-17 17:18:13.163601","version":"2.10.4"}
|
|
@ -27,7 +27,6 @@
|
|||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application
|
||||
android:name="io.flutter.app.FlutterApplication"
|
||||
android:label="flutter_inappwebview_example"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
|
@ -36,22 +35,22 @@
|
|||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:launchMode="singleTop"
|
||||
android:name=".EmbedderV1Activity"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
until Flutter renders its first frame. It can be removed if
|
||||
there is no splash screen (such as the default splash screen
|
||||
defined in @style/LaunchTheme). -->
|
||||
<meta-data
|
||||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||
android:value="true"/>
|
||||
</activity>
|
||||
<!-- <activity-->
|
||||
<!-- android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"-->
|
||||
<!-- android:exported="true"-->
|
||||
<!-- android:hardwareAccelerated="true"-->
|
||||
<!-- android:launchMode="singleTop"-->
|
||||
<!-- android:name=".EmbedderV1Activity"-->
|
||||
<!-- android:theme="@style/LaunchTheme"-->
|
||||
<!-- android:windowSoftInputMode="adjustResize">-->
|
||||
<!-- <!– This keeps the window background of the activity showing-->
|
||||
<!-- until Flutter renders its first frame. It can be removed if-->
|
||||
<!-- there is no splash screen (such as the default splash screen-->
|
||||
<!-- defined in @style/LaunchTheme). –>-->
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"-->
|
||||
<!-- android:value="true"/>-->
|
||||
<!-- </activity>-->
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:hardwareAccelerated="true"
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.2'
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Sat Sep 26 11:13:08 CEST 2020
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
|
|
|
@ -2705,7 +2705,7 @@ void main() {
|
|||
expect(numberOfMatches, 2);
|
||||
});
|
||||
|
||||
testWidgets('onDownloadStart', (WidgetTester tester) async {
|
||||
testWidgets('onDownloadStartRequest', (WidgetTester tester) async {
|
||||
final Completer controllerCompleter = Completer<InAppWebViewController>();
|
||||
final Completer<String> onDownloadStartCompleter = Completer<String>();
|
||||
await tester.pumpWidget(
|
||||
|
@ -2739,8 +2739,8 @@ void main() {
|
|||
onWebViewCreated: (controller) {
|
||||
controllerCompleter.complete(controller);
|
||||
},
|
||||
onDownloadStart: (controller, url) {
|
||||
onDownloadStartCompleter.complete(url.toString());
|
||||
onDownloadStartRequest: (controller, request) {
|
||||
onDownloadStartCompleter.complete(request.url.toString());
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
<string>9.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
|||
s.license = { :type => 'MIT' }
|
||||
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
|
||||
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.ios.deployment_target = '9.0'
|
||||
# Framework linking is handled by Flutter tooling, not CocoaPods.
|
||||
# Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs.
|
||||
s.vendored_frameworks = 'path/to/nothing'
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#!/bin/sh
|
||||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre"
|
||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.10.4"
|
||||
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
||||
export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart"
|
||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
|
||||
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 50;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
|
@ -170,7 +170,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1240;
|
||||
LastUpgradeCheck = 1110;
|
||||
LastUpgradeCheck = 1300;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
|
@ -375,7 +375,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -427,7 +427,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1110"
|
||||
LastUpgradeVersion = "1300"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
|
|
@ -67,6 +67,7 @@ class _ChromeSafariBrowserExampleScreenState
|
|||
options: ChromeSafariBrowserClassOptions(
|
||||
android: AndroidChromeCustomTabsOptions(
|
||||
addDefaultShareMenuItem: false,
|
||||
singleInstance: false,
|
||||
keepAliveEnabled: true),
|
||||
ios: IOSSafariOptions(
|
||||
dismissButtonStyle:
|
||||
|
|
|
@ -24,7 +24,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
useShouldOverrideUrlLoading: true,
|
||||
mediaPlaybackRequiresUserGesture: false,
|
||||
mediaPlaybackRequiresUserGesture: false
|
||||
),
|
||||
android: AndroidInAppWebViewOptions(
|
||||
useHybridComposition: true,
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/bin/cache/dart-sdk/lib/_internal/js_runtime/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/bin/cache/dart-sdk/lib/_internal/js_runtime/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/bin/cache/dart-sdk/lib/_internal/js_runtime/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/packages/flutter_tools/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/packages/flutter_tools/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fvm/flutter_sdk/packages/flutter_tools/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
|
@ -80,6 +86,5 @@
|
|||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Flutter Plugins" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -34,3 +34,5 @@ Icon?
|
|||
.tags*
|
||||
|
||||
/Flutter/Generated.xcconfig
|
||||
/Flutter/ephemeral/
|
||||
/Flutter/flutter_export_environment.sh
|
|
@ -92,4 +92,9 @@ public class HeadlessInAppWebView : FlutterMethodCallDelegate {
|
|||
HeadlessInAppWebViewManager.webViews.removeValue(forKey: id)
|
||||
flutterWebView = nil
|
||||
}
|
||||
|
||||
deinit {
|
||||
print("HeadlessInAppWebView - dealloc")
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
var pullToRefreshControl: PullToRefreshControl?
|
||||
var webMessageChannels: [String:WebMessageChannel] = [:]
|
||||
var webMessageListeners: [WebMessageListener] = []
|
||||
var currentOriginalUrl: URL?
|
||||
|
||||
static var sslCertificatesMap: [String: SslCertificate] = [:] // [URL host name : SslCertificate]
|
||||
static var credentialsProposed: [URLCredential] = []
|
||||
|
@ -26,6 +27,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
var lastScrollX: CGFloat = 0
|
||||
var lastScrollY: CGFloat = 0
|
||||
|
||||
// Used to manage pauseTimers() and resumeTimers()
|
||||
var isPausedTimers = false
|
||||
var isPausedTimersCompletionHandler: (() -> Void)?
|
||||
|
||||
|
@ -405,9 +407,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
if #available(iOS 9.0, *) {
|
||||
configuration.allowsAirPlayForMediaPlayback = options.allowsAirPlayForMediaPlayback
|
||||
configuration.allowsPictureInPictureMediaPlayback = options.allowsPictureInPictureMediaPlayback
|
||||
if !options.applicationNameForUserAgent.isEmpty {
|
||||
configuration.applicationNameForUserAgent = options.applicationNameForUserAgent
|
||||
}
|
||||
}
|
||||
|
||||
configuration.preferences.javaScriptCanOpenWindowsAutomatically = options.javaScriptCanOpenWindowsAutomatically
|
||||
|
@ -499,6 +498,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
} else if options.cacheEnabled {
|
||||
configuration.websiteDataStore = WKWebsiteDataStore.default()
|
||||
}
|
||||
if !options.applicationNameForUserAgent.isEmpty {
|
||||
if let applicationNameForUserAgent = configuration.applicationNameForUserAgent {
|
||||
configuration.applicationNameForUserAgent = applicationNameForUserAgent + " " + options.applicationNameForUserAgent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
|
@ -527,7 +531,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
// Set Cookies in iOS 11 and above, initialize websiteDataStore before setting cookies
|
||||
// See also https://forums.developer.apple.com/thread/97194
|
||||
// check if websiteDataStore has not been initialized before
|
||||
if(!options.incognito && options.cacheEnabled) {
|
||||
if(!options.incognito && !options.cacheEnabled) {
|
||||
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
|
||||
}
|
||||
for cookie in HTTPCookieStorage.shared.cookies ?? [] {
|
||||
|
@ -1542,7 +1546,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
let mimeType = navigationResponse.response.mimeType
|
||||
if let url = navigationResponse.response.url, navigationResponse.isForMainFrame {
|
||||
if url.scheme != "file", mimeType != nil, !mimeType!.starts(with: "text/") {
|
||||
onDownloadStart(url: url.absoluteString)
|
||||
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
|
||||
userAgent: nil,
|
||||
contentDisposition: nil,
|
||||
mimeType: mimeType,
|
||||
contentLength: navigationResponse.response.expectedContentLength,
|
||||
suggestedFilename: navigationResponse.response.suggestedFilename,
|
||||
textEncodingName: navigationResponse.response.textEncodingName)
|
||||
onDownloadStartRequest(request: downloadStartRequest)
|
||||
if useOnNavigationResponse == nil || !useOnNavigationResponse! {
|
||||
decisionHandler(.cancel)
|
||||
}
|
||||
|
@ -1557,6 +1568,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
|
||||
public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||||
currentOriginalUrl = url
|
||||
lastTouchPoint = nil
|
||||
|
||||
disposeWebMessageChannels()
|
||||
initializeWindowIdJS()
|
||||
|
||||
|
@ -2356,9 +2370,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
channel?.invokeMethod("onOverScrolled", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onDownloadStart(url: String) {
|
||||
let arguments: [String: Any] = ["url": url]
|
||||
channel?.invokeMethod("onDownloadStart", arguments: arguments)
|
||||
public func onDownloadStartRequest(request: DownloadStartRequest) {
|
||||
channel?.invokeMethod("onDownloadStartRequest", arguments: request.toMap())
|
||||
}
|
||||
|
||||
public func onLoadResourceCustomScheme(url: String, result: FlutterResult?) {
|
||||
|
@ -2723,6 +2736,10 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
|||
scrollView.setZoomScale(currentZoomScale * CGFloat(zoomFactor), animated: animated)
|
||||
}
|
||||
|
||||
public func getOriginalUrl() -> URL? {
|
||||
return currentOriginalUrl
|
||||
}
|
||||
|
||||
public func getZoomScale() -> Float {
|
||||
return Float(scrollView.zoomScale)
|
||||
}
|
||||
|
@ -2883,10 +2900,7 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
|||
}
|
||||
|
||||
public func dispose() {
|
||||
if isPausedTimers, let completionHandler = isPausedTimersCompletionHandler {
|
||||
isPausedTimersCompletionHandler = nil
|
||||
completionHandler()
|
||||
}
|
||||
resumeTimers()
|
||||
stopLoading()
|
||||
disposeWebMessageChannels()
|
||||
for webMessageListener in webMessageListeners {
|
||||
|
|
|
@ -289,8 +289,8 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
|
|||
result(webView?.getContentHeight())
|
||||
break
|
||||
case "zoomBy":
|
||||
let zoomFactor = arguments!["zoomFactor"] as! Float
|
||||
let animated = arguments!["iosAnimated"] as! Bool
|
||||
let zoomFactor = (arguments!["zoomFactor"] as! NSNumber).floatValue
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
webView?.zoomBy(zoomFactor: zoomFactor, animated: animated)
|
||||
result(true)
|
||||
break
|
||||
|
@ -298,6 +298,9 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
|
|||
webView?.reloadFromOrigin()
|
||||
result(true)
|
||||
break
|
||||
case "getOriginalUrl":
|
||||
result(webView?.getOriginalUrl()?.absoluteString)
|
||||
break
|
||||
case "getZoomScale":
|
||||
result(webView?.getZoomScale())
|
||||
break
|
||||
|
|
|
@ -16,7 +16,7 @@ public class Options<T>: NSObject {
|
|||
|
||||
func parse(options: [String: Any?]) -> Options {
|
||||
for (key, value) in options {
|
||||
if value != nil, !(value is NSNull), self.responds(to: Selector(key)) {
|
||||
if !(value is NSNull), value != nil, self.responds(to: Selector(key)) {
|
||||
self.setValue(value, forKey: key)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched = null;
|
|||
if (target.tagName === 'IMG') {
|
||||
var img = target;
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched = {
|
||||
src: img.src
|
||||
url: img.src
|
||||
};
|
||||
var parent = img.parentNode;
|
||||
while (parent) {
|
||||
|
@ -47,7 +47,7 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched = null;
|
|||
var images = link.getElementsByTagName('img');
|
||||
var img = (images.length > 0) ? images[0] : null;
|
||||
var imgSrc = (img != null) ? img.src : null;
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched = (img != null) ? {src: img.src} : window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched;
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched = (img != null) ? {url: imgSrc} : window.\(JAVASCRIPT_BRIDGE_NAME)._lastImageTouched;
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME)._lastAnchorOrImageTouched = {
|
||||
title: link.textContent,
|
||||
url: link.href,
|
||||
|
|
|
@ -36,7 +36,7 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._normalizeIPv6 = function(ip_string) {
|
|||
// replace ipv4 address if any
|
||||
var ipv4 = ip_string.match(/(.*:)([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$)/);
|
||||
if (ipv4) {
|
||||
var ip_string = ipv4[1];
|
||||
ip_string = ipv4[1];
|
||||
ipv4 = ipv4[2].match(/[0-9]+/g);
|
||||
for (var i = 0;i < 4;i ++) {
|
||||
var byte = parseInt(ipv4[i],10);
|
||||
|
@ -85,12 +85,12 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._isOriginAllowed = function(allowedOriginRules,
|
|||
var IPv6 = null;
|
||||
if (rule.host != null && rule.host[0] === "[") {
|
||||
try {
|
||||
IPv6 = normalizeIPv6(rule.host.substring(1, rule.host.length - 1));
|
||||
IPv6 = window.\(JAVASCRIPT_BRIDGE_NAME)._normalizeIPv6(rule.host.substring(1, rule.host.length - 1));
|
||||
} catch {}
|
||||
}
|
||||
var hostIPv6 = null;
|
||||
try {
|
||||
hostIPv6 = normalizeIPv6(host);
|
||||
hostIPv6 = window.\(JAVASCRIPT_BRIDGE_NAME)._normalizeIPv6(host);
|
||||
} catch {}
|
||||
|
||||
var schemeAllowed = scheme == rule.scheme;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// DownloadStartRequest.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 17/04/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class DownloadStartRequest: NSObject {
|
||||
var url: String
|
||||
var userAgent: String?
|
||||
var contentDisposition: String?
|
||||
var mimeType: String?
|
||||
var contentLength: Int64
|
||||
var suggestedFilename: String?
|
||||
var textEncodingName: String?
|
||||
|
||||
public init(url: String, userAgent: String?, contentDisposition: String?,
|
||||
mimeType: String?, contentLength: Int64,
|
||||
suggestedFilename: String?, textEncodingName: String?) {
|
||||
self.url = url
|
||||
self.userAgent = userAgent
|
||||
self.contentDisposition = contentDisposition
|
||||
self.mimeType = mimeType
|
||||
self.contentLength = contentLength
|
||||
self.suggestedFilename = suggestedFilename
|
||||
self.textEncodingName = textEncodingName
|
||||
}
|
||||
|
||||
public func toMap () -> [String:Any?] {
|
||||
return [
|
||||
"url": url,
|
||||
"userAgent": userAgent,
|
||||
"contentDisposition": contentDisposition,
|
||||
"mimeType": mimeType,
|
||||
"contentLength": contentLength,
|
||||
"suggestedFilename": suggestedFilename,
|
||||
"textEncodingName": textEncodingName
|
||||
]
|
||||
}
|
||||
}
|
|
@ -63,6 +63,7 @@ extension URLRequest {
|
|||
"url": url?.absoluteString,
|
||||
"method": httpMethod,
|
||||
"headers": allHTTPHeaderFields,
|
||||
"body": httpBody.map(FlutterStandardTypedData.init(bytes:)),
|
||||
"iosAllowsCellularAccess": allowsCellularAccess,
|
||||
"iosAllowsConstrainedNetworkAccess": iosAllowsConstrainedNetworkAccess,
|
||||
"iosAllowsExpensiveNetworkAccess": iosAllowsExpensiveNetworkAccess,
|
||||
|
|
|
@ -83,8 +83,9 @@ public class WebMessageListener : FlutterMethodCallDelegate {
|
|||
return "'*'"
|
||||
}
|
||||
let rule = URL(string: allowedOriginRule)!
|
||||
let host = rule.host != nil ? "'" + rule.host!.replacingOccurrences(of: "\'", with: "\\'") + "'" : "null"
|
||||
return """
|
||||
{scheme: '\(rule.scheme!)', host: '\(rule.host?.replacingOccurrences(of: "\'", with: "\\'") ?? "null")', port: \(rule.port != nil ? String(rule.port!) : "null")}
|
||||
{scheme: '\(rule.scheme!)', host: \(host), port: \(rule.port != nil ? String(rule.port!) : "null")}
|
||||
"""
|
||||
}.joined(separator: ", ")
|
||||
let source = """
|
||||
|
|
|
@ -35,6 +35,12 @@ class AndroidChromeCustomTabsOptions
|
|||
///Set to `true` to enable Keep Alive. The default value is `false`.
|
||||
bool keepAliveEnabled;
|
||||
|
||||
///Set to `true` to launch the Android activity in `singleInstance` mode. The default value is `false`.
|
||||
bool singleInstance;
|
||||
|
||||
///Set to `true` to launch the Android intent with the flag `FLAG_ACTIVITY_NO_HISTORY`. The default value is `false`.
|
||||
bool noHistory;
|
||||
|
||||
AndroidChromeCustomTabsOptions(
|
||||
{this.addDefaultShareMenuItem = true,
|
||||
this.showTitle = true,
|
||||
|
@ -42,7 +48,9 @@ class AndroidChromeCustomTabsOptions
|
|||
this.enableUrlBarHiding = false,
|
||||
this.instantAppsEnabled = false,
|
||||
this.packageName,
|
||||
this.keepAliveEnabled = false});
|
||||
this.keepAliveEnabled = false,
|
||||
this.singleInstance = false,
|
||||
this.noHistory = false});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -53,7 +61,9 @@ class AndroidChromeCustomTabsOptions
|
|||
"enableUrlBarHiding": enableUrlBarHiding,
|
||||
"instantAppsEnabled": instantAppsEnabled,
|
||||
"packageName": packageName,
|
||||
"keepAliveEnabled": keepAliveEnabled
|
||||
"keepAliveEnabled": keepAliveEnabled,
|
||||
"singleInstance": singleInstance,
|
||||
"noHistory": noHistory
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -68,6 +78,8 @@ class AndroidChromeCustomTabsOptions
|
|||
options.instantAppsEnabled = map["instantAppsEnabled"];
|
||||
options.packageName = map["packageName"];
|
||||
options.keepAliveEnabled = map["keepAliveEnabled"];
|
||||
options.singleInstance = map["singleInstance"];
|
||||
options.noHistory = map["noHistory"];
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,12 @@ class InAppBrowser {
|
|||
///The window id of a [CreateWindowAction.windowId].
|
||||
final int? windowId;
|
||||
|
||||
///Represents the WebView native implementation to be used.
|
||||
///The default value is [WebViewImplementation.NATIVE].
|
||||
final WebViewImplementation implementation;
|
||||
|
||||
///
|
||||
InAppBrowser({this.windowId, this.initialUserScripts}) {
|
||||
InAppBrowser({this.windowId, this.initialUserScripts, this.implementation = WebViewImplementation.NATIVE}) {
|
||||
id = IdGenerator.generate();
|
||||
this._channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$id');
|
||||
|
@ -109,6 +113,7 @@ class InAppBrowser {
|
|||
() => options?.toMap() ?? InAppBrowserClassOptions().toMap());
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
args.putIfAbsent('implementation', () => implementation.toValue());
|
||||
args.putIfAbsent('initialUserScripts',
|
||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||
args.putIfAbsent(
|
||||
|
@ -167,6 +172,7 @@ class InAppBrowser {
|
|||
() => options?.toMap() ?? InAppBrowserClassOptions().toMap());
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
args.putIfAbsent('implementation', () => implementation.toValue());
|
||||
args.putIfAbsent('initialUserScripts',
|
||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||
args.putIfAbsent(
|
||||
|
@ -207,6 +213,7 @@ class InAppBrowser {
|
|||
'historyUrl', () => androidHistoryUrl?.toString() ?? "about:blank");
|
||||
args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {});
|
||||
args.putIfAbsent('windowId', () => windowId);
|
||||
args.putIfAbsent('implementation', () => implementation.toValue());
|
||||
args.putIfAbsent('initialUserScripts',
|
||||
() => initialUserScripts?.map((e) => e.toMap()).toList() ?? []);
|
||||
args.putIfAbsent(
|
||||
|
@ -290,16 +297,16 @@ class InAppBrowser {
|
|||
|
||||
///Event fired when the [InAppBrowser] starts to load an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewClient.onPageStarted](https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)))
|
||||
///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview))
|
||||
void onLoadStart(Uri? url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] finishes loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewClient.onPageFinished](https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)))
|
||||
///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview))
|
||||
void onLoadStop(Uri? url) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] encounters an error loading an [url].
|
||||
|
@ -326,7 +333,9 @@ class InAppBrowser {
|
|||
|
||||
///Event fired when the current [progress] (range 0-100) of loading a page is changed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebChromeClient.onProgressChanged](https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)))
|
||||
///- iOS
|
||||
void onProgressChanged(int progress) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] webview receives a [ConsoleMessage].
|
||||
|
@ -368,16 +377,21 @@ class InAppBrowser {
|
|||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll
|
||||
void onScrollChanged(int x, int y) {}
|
||||
|
||||
///Event fired when [InAppBrowser] recognizes and starts a downloadable file.
|
||||
///Use [onDownloadStartRequest] instead
|
||||
@Deprecated('Use `onDownloadStartRequest` instead')
|
||||
void onDownloadStart(Uri url) {}
|
||||
|
||||
///Event fired when [WebView] recognizes a downloadable file.
|
||||
///To download the file, you can use the [flutter_downloader](https://pub.dev/packages/flutter_downloader) plugin.
|
||||
///
|
||||
///[url] represents the url of the file.
|
||||
///[downloadStartRequest] represents the request of the file to download.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
void onDownloadStart(Uri url) {}
|
||||
void onDownloadStartRequest(DownloadStartRequest downloadStartRequest) {}
|
||||
|
||||
///Event fired when the [InAppBrowser] webview finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
|
||||
///
|
||||
|
@ -501,7 +515,7 @@ class InAppBrowser {
|
|||
URLAuthenticationChallenge challenge) {}
|
||||
|
||||
///Event fired as find-on-page operations progress.
|
||||
///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true.
|
||||
///The listener may be notified multiple times while the operation is underway, and the [numberOfMatches] value should not be considered final unless [isDoneCounting] is true.
|
||||
///
|
||||
///[activeMatchOrdinal] represents the zero-based ordinal of the currently selected match.
|
||||
///
|
||||
|
@ -509,7 +523,9 @@ class InAppBrowser {
|
|||
///
|
||||
///[isDoneCounting] whether the find operation has actually completed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setFindListener(android.webkit.WebView.FindListener)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.FindListener.onFindResultReceived](https://developer.android.com/reference/android/webkit/WebView.FindListener#onFindResultReceived(int,%20int,%20boolean)))
|
||||
///- iOS
|
||||
void onFindResultReceived(
|
||||
int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) {}
|
||||
|
||||
|
@ -562,7 +578,9 @@ class InAppBrowser {
|
|||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
void onPrint(Uri? url) {}
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
|
|
|
@ -56,17 +56,16 @@ class InAppLocalhostServer {
|
|||
return;
|
||||
}
|
||||
|
||||
var contentType = ['text', 'html'];
|
||||
var contentType = ContentType('text', 'html', charset: 'utf-8');
|
||||
if (!request.requestedUri.path.endsWith('/') &&
|
||||
request.requestedUri.pathSegments.isNotEmpty) {
|
||||
var mimeType = MimeTypeResolver.lookup(request.requestedUri.path);
|
||||
if (mimeType != null) {
|
||||
contentType = mimeType.split('/');
|
||||
contentType = _getContentTypeFromMimeType(mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
request.response.headers.contentType =
|
||||
ContentType(contentType[0], contentType[1], charset: 'utf-8');
|
||||
request.response.headers.contentType = contentType;
|
||||
request.response.add(body);
|
||||
request.response.close();
|
||||
});
|
||||
|
@ -93,4 +92,20 @@ class InAppLocalhostServer {
|
|||
bool isRunning() {
|
||||
return this._server != null;
|
||||
}
|
||||
|
||||
ContentType _getContentTypeFromMimeType(String mimeType) {
|
||||
final contentType = mimeType.split('/');
|
||||
String? charset;
|
||||
|
||||
if (_isTextFile(mimeType)) {
|
||||
charset = 'utf-8';
|
||||
}
|
||||
|
||||
return ContentType(contentType[0], contentType[1], charset: charset);
|
||||
}
|
||||
|
||||
bool _isTextFile(String mimeType) {
|
||||
final textFile = RegExp(r'^text\/|^application\/(javascript|json)');
|
||||
return textFile.hasMatch(mimeType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,11 +59,8 @@ class AndroidInAppWebViewController {
|
|||
await _channel.invokeMethod('resume', args);
|
||||
}
|
||||
|
||||
///Gets the URL that was originally requested for the current page.
|
||||
///This is not always the same as the URL passed to [InAppWebView.onLoadStarted] because although the load for that URL has begun,
|
||||
///the current page may not have changed. Also, there may have been redirects resulting in a different URL to that originally requested.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getOriginalUrl()
|
||||
///Use [InAppWebViewController.getOriginalUrl] instead.
|
||||
@Deprecated('Use `InAppWebViewController.getOriginalUrl` instead')
|
||||
Future<Uri?> getOriginalUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
String? url = await _channel.invokeMethod('getOriginalUrl', args);
|
||||
|
@ -114,7 +111,8 @@ class AndroidInAppWebViewController {
|
|||
|
||||
///Clears the internal back/forward list.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#clearHistory()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.clearHistory](https://developer.android.com/reference/android/webkit/WebView#clearHistory())).
|
||||
Future<void> clearHistory() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('clearHistory', args);
|
||||
|
|
|
@ -53,6 +53,7 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.contextMenu,
|
||||
this.initialUserScripts,
|
||||
this.pullToRefreshController,
|
||||
this.implementation = WebViewImplementation.NATIVE,
|
||||
this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
|
@ -63,7 +64,8 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.shouldOverrideUrlLoading,
|
||||
this.onLoadResource,
|
||||
this.onScrollChanged,
|
||||
this.onDownloadStart,
|
||||
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -139,14 +141,13 @@ class HeadlessInAppWebView implements WebView {
|
|||
args.putIfAbsent(
|
||||
'params',
|
||||
() => <String, dynamic>{
|
||||
'initialUrlRequest': (this.initialUrlRequest ??
|
||||
URLRequest(url: Uri.parse("about:blank")))
|
||||
.toMap(),
|
||||
'initialUrlRequest': this.initialUrlRequest?.toMap(),
|
||||
'initialFile': this.initialFile,
|
||||
'initialData': this.initialData?.toMap(),
|
||||
'initialOptions': this.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': this.contextMenu?.toMap() ?? {},
|
||||
'windowId': this.windowId,
|
||||
'implementation': this.implementation.toValue(),
|
||||
'initialUserScripts':
|
||||
this.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
||||
'pullToRefreshOptions':
|
||||
|
@ -227,6 +228,9 @@ class HeadlessInAppWebView implements WebView {
|
|||
@override
|
||||
final PullToRefreshController? pullToRefreshController;
|
||||
|
||||
@override
|
||||
final WebViewImplementation implementation;
|
||||
|
||||
@override
|
||||
void Function(InAppWebViewController controller)?
|
||||
androidOnGeolocationPermissionsHidePrompt;
|
||||
|
@ -298,8 +302,15 @@ class HeadlessInAppWebView implements WebView {
|
|||
@override
|
||||
void Function(InAppWebViewController controller)? onWindowBlur;
|
||||
|
||||
///Use [onDownloadStartRequest] instead
|
||||
@Deprecated('Use `onDownloadStartRequest` instead')
|
||||
@override
|
||||
void Function(InAppWebViewController controller, Uri url)? onDownloadStart;
|
||||
final void Function(InAppWebViewController controller, Uri url)?
|
||||
onDownloadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
|
||||
onDownloadStartRequest;
|
||||
|
||||
@override
|
||||
void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
|
|
|
@ -41,6 +41,7 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.initialOptions,
|
||||
this.initialUserScripts,
|
||||
this.pullToRefreshController,
|
||||
this.implementation = WebViewImplementation.NATIVE,
|
||||
this.contextMenu,
|
||||
this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
|
@ -52,7 +53,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.shouldOverrideUrlLoading,
|
||||
this.onLoadResource,
|
||||
this.onScrollChanged,
|
||||
this.onDownloadStart,
|
||||
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -135,6 +137,9 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
@override
|
||||
final URLRequest? initialUrlRequest;
|
||||
|
||||
@override
|
||||
final WebViewImplementation implementation;
|
||||
|
||||
@override
|
||||
final UnmodifiableListView<UserScript>? initialUserScripts;
|
||||
|
||||
|
@ -207,10 +212,16 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
InAppWebViewController controller, Uri url, bool precomposed)?
|
||||
androidOnReceivedTouchIconUrl;
|
||||
|
||||
///Use [onDownloadStartRequest] instead
|
||||
@Deprecated('Use `onDownloadStartRequest` instead')
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uri url)?
|
||||
onDownloadStart;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
|
||||
onDownloadStartRequest;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;
|
||||
|
@ -395,14 +406,13 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||
layoutDirection: TextDirection.rtl,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrlRequest': (widget.initialUrlRequest ??
|
||||
URLRequest(url: Uri.parse("about:blank")))
|
||||
.toMap(),
|
||||
'initialUrlRequest': widget.initialUrlRequest?.toMap(),
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialOptions': widget.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {},
|
||||
'windowId': widget.windowId,
|
||||
'implementation': widget.implementation.toValue(),
|
||||
'initialUserScripts':
|
||||
widget.initialUserScripts?.map((e) => e.toMap()).toList() ??
|
||||
[],
|
||||
|
@ -423,16 +433,15 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||
onPlatformViewCreated: _onPlatformViewCreated,
|
||||
gestureRecognizers: widget.gestureRecognizers,
|
||||
layoutDirection: TextDirection.rtl,
|
||||
layoutDirection: Directionality.maybeOf(context) ?? TextDirection.rtl,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrlRequest': (widget.initialUrlRequest ??
|
||||
URLRequest(url: Uri.parse("about:blank")))
|
||||
.toMap(),
|
||||
'initialUrlRequest': widget.initialUrlRequest?.toMap(),
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialOptions': widget.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {},
|
||||
'windowId': widget.windowId,
|
||||
'implementation': widget.implementation.toValue(),
|
||||
'initialUserScripts':
|
||||
widget.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
||||
'pullToRefreshOptions':
|
||||
|
@ -448,14 +457,13 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
onPlatformViewCreated: _onPlatformViewCreated,
|
||||
gestureRecognizers: widget.gestureRecognizers,
|
||||
creationParams: <String, dynamic>{
|
||||
'initialUrlRequest': (widget.initialUrlRequest ??
|
||||
URLRequest(url: Uri.parse("about:blank")))
|
||||
.toMap(),
|
||||
'initialUrlRequest': widget.initialUrlRequest?.toMap(),
|
||||
'initialFile': widget.initialFile,
|
||||
'initialData': widget.initialData?.toMap(),
|
||||
'initialOptions': widget.initialOptions?.toMap() ?? {},
|
||||
'contextMenu': widget.contextMenu?.toMap() ?? {},
|
||||
'windowId': widget.windowId,
|
||||
'implementation': widget.implementation.toValue(),
|
||||
'initialUserScripts':
|
||||
widget.initialUserScripts?.map((e) => e.toMap()).toList() ?? [],
|
||||
'pullToRefreshOptions':
|
||||
|
|
|
@ -201,15 +201,26 @@ class InAppWebViewController {
|
|||
_inAppBrowser!.onScrollChanged(x, y);
|
||||
}
|
||||
break;
|
||||
case "onDownloadStart":
|
||||
if ((_webview != null && _webview!.onDownloadStart != null) ||
|
||||
case "onDownloadStartRequest":
|
||||
if ((_webview != null &&
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
(_webview!.onDownloadStart != null || _webview!.onDownloadStartRequest != null)) ||
|
||||
_inAppBrowser != null) {
|
||||
String url = call.arguments["url"];
|
||||
Uri uri = Uri.parse(url);
|
||||
if (_webview != null && _webview!.onDownloadStart != null)
|
||||
_webview!.onDownloadStart!(this, uri);
|
||||
else
|
||||
_inAppBrowser!.onDownloadStart(uri);
|
||||
Map<String, dynamic> arguments = call.arguments.cast<String, dynamic>();
|
||||
DownloadStartRequest downloadStartRequest = DownloadStartRequest.fromMap(arguments)!;
|
||||
|
||||
if (_webview != null) {
|
||||
if (_webview!.onDownloadStartRequest != null)
|
||||
_webview!.onDownloadStartRequest!(this, downloadStartRequest);
|
||||
else {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_webview!.onDownloadStart!(this, downloadStartRequest.url);
|
||||
}
|
||||
} else {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_inAppBrowser!.onDownloadStart(downloadStartRequest.url);
|
||||
_inAppBrowser!.onDownloadStartRequest(downloadStartRequest);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "onLoadResourceCustomScheme":
|
||||
|
@ -375,6 +386,7 @@ class InAppWebViewController {
|
|||
} else {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_inAppBrowser!.androidOnScaleChanged(oldScale, newScale);
|
||||
_inAppBrowser!.onZoomScaleChanged(oldScale, newScale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -904,9 +916,9 @@ class InAppWebViewController {
|
|||
///Gets the URL for the current page.
|
||||
///This is not always the same as the URL passed to [WebView.onLoadStart] because although the load for that URL has begun, the current page may not have changed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getUrl()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415005-url
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getUrl](https://developer.android.com/reference/android/webkit/WebView#getUrl()))
|
||||
///- iOS ([Official API - WKWebView.url](https://developer.apple.com/documentation/webkit/wkwebview/1415005-url))
|
||||
Future<Uri?> getUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
String? url = await _channel.invokeMethod('getUrl', args);
|
||||
|
@ -915,9 +927,9 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the title for the current page.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getTitle()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415015-title
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getTitle](https://developer.android.com/reference/android/webkit/WebView#getTitle()))
|
||||
///- iOS ([Official API - WKWebView.title](https://developer.apple.com/documentation/webkit/wkwebview/1415015-title))
|
||||
Future<String?> getTitle() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getTitle', args);
|
||||
|
@ -925,9 +937,9 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the progress for the current page. The progress value is between 0 and 100.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getProgress()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getProgress](https://developer.android.com/reference/android/webkit/WebView#getProgress()))
|
||||
///- iOS ([Official API - WKWebView.estimatedProgress](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress))
|
||||
Future<int?> getProgress() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getProgress', args);
|
||||
|
@ -1138,21 +1150,20 @@ class InAppWebViewController {
|
|||
|
||||
///Loads the given [urlRequest].
|
||||
///
|
||||
///[iosAllowingReadAccessTo], used in combination with [urlRequest] (using the `file://` scheme),
|
||||
///is an iOS-specific argument that represents the URL from which to read the web content.
|
||||
///- [allowingReadAccessTo], used in combination with [urlRequest] (using the `file://` scheme),
|
||||
///it represents the URL from which to read the web content.
|
||||
///This URL must be a file-based URL (using the `file://` scheme).
|
||||
///Specify the same value as the URL parameter to prevent WebView from reading any other content.
|
||||
///Specify a directory to give WebView permission to read additional files in the specified directory.
|
||||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**NOTE for Android**: when loading an URL Request using "POST" method, headers are ignored.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String)
|
||||
///
|
||||
///**Official iOS API**:
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1414954-load
|
||||
///- if [iosAllowingReadAccessTo] is used, https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.loadUrl](https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String))). If method is "POST", [Official API - WebView.postUrl](https://developer.android.com/reference/android/webkit/WebView#postUrl(java.lang.String,%20byte[]))
|
||||
///- iOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load). If [allowingReadAccessTo] is used, [Official API - WKWebView.loadFileURL](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl))
|
||||
Future<void> loadUrl(
|
||||
{required URLRequest urlRequest, Uri? iosAllowingReadAccessTo}) async {
|
||||
{required URLRequest urlRequest, @Deprecated('Use `allowingReadAccessTo` instead') Uri? iosAllowingReadAccessTo, Uri? allowingReadAccessTo}) async {
|
||||
assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty);
|
||||
assert(iosAllowingReadAccessTo == null ||
|
||||
iosAllowingReadAccessTo.isScheme("file"));
|
||||
|
@ -1160,19 +1171,21 @@ class InAppWebViewController {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('urlRequest', () => urlRequest.toMap());
|
||||
args.putIfAbsent(
|
||||
'allowingReadAccessTo', () => iosAllowingReadAccessTo?.toString());
|
||||
'allowingReadAccessTo', () => allowingReadAccessTo?.toString() ?? iosAllowingReadAccessTo?.toString());
|
||||
await _channel.invokeMethod('loadUrl', args);
|
||||
}
|
||||
|
||||
///Loads the given [url] with [postData] (x-www-form-urlencoded) using `POST` method into this WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#postUrl(java.lang.String,%20byte[])
|
||||
///
|
||||
///Example
|
||||
///```dart
|
||||
///var postData = Uint8List.fromList(utf8.encode("firstname=Foo&surname=Bar"));
|
||||
///controller.postUrl(url: Uri.parse("https://www.example.com/"), postData: postData);
|
||||
///```
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.postUrl](https://developer.android.com/reference/android/webkit/WebView#postUrl(java.lang.String,%20byte[])))
|
||||
///- iOS
|
||||
Future<void> postUrl({required Uri url, required Uint8List postData}) async {
|
||||
assert(url.toString().isNotEmpty);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1183,27 +1196,30 @@ class InAppWebViewController {
|
|||
|
||||
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
|
||||
///
|
||||
///- [mimeType] parameter specifies the format of the data. The default value is `"text/html"`.
|
||||
///- [encoding] parameter specifies the encoding of the data. The default value is `"utf8"`.
|
||||
///- [androidHistoryUrl] parameter is the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL. This parameter is used only on Android.
|
||||
///- [iosAllowingReadAccessTo], used in combination with [baseUrl] (using the `file://` scheme),
|
||||
///is an iOS-specific argument that represents the URL from which to read the web content.
|
||||
///- [mimeType] argument specifies the format of the data. The default value is `"text/html"`.
|
||||
///- [encoding] argument specifies the encoding of the data. The default value is `"utf8"`.
|
||||
///- [historyUrl] is an Android-specific argument that represents the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL.
|
||||
///- [allowingReadAccessTo], used in combination with [baseUrl] (using the `file://` scheme),
|
||||
///it represents the URL from which to read the web content.
|
||||
///This [baseUrl] must be a file-based URL (using the `file://` scheme).
|
||||
///Specify the same value as the [baseUrl] parameter to prevent WebView from reading any other content.
|
||||
///Specify a directory to give WebView permission to read additional files in the specified directory.
|
||||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**:
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1415011-load
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.loadDataWithBaseURL](https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String)))
|
||||
///- iOS ([Official API - WKWebView.loadHTMLString](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring) or [Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1415011-load))
|
||||
Future<void> loadData(
|
||||
{required String data,
|
||||
String mimeType = "text/html",
|
||||
String encoding = "utf8",
|
||||
Uri? baseUrl,
|
||||
@Deprecated('Use `historyUrl` instead')
|
||||
Uri? androidHistoryUrl,
|
||||
Uri? iosAllowingReadAccessTo}) async {
|
||||
Uri? historyUrl,
|
||||
@Deprecated('Use `allowingReadAccessTo` instead')
|
||||
Uri? iosAllowingReadAccessTo,
|
||||
Uri? allowingReadAccessTo}) async {
|
||||
assert(iosAllowingReadAccessTo == null ||
|
||||
iosAllowingReadAccessTo.isScheme("file"));
|
||||
|
||||
|
@ -1213,9 +1229,9 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('encoding', () => encoding);
|
||||
args.putIfAbsent('baseUrl', () => baseUrl?.toString() ?? "about:blank");
|
||||
args.putIfAbsent(
|
||||
'historyUrl', () => androidHistoryUrl?.toString() ?? "about:blank");
|
||||
'historyUrl', () => historyUrl?.toString() ?? androidHistoryUrl?.toString() ?? "about:blank");
|
||||
args.putIfAbsent(
|
||||
'allowingReadAccessTo', () => iosAllowingReadAccessTo?.toString());
|
||||
'allowingReadAccessTo', () => allowingReadAccessTo?.toString() ?? iosAllowingReadAccessTo?.toString());
|
||||
await _channel.invokeMethod('loadData', args);
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1264,10 @@ class InAppWebViewController {
|
|||
///controller.loadFile(assetFilePath: "assets/index.html");
|
||||
///...
|
||||
///```
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.loadUrl](https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String)))
|
||||
///- iOS ([Official API - WKWebView.load](https://developer.apple.com/documentation/webkit/wkwebview/1414954-load))
|
||||
Future<void> loadFile({required String assetFilePath}) async {
|
||||
assert(assetFilePath.isNotEmpty);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1257,9 +1277,9 @@ class InAppWebViewController {
|
|||
|
||||
///Reloads the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#reload()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414969-reload
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.reload](https://developer.android.com/reference/android/webkit/WebView#reload()))
|
||||
///- iOS ([Official API - WKWebView.reload](https://developer.apple.com/documentation/webkit/wkwebview/1414969-reload))
|
||||
Future<void> reload() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('reload', args);
|
||||
|
@ -1267,9 +1287,9 @@ class InAppWebViewController {
|
|||
|
||||
///Goes back in the history of the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goBack()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goBack](https://developer.android.com/reference/android/webkit/WebView#goBack()))
|
||||
///- iOS ([Official API - WKWebView.goBack](https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback))
|
||||
Future<void> goBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('goBack', args);
|
||||
|
@ -1277,9 +1297,9 @@ class InAppWebViewController {
|
|||
|
||||
///Returns a boolean value indicating whether the WebView can move backward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#canGoBack()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.canGoBack](https://developer.android.com/reference/android/webkit/WebView#canGoBack()))
|
||||
///- iOS ([Official API - WKWebView.canGoBack](https://developer.apple.com/documentation/webkit/wkwebview/1414966-cangoback))
|
||||
Future<bool> canGoBack() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('canGoBack', args);
|
||||
|
@ -1287,9 +1307,9 @@ class InAppWebViewController {
|
|||
|
||||
///Goes forward in the history of the WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goForward()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goForward](https://developer.android.com/reference/android/webkit/WebView#goForward()))
|
||||
///- iOS ([Official API - WKWebView.goForward](https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward))
|
||||
Future<void> goForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('goForward', args);
|
||||
|
@ -1297,9 +1317,9 @@ class InAppWebViewController {
|
|||
|
||||
///Returns a boolean value indicating whether the WebView can move forward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#canGoForward()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.canGoForward](https://developer.android.com/reference/android/webkit/WebView#canGoForward()))
|
||||
///- iOS ([Official API - WKWebView.canGoForward](https://developer.apple.com/documentation/webkit/wkwebview/1414962-cangoforward))
|
||||
Future<bool> canGoForward() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('canGoForward', args);
|
||||
|
@ -1307,9 +1327,9 @@ class InAppWebViewController {
|
|||
|
||||
///Goes to the history item that is the number of steps away from the current item. Steps is negative if backward and positive if forward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#goBackOrForward(int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414991-go
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goBackOrForward](https://developer.android.com/reference/android/webkit/WebView#goBackOrForward(int)))
|
||||
///- iOS ([Official API - WKWebView.go](https://developer.apple.com/documentation/webkit/wkwebview/1414991-go))
|
||||
Future<void> goBackOrForward({required int steps}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('steps', () => steps);
|
||||
|
@ -1318,7 +1338,9 @@ class InAppWebViewController {
|
|||
|
||||
///Returns a boolean value indicating whether the WebView can go back or forward the given number of steps. Steps is negative if backward and positive if forward.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#canGoBackOrForward(int)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.canGoBackOrForward](https://developer.android.com/reference/android/webkit/WebView#canGoBackOrForward(int)))
|
||||
///- iOS
|
||||
Future<bool> canGoBackOrForward({required int steps}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('steps', () => steps);
|
||||
|
@ -1326,13 +1348,22 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
///Navigates to a [WebHistoryItem] from the back-forward [WebHistory.list] and sets it as the current item.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> goTo({required WebHistoryItem historyItem}) async {
|
||||
if (historyItem.offset != null) {
|
||||
await goBackOrForward(steps: historyItem.offset!);
|
||||
var steps = historyItem.offset;
|
||||
if (steps != null) {
|
||||
await goBackOrForward(steps: steps);
|
||||
}
|
||||
}
|
||||
|
||||
///Check if the WebView instance is in a loading state.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<bool> isLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('isLoading', args);
|
||||
|
@ -1340,9 +1371,9 @@ class InAppWebViewController {
|
|||
|
||||
///Stops the WebView from loading.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#stopLoading()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.stopLoading](https://developer.android.com/reference/android/webkit/WebView#stopLoading()))
|
||||
///- iOS ([Official API - WKWebView.stopLoading](https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading))
|
||||
Future<void> stopLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('stopLoading', args);
|
||||
|
@ -1362,19 +1393,22 @@ class InAppWebViewController {
|
|||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
|
||||
///
|
||||
///**Official iOS API**:
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript
|
||||
///- https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.evaluateJavascript](https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)))
|
||||
///- iOS ([Official API - WKWebView.evaluateJavascript](https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript))
|
||||
Future<dynamic> evaluateJavascript(
|
||||
{required String source, ContentWorld? contentWorld}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('source', () => source);
|
||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
||||
if (data != null && defaultTargetPlatform == TargetPlatform.android)
|
||||
data = json.decode(data);
|
||||
if (data != null && defaultTargetPlatform == TargetPlatform.android) {
|
||||
try {
|
||||
// try to json decode the data coming from JavaScript
|
||||
// otherwise return it as it is.
|
||||
data = json.decode(data);
|
||||
} catch (e) {}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1386,6 +1420,10 @@ class InAppWebViewController {
|
|||
///because, in these events, the [WebView] is not ready to handle it yet.
|
||||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> injectJavascriptFileFromUrl(
|
||||
{required Uri urlFile,
|
||||
ScriptHtmlTagAttributes? scriptHtmlTagAttributes}) async {
|
||||
|
@ -1407,6 +1445,10 @@ class InAppWebViewController {
|
|||
///because, in these events, the [WebView] is not ready to handle it yet.
|
||||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<dynamic> injectJavascriptFileFromAsset(
|
||||
{required String assetFilePath}) async {
|
||||
String source = await rootBundle.loadString(assetFilePath);
|
||||
|
@ -1419,6 +1461,10 @@ class InAppWebViewController {
|
|||
///because, in these events, the [WebView] is not ready to handle it yet.
|
||||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> injectCSSCode({required String source}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('source', () => source);
|
||||
|
@ -1433,6 +1479,10 @@ class InAppWebViewController {
|
|||
///because, in these events, the [WebView] is not ready to handle it yet.
|
||||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> injectCSSFileFromUrl(
|
||||
{required Uri urlFile,
|
||||
CSSLinkHtmlTagAttributes? cssLinkHtmlTagAttributes}) async {
|
||||
|
@ -1450,6 +1500,10 @@ class InAppWebViewController {
|
|||
///because, in these events, the [WebView] is not ready to handle it yet.
|
||||
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
|
||||
///where you know the page is ready "enough".
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> injectCSSFileFromAsset({required String assetFilePath}) async {
|
||||
String source = await rootBundle.loadString(assetFilePath);
|
||||
await injectCSSCode(source: source);
|
||||
|
@ -1505,6 +1559,10 @@ class InAppWebViewController {
|
|||
///**NOTE**: This method should be called, for example, in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events or, at least,
|
||||
///before you know that your JavaScript code will call the `window.flutter_inappwebview.callHandler` method,
|
||||
///otherwise you won't be able to intercept the JavaScript message.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
void addJavaScriptHandler(
|
||||
{required String handlerName,
|
||||
required JavaScriptHandlerCallback callback}) {
|
||||
|
@ -1516,6 +1574,10 @@ class InAppWebViewController {
|
|||
///Removes a JavaScript message handler previously added with the [addJavaScriptHandler()] associated to [handlerName] key.
|
||||
///Returns the value associated with [handlerName] before it was removed.
|
||||
///Returns `null` if [handlerName] was not found.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
JavaScriptHandlerCallback? removeJavaScriptHandler(
|
||||
{required String handlerName}) {
|
||||
return this.javaScriptHandlersMap.remove(handlerName);
|
||||
|
@ -1527,7 +1589,9 @@ class InAppWebViewController {
|
|||
///
|
||||
///**NOTE for iOS**: available on iOS 11.0+.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/2873260-takesnapshot
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS ([Official API - WKWebView.takeSnapshot](https://developer.apple.com/documentation/webkit/wkwebview/2873260-takesnapshot))
|
||||
Future<Uint8List?> takeScreenshot(
|
||||
{ScreenshotConfiguration? screenshotConfiguration}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1537,6 +1601,10 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
///Sets the WebView options with the new [options] and evaluates them.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> setOptions({required InAppWebViewGroupOptions options}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
|
@ -1545,6 +1613,10 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
///Gets the current WebView options. Returns `null` if it wasn't able to get them.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<InAppWebViewGroupOptions?> getOptions() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
|
@ -1563,9 +1635,9 @@ class InAppWebViewController {
|
|||
///Multiple calls to this method may return different objects.
|
||||
///The object returned from this method will not be updated to reflect any new state.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#copyBackForwardList()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414977-backforwardlist
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.copyBackForwardList](https://developer.android.com/reference/android/webkit/WebView#copyBackForwardList()))
|
||||
///- iOS ([Official API - WKWebView.backForwardList](https://developer.apple.com/documentation/webkit/wkwebview/1414977-backforwardlist))
|
||||
Future<WebHistory?> getCopyBackForwardList() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? result =
|
||||
|
@ -1574,7 +1646,11 @@ class InAppWebViewController {
|
|||
return WebHistory.fromMap(result);
|
||||
}
|
||||
|
||||
///Clears all the webview's cache.
|
||||
///Clears all the WebView's cache.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> clearCache() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('clearCache', args);
|
||||
|
@ -1584,24 +1660,28 @@ class InAppWebViewController {
|
|||
///
|
||||
///[find] represents the string to find.
|
||||
///
|
||||
///**NOTE**: on Android, it finds all instances asynchronously. Successive calls to this will cancel any pending searches.
|
||||
///**NOTE**: on Android native WebView, it finds all instances asynchronously. Successive calls to this will cancel any pending searches.
|
||||
///
|
||||
///**NOTE**: on iOS, this is implemented using CSS and Javascript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#findAllAsync(java.lang.String)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.findAllAsync](https://developer.android.com/reference/android/webkit/WebView#findAllAsync(java.lang.String)))
|
||||
///- iOS
|
||||
Future<void> findAllAsync({required String find}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('find', () => find);
|
||||
await _channel.invokeMethod('findAllAsync', args);
|
||||
}
|
||||
|
||||
///Highlights and scrolls to the next match found by [findAllAsync()]. Notifies [WebView.onFindResultReceived] listener.
|
||||
///Highlights and scrolls to the next match found by [findAllAsync]. Notifies [WebView.onFindResultReceived] listener.
|
||||
///
|
||||
///[forward] represents the direction to search.
|
||||
///
|
||||
///**NOTE**: on iOS, this is implemented using CSS and Javascript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#findNext(boolean)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.findNext](https://developer.android.com/reference/android/webkit/WebView#findNext(boolean)))
|
||||
///- iOS
|
||||
Future<void> findNext({required bool forward}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('forward', () => forward);
|
||||
|
@ -1612,22 +1692,32 @@ class InAppWebViewController {
|
|||
///
|
||||
///**NOTE**: on iOS, this is implemented using CSS and Javascript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#clearMatches()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.clearMatches](https://developer.android.com/reference/android/webkit/WebView#clearMatches()))
|
||||
///- iOS
|
||||
Future<void> clearMatches() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('clearMatches', args);
|
||||
}
|
||||
|
||||
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()].
|
||||
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<String> getTRexRunnerHtml() async {
|
||||
return await rootBundle
|
||||
.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.html");
|
||||
.loadString("packages/flutter_inappwebview/assets/t_rex_runner/t-rex.html");
|
||||
}
|
||||
|
||||
///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml()].
|
||||
///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<String> getTRexRunnerCss() async {
|
||||
return await rootBundle
|
||||
.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.css");
|
||||
.loadString("packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css");
|
||||
}
|
||||
|
||||
///Scrolls the WebView to the position.
|
||||
|
@ -1638,9 +1728,9 @@ class InAppWebViewController {
|
|||
///
|
||||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollTo(int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - View.scrollTo](https://developer.android.com/reference/android/view/View#scrollTo(int,%20int)))
|
||||
///- iOS ([Official API - UIScrollView.setContentOffset](https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset))
|
||||
Future<void> scrollTo(
|
||||
{required int x, required int y, bool animated = false}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1658,9 +1748,9 @@ class InAppWebViewController {
|
|||
///
|
||||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollBy(int,%20int)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - View.scrollBy](https://developer.android.com/reference/android/view/View#scrollBy(int,%20int)))
|
||||
///- iOS ([Official API - UIScrollView.setContentOffset](https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset))
|
||||
Future<void> scrollBy(
|
||||
{required int x, required int y, bool animated = false}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -1670,12 +1760,14 @@ class InAppWebViewController {
|
|||
await _channel.invokeMethod('scrollBy', args);
|
||||
}
|
||||
|
||||
///On Android, it pauses all layout, parsing, and JavaScript timers for all WebViews.
|
||||
///On Android native WebView, it pauses all layout, parsing, and JavaScript timers for all WebViews.
|
||||
///This is a global requests, not restricted to just this WebView. This can be useful if the application has been paused.
|
||||
///
|
||||
///On iOS, it is restricted to just this WebView.
|
||||
///On iOS, it is implemented using JavaScript and it is restricted to just this WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#pauseTimers()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.pauseTimers](https://developer.android.com/reference/android/webkit/WebView#pauseTimers()))
|
||||
///- iOS
|
||||
Future<void> pauseTimers() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('pauseTimers', args);
|
||||
|
@ -1683,9 +1775,11 @@ class InAppWebViewController {
|
|||
|
||||
///On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers.
|
||||
///
|
||||
///On iOS, it resumes all layout, parsing, and JavaScript timers to just this WebView.
|
||||
///On iOS, it is implemented using JavaScript and it resumes all layout, parsing, and JavaScript timers to just this WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#resumeTimers()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.resumeTimers](https://developer.android.com/reference/android/webkit/WebView#resumeTimers()))
|
||||
///- iOS
|
||||
Future<void> resumeTimers() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('resumeTimers', args);
|
||||
|
@ -1695,9 +1789,9 @@ class InAppWebViewController {
|
|||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/print/PrintManager
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintManager](https://developer.android.com/reference/android/print/PrintManager))
|
||||
///- iOS ([Official API - UIPrintInteractionController](https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller))
|
||||
Future<void> printCurrentPage() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('printCurrentPage', args);
|
||||
|
@ -1705,9 +1799,9 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the height of the HTML content.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getContentHeight()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619399-contentsize
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getContentHeight](https://developer.android.com/reference/android/webkit/WebView#getContentHeight()))
|
||||
///- iOS ([Official API - UIScrollView.contentSize](https://developer.apple.com/documentation/uikit/uiscrollview/1619399-contentsize))
|
||||
Future<int?> getContentHeight() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getContentHeight', args);
|
||||
|
@ -1717,16 +1811,16 @@ class InAppWebViewController {
|
|||
///
|
||||
///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 (excluded) to 100.0 (included).
|
||||
///
|
||||
///[iosAnimated] `true` to animate the transition to the new scale, `false` to make the transition immediate.
|
||||
///[animated] `true` to animate the transition to the new scale, `false` to make the transition immediate.
|
||||
///**NOTE**: available only on iOS.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#zoomBy(float)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619412-setzoomscale
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.zoomBy](https://developer.android.com/reference/android/webkit/WebView#zoomBy(float)))
|
||||
///- iOS ([Official API - UIScrollView.setZoomScale](https://developer.apple.com/documentation/uikit/uiscrollview/1619412-setzoomscale))
|
||||
Future<void> zoomBy(
|
||||
{required double zoomFactor, bool iosAnimated = false}) async {
|
||||
{required double zoomFactor, @Deprecated('Use `animated` instead') bool? iosAnimated, bool animated = false}) async {
|
||||
assert(defaultTargetPlatform != TargetPlatform.android ||
|
||||
(defaultTargetPlatform == TargetPlatform.android &&
|
||||
zoomFactor > 0.01 &&
|
||||
|
@ -1734,13 +1828,28 @@ class InAppWebViewController {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('zoomFactor', () => zoomFactor);
|
||||
args.putIfAbsent('iosAnimated', () => iosAnimated);
|
||||
args.putIfAbsent('animated', () => iosAnimated ?? animated);
|
||||
return await _channel.invokeMethod('zoomBy', args);
|
||||
}
|
||||
|
||||
///Gets the URL that was originally requested for the current page.
|
||||
///This is not always the same as the URL passed to [InAppWebView.onLoadStarted] because although the load for that URL has begun,
|
||||
///the current page may not have changed. Also, there may have been redirects resulting in a different URL to that originally requested.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getOriginalUrl](https://developer.android.com/reference/android/webkit/WebView#getOriginalUrl()))
|
||||
///- iOS
|
||||
Future<Uri?> getOriginalUrl() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
String? url = await _channel.invokeMethod('getOriginalUrl', args);
|
||||
return url != null ? Uri.parse(url) : null;
|
||||
}
|
||||
|
||||
///Gets the current zoom scale of the WebView.
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS ([Official API - UIScrollView.zoomScale](https://developer.apple.com/documentation/uikit/uiscrollview/1619419-zoomscale))
|
||||
Future<double?> getZoomScale() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getZoomScale', args);
|
||||
|
@ -1754,9 +1863,13 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the selected text.
|
||||
///
|
||||
///**NOTE**: This method is implemented with using JavaScript.
|
||||
///**NOTE**: this method is implemented with using JavaScript.
|
||||
///
|
||||
///**NOTE for Android**: available only on Android 19+.
|
||||
///**NOTE for Android native WebView**: available only on Android 19+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<String?> getSelectedText() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getSelectedText', args);
|
||||
|
@ -1764,9 +1877,11 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the hit result for hitting an HTML elements.
|
||||
///
|
||||
///**NOTE**: On iOS it is implemented using JavaScript.
|
||||
///**NOTE**: On iOS, it is implemented using JavaScript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getHitTestResult()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getHitTestResult](https://developer.android.com/reference/android/webkit/WebView#getHitTestResult()))
|
||||
///- iOS
|
||||
Future<InAppWebViewHitTestResult?> getHitTestResult() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? hitTestResultMap =
|
||||
|
@ -1785,11 +1900,11 @@ class InAppWebViewController {
|
|||
return InAppWebViewHitTestResult(type: type, extra: extra);
|
||||
}
|
||||
|
||||
///Clears the current focus. It will clear also, for example, the current text selection.
|
||||
///Clears the current focus. On iOS and Android native WebView, it will clear also, for example, the current text selection.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/ViewGroup#clearFocus()
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - ViewGroup.clearFocus](https://developer.android.com/reference/android/view/ViewGroup#clearFocus()))
|
||||
///- iOS ([Official API - UIResponder.resignFirstResponder](https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder))
|
||||
Future<void> clearFocus() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('clearFocus', args);
|
||||
|
@ -1805,9 +1920,11 @@ class InAppWebViewController {
|
|||
|
||||
///Requests the anchor or image element URL at the last tapped point.
|
||||
///
|
||||
///**NOTE**: On iOS it is implemented using JavaScript.
|
||||
///**NOTE**: On iOS, it is implemented using JavaScript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#requestFocusNodeHref(android.os.Message)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.requestFocusNodeHref](https://developer.android.com/reference/android/webkit/WebView#requestFocusNodeHref(android.os.Message))).
|
||||
///- iOS.
|
||||
Future<RequestFocusNodeHrefResult?> requestFocusNodeHref() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? result =
|
||||
|
@ -1823,9 +1940,11 @@ class InAppWebViewController {
|
|||
|
||||
///Requests the URL of the image last touched by the user.
|
||||
///
|
||||
///**NOTE**: On iOS it is implemented using JavaScript.
|
||||
///**NOTE**: On iOS, it is implemented using JavaScript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#requestImageRef(android.os.Message)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.requestImageRef](https://developer.android.com/reference/android/webkit/WebView#requestImageRef(android.os.Message))).
|
||||
///- iOS.
|
||||
Future<RequestImageRefResult?> requestImageRef() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<dynamic, dynamic>? result =
|
||||
|
@ -1947,7 +2066,9 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the SSL certificate for the main top-level page or null if there is no certificate (the site is not secure).
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getCertificate()
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.getCertificate](https://developer.android.com/reference/android/webkit/WebView#getCertificate())).
|
||||
///- iOS.
|
||||
Future<SslCertificate?> getCertificate() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? sslCertificateMap =
|
||||
|
@ -2155,11 +2276,13 @@ class InAppWebViewController {
|
|||
///
|
||||
///This method should be called when the page is loaded, for example, when the [WebView.onLoadStop] is fired, otherwise the [WebMessageChannel] won't work.
|
||||
///
|
||||
///**NOTE for Android**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.CREATE_WEB_MESSAGE_CHANNEL].
|
||||
///**NOTE for Android native WebView**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.CREATE_WEB_MESSAGE_CHANNEL].
|
||||
///
|
||||
///**NOTE for iOS**: This is implemented using Javascript.
|
||||
///**NOTE**: On iOS, it is implemented using JavaScript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewCompat#createWebMessageChannel(android.webkit.WebView)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewCompat.createWebMessageChannel](https://developer.android.com/reference/androidx/webkit/WebViewCompat#createWebMessageChannel(android.webkit.WebView))).
|
||||
///- iOS.
|
||||
Future<WebMessageChannel?> createWebMessageChannel() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? result =
|
||||
|
@ -2173,11 +2296,13 @@ class InAppWebViewController {
|
|||
///
|
||||
///A target origin can be set as a wildcard ("*"). However this is not recommended.
|
||||
///
|
||||
///**NOTE for Android**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.POST_WEB_MESSAGE].
|
||||
///**NOTE for Android native WebView**: This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.POST_WEB_MESSAGE].
|
||||
///
|
||||
///**NOTE for iOS**: This is implemented using Javascript.
|
||||
///**NOTE**: On iOS, it is implemented using JavaScript.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewCompat#postWebMessage(android.webkit.WebView,%20androidx.webkit.WebMessageCompat,%20android.net.Uri)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewCompat.postWebMessage](https://developer.android.com/reference/androidx/webkit/WebViewCompat#postWebMessage(android.webkit.WebView,%20androidx.webkit.WebMessageCompat,%20android.net.Uri))).
|
||||
///- iOS.
|
||||
Future<void> postWebMessage(
|
||||
{required WebMessage message, Uri? targetOrigin}) async {
|
||||
if (targetOrigin == null) {
|
||||
|
|
|
@ -22,16 +22,16 @@ abstract class WebView {
|
|||
|
||||
///Event fired when the [WebView] starts to load an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewClient.onPageStarted](https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap)))
|
||||
///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455621-webview))
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onLoadStart;
|
||||
|
||||
///Event fired when the [WebView] finishes loading an [url].
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebViewClient.onPageFinished](https://developer.android.com/reference/android/webkit/WebViewClient#onPageFinished(android.webkit.WebView,%20java.lang.String)))
|
||||
///- iOS ([Official API - WKNavigationDelegate.webView](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview))
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onLoadStop;
|
||||
|
||||
///Event fired when the [WebView] encounters an error loading an [url].
|
||||
|
@ -60,7 +60,9 @@ abstract class WebView {
|
|||
|
||||
///Event fired when the current [progress] of loading a page is changed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebChromeClient.onProgressChanged](https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)))
|
||||
///- iOS
|
||||
final void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
||||
|
@ -110,18 +112,23 @@ abstract class WebView {
|
|||
final void Function(InAppWebViewController controller, int x, int y)?
|
||||
onScrollChanged;
|
||||
|
||||
///Use [onDownloadStartRequest] instead
|
||||
@Deprecated('Use `onDownloadStartRequest` instead')
|
||||
final void Function(InAppWebViewController controller, Uri url)?
|
||||
onDownloadStart;
|
||||
|
||||
///Event fired when [WebView] recognizes a downloadable file.
|
||||
///To download the file, you can use the [flutter_downloader](https://pub.dev/packages/flutter_downloader) plugin.
|
||||
///
|
||||
///[url] represents the url of the file.
|
||||
///[downloadStartRequest] represents the request of the file to download.
|
||||
///
|
||||
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
|
||||
///
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
|
||||
final void Function(InAppWebViewController controller, Uri url)?
|
||||
onDownloadStart;
|
||||
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
|
||||
onDownloadStartRequest;
|
||||
|
||||
///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
|
||||
///
|
||||
|
@ -254,7 +261,7 @@ abstract class WebView {
|
|||
onReceivedClientCertRequest;
|
||||
|
||||
///Event fired as find-on-page operations progress.
|
||||
///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true.
|
||||
///The listener may be notified multiple times while the operation is underway, and the [numberOfMatches] value should not be considered final unless [isDoneCounting] is true.
|
||||
///
|
||||
///[activeMatchOrdinal] represents the zero-based ordinal of the currently selected match.
|
||||
///
|
||||
|
@ -262,7 +269,9 @@ abstract class WebView {
|
|||
///
|
||||
///[isDoneCounting] whether the find operation has actually completed.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setFindListener(android.webkit.WebView.FindListener)
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.FindListener.onFindResultReceived](https://developer.android.com/reference/android/webkit/WebView.FindListener#onFindResultReceived(int,%20int,%20boolean)))
|
||||
///- iOS
|
||||
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
|
||||
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;
|
||||
|
||||
|
@ -340,7 +349,9 @@ abstract class WebView {
|
|||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onPrint;
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
|
@ -674,6 +685,10 @@ abstract class WebView {
|
|||
///**NOTE for Android**: to be able to use the "pull-to-refresh" feature, [AndroidInAppWebViewOptions.useHybridComposition] must be `true`.
|
||||
final PullToRefreshController? pullToRefreshController;
|
||||
|
||||
///Represents the WebView native implementation to be used.
|
||||
///The default value is [WebViewImplementation.NATIVE].
|
||||
final WebViewImplementation implementation;
|
||||
|
||||
WebView(
|
||||
{this.windowId,
|
||||
this.onWebViewCreated,
|
||||
|
@ -686,7 +701,8 @@ abstract class WebView {
|
|||
this.shouldOverrideUrlLoading,
|
||||
this.onLoadResource,
|
||||
this.onScrollChanged,
|
||||
this.onDownloadStart,
|
||||
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -722,7 +738,7 @@ abstract class WebView {
|
|||
this.androidOnRenderProcessUnresponsive,
|
||||
this.androidOnFormResubmission,
|
||||
@Deprecated('Use `onZoomScaleChanged` instead')
|
||||
this.androidOnScaleChanged,
|
||||
this.androidOnScaleChanged,
|
||||
this.androidOnReceivedIcon,
|
||||
this.androidOnReceivedTouchIconUrl,
|
||||
this.androidOnJsBeforeUnload,
|
||||
|
@ -737,5 +753,6 @@ abstract class WebView {
|
|||
this.initialOptions,
|
||||
this.contextMenu,
|
||||
this.initialUserScripts,
|
||||
this.pullToRefreshController});
|
||||
this.pullToRefreshController,
|
||||
this.implementation = WebViewImplementation.NATIVE});
|
||||
}
|
||||
|
|
|
@ -580,6 +580,7 @@ class MimeTypeResolver {
|
|||
"zirz": "application/vnd.zul",
|
||||
"zaz": "application/vnd.zzazz.deck+xml",
|
||||
"vxml": "application/voicexml+xml",
|
||||
"wasm": "application/wasm",
|
||||
"wgt": "application/widget",
|
||||
"hlp": "application/winhlp",
|
||||
"wsdl": "application/wsdl+xml",
|
||||
|
|
|
@ -4052,7 +4052,7 @@ class NavigationAction {
|
|||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"request": request.toString(),
|
||||
"request": request.toMap(),
|
||||
"isForMainFrame": isForMainFrame,
|
||||
"androidHasGesture": androidHasGesture,
|
||||
"androidIsRedirect": androidIsRedirect,
|
||||
|
@ -6850,3 +6850,114 @@ class AndroidPullToRefreshSize {
|
|||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents the [WebView] native implementation to be used.
|
||||
class WebViewImplementation {
|
||||
final int _value;
|
||||
|
||||
const WebViewImplementation._internal(this._value);
|
||||
|
||||
static final Set<WebViewImplementation> values = [
|
||||
WebViewImplementation.NATIVE
|
||||
].toSet();
|
||||
|
||||
static WebViewImplementation? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return WebViewImplementation.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 0:
|
||||
default:
|
||||
return "NATIVE";
|
||||
}
|
||||
}
|
||||
|
||||
///Default native implementation, such as `WKWebView` for iOS and `android.webkit.WebView` for Android.
|
||||
static const NATIVE = const WebViewImplementation._internal(0);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class representing a download request of the WebView used by the event [WebView.onDownloadStartRequest].
|
||||
class DownloadStartRequest {
|
||||
///The full url to the content that should be downloaded.
|
||||
Uri url;
|
||||
|
||||
///the user agent to be used for the download.
|
||||
String? userAgent;
|
||||
|
||||
///Content-disposition http header, if present.
|
||||
String? contentDisposition;
|
||||
|
||||
///The mimetype of the content reported by the server.
|
||||
String? mimeType;
|
||||
|
||||
///The file size reported by the server.
|
||||
int contentLength;
|
||||
|
||||
///A suggested filename to use if saving the resource to disk.
|
||||
String? suggestedFilename;
|
||||
|
||||
///The name of the text encoding of the receiver, or `null` if no text encoding was specified.
|
||||
String? textEncodingName;
|
||||
|
||||
DownloadStartRequest(
|
||||
{required this.url,
|
||||
this.userAgent,
|
||||
this.contentDisposition,
|
||||
this.mimeType,
|
||||
required this.contentLength,
|
||||
this.suggestedFilename,
|
||||
this.textEncodingName});
|
||||
|
||||
static DownloadStartRequest? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DownloadStartRequest(
|
||||
url: Uri.parse(map["url"]),
|
||||
userAgent: map["userAgent"],
|
||||
contentDisposition: map["contentDisposition"],
|
||||
mimeType: map["mimeType"],
|
||||
contentLength: map["contentLength"],
|
||||
suggestedFilename: map["suggestedFilename"],
|
||||
textEncodingName: map["textEncodingName"]);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"url": url.toString(),
|
||||
"userAgent": userAgent,
|
||||
"contentDisposition": contentDisposition,
|
||||
"mimeType": mimeType,
|
||||
"contentLength": contentLength,
|
||||
"suggestedFilename": suggestedFilename,
|
||||
"textEncodingName": textEncodingName
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
10
pubspec.yaml
10
pubspec.yaml
|
@ -1,11 +1,11 @@
|
|||
name: flutter_inappwebview
|
||||
description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
|
||||
version: 5.3.3
|
||||
version: 5.4.0
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0-0 <3.0.0"
|
||||
flutter: ">=1.22.2"
|
||||
sdk: ">=2.14.0 <3.0.0"
|
||||
flutter: ">=2.5.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
@ -30,8 +30,8 @@ flutter:
|
|||
pluginClass: InAppWebViewFlutterPlugin
|
||||
|
||||
assets:
|
||||
- packages/flutter_inappwebview/t_rex_runner/t-rex.html
|
||||
- packages/flutter_inappwebview/t_rex_runner/t-rex.css
|
||||
- packages/flutter_inappwebview/assets/t_rex_runner/t-rex.html
|
||||
- packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css
|
||||
# To add assets to your plugin package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
|
|
Loading…
Reference in New Issue