This commit is contained in:
pichillilorenzo 2018-10-22 00:41:39 +02:00
parent ee7910b0b7
commit 7756aa8622
36 changed files with 3132 additions and 1690 deletions

View File

@ -15,7 +15,36 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment=""> <list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/InAppWebViewOptions.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" /> <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Options.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsActivity.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ChromeCustomTabsOptions.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/CustomTabActivityHelper.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/CustomTabsHelper.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/KeepAliveService.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ServiceConnection.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/chrome_custom_tabs/ServiceConnectionCallback.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/res/layout/activity_web_view.xml" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/res/layout/activity_web_view.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/res/menu/menu_main.xml" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/res/menu/menu_main.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/flutter_inappbrowser.iml" beforeDir="false" afterPath="$PROJECT_DIR$/flutter_inappbrowser.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Storyboards/WebView.storyboard" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Storyboards/WebView.storyboard" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
</list> </list>
<ignored path="$PROJECT_DIR$/.dart_tool/" /> <ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" /> <ignored path="$PROJECT_DIR$/.idea/" />
@ -35,8 +64,8 @@
<file leaf-file-name="flutter_inappbrowser.dart" pinned="false" current-in-tab="false"> <file leaf-file-name="flutter_inappbrowser.dart" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart"> <entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="129"> <state relative-caret-position="133">
<caret line="581" column="54" selection-start-line="581" selection-start-column="47" selection-end-line="581" selection-end-column="54" /> <caret line="500" column="57" selection-start-line="500" selection-start-column="57" selection-end-line="500" selection-end-column="57" />
<folding> <folding>
<element signature="e#814#831#0" expanded="true" /> <element signature="e#814#831#0" expanded="true" />
</folding> </folding>
@ -44,11 +73,14 @@
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="pubspec.yaml" pinned="false" current-in-tab="false"> <file leaf-file-name="main.dart" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405"> <state relative-caret-position="721">
<caret line="27" column="15" selection-start-line="27" selection-start-column="15" selection-end-line="27" selection-end-column="15" /> <caret line="254" column="25" selection-start-line="254" selection-start-column="25" selection-end-line="254" selection-end-column="25" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
@ -57,8 +89,8 @@
<entry file="file://$PROJECT_DIR$/README.md"> <entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]"> <provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT"> <state split_layout="SPLIT">
<first_editor relative-caret-position="382"> <first_editor relative-caret-position="120">
<caret line="509" column="29" selection-start-line="509" selection-start-column="29" selection-end-line="509" selection-end-column="29" /> <caret line="8" column="91" selection-start-line="8" selection-start-column="91" selection-end-line="8" selection-end-column="91" />
</first_editor> </first_editor>
<second_editor> <second_editor>
<markdownNavigatorState /> <markdownNavigatorState />
@ -67,6 +99,29 @@
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="CHANGELOG.md" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="390">
<caret line="26" column="34" selection-start-line="26" selection-start-column="34" selection-end-line="26" selection-end-column="34" />
</first_editor>
<second_editor>
<markdownNavigatorState />
</second_editor>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="pubspec.yaml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="3" column="52" lean-forward="true" selection-start-line="3" selection-start-column="52" selection-end-line="3" selection-end-column="52" />
</state>
</provider>
</entry>
</file>
</leaf> </leaf>
</component> </component>
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
@ -78,36 +133,36 @@
</component> </component>
<component name="FindInProjectRecents"> <component name="FindInProjectRecents">
<findStrings> <findStrings>
<find>Client</find> <find>isHi</find>
<find>LOAD_START_EVENT</find> <find>isHidde</find>
<find>loadstop</find> <find>onWebViewCreated</find>
<find>JSONO</find> <find>WebViewCreatedCallback</find>
<find>closeDialog</find> <find>MethodChannel</find>
<find>LOAD_STOP_EVENT</find> <find>WebViewController</find>
<find>com.pichillilorenzo.flutterwebview</find> <find>HashMap</find>
<find>flutter_webview</find> <find>String code</find>
<find>show</find> <find>flutter_inappwebview</find>
<find>SELF</find> <find>_closeServer</find>
<find>customscheme</find> <find>_startS</find>
<find>EXIT</find> <find>_throwIsAlreadyOpened</find>
<find>injectScriptCode</find> <find>isHidden</find>
<find>injectDeferredObject</find> <find>shouldOverrideUrlLoading</find>
<find>sourceFile</find> <find>toolbarTopFixedTitle</find>
<find>hideUrlBar</find> <find>useChromeSafariBrowser</find>
<find>InAppBrowser</find> <find>toolbat</find>
<find>presentationStyle</find> <find>onProgress</find>
<find>###</find> <find>goBack</find>
<find>inAppBrowserFallback</find> <find>_controller</find>
<find>target</find> <find>canGoBack</find>
<find>.assets</find> <find>getOp</find>
<find>_blank</find> <find>onLoadError</find>
<find>.html</find> <find>StatefulWidget</find>
<find>close(</find> <find>onLoadResource</find>
<find>isOpened</find> <find>useShouldOverrideUrlLoading</find>
<find>javascript</find> <find>):</find>
<find>header</find> <find>InAppLocalhostServer</find>
<find>localhost</find> <find>local</find>
<find>/main.dart</find> <find>openWithSystemBrowser</find>
</findStrings> </findStrings>
<replaceStrings> <replaceStrings>
<replace>activity.getPreferences(0)</replace> <replace>activity.getPreferences(0)</replace>
@ -147,20 +202,20 @@
<option value="$PROJECT_DIR$/example/html/index.html" /> <option value="$PROJECT_DIR$/example/html/index.html" />
<option value="$PROJECT_DIR$/example/assets/css/style.css" /> <option value="$PROJECT_DIR$/example/assets/css/style.css" />
<option value="$PROJECT_DIR$/example/assets/index.html" /> <option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/pubspec.yaml" /> <option value="$PROJECT_DIR$/example/ios/Flutter/Generated.xcconfig" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/CHANGELOG.md" /> <option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/example/lib/main.dart" /> <option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" /> <option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
<option value="$PROJECT_DIR$/example/ios/Flutter/Generated.xcconfig" /> <option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/README.md" /> <option value="$PROJECT_DIR$/README.md" />
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectFrameBounds"> <component name="ProjectFrameBounds">
<option name="x" value="116" /> <option name="x" value="2053" />
<option name="y" value="23" /> <option name="y" value="23" />
<option name="width" value="1695" /> <option name="width" value="1787" />
<option name="height" value="1057" /> <option name="height" value="1057" />
</component> </component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
@ -176,11 +231,6 @@
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" /> <item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" /> <item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
</path> </path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" />
</path>
<path> <path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" /> <item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" /> <item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
@ -202,8 +252,8 @@
<select /> <select />
</subPane> </subPane>
</pane> </pane>
<pane id="AndroidView" />
<pane id="PackagesPane" /> <pane id="PackagesPane" />
<pane id="AndroidView" />
</panes> </panes>
</component> </component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
@ -360,77 +410,43 @@
<servers /> <servers />
</component> </component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="116" y="23" width="1695" height="1057" extended-state="0" /> <frame x="2053" y="23" width="1787" height="1057" extended-state="0" />
<editor active="true" /> <editor active="true" />
<layout> <layout>
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" /> <window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info id="Build Variants" order="2" side_tool="true" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5035553" side_tool="true" weight="0.25689086" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.32855567" />
<window_info anchor="right" id="Flutter Outline" order="3" weight="0.32922077" />
<window_info anchor="bottom" id="Logcat" order="11" />
<window_info id="Capture Tool" order="2" />
<window_info id="Designer" order="2" />
<window_info id="Structure" order="1" sideWeight="0.50275636" side_tool="true" weight="0.1910871" />
<window_info anchor="right" id="Device File Explorer" order="3" side_tool="true" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.34364995" />
<window_info anchor="bottom" id="TODO" order="6" /> <window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.23692636" /> <window_info anchor="bottom" id="Messages" order="12" weight="0.23692636" />
<window_info anchor="right" id="Palette&#9;" order="3" /> <window_info anchor="right" id="Palette&#9;" order="9" />
<window_info id="Image Layers" order="2" /> <window_info id="Image Layers" order="7" />
<window_info anchor="right" id="Capture Analysis" order="3" /> <window_info id="Build Variants" order="3" side_tool="true" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49644473" weight="0.36179295" /> <window_info anchor="right" id="Capture Analysis" order="4" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5035553" side_tool="true" weight="0.25689086" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.3276414" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49644473" weight="0.3564568" />
<window_info anchor="bottom" id="Version Control" order="9" /> <window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.49644473" visible="true" weight="0.25080043" /> <window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49644473" visible="true" weight="0.35005337" />
<window_info id="Captures" order="2" weight="0.32936507" /> <window_info anchor="right" id="Flutter Outline" order="6" weight="0.32922077" />
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.49724367" visible="true" weight="0.25771326" /> <window_info anchor="bottom" id="Logcat" order="11" />
<window_info anchor="bottom" id="Find" order="1" weight="0.3276414" /> <window_info id="Captures" order="4" weight="0.32936507" />
<window_info anchor="right" id="Theme Preview" order="3" /> <window_info id="Capture Tool" order="6" />
<window_info id="Favorites" order="2" side_tool="true" /> <window_info id="Designer" order="2" />
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.49724367" visible="true" weight="0.14670487" />
<window_info id="Structure" order="1" sideWeight="0.50275636" side_tool="true" weight="0.1910871" />
<window_info anchor="right" id="Device File Explorer" order="5" side_tool="true" />
<window_info anchor="right" id="Theme Preview" order="7" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.34364995" />
<window_info id="Favorites" order="5" side_tool="true" />
<window_info anchor="right" id="Flutter Inspector" order="3" weight="0.32938388" /> <window_info anchor="right" id="Flutter Inspector" order="3" weight="0.32938388" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" /> <window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Assistant" order="4" visible="true" weight="0.32987013" /> <window_info anchor="right" id="Assistant" order="8" visible="true" weight="0.32987013" />
<window_info anchor="bottom" id="Message" order="0" /> <window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" /> <window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32745314" />
</layout> </layout>
<layout-to-restore>
<window_info id="Designer" order="4" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.3290735" />
<window_info id="Build Variants" order="2" side_tool="true" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.4973545" weight="0.32161874" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" id="Flutter Inspector" order="8" weight="0.32987013" />
<window_info id="Favorites" order="7" side_tool="true" />
<window_info id="Captures" order="6" weight="0.32936507" />
<window_info id="Capture Tool" order="3" />
<window_info anchor="right" id="Capture Analysis" order="6" />
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5026455" side_tool="true" weight="0.31735888" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Device File Explorer" order="4" side_tool="true" />
<window_info anchor="right" id="Flutter Outline" order="3" weight="0.32936507" />
<window_info anchor="bottom" id="Logcat" order="11" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.4973545" visible="true" weight="0.27888888" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.18376623" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.23777778" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info id="Image Layers" order="5" />
<window_info anchor="right" id="Palette&#9;" order="5" />
<window_info anchor="right" id="Theme Preview" order="7" />
<window_info id="Structure" order="1" weight="0.24969475" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="Find" order="1" weight="0.3290735" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
</layout-to-restore>
</component> </component>
<component name="UnknownFeatures"> <component name="UnknownFeatures">
<option featureType="com.intellij.fileTypeFactory" implementationName="*.css" /> <option featureType="com.intellij.fileTypeFactory" implementationName="*.css" />
@ -440,15 +456,10 @@
</component> </component>
<component name="XDebuggerManager"> <component name="XDebuggerManager">
<breakpoint-manager> <breakpoint-manager>
<option name="time" value="14" /> <option name="time" value="15" />
</breakpoint-manager> </breakpoint-manager>
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/example/pubspec.lock">
<provider selected="true" editor-type-id="text-editor">
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/android/gradle.properties"> <entry file="file://$PROJECT_DIR$/example/android/gradle.properties">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state /> <state />
@ -608,40 +619,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="60">
<caret line="4" column="21" selection-start-line="4" selection-start-column="21" selection-end-line="4" selection-end-column="21" />
</first_editor>
<second_editor>
<markdownNavigatorState />
</second_editor>
</state>
</provider>
<provider editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="69" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="73" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="14" selection-start-line="2" selection-start-column="14" selection-end-line="2" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="495">
<caret line="33" column="11" selection-start-line="23" selection-start-column="30" selection-end-line="33" selection-end-column="11" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/flutter_inappbrowser.iml"> <entry file="file://$PROJECT_DIR$/flutter_inappbrowser.iml">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330"> <state relative-caret-position="330">
@ -712,21 +689,65 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor />
<second_editor>
<markdownNavigatorState />
</second_editor>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart"> <entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="129"> <state relative-caret-position="133">
<caret line="581" column="54" selection-start-line="581" selection-start-column="47" selection-end-line="581" selection-end-column="54" /> <caret line="500" column="57" selection-start-line="500" selection-start-column="57" selection-end-line="500" selection-end-column="57" />
<folding> <folding>
<element signature="e#814#831#0" expanded="true" /> <element signature="e#814#831#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="721">
<caret line="254" column="25" selection-start-line="254" selection-start-column="25" selection-end-line="254" selection-end-column="25" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="3" column="52" lean-forward="true" selection-start-line="3" selection-start-column="52" selection-end-line="3" selection-end-column="52" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="390">
<caret line="26" column="34" selection-start-line="26" selection-start-column="34" selection-end-line="26" selection-end-column="34" />
</first_editor>
<second_editor>
<markdownNavigatorState />
</second_editor>
</state>
</provider>
<provider editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="69" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="73" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md"> <entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]"> <provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT"> <state split_layout="SPLIT">
<first_editor relative-caret-position="382"> <first_editor relative-caret-position="120">
<caret line="509" column="29" selection-start-line="509" selection-start-column="29" selection-end-line="509" selection-end-column="29" /> <caret line="8" column="91" selection-start-line="8" selection-start-column="91" selection-end-line="8" selection-end-column="91" />
</first_editor> </first_editor>
<second_editor> <second_editor>
<markdownNavigatorState /> <markdownNavigatorState />

View File

@ -1,3 +1,14 @@
## 0.5.0
- added initial support for Inline WebViews using the `InAppWebView` widget
- added `InAppBrowser.openFile()` method
- added `InAppBrowser.onProgressChanged()` event
- moved `InAppBrowser` WebView related functions on the `InAppWebViewController` class
- added `InAppLocalhostServer` class
- added `InAppWebView.canGoBack()` and `InAppWebView.canGoForward()` methods
- removed `openWithSystemBrowser` and `isLocalFile` option. Now use the corresponding method
- code refactoring
## 0.4.1 ## 0.4.1
- added `InAppBrowser.takeScreenshot()` - added `InAppBrowser.takeScreenshot()`

889
README.md

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application> <application>
<activity android:theme="@style/AppTheme" android:name=".WebViewActivity" android:configChanges="orientation|screenSize"></activity> <activity android:theme="@style/AppTheme" android:name=".InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
<activity android:theme="@style/ThemeTransparent" android:name=".chrome_custom_tabs.ChromeCustomTabsActivity" android:configChanges="orientation|screenSize"></activity> <activity android:theme="@style/ThemeTransparent" android:name=".ChromeCustomTabs.ChromeCustomTabsActivity" android:configChanges="orientation|screenSize"></activity>
</application> </application>
</manifest> </manifest>

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
@ -6,10 +6,8 @@ import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsIntent;
import android.util.Log;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserOptions;
import com.pichillilorenzo.flutter_inappbrowser.R; import com.pichillilorenzo.flutter_inappbrowser.R;
import java.util.HashMap; import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import com.pichillilorenzo.flutter_inappbrowser.Options; import com.pichillilorenzo.flutter_inappbrowser.Options;

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.app.Activity; import android.app.Activity;
import android.net.Uri; import android.net.Uri;
@ -10,8 +10,6 @@ import android.support.customtabs.CustomTabsSession;
import java.util.List; import java.util.List;
import static android.support.v4.app.ActivityCompat.startActivityForResult;
/** /**
* This is a helper class to manage the connection to the Custom Tabs Service. * This is a helper class to manage the connection to the Custom Tabs Service.
*/ */

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -6,7 +6,6 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.support.customtabs.CustomTabsClient;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.content.ComponentName; import android.content.ComponentName;
import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsClient;

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs; package com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs;
import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsClient;

View File

@ -0,0 +1,191 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import static io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.platform.PlatformView;
public class FlutterWebView implements PlatformView, MethodCallHandler {
static final String LOG_TAG = "FlutterWebView";
public final Activity activity;
public InAppWebView webView;
public MethodChannel channel;
public final Registrar registrar;
public final Context context;
public FlutterWebView(Registrar registrar, int id, HashMap<String, Object> params) {
this.registrar = registrar;
this.activity = registrar.activity();
this.context = registrar.context();
String initialUrl = (String) params.get("initialUrl");
String initialFile = (String) params.get("initialFile");
Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders");
HashMap<String, Object> initialOptions = (HashMap<String, Object>) params.get("initialOptions");
InAppWebViewOptions options = new InAppWebViewOptions();
options.parse(initialOptions);
if (initialFile != null) {
try {
initialUrl = Util.getUrlAsset(registrar, initialFile);
} catch (IOException e) {
e.printStackTrace();
Log.e(LOG_TAG, initialFile + " asset file cannot be found!", e);
return;
}
}
webView = new InAppWebView(context, this, id, options);
webView.prepare();
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappwebview_" + id);
channel.setMethodCallHandler(this);
webView.loadUrl(initialUrl, initialHeaders);
}
@Override
public View getView() {
return webView;
}
@Override
public void onMethodCall(MethodCall call, Result result) {
String source;
String jsWrapper;
String urlFile;
switch (call.method) {
case "loadUrl":
if (webView != null)
webView.loadUrl(call.argument("url").toString(), (Map<String, String>) call.argument("headers"), result);
else
result.success(false);
break;
case "loadFile":
if (webView != null)
webView.loadFile(call.argument("url").toString(), (Map<String, String>) call.argument("headers"), result);
else
result.success(false);
break;
case "injectScriptCode":
if (webView != null) {
source = call.argument("source").toString();
jsWrapper = "(function(){return JSON.stringify(eval(%s));})();";
webView.injectDeferredObject(source, jsWrapper, result);
}
else {
result.success("");
}
break;
case "injectScriptFile":
if (webView != null) {
urlFile = call.argument("urlFile").toString();
jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document);";
webView.injectDeferredObject(urlFile, jsWrapper, null);
}
result.success(true);
break;
case "injectStyleCode":
if (webView != null) {
source = call.argument("source").toString();
jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document);";
webView.injectDeferredObject(source, jsWrapper, null);
}
result.success(true);
break;
case "injectStyleFile":
if (webView != null) {
urlFile = call.argument("urlFile").toString();
jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document);";
webView.injectDeferredObject(urlFile, jsWrapper, null);
}
result.success(true);
break;
case "reload":
if (webView != null)
webView.reload();
result.success(true);
break;
case "goBack":
if (webView != null)
webView.goBack();
result.success(true);
break;
case "canGoBack":
result.success((webView != null) && webView.canGoBack());
break;
case "goForward":
if (webView != null)
webView.goForward();
result.success(true);
break;
case "canGoForward":
result.success((webView != null) && webView.canGoForward());
break;
case "stopLoading":
if (webView != null)
webView.stopLoading();
result.success(true);
break;
case "isLoading":
result.success((webView != null) && webView.isLoading());
break;
case "takeScreenshot":
result.success((webView != null) ? webView.takeScreenshot() : null);
break;
case "setOptions":
if (webView != null) {
InAppWebViewOptions inAppWebViewOptions = new InAppWebViewOptions();
HashMap<String, Object> inAppWebViewOptionsMap = (HashMap<String, Object>) call.argument("options");
inAppWebViewOptions.parse(inAppWebViewOptionsMap);
webView.setOptions(inAppWebViewOptions, inAppWebViewOptionsMap);
}
result.success(true);
break;
case "getOptions":
result.success((webView != null) ? webView.getOptions() : null);
break;
case "dispose":
dispose();
result.success(true);
break;
default:
result.notImplemented();
}
}
@Override
public void dispose() {
if (webView != null) {
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView = null;
}
});
webView.loadUrl("about:blank");
}
}
}

View File

@ -0,0 +1,32 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity;
import android.content.Context;
import java.util.HashMap;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
public class FlutterWebViewFactory extends PlatformViewFactory {
private final BinaryMessenger messenger;
private final Registrar registrar;
private final Activity activity;
public FlutterWebViewFactory(Registrar registrar, Activity activity) {
super(StandardMessageCodec.INSTANCE);
this.registrar = registrar;
this.messenger = registrar.messenger();
this.activity = activity;
}
@Override
public PlatformView create(Context context, int id, Object args) {
HashMap<String, Object> params = (HashMap<String, Object>) args;
return new FlutterWebView(registrar, id, params);
}
}

View File

@ -0,0 +1,368 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.graphics.drawable.ColorDrawable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SearchView;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
public class InAppBrowserActivity extends AppCompatActivity {
static final String LOG_TAG = "InAppBrowserActivity";
public String uuid;
public InAppWebView webView;
public ActionBar actionBar;
public Menu menu;
public SearchView searchView;
public InAppBrowserOptions options;
public Map<String, String> headers;
public ProgressBar progressBar;
public boolean isHidden = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
webView = findViewById(R.id.webView);
webView.inAppBrowserActivity = this;
Bundle b = getIntent().getExtras();
uuid = b.getString("uuid");
String url = b.getString("url");
HashMap<String, Object> optionsMap = (HashMap<String, Object>) b.getSerializable("options");
options = new InAppBrowserOptions();
options.parse(optionsMap);
InAppWebViewOptions webViewOptions = new InAppWebViewOptions();
webViewOptions.parse(optionsMap);
webView.options = webViewOptions;
headers = (HashMap<String, String>) b.getSerializable("headers");
InAppBrowserFlutterPlugin.webViewActivities.put(uuid, this);
actionBar = getSupportActionBar();
prepareView();
webView.loadUrl(url, headers);
//webView.loadData("<!DOCTYPE assets> <assets lang=\"en\"> <head> <meta charset=\"UTF-8\"> <title>Document</title> </head> <body> ciao <img src=\"https://via.placeholder.com/350x150\" /> <img src=\"./images/test\" alt=\"not found\" /></body> </assets>", "text/assets", "utf8");
}
private void prepareView() {
webView.prepare();
if (options.hidden)
hide();
else
show();
progressBar = findViewById(R.id.progressBar);
if (!options.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
actionBar.setDisplayShowTitleEnabled(!options.hideTitleBar);
if (!options.toolbarTop)
actionBar.hide();
if (!options.toolbarTopBackgroundColor.isEmpty())
actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(options.toolbarTopBackgroundColor)));
if (!options.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(options.toolbarTopFixedTitle);
}
@Override
public boolean onCreateOptionsMenu(Menu m) {
menu = m;
MenuInflater inflater = getMenuInflater();
// Inflate menu to add items to action bar if it is present.
inflater.inflate(R.menu.menu_main, menu);
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setFocusable(true);
if (options.hideUrlBar)
menu.findItem(R.id.menu_search).setVisible(false);
searchView.setQuery(webView.getUrl(), false);
if (options.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(webView.getTitle());
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
if (!query.isEmpty()) {
webView.loadUrl(query);
searchView.setQuery("", false);
searchView.setIconified(true);
return true;
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
if (searchView.getQuery().toString().isEmpty())
searchView.setQuery(webView.getUrl(), false);
return false;
}
});
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (!b) {
searchView.setQuery("", false);
searchView.setIconified(true);
}
}
});
return true;
}
public void loadUrl(String url, MethodChannel.Result result) {
if (webView != null) {
webView.loadUrl(url, result);
} else {
result.error(LOG_TAG, "Cannot load url " + url, null);
}
}
public void loadUrl(String url, Map<String, String> headers, MethodChannel.Result result) {
if (webView != null) {
webView.loadUrl(url, headers, result);
} else {
result.error(LOG_TAG, "Cannot load url " + url, null);
}
}
public void loadFile(String url, MethodChannel.Result result) {
if (webView != null) {
webView.loadFile(url, result);
} else {
result.error(LOG_TAG, "Cannot load file " + url, null);
}
}
public void loadFile(String url, Map<String, String> headers, MethodChannel.Result result) {
if (webView != null) {
webView.loadFile(url, headers, result);
} else {
result.error(LOG_TAG, "Cannot load file " + url, null);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
if (canGoBack())
goBack();
else if (options.closeOnCannotGoBack)
InAppBrowserFlutterPlugin.close(uuid, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void close() {
hide();
finish();
}
public void reload() {
if (webView != null)
webView.reload();
}
public void goBack() {
if (webView != null && canGoBack())
webView.goBack();
}
public void goForward() {
if (webView != null && canGoForward())
webView.goForward();
}
public boolean canGoBack() {
return webView.canGoBack();
}
public boolean canGoForward() {
return webView.canGoForward();
}
public void hide() {
isHidden = true;
Intent openActivity = new Intent(this, InAppBrowserFlutterPlugin.registrar.activity().getClass());
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0);
}
public void show() {
isHidden = false;
Intent openActivity = new Intent(InAppBrowserFlutterPlugin.registrar.activity(), InAppBrowserActivity.class);
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0);
}
public void stopLoading() {
if (webView != null)
webView.stopLoading();
}
public boolean isLoading() {
if (webView != null)
return webView.isLoading;
return false;
}
public void goBackButtonClicked(MenuItem item) {
goBack();
}
public void goForwardButtonClicked(MenuItem item) {
goForward();
}
public void shareButtonClicked(MenuItem item) {
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
startActivity(Intent.createChooser(share, "Share"));
}
public void reloadButtonClicked(MenuItem item) {
reload();
}
public void closeButtonClicked(MenuItem item) {
InAppBrowserFlutterPlugin.close(uuid, null);
}
public byte[] takeScreenshot() {
if (webView != null) {
Picture picture = webView.capturePicture();
Bitmap b = Bitmap.createBitmap( webView.getWidth(),
webView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
picture.draw(c);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
return null;
}
public void setOptions(InAppBrowserOptions newOptions, HashMap<String, Object> newOptionsMap) {
InAppWebViewOptions newInAppWebViewOptions = new InAppWebViewOptions();
newInAppWebViewOptions.parse(newOptionsMap);
webView.setOptions(newInAppWebViewOptions, newOptionsMap);
if (newOptionsMap.get("hidden") != null && options.hidden != newOptions.hidden) {
if (newOptions.hidden)
hide();
else
show();
}
if (newOptionsMap.get("progressBar") != null && options.progressBar != newOptions.progressBar && progressBar != null) {
if (newOptions.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
}
if (newOptionsMap.get("hideTitleBar") != null && options.hideTitleBar != newOptions.hideTitleBar)
actionBar.setDisplayShowTitleEnabled(!newOptions.hideTitleBar);
if (newOptionsMap.get("toolbarTop") != null && options.toolbarTop != newOptions.toolbarTop) {
if (!newOptions.toolbarTop)
actionBar.hide();
else
actionBar.show();
}
if (newOptionsMap.get("toolbarTopBackgroundColor") != null && options.toolbarTopBackgroundColor != newOptions.toolbarTopBackgroundColor && !newOptions.toolbarTopBackgroundColor.isEmpty())
actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(newOptions.toolbarTopBackgroundColor)));
if (newOptionsMap.get("toolbarTopFixedTitle") != null && options.toolbarTopFixedTitle != newOptions.toolbarTopFixedTitle && !newOptions.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(newOptions.toolbarTopFixedTitle);
if (newOptionsMap.get("hideUrlBar") != null && options.hideUrlBar != newOptions.hideUrlBar) {
if (newOptions.hideUrlBar)
menu.findItem(R.id.menu_search).setVisible(false);
else
menu.findItem(R.id.menu_search).setVisible(true);
}
options = newOptions;
}
public HashMap<String, Object> getOptions() {
HashMap<String, Object> webViewOptionsMap = webView.getOptions();
if (options == null || webViewOptionsMap == null)
return null;
HashMap<String, Object> optionsMap = options.getHashMap();
optionsMap.putAll(webViewOptionsMap);
return optionsMap;
}
public void injectDeferredObject(String source, String jsWrapper, MethodChannel.Result result) {
if (webView != null)
webView.injectDeferredObject(source, jsWrapper, result);
else
result.success("");
}
}

View File

@ -25,29 +25,20 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.AssetManager;
import android.os.Parcelable; import android.os.Parcelable;
import android.provider.Browser; import android.provider.Browser;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Base64;
import android.util.JsonReader;
import android.util.JsonToken;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.webkit.ValueCallback;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.util.Log; import android.util.Log;
import com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs.ChromeCustomTabsActivity; import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.ChromeCustomTabsActivity;
import com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs.ChromeCustomTabsOptions; import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.CustomTabActivityHelper;
import com.pichillilorenzo.flutter_inappbrowser.chrome_custom_tabs.CustomTabActivityHelper;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -67,13 +58,11 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
public static Registrar registrar; public static Registrar registrar;
public Activity activity; public Activity activity;
public static MethodChannel channel; public static MethodChannel channel;
public static Map<String, WebViewActivity> webViewActivities = new HashMap<>(); public static Map<String, InAppBrowserActivity> webViewActivities = new HashMap<>();
public static Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>(); public static Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>();
protected static final String LOG_TAG = "IABFlutterPlugin"; protected static final String LOG_TAG = "IABFlutterPlugin";
static final String ANDROID_ASSET_URL = "file:///android_asset/";
public InAppBrowserFlutterPlugin(Registrar r, Activity activity) { public InAppBrowserFlutterPlugin(Registrar r, Activity activity) {
registrar = r; registrar = r;
this.activity = activity; this.activity = activity;
@ -84,8 +73,15 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
* Plugin registration. * Plugin registration.
*/ */
public static void registerWith(Registrar registrar) { public static void registerWith(Registrar registrar) {
Activity activity = registrar.activity();
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser"); final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
channel.setMethodCallHandler(new InAppBrowserFlutterPlugin(registrar, registrar.activity())); channel.setMethodCallHandler(new InAppBrowserFlutterPlugin(registrar, activity));
registrar
.platformViewRegistry()
.registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, activity));
} }
@Override @Override
@ -113,48 +109,32 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
final String uuidFallback = (String) call.argument("uuidFallback"); final String uuidFallback = (String) call.argument("uuidFallback");
final ChromeCustomTabsOptions options = new ChromeCustomTabsOptions(); final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
options.parse((HashMap<String, Object>) call.argument("options"));
final InAppBrowserOptions optionsFallback = new InAppBrowserOptions(); final HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
optionsFallback.parse((HashMap<String, Object>) call.argument("optionsFallback"));
open(uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result); open(uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result);
} else { } else {
String url = url_final; String url = url_final;
final InAppBrowserOptions options = new InAppBrowserOptions(); final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
options.parse((HashMap<String, Object>) call.argument("options"));
if (options.isLocalFile) { final boolean isLocalFile = (boolean) call.argument("isLocalFile");
final boolean openWithSystemBrowser = (boolean) call.argument("openWithSystemBrowser");
if (isLocalFile) {
// check if the asset file exists // check if the asset file exists
String key = registrar.lookupKeyForAsset(url);
AssetManager mg = registrar.activeContext().getResources().getAssets();
InputStream is = null;
boolean assetExists = false;
try { try {
is = mg.open(key); url = Util.getUrlAsset(registrar, url);
assetExists = true; } catch (IOException e) {
} catch (IOException ex) { e.printStackTrace();
result.error(LOG_TAG, url + " asset file cannot be found!", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (!assetExists) {
result.error(LOG_TAG, key + " asset file cannot be found!", null);
return; return;
} }
url = ANDROID_ASSET_URL + key;
} }
// SYSTEM // SYSTEM
if (options.openWithSystemBrowser) { if (openWithSystemBrowser) {
Log.d(LOG_TAG, "in system"); Log.d(LOG_TAG, "in system");
openExternal(url, result); openExternal(url, result);
} }
@ -257,9 +237,9 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
switch (optionsType){ switch (optionsType){
case "InAppBrowserOptions": case "InAppBrowserOptions":
InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions(); InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions();
HashMap<String, Object> inAppBroeserOptionsMap = (HashMap<String, Object>) call.argument("options"); HashMap<String, Object> inAppBrowserOptionsMap = (HashMap<String, Object>) call.argument("options");
inAppBrowserOptions.parse(inAppBroeserOptionsMap); inAppBrowserOptions.parse(inAppBrowserOptionsMap);
setOptions(uuid, inAppBrowserOptions, inAppBroeserOptionsMap); setOptions(uuid, inAppBrowserOptions, inAppBrowserOptionsMap);
break; break;
default: default:
result.error(LOG_TAG, "Options " + optionsType + " not available.", null); result.error(LOG_TAG, "Options " + optionsType + " not available.", null);
@ -276,85 +256,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
/**
* Inject an object (script or style) into the InAppBrowserFlutterPlugin WebView.
* <p>
* This is a helper method for the inject{Script|Style}{Code|File} API calls, which
* provides a consistent method for injecting JavaScript code into the document.
* <p>
* If a wrapper string is supplied, then the source string will be JSON-encoded (adding
* quotes) and wrapped using string formatting. (The wrapper string should have a single
* '%s' marker)
*
* @param uuid
* @param source The source object (filename or script/style text) to inject into
* the document.
* @param jsWrapper A JavaScript string to wrap the source string in, so that the object
* is properly injected, or null if the source string is JavaScript text
* @param result
*/
private void injectDeferredObject(String uuid, String source, String jsWrapper, final Result result) { private void injectDeferredObject(String uuid, String source, String jsWrapper, final Result result) {
final WebViewActivity webViewActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) { if (inAppBrowserActivity != null) {
String scriptToInject; inAppBrowserActivity.injectDeferredObject(source, jsWrapper, result);
if (jsWrapper != null) {
org.json.JSONArray jsonEsc = new org.json.JSONArray();
jsonEsc.put(source);
String jsonRepr = jsonEsc.toString();
String jsonSourceString = jsonRepr.substring(1, jsonRepr.length() - 1);
scriptToInject = String.format(jsWrapper, jsonSourceString);
} else {
scriptToInject = source;
}
final String finalScriptToInject = scriptToInject;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
// This action will have the side-effect of blurring the currently focused element
webViewActivity.webView.loadUrl("javascript:" + finalScriptToInject);
} else {
webViewActivity.webView.evaluateJavascript(finalScriptToInject, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
if (result == null)
return;
JsonReader reader = new JsonReader(new StringReader(s));
// Must set lenient to parse single values
reader.setLenient(true);
try {
String msg;
if (reader.peek() == JsonToken.STRING) {
msg = reader.nextString();
JsonReader reader2 = new JsonReader(new StringReader(msg));
reader2.setLenient(true);
if (reader2.peek() == JsonToken.STRING)
msg = reader2.nextString();
result.success(msg);
} else {
result.success("");
}
} catch (IOException e) {
Log.e(LOG_TAG, "IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
}
}
});
} else { } else {
Log.d(LOG_TAG, "Can't inject code into the system browser"); Log.d(LOG_TAG, "Can't inject code into the system browser");
} }
@ -435,14 +340,14 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
} }
public void open(String uuid, String uuidFallback, String url, Options options, Map<String, String> headers, boolean useChromeSafariBrowser, InAppBrowserOptions optionsFallback, Result result) { public void open(String uuid, String uuidFallback, String url, HashMap<String, Object> options, Map<String, String> headers, boolean useChromeSafariBrowser, HashMap<String, Object> optionsFallback, Result result) {
Intent intent = null; Intent intent = null;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("url", url); extras.putString("url", url);
extras.putString("uuid", uuid); extras.putString("uuid", uuid);
extras.putSerializable("options", options.getHashMap()); extras.putSerializable("options", options);
extras.putSerializable("headers", (Serializable) headers); extras.putSerializable("headers", (Serializable) headers);
if (useChromeSafariBrowser && CustomTabActivityHelper.isAvailable(activity)) { if (useChromeSafariBrowser && CustomTabActivityHelper.isAvailable(activity)) {
@ -454,15 +359,15 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// overwrite with extras fallback parameters // overwrite with extras fallback parameters
extras.putString("uuid", uuidFallback); extras.putString("uuid", uuidFallback);
if (optionsFallback != null) if (optionsFallback != null)
extras.putSerializable("options", optionsFallback.getHashMap()); extras.putSerializable("options", optionsFallback);
else else
extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap()); extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap());
extras.putSerializable("headers", (Serializable) headers); extras.putSerializable("headers", (Serializable) headers);
intent = new Intent(activity, WebViewActivity.class); intent = new Intent(activity, InAppBrowserActivity.class);
} }
// native webview // native webview
else if (!useChromeSafariBrowser) { else if (!useChromeSafariBrowser) {
intent = new Intent(activity, WebViewActivity.class); intent = new Intent(activity, InAppBrowserActivity.class);
} }
else { else {
Log.d(LOG_TAG, "No WebView fallback declared."); Log.d(LOG_TAG, "No WebView fallback declared.");
@ -479,93 +384,93 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
public void loadUrl(String uuid, String url, Map<String, String> headers, Result result) { public void loadUrl(String uuid, String url, Map<String, String> headers, Result result) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) { if (inAppBrowserActivity != null) {
if (headers != null) if (headers != null)
webViewActivity.loadUrl(url, headers, result); inAppBrowserActivity.loadUrl(url, headers, result);
else else
webViewActivity.loadUrl(url, result); inAppBrowserActivity.loadUrl(url, result);
} }
} }
public void loadFile(String uuid, String url, Map<String, String> headers, Result result) { public void loadFile(String uuid, String url, Map<String, String> headers, Result result) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) { if (inAppBrowserActivity != null) {
if (headers != null) if (headers != null)
webViewActivity.loadFile(url, headers, result); inAppBrowserActivity.loadFile(url, headers, result);
else else
webViewActivity.loadFile(url, result); inAppBrowserActivity.loadFile(url, result);
} }
} }
public void show(String uuid) { public void show(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.show(); inAppBrowserActivity.show();
} }
public void hide(String uuid) { public void hide(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.hide(); inAppBrowserActivity.hide();
} }
public void reload(String uuid) { public void reload(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.reload(); inAppBrowserActivity.reload();
} }
public boolean isLoading(String uuid) { public boolean isLoading(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.isLoading(); return inAppBrowserActivity.isLoading();
return false; return false;
} }
public boolean isHidden(String uuid) { public boolean isHidden(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.isHidden; return inAppBrowserActivity.isHidden;
return false; return false;
} }
public void stopLoading(String uuid) { public void stopLoading(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.stopLoading(); inAppBrowserActivity.stopLoading();
} }
public void goBack(String uuid) { public void goBack(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.goBack(); inAppBrowserActivity.goBack();
} }
public boolean canGoBack(String uuid) { public boolean canGoBack(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.canGoBack(); return inAppBrowserActivity.canGoBack();
return false; return false;
} }
public void goForward(String uuid) { public void goForward(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.goForward(); inAppBrowserActivity.goForward();
} }
public boolean canGoForward(String uuid) { public boolean canGoForward(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.canGoForward(); return inAppBrowserActivity.canGoForward();
return false; return false;
} }
public static void close(final String uuid, final Result result) { public static void close(final String uuid, final Result result) {
final WebViewActivity webViewActivity = webViewActivities.get(uuid); final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) { if (inAppBrowserActivity != null) {
registrar.activity().runOnUiThread(new Runnable() { registrar.activity().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -576,23 +481,23 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
// The JS protects against multiple calls, so this should happen only when // The JS protects against multiple calls, so this should happen only when
// close() is called by other native code. // close() is called by other native code.
if (webViewActivity == null) { if (inAppBrowserActivity == null) {
if (result != null) { if (result != null) {
result.success(true); result.success(true);
} }
return; return;
} }
webViewActivity.webView.setWebViewClient(new WebViewClient() { inAppBrowserActivity.webView.setWebViewClient(new WebViewClient() {
// NB: wait for about:blank before dismissing // NB: wait for about:blank before dismissing
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
webViewActivity.close(); inAppBrowserActivity.close();
} }
}); });
// NB: From SDK 19: "If you call methods on WebView from any thread // NB: From SDK 19: "If you call methods on WebView from any thread
// other than your app's UI thread, it can cause unexpected results." // other than your app's UI thread, it can cause unexpected results."
// http://developer.android.com/guide/webapps/migrating.html#Threads // http://developer.android.com/guide/webapps/migrating.html#Threads
webViewActivity.webView.loadUrl("about:blank"); inAppBrowserActivity.webView.loadUrl("about:blank");
if (result != null) { if (result != null) {
result.success(true); result.success(true);
} }
@ -605,22 +510,22 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
} }
public byte[] takeScreenshot(String uuid) { public byte[] takeScreenshot(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.takeScreenshot(); return inAppBrowserActivity.takeScreenshot();
return null; return null;
} }
public void setOptions(String uuid, InAppBrowserOptions options, HashMap<String, Object> optionsMap) { public void setOptions(String uuid, InAppBrowserOptions options, HashMap<String, Object> optionsMap) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
webViewActivity.setOptions(options, optionsMap); inAppBrowserActivity.setOptions(options, optionsMap);
} }
public HashMap<String, Object> getOptions(String uuid) { public HashMap<String, Object> getOptions(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid); InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (webViewActivity != null) if (inAppBrowserActivity != null)
return webViewActivity.getOptions(); return inAppBrowserActivity.getOptions();
return null; return null;
} }

View File

@ -4,29 +4,13 @@ public class InAppBrowserOptions extends Options {
static final String LOG_TAG = "InAppBrowserOptions"; static final String LOG_TAG = "InAppBrowserOptions";
public boolean useShouldOverrideUrlLoading = false;
public boolean useOnLoadResource = false;
public boolean openWithSystemBrowser = false;
public boolean clearCache = false;
public String userAgent = "";
public boolean javaScriptEnabled = true;
public boolean javaScriptCanOpenWindowsAutomatically = false;
public boolean hidden = false; public boolean hidden = false;
public boolean toolbarTop = true; public boolean toolbarTop = true;
public String toolbarTopBackgroundColor = ""; public String toolbarTopBackgroundColor = "";
public String toolbarTopFixedTitle = ""; public String toolbarTopFixedTitle = "";
public boolean hideUrlBar = false; public boolean hideUrlBar = false;
public boolean mediaPlaybackRequiresUserGesture = true;
public boolean isLocalFile = false;
public boolean hideTitleBar = false; public boolean hideTitleBar = false;
public boolean closeOnCannotGoBack = true; public boolean closeOnCannotGoBack = true;
public boolean clearSessionCache = false;
public boolean builtInZoomControls = false;
public boolean supportZoom = true;
public boolean databaseEnabled = false;
public boolean domStorageEnabled = false;
public boolean useWideViewPort = true;
public boolean safeBrowsingEnabled = true;
public boolean progressBar = true; public boolean progressBar = true;
} }

View File

@ -1,65 +1,82 @@
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.ConsoleMessage; import android.webkit.ConsoleMessage;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebView; import android.webkit.WebView;
import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class InAppBrowserWebChromeClient extends WebChromeClient { import io.flutter.plugin.common.MethodChannel;
public class InAppWebChromeClient extends WebChromeClient {
protected static final String LOG_TAG = "IABWebChromeClient"; protected static final String LOG_TAG = "IABWebChromeClient";
private WebViewActivity activity; private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
private ValueCallback<Uri[]> mUploadMessageArray; private ValueCallback<Uri[]> mUploadMessageArray;
private ValueCallback<Uri> mUploadMessage; private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1; private final static int FILECHOOSER_RESULTCODE = 1;
public InAppBrowserWebChromeClient(WebViewActivity activity) { public InAppWebChromeClient(Object obj) {
super(); super();
this.activity = activity; if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
} }
@Override @Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) { public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("sourceURL", consoleMessage.sourceId()); obj.put("sourceURL", consoleMessage.sourceId());
obj.put("lineNumber", consoleMessage.lineNumber()); obj.put("lineNumber", consoleMessage.lineNumber());
obj.put("message", consoleMessage.message()); obj.put("message", consoleMessage.message());
obj.put("messageLevel", consoleMessage.messageLevel().toString()); obj.put("messageLevel", consoleMessage.messageLevel().toString());
InAppBrowserFlutterPlugin.channel.invokeMethod("onConsoleMessage", obj); getChannel().invokeMethod("onConsoleMessage", obj);
return true; return true;
} }
@Override @Override
public void onProgressChanged(WebView view, int progress) { public void onProgressChanged(WebView view, int progress) {
if (activity.progressBar != null) { if (inAppBrowserActivity != null && inAppBrowserActivity.progressBar != null) {
activity.progressBar.setVisibility(View.VISIBLE); inAppBrowserActivity.progressBar.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
activity.progressBar.setProgress(progress, true); inAppBrowserActivity.progressBar.setProgress(progress, true);
} else { } else {
activity.progressBar.setProgress(progress); inAppBrowserActivity.progressBar.setProgress(progress);
} }
if (progress == 100) { if (progress == 100) {
activity.progressBar.setVisibility(View.GONE); inAppBrowserActivity.progressBar.setVisibility(View.GONE);
} }
} }
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("progress", progress);
getChannel().invokeMethod("onProgressChanged", obj);
super.onProgressChanged(view, progress); super.onProgressChanged(view, progress);
} }
@Override @Override
public void onReceivedTitle(WebView view, String title) { public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title); super.onReceivedTitle(view, title);
if (activity.actionBar != null && activity.options.toolbarTopFixedTitle.isEmpty()) if (inAppBrowserActivity != null && inAppBrowserActivity.actionBar != null && inAppBrowserActivity.options.toolbarTopFixedTitle.isEmpty())
activity.actionBar.setTitle(title); inAppBrowserActivity.actionBar.setTitle(title);
} }
@Override @Override
@ -76,7 +93,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT); Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE); i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*"); i.setType("image/*");
activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
} }
@ -86,7 +103,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT); Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE); i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*"); i.setType("*/*");
activity.startActivityForResult( ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(
Intent.createChooser(i, "File Browser"), Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE); FILECHOOSER_RESULTCODE);
} }
@ -97,7 +114,7 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
Intent i = new Intent(Intent.ACTION_GET_CONTENT); Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE); i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*"); i.setType("image/*");
activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
} }
@ -120,7 +137,11 @@ public class InAppBrowserWebChromeClient extends WebChromeClient {
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
activity.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
return true; return true;
} }
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
}
} }

View File

@ -0,0 +1,374 @@
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Build;
import android.util.AttributeSet;
import android.util.JsonReader;
import android.util.JsonToken;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.webkit.WebView;
import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappbrowser.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import static com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin.registrar;
public class InAppWebView extends WebView {
static final String LOG_TAG = "InAppWebView";
public InAppBrowserActivity inAppBrowserActivity;
public FlutterWebView flutterWebView;
int id;
InAppWebViewClient inAppWebViewClient;
InAppWebChromeClient inAppWebChromeClient;
public InAppWebViewOptions options;
public boolean isLoading = false;
OkHttpClient httpClient;
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
static final String consoleLogJS = "(function() {" +
" var oldLogs = {" +
" 'log': console.log," +
" 'debug': console.debug," +
" 'error': console.error," +
" 'info': console.info," +
" 'warn': console.warn" +
" };" +
" for (var k in oldLogs) {" +
" (function(oldLog) {" +
" console[oldLog] = function() {" +
" var message = '';" +
" for (var i in arguments) {" +
" if (message == '') {" +
" message += arguments[i];" +
" }" +
" else {" +
" message += ' ' + arguments[i];" +
" }" +
" }" +
" oldLogs[oldLog].call(console, message);" +
" }" +
" })(k);" +
" }" +
"})();";
public InAppWebView(Context context) {
super(context);
}
public InAppWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InAppWebView(Context context, AttributeSet attrs, int defaultStyle) {
super(context, attrs, defaultStyle);
}
public InAppWebView(Context context, Object obj, int id, InAppWebViewOptions options) {
super(context);
if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
this.id = id;
this.options = options;
}
public void prepare() {
boolean isFromInAppBrowserActivity = inAppBrowserActivity != null;
httpClient = new OkHttpClient().newBuilder().cache(new Cache(getContext().getCacheDir(), okHttpClientCacheSize)).build();
addJavascriptInterface(new JavaScriptBridgeInterface((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView), JavaScriptBridgeInterface.name);
inAppWebChromeClient = new InAppWebChromeClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
setWebChromeClient(inAppWebChromeClient);
inAppWebViewClient = new InAppWebViewClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
setWebViewClient(inAppWebViewClient);
// final Activity activity = this;
//
// webView.setDownloadListener(new DownloadListener() {
// @Override
// public void onDownloadStart(final String url, final String userAgent,
// final String contentDisposition, final String mimetype,
// final long contentLength) {
//
// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
// @Override
// public void run(){
// DownloadManager.Request request = new DownloadManager.Request(
// Uri.parse(url));
//
// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// request.allowScanningByMediaScanner();
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
// request.setVisibleInDownloadsUi(true);
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
// if (dm != null) {
// dm.enqueue(request);
// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
// Toast.LENGTH_LONG).show();
// }
// else {
// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
// Toast.LENGTH_LONG).show();
// }
// }
// });
// }
// });
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(options.javaScriptEnabled);
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
settings.setBuiltInZoomControls(options.builtInZoomControls);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
settings.setMediaPlaybackRequiresUserGesture(options.mediaPlaybackRequiresUserGesture);
settings.setDatabaseEnabled(options.databaseEnabled);
settings.setDomStorageEnabled(options.domStorageEnabled);
if (!options.userAgent.isEmpty())
settings.setUserAgentString(options.userAgent);
if (options.clearCache)
clearAllCache();
else if (options.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
// Enable Thirdparty Cookies on >=Android 5.0 device
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
CookieManager.getInstance().setAcceptThirdPartyCookies(this, true);
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(options.useWideViewPort);
settings.setSupportZoom(options.supportZoom);
// fix webview scaling
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
else
settings.setTextZoom(100);
}
public void loadUrl(String url, MethodChannel.Result result) {
if (!url.isEmpty()) {
loadUrl(url);
} else {
result.error(LOG_TAG, "url is empty", null);
}
}
public void loadUrl(String url, Map<String, String> headers, MethodChannel.Result result) {
if (!url.isEmpty()) {
loadUrl(url, headers);
} else {
result.error(LOG_TAG, "url is empty", null);
}
}
public void loadFile(String url, MethodChannel.Result result) {
try {
url = Util.getUrlAsset(registrar, url);
} catch (IOException e) {
result.error(LOG_TAG, url + " asset file cannot be found!", e);
return;
}
if (!url.isEmpty()) {
loadUrl(url);
} else {
result.error(LOG_TAG, "url is empty", null);
}
}
public void loadFile(String url, Map<String, String> headers, MethodChannel.Result result) {
try {
url = Util.getUrlAsset(registrar, url);
} catch (IOException e) {
result.error(LOG_TAG, url + " asset file cannot be found!", e);
return;
}
if (!url.isEmpty()) {
loadUrl(url, headers);
} else {
result.error(LOG_TAG, "url is empty", null);
}
}
public boolean isLoading() {
return isLoading;
}
private void clearCookies() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().removeAllCookies(new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean aBoolean) {
}
});
} else {
CookieManager.getInstance().removeAllCookie();
}
}
public void clearAllCache() {
clearCache(true);
clearCookies();
clearFormData();
}
public byte[] takeScreenshot() {
Picture picture = capturePicture();
Bitmap b = Bitmap.createBitmap( getWidth(),
getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
picture.draw(c);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
public void setOptions(InAppWebViewOptions newOptions, HashMap<String, Object> newOptionsMap) {
WebSettings settings = getSettings();
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
if (newOptionsMap.get("mediaPlaybackRequiresUserGesture") != null && options.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture)
settings.setMediaPlaybackRequiresUserGesture(newOptions.mediaPlaybackRequiresUserGesture);
if (newOptionsMap.get("databaseEnabled") != null && options.databaseEnabled != newOptions.databaseEnabled)
settings.setDatabaseEnabled(newOptions.databaseEnabled);
if (newOptionsMap.get("domStorageEnabled") != null && options.domStorageEnabled != newOptions.domStorageEnabled)
settings.setDomStorageEnabled(newOptions.domStorageEnabled);
if (newOptionsMap.get("userAgent") != null && options.userAgent != newOptions.userAgent && !newOptions.userAgent.isEmpty())
settings.setUserAgentString(newOptions.userAgent);
if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
clearAllCache();
else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
settings.setUseWideViewPort(newOptions.useWideViewPort);
if (newOptionsMap.get("supportZoom") != null && options.supportZoom != newOptions.supportZoom)
settings.setSupportZoom(newOptions.supportZoom);
options = newOptions;
}
public HashMap<String, Object> getOptions() {
return (options != null) ? options.getHashMap() : null;
}
public void injectDeferredObject(String source, String jsWrapper, final MethodChannel.Result result) {
String scriptToInject;
if (jsWrapper != null) {
org.json.JSONArray jsonEsc = new org.json.JSONArray();
jsonEsc.put(source);
String jsonRepr = jsonEsc.toString();
String jsonSourceString = jsonRepr.substring(1, jsonRepr.length() - 1);
scriptToInject = String.format(jsWrapper, jsonSourceString);
} else {
scriptToInject = source;
}
final String finalScriptToInject = scriptToInject;
( (inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity ).runOnUiThread(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
// This action will have the side-effect of blurring the currently focused element
loadUrl("javascript:" + finalScriptToInject);
} else {
evaluateJavascript(finalScriptToInject, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
if (result == null)
return;
JsonReader reader = new JsonReader(new StringReader(s));
// Must set lenient to parse single values
reader.setLenient(true);
try {
String msg;
if (reader.peek() == JsonToken.STRING) {
msg = reader.nextString();
JsonReader reader2 = new JsonReader(new StringReader(msg));
reader2.setLenient(true);
if (reader2.peek() == JsonToken.STRING)
msg = reader2.nextString();
result.success(msg);
} else {
result.success("");
}
} catch (IOException e) {
Log.e(LOG_TAG, "IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
}
}
});
}
}

View File

@ -1,4 +1,4 @@
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -16,6 +16,11 @@ import android.webkit.WebResourceResponse;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -27,16 +32,24 @@ import io.flutter.plugin.common.MethodChannel;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
public class InAppBrowserWebViewClient extends WebViewClient { public class InAppWebViewClient extends WebViewClient {
protected static final String LOG_TAG = "IABWebViewClient"; protected static final String LOG_TAG = "IABWebViewClient";
private WebViewActivity activity; private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>(); Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>();
long startPageTime = 0; long startPageTime = 0;
public InAppBrowserWebViewClient(WebViewActivity activity) { public InAppWebViewClient(Object obj) {
super(); super();
this.activity = activity; if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
prepareStatusCodeMapping();
}
private void prepareStatusCodeMapping () {
statusCodeMapping.put(100, "Continue"); statusCodeMapping.put(100, "Continue");
statusCodeMapping.put(101, "Switching Protocols"); statusCodeMapping.put(101, "Switching Protocols");
statusCodeMapping.put(200, "OK"); statusCodeMapping.put(200, "OK");
@ -90,11 +103,12 @@ public class InAppBrowserWebViewClient extends WebViewClient {
@Override @Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) { public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (activity.options.useShouldOverrideUrlLoading) { if (((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useShouldOverrideUrlLoading) {
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url); obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("shouldOverrideUrlLoading", obj); getChannel().invokeMethod("shouldOverrideUrlLoading", obj);
return true; return true;
} }
@ -102,7 +116,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_DIAL); Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
activity.startActivity(intent); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true; return true;
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString()); Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
@ -111,7 +125,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
activity.startActivity(intent); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true; return true;
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error with " + url + ": " + e.toString()); Log.e(LOG_TAG, "Error with " + url + ": " + e.toString());
@ -142,7 +156,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
intent.setData(Uri.parse("sms:" + address)); intent.setData(Uri.parse("sms:" + address));
intent.putExtra("address", address); intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms"); intent.setType("vnd.android-dir/mms-sms");
activity.startActivity(intent); ((inAppBrowserActivity != null) ? inAppBrowserActivity : flutterWebView.activity).startActivity(intent);
return true; return true;
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString()); Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
@ -167,23 +181,24 @@ public class InAppBrowserWebViewClient extends WebViewClient {
startPageTime = System.currentTimeMillis(); startPageTime = System.currentTimeMillis();
activity.isLoading = true; ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = true;
if (activity.searchView != null && !url.equals(activity.searchView.getQuery().toString())) { if (inAppBrowserActivity != null && inAppBrowserActivity.searchView != null && !url.equals(inAppBrowserActivity.searchView.getQuery().toString())) {
activity.searchView.setQuery(url, false); inAppBrowserActivity.searchView.setQuery(url, false);
} }
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url); obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStart", obj); getChannel().invokeMethod("onLoadStart", obj);
} }
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url); super.onPageFinished(view, url);
activity.isLoading = false; ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage // CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -197,38 +212,41 @@ public class InAppBrowserWebViewClient extends WebViewClient {
view.requestFocus(); view.requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
view.evaluateJavascript(WebViewActivity.consoleLogJS, null); view.evaluateJavascript(InAppWebView.consoleLogJS, null);
view.evaluateJavascript(JavaScriptBridgeInterface.flutterInAppBroserJSClass, null); view.evaluateJavascript(JavaScriptBridgeInterface.flutterInAppBroserJSClass, null);
} }
else { else {
view.loadUrl("javascript:"+WebViewActivity.consoleLogJS); view.loadUrl("javascript:"+InAppWebView.consoleLogJS);
view.loadUrl("javascript:"+JavaScriptBridgeInterface.flutterInAppBroserJSClass); view.loadUrl("javascript:"+JavaScriptBridgeInterface.flutterInAppBroserJSClass);
} }
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url); obj.put("url", url);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadStop", obj); getChannel().invokeMethod("onLoadStop", obj);
} }
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl); super.onReceivedError(view, errorCode, description, failingUrl);
activity.isLoading = false; ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", failingUrl); obj.put("url", failingUrl);
obj.put("code", errorCode); obj.put("code", errorCode);
obj.put("message", description); obj.put("message", description);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadError", obj); getChannel().invokeMethod("onLoadError", obj);
} }
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error); super.onReceivedSslError(view, handler, error);
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", error.getUrl()); obj.put("url", error.getUrl());
obj.put("code", error.getPrimaryError()); obj.put("code", error.getPrimaryError());
String message; String message;
@ -254,7 +272,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
break; break;
} }
obj.put("message", "SslError: " + message); obj.put("message", "SslError: " + message);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadError", obj); getChannel().invokeMethod("onLoadError", obj);
handler.cancel(); handler.cancel();
} }
@ -271,8 +289,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override @Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (!request.getMethod().toLowerCase().equals("get") ||
if (!request.getMethod().toLowerCase().equals("get") || !activity.options.useOnLoadResource) { !(((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).options.useOnLoadResource)) {
return null; return null;
} }
@ -282,7 +300,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
Request mRequest = new Request.Builder().url(url).build(); Request mRequest = new Request.Builder().url(url).build();
long startResourceTime = System.currentTimeMillis(); long startResourceTime = System.currentTimeMillis();
Response response = activity.httpClient.newCall(mRequest).execute(); Response response = ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).httpClient.newCall(mRequest).execute();
long startTime = startResourceTime - startPageTime; long startTime = startResourceTime - startPageTime;
startTime = (startTime < 0) ? 0 : startTime; startTime = (startTime < 0) ? 0 : startTime;
long duration = System.currentTimeMillis() - startResourceTime; long duration = System.currentTimeMillis() - startResourceTime;
@ -319,7 +337,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
Map<String, Object> res = new HashMap<>(); Map<String, Object> res = new HashMap<>();
Map<String, Object> req = new HashMap<>(); Map<String, Object> req = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
byte[] dataBytes = response.body().bytes(); byte[] dataBytes = response.body().bytes();
InputStream dataStream = new ByteArrayInputStream(dataBytes); InputStream dataStream = new ByteArrayInputStream(dataBytes);
@ -338,7 +357,7 @@ public class InAppBrowserWebViewClient extends WebViewClient {
obj.put("response", res); obj.put("response", res);
obj.put("request", req); obj.put("request", req);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadResource", obj); getChannel().invokeMethod("onLoadResource", obj);
return new WebResourceResponse( return new WebResourceResponse(
response.header("content-type", "text/plain").split(";")[0].trim(), response.header("content-type", "text/plain").split(";")[0].trim(),
@ -359,5 +378,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
return null; return null;
} }
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
}
} }

View File

@ -0,0 +1,24 @@
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import com.pichillilorenzo.flutter_inappbrowser.Options;
public class InAppWebViewOptions extends Options {
static final String LOG_TAG = "InAppWebViewOptions";
public boolean useShouldOverrideUrlLoading = false;
public boolean useOnLoadResource = false;
public boolean clearCache = false;
public String userAgent = "";
public boolean javaScriptEnabled = true;
public boolean javaScriptCanOpenWindowsAutomatically = false;
public boolean mediaPlaybackRequiresUserGesture = true;
public boolean clearSessionCache = false;
public boolean builtInZoomControls = false;
public boolean supportZoom = true;
public boolean databaseEnabled = false;
public boolean domStorageEnabled = false;
public boolean useWideViewPort = true;
public boolean safeBrowsingEnabled = true;
}

View File

@ -5,25 +5,36 @@ import android.webkit.JavascriptInterface;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
public class JavaScriptBridgeInterface { public class JavaScriptBridgeInterface {
private static final String LOG_TAG = "JSBridgeInterface"; private static final String LOG_TAG = "JSBridgeInterface";
static final String name = "flutter_inappbrowser"; public static final String name = "flutter_inappbrowser";
WebViewActivity activity; private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity;
static final String flutterInAppBroserJSClass = "window." + name + ".callHandler = function(handlerName, ...args) {" + public static final String flutterInAppBroserJSClass = "window." + name + ".callHandler = function(handlerName, ...args) {" +
"window." + name + "._callHandler(handlerName, JSON.stringify(args));" + "window." + name + "._callHandler(handlerName, JSON.stringify(args));" +
"}"; "}";
JavaScriptBridgeInterface(WebViewActivity a) { public JavaScriptBridgeInterface(Object obj) {
activity = a; if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj;
else if (obj instanceof FlutterWebView)
this.flutterWebView = (FlutterWebView) obj;
} }
@JavascriptInterface @JavascriptInterface
public void _callHandler(String handlerName, String args) { public void _callHandler(String handlerName, String args) {
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
obj.put("uuid", activity.uuid); if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("handlerName", handlerName); obj.put("handlerName", handlerName);
obj.put("args", args); obj.put("args", args);
InAppBrowserFlutterPlugin.channel.invokeMethod("onCallJsHandler", obj); getChannel().invokeMethod("onCallJsHandler", obj);
}
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
} }
} }

View File

@ -9,7 +9,7 @@ import java.util.HashMap;
public class Options { public class Options {
static String LOG_TAG = ""; static String LOG_TAG = "Options";
public Options parse(HashMap<String, Object> options) { public Options parse(HashMap<String, Object> options) {
Iterator it = options.entrySet().iterator(); Iterator it = options.entrySet().iterator();

View File

@ -0,0 +1,39 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.content.res.AssetManager;
import java.io.IOException;
import java.io.InputStream;
import io.flutter.plugin.common.PluginRegistry;
public class Util {
public static final String ANDROID_ASSET_URL = "file:///android_asset/";
public static String getUrlAsset (PluginRegistry.Registrar registrar, String assetFilePath) throws IOException {
String key = registrar.lookupKeyForAsset(assetFilePath);
AssetManager mg = registrar.activeContext().getResources().getAssets();
InputStream is = null;
IOException e = null;
try {
is = mg.open(key);
} catch (IOException ex) {
e = ex;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) {
e = ex;
}
}
}
if (e != null) {
throw e;
}
return ANDROID_ASSET_URL + key;
}
}

View File

@ -1,517 +0,0 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.SearchView;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
public class WebViewActivity extends AppCompatActivity {
String uuid;
WebView webView;
ActionBar actionBar;
Menu menu;
InAppBrowserWebViewClient inAppBrowserWebViewClient;
InAppBrowserWebChromeClient inAppBrowserWebChromeClient;
SearchView searchView;
InAppBrowserOptions options;
Map<String, String> headers;
ProgressBar progressBar;
public boolean isLoading = false;
public boolean isHidden = false;
OkHttpClient httpClient;
static final String consoleLogJS = "(function() {" +
" var oldLogs = {" +
" 'log': console.log," +
" 'debug': console.debug," +
" 'error': console.error," +
" 'info': console.info," +
" 'warn': console.warn" +
" };" +
" for (var k in oldLogs) {" +
" (function(oldLog) {" +
" console[oldLog] = function() {" +
" var message = '';" +
" for (var i in arguments) {" +
" if (message == '') {" +
" message += arguments[i];" +
" }" +
" else {" +
" message += ' ' + arguments[i];" +
" }" +
" }" +
" oldLogs[oldLog].call(console, message);" +
" }" +
" })(k);" +
" }" +
"})();";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
webView = findViewById(R.id.webView);
Bundle b = getIntent().getExtras();
uuid = b.getString("uuid");
String url = b.getString("url");
options = new InAppBrowserOptions();
options.parse((HashMap<String, Object>) b.getSerializable("options"));
headers = (HashMap<String, String>) b.getSerializable("headers");
InAppBrowserFlutterPlugin.webViewActivities.put(uuid, this);
actionBar = getSupportActionBar();
prepareWebView();
int cacheSize = 10 * 1024 * 1024; // 10MB
httpClient = new OkHttpClient().newBuilder().cache(new Cache(getApplicationContext().getCacheDir(), cacheSize)).build();
webView.loadUrl(url, headers);
//webView.loadData("<!DOCTYPE assets> <assets lang=\"en\"> <head> <meta charset=\"UTF-8\"> <title>Document</title> </head> <body> ciao <img src=\"https://via.placeholder.com/350x150\" /> <img src=\"./images/test\" alt=\"not found\" /></body> </assets>", "text/assets", "utf8");
}
private void prepareWebView() {
webView.addJavascriptInterface(new JavaScriptBridgeInterface(this), JavaScriptBridgeInterface.name);
inAppBrowserWebChromeClient = new InAppBrowserWebChromeClient(this);
webView.setWebChromeClient(inAppBrowserWebChromeClient);
inAppBrowserWebViewClient = new InAppBrowserWebViewClient(this);
webView.setWebViewClient(inAppBrowserWebViewClient);
// final Activity activity = this;
//
// webView.setDownloadListener(new DownloadListener() {
// @Override
// public void onDownloadStart(final String url, final String userAgent,
// final String contentDisposition, final String mimetype,
// final long contentLength) {
//
// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
// @Override
// public void run(){
// DownloadManager.Request request = new DownloadManager.Request(
// Uri.parse(url));
//
// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// request.allowScanningByMediaScanner();
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
// request.setVisibleInDownloadsUi(true);
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
// if (dm != null) {
// dm.enqueue(request);
// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
// Toast.LENGTH_LONG).show();
// }
// else {
// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
// Toast.LENGTH_LONG).show();
// }
// }
// });
// }
// });
WebSettings settings = webView.getSettings();
if (options.hidden)
hide();
else
show();
settings.setJavaScriptEnabled(options.javaScriptEnabled);
settings.setJavaScriptCanOpenWindowsAutomatically(options.javaScriptCanOpenWindowsAutomatically);
settings.setBuiltInZoomControls(options.builtInZoomControls);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(options.safeBrowsingEnabled);
settings.setMediaPlaybackRequiresUserGesture(options.mediaPlaybackRequiresUserGesture);
settings.setDatabaseEnabled(options.databaseEnabled);
settings.setDomStorageEnabled(options.domStorageEnabled);
if (!options.userAgent.isEmpty())
settings.setUserAgentString(options.userAgent);
if (options.clearCache)
clearCache();
else if (options.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
// Enable Thirdparty Cookies on >=Android 5.0 device
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(options.useWideViewPort);
settings.setSupportZoom(options.supportZoom);
// fix webview scaling
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
else
settings.setTextZoom(100);
progressBar = findViewById(R.id.progressBar);
if (!options.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
actionBar.setDisplayShowTitleEnabled(!options.hideTitleBar);
if (!options.toolbarTop)
actionBar.hide();
if (!options.toolbarTopBackgroundColor.isEmpty())
actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(options.toolbarTopBackgroundColor)));
if (!options.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(options.toolbarTopFixedTitle);
}
@Override
public boolean onCreateOptionsMenu(Menu m) {
menu = m;
MenuInflater inflater = getMenuInflater();
// Inflate menu to add items to action bar if it is present.
inflater.inflate(R.menu.menu_main, menu);
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setFocusable(true);
if (options.hideUrlBar)
menu.findItem(R.id.menu_search).setVisible(false);
searchView.setQuery(webView.getUrl(), false);
if (options.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(webView.getTitle());
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
if (!query.isEmpty()) {
webView.loadUrl(query);
searchView.setQuery("", false);
searchView.setIconified(true);
return true;
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
if (searchView.getQuery().toString().isEmpty())
searchView.setQuery(webView.getUrl(), false);
return false;
}
});
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (!b) {
searchView.setQuery("", false);
searchView.setIconified(true);
}
}
});
return true;
}
public void loadUrl(String url, MethodChannel.Result result) {
if (webView != null && !url.isEmpty()) {
webView.loadUrl(url);
} else {
result.error("Cannot load url", "", null);
}
}
public void loadUrl(String url, Map<String, String> headers, MethodChannel.Result result) {
if (webView != null && !url.isEmpty()) {
webView.loadUrl(url, headers);
} else {
result.error("Cannot load url", "", null);
}
}
public void loadFile(String url, MethodChannel.Result result) {
if (webView != null && !url.isEmpty()) {
webView.loadUrl(url);
} else {
result.error("Cannot load url", "", null);
}
}
public void loadFile(String url, Map<String, String> headers, MethodChannel.Result result) {
if (webView != null && !url.isEmpty()) {
webView.loadUrl(url, headers);
} else {
result.error("Cannot load url", "", null);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
if (canGoBack())
goBack();
else if (options.closeOnCannotGoBack)
InAppBrowserFlutterPlugin.close(uuid, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void close() {
hide();
finish();
}
public void reload() {
if (webView != null)
webView.reload();
}
public void goBack() {
if (webView != null && canGoBack())
webView.goBack();
}
public void goForward() {
if (webView != null && canGoForward())
webView.goForward();
}
public boolean canGoBack() {
return webView.canGoBack();
}
public boolean canGoForward() {
return webView.canGoForward();
}
public void hide() {
isHidden = true;
Intent openActivity = new Intent(this, InAppBrowserFlutterPlugin.registrar.activity().getClass());
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0);
}
public void show() {
isHidden = false;
Intent openActivity = new Intent(InAppBrowserFlutterPlugin.registrar.activity(), WebViewActivity.class);
openActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityIfNeeded(openActivity, 0);
}
public void stopLoading() {
if (webView != null)
webView.stopLoading();
}
public boolean isLoading() {
if (webView != null)
return isLoading;
return false;
}
private void clearCookies() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().removeAllCookies(new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean aBoolean) {
}
});
} else {
CookieManager.getInstance().removeAllCookie();
}
}
private void clearCache() {
if (webView != null) {
webView.clearCache(true);
clearCookies();
webView.clearFormData();
}
}
public void goBackButtonClicked(MenuItem item) {
goBack();
}
public void goForwardButtonClicked(MenuItem item) {
goForward();
}
public void shareButtonClicked(MenuItem item) {
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
startActivity(Intent.createChooser(share, "Share"));
}
public void reloadButtonClicked(MenuItem item) {
reload();
}
public void closeButtonClicked(MenuItem item) {
InAppBrowserFlutterPlugin.close(uuid, null);
}
public byte[] takeScreenshot() {
if (webView != null) {
Picture picture = webView.capturePicture();
Bitmap b = Bitmap.createBitmap( webView.getWidth(),
webView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
picture.draw(c);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
return null;
}
public void setOptions(InAppBrowserOptions newOptions, HashMap<String, Object> newOptionsMap) {
WebSettings settings = webView.getSettings();
if (newOptionsMap.get("hidden") != null && options.hidden != newOptions.hidden) {
if (newOptions.hidden)
hide();
else
show();
}
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
if (newOptionsMap.get("mediaPlaybackRequiresUserGesture") != null && options.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture)
settings.setMediaPlaybackRequiresUserGesture(newOptions.mediaPlaybackRequiresUserGesture);
if (newOptionsMap.get("databaseEnabled") != null && options.databaseEnabled != newOptions.databaseEnabled)
settings.setDatabaseEnabled(newOptions.databaseEnabled);
if (newOptionsMap.get("domStorageEnabled") != null && options.domStorageEnabled != newOptions.domStorageEnabled)
settings.setDomStorageEnabled(newOptions.domStorageEnabled);
if (newOptionsMap.get("userAgent") != null && options.userAgent != newOptions.userAgent && !newOptions.userAgent.isEmpty())
settings.setUserAgentString(newOptions.userAgent);
if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
clearCache();
else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
settings.setUseWideViewPort(newOptions.useWideViewPort);
if (newOptionsMap.get("supportZoom") != null && options.supportZoom != newOptions.supportZoom)
settings.setSupportZoom(newOptions.supportZoom);
if (newOptionsMap.get("progressBar") != null && options.progressBar != newOptions.progressBar && progressBar != null) {
if (newOptions.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
}
if (newOptionsMap.get("hideTitleBar") != null && options.hideTitleBar != newOptions.hideTitleBar)
actionBar.setDisplayShowTitleEnabled(!newOptions.hideTitleBar);
if (newOptionsMap.get("toolbarTop") != null && options.toolbarTop != newOptions.toolbarTop) {
if (!newOptions.toolbarTop)
actionBar.hide();
else
actionBar.show();
}
if (newOptionsMap.get("toolbarTopBackgroundColor") != null && options.toolbarTopBackgroundColor != newOptions.toolbarTopBackgroundColor && !newOptions.toolbarTopBackgroundColor.isEmpty())
actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(newOptions.toolbarTopBackgroundColor)));
if (newOptionsMap.get("toolbarTopFixedTitle") != null && options.toolbarTopFixedTitle != newOptions.toolbarTopFixedTitle && !newOptions.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(newOptions.toolbarTopFixedTitle);
if (newOptionsMap.get("hideUrlBar") != null && options.hideUrlBar != newOptions.hideUrlBar) {
if (newOptions.hideUrlBar)
menu.findItem(R.id.menu_search).setVisible(false);
else
menu.findItem(R.id.menu_search).setVisible(true);
}
options = newOptions;
}
public HashMap<String, Object> getOptions() {
return (options != null) ? options.getHashMap() : null;
}
}

View File

@ -7,15 +7,13 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:clickable="true" android:clickable="true"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
tools:context=".WebViewActivity" tools:context=".InAppBrowserActivity"
android:focusable="true"> android:focusable="true">
<WebView <com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView
android:id="@+id/webView" android:id="@+id/webView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent" />
</WebView>
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"

View File

@ -3,7 +3,7 @@
xmlns:appcompat="http://schemas.android.com/apk/res-auto" xmlns:appcompat="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".WebViewActivity"> tools:context=".InAppBrowserActivity">
<item <item
android:id="@+id/action_go_back" android:id="@+id/action_go_back"

View File

@ -7,15 +7,20 @@ class MyInAppBrowser extends InAppBrowser {
@override @override
Future onLoadStart(String url) async { Future onLoadStart(String url) async {
print("\n\nStarted $url\n\n"); print("\n\nStarted $url\n\n");
//print("\n\n ${await this.isHidden()} \n\n"); print("\n\n ${await this.isHidden()} \n\n");
print(await this.webViewController.canGoBack());
print(await this.webViewController.canGoForward());
} }
@override @override
Future onLoadStop(String url) async { Future onLoadStop(String url) async {
print("\n\nStopped $url\n\n"); print("\n\nStopped $url\n\n");
// var screenshot = await this.takeScreenshot(); // print(await this.webViewController.canGoBack());
// await this.injectScriptCode(""" // print(await this.webViewController.canGoForward());
// var screenshot = await this.webViewController.takeScreenshot();
// await this.webViewController.injectScriptCode("""
// document.body.innerHTML = '<img style="max-width: 100%; width: 100%" src="data:image/png;base64,${base64.encode(screenshot)}" />'; // document.body.innerHTML = '<img style="max-width: 100%; width: 100%" src="data:image/png;base64,${base64.encode(screenshot)}" />';
// """); // """);
@ -48,49 +53,49 @@ class MyInAppBrowser extends InAppBrowser {
// } // }
// print("\n\n ${await this.isHidden()} \n\n"); // print("\n\n ${await this.isHidden()} \n\n");
// await this.injectScriptCode("window.flutter_inappbrowser.callHandler('handlerTest', 1, 5,'string', {'key': 5}, [4,6,8]);");
// await this.injectScriptCode("window.flutter_inappbrowser.callHandler('handlerTest2', false, null, undefined);");
// await this.injectScriptCode("setTimeout(function(){window.flutter_inappbrowser.callHandler('handlerTest', 'anotherString');}, 1000);");
// //
// await this.injectScriptCode("console.log({'testObject': 5});"); // await this.webViewController.injectScriptCode("window.flutter_inappbrowser.callHandler('handlerTest', 1, 5,'string', {'key': 5}, [4,6,8]);");
// await this.injectScriptCode("console.warn('testWarn',null);"); // await this.webViewController.injectScriptCode("window.flutter_inappbrowser.callHandler('handlerTest2', false, null, undefined);");
// await this.injectScriptCode("console.log('testObjectStringify', JSON.stringify({'asd': 5}));"); // await this.webViewController.injectScriptCode("setTimeout(function(){window.flutter_inappbrowser.callHandler('handlerTest', 'anotherString');}, 1000);");
// await this.injectScriptCode("console.info('testInfo', 6);");
// await this.injectScriptCode("console.error('testError', false);");
// await this.injectScriptCode("console.debug('testDebug', true);");
// print(await this.injectScriptCode("document.body.innerHTML")); // await this.webViewController.injectScriptCode("console.log({'testObject': 5});");
// await this.webViewController.injectScriptCode("console.warn('testWarn',null);");
// print(await this.injectScriptCode("null")); // await this.webViewController.injectScriptCode("console.log('testObjectStringify', JSON.stringify({'asd': 5}));");
// print(await this.injectScriptCode("undefined")); // await this.webViewController.injectScriptCode("console.info('testInfo', 6);");
// print(await this.injectScriptCode("3")); // await this.webViewController.injectScriptCode("console.error('testError', false);");
// print(await this.injectScriptCode(""" // await this.webViewController.injectScriptCode("console.debug('testDebug', true);");
//
// print(await this.webViewController.injectScriptCode("document.body.innerHTML"));
//
// print(await this.webViewController.injectScriptCode("null"));
// print(await this.webViewController.injectScriptCode("undefined"));
// print(await this.webViewController.injectScriptCode("3"));
// print(await this.webViewController.injectScriptCode("""
// function asd (a,b) { // function asd (a,b) {
// return a+b; // return a+b;
// }; // };
// asd(3,5); // asd(3,5);
// """)); // """));
// print(await this.injectScriptCode(""" // print(await this.webViewController.injectScriptCode("""
// ["3",56,"sdf"]; // ["3",56,"sdf"];
// """)); // """));
// print(await this.injectScriptCode(""" // print(await this.webViewController.injectScriptCode("""
// var x = {"as":4, "dfdfg": 6}; // var x = {"as":4, "dfdfg": 6};
// x; // x;
// """)); // """));
// //
// await this.injectScriptFile("https://code.jquery.com/jquery-3.3.1.min.js"); // await this.webViewController.injectScriptFile("https://code.jquery.com/jquery-3.3.1.min.js");
// this.injectScriptCode(""" // this.webViewController.injectScriptCode("""
// \$( "body" ).html( "Next Step..." ) // \$( "body" ).html( "Next Step..." )
// """); // """);
// //
// // add custom css // // add custom css
// this.injectStyleCode(""" // this.webViewController.injectStyleCode("""
// body { // body {
// background-color: #3c3c3c !important; // background-color: #3c3c3c !important;
// } // }
// """); // """);
// this.injectStyleFile("https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"); // this.webViewController.injectStyleFile("https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css");
} }
@override @override
@ -98,6 +103,11 @@ class MyInAppBrowser extends InAppBrowser {
print("\n\nCan't load $url.. Error: $message\n\n"); print("\n\nCan't load $url.. Error: $message\n\n");
} }
@override
void onProgressChanged(int progress) {
print("Progress: $progress");
}
@override @override
void onExit() { void onExit() {
print("\n\nBrowser closed!\n\n"); print("\n\nBrowser closed!\n\n");
@ -106,7 +116,7 @@ class MyInAppBrowser extends InAppBrowser {
@override @override
void shouldOverrideUrlLoading(String url) { void shouldOverrideUrlLoading(String url) {
print("\n\n override $url\n\n"); print("\n\n override $url\n\n");
this.loadUrl(url); this.webViewController.loadUrl(url);
} }
@override @override
@ -159,8 +169,10 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
// adding a webview fallback // adding a webview fallback
MyChromeSafariBrowser chromeSafariBrowser = MyChromeSafariBrowser chromeSafariBrowser =
new MyChromeSafariBrowser(inAppBrowserFallback); new MyChromeSafariBrowser(inAppBrowserFallback);
InAppLocalhostServer localhostServer = new InAppLocalhostServer();
Future main() async { Future main() async {
// await localhostServer.start();
runApp(new MyApp()); runApp(new MyApp());
} }
@ -173,15 +185,15 @@ class _MyAppState extends State<MyApp> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// int indexTest = inAppBrowserFallback.addJavaScriptHandler("handlerTest", // int indexTest = inAppBrowserFallback.webViewController.addJavaScriptHandler("handlerTest",
// (arguments) async { // (arguments) async {
// print("handlerTest arguments"); // print("handlerTest arguments");
// print(arguments); // print(arguments);
// }); // });
// int indexTest2 = inAppBrowserFallback.addJavaScriptHandler("test2", (arguments) async { // int indexTest2 = inAppBrowserFallback.webViewController.addJavaScriptHandler("test2", (arguments) async {
// print("handlerTest2 arguments"); // print("handlerTest2 arguments");
// print(arguments); // print(arguments);
// inAppBrowserFallback.removeJavaScriptHandler("test", indexTest); // inAppBrowserFallback.webViewController.removeJavaScriptHandler("test", indexTest);
// }); // });
} }
@ -194,34 +206,32 @@ class _MyAppState extends State<MyApp> {
), ),
body: new Center( body: new Center(
child: new RaisedButton( child: new RaisedButton(
onPressed: () async { onPressed: () async {
// await chromeSafariBrowser.open("https://flutter.io/"); // await chromeSafariBrowser.open("https://flutter.io/");
//
// await InAppBrowser.openWithSystemBrowser("https://flutter.io/"); // await InAppBrowser.openWithSystemBrowser("https://flutter.io/");
//
// await inAppBrowserFallback.openOnLocalhost("assets/index.html", options: { // await inAppBrowserFallback.open(url: "http://localhost:8080/assets/index.html", options: {
// "useOnLoadResource": true, // "useOnLoadResource": true,
// //"hidden": true, // //"hidden": true,
// //"toolbarTopFixedTitle": "Fixed title", // //"toolbarTopFixedTitle": "Fixed title",
// //"useShouldOverrideUrlLoading": true // //"useShouldOverrideUrlLoading": true
// //"hideUrlBar": true, // //"hideUrlBar": true,
// //"toolbarTop": false, // //"toolbarTop": false,
// //"toolbarBottom": false // "toolbarBottom": false
// }); // });
//
// await inAppBrowserFallback.open(url: "assets/index.html", options: { // await inAppBrowserFallback.openFile("assets/index.html", options: {
// "isLocalFile": true,
// "useOnLoadResource": true, // "useOnLoadResource": true,
// //"hidden": true, // //"hidden": true,
// //"toolbarTopFixedTitle": "Fixed title",
// //"useShouldOverrideUrlLoading": true // //"useShouldOverrideUrlLoading": true
// //"hideUrlBar": true, // //"hideUrlBar": true,
// //"toolbarTop": false, // //"toolbarTop": false,
// //"toolbarBottom": false // //"toolbarBottom": false
// }); // });
//
await inAppBrowserFallback.open(url: "https://flutter.io/", options: { await inAppBrowserFallback.open(url: "https://flutter.io/", options: {
//"useOnLoadResource": true, "useOnLoadResource": true,
//"hidden": true, //"hidden": true,
//"toolbarTopFixedTitle": "Fixed title", //"toolbarTopFixedTitle": "Fixed title",
//"useShouldOverrideUrlLoading": true //"useShouldOverrideUrlLoading": true
@ -229,11 +239,143 @@ class _MyAppState extends State<MyApp> {
//"toolbarTop": false, //"toolbarTop": false,
//"toolbarBottom": false //"toolbarBottom": false
}); });
//await inAppBrowserFallback.openOnLocalhost("assets/index.html"); },
}, child: Text("Open InAppBrowser")
child: Text("Open InAppBrowser")), ),
), ),
), ),
); );
} }
} }
// Inline WebView Example
//
//import 'dart:async';
//import 'package:flutter/material.dart';
//import 'package:flutter_inappbrowser/flutter_inappbrowser.dart';
//
//Future main() async {
// runApp(new MyApp());
//}
//
//class MyApp extends StatefulWidget {
// @override
// _MyAppState createState() => new _MyAppState();
//}
//
//class _MyAppState extends State<MyApp> {
//
// InAppWebViewController webView;
// String url = "";
// double progress = 0;
//
// @override
// void initState() {
// super.initState();
// }
//
// @override
// void dispose() {
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return MaterialApp(
// home: Scaffold(
// appBar: AppBar(
// title: const Text('Inline WebView example app'),
// ),
// body: Container(
// child: Column(
// children: <Widget>[
// Container(
// padding: EdgeInsets.all(20.0),
// child: Text("CURRENT URL\n${ (url.length > 50) ? url.substring(0, 50) + "..." : url }"),
// ),
// (progress != 1.0) ? LinearProgressIndicator(value: progress) : null,
// Expanded(
// child: Container(
// margin: const EdgeInsets.all(10.0),
// decoration: BoxDecoration(
// border: Border.all(color: Colors.blueAccent)
// ),
// child: InAppWebView(
// initialUrl: "https://flutter.io/",
// initialHeaders: {
//
// },
// initialOptions: {
//
// },
// onWebViewCreated: (InAppWebViewController controller) {
// webView = controller;
// },
// onLoadStart: (InAppWebViewController controller, String url) {
// print("started $url");
// setState(() {
// this.url = url;
// });
// },
// onProgressChanged: (InAppWebViewController controller, int progress) {
// setState(() {
// this.progress = progress/100;
// });
// },
// ),
// ),
// ),
// ButtonBar(
// alignment: MainAxisAlignment.center,
// children: <Widget>[
// RaisedButton(
// child: Icon(Icons.arrow_back),
// onPressed: () {
// if (webView != null) {
// webView.goBack();
// }
// },
// ),
// RaisedButton(
// child: Icon(Icons.arrow_forward),
// onPressed: () {
// if (webView != null) {
// webView.goForward();
// }
// },
// ),
// RaisedButton(
// child: Icon(Icons.refresh),
// onPressed: () {
// if (webView != null) {
// webView.reload();
// }
// },
// ),
// ],
// ),
// ].where((Object o) => o != null).toList(),
// ),
// ),
// bottomNavigationBar: BottomNavigationBar(
// currentIndex: 0,
// items: [
// BottomNavigationBarItem(
// icon: Icon(Icons.home),
// title: Text('Home'),
// ),
// BottomNavigationBarItem(
// icon: Icon(Icons.mail),
// title: Text('Item 2'),
// ),
// BottomNavigationBarItem(
// icon: Icon(Icons.person),
// title: Text('Item 3')
// )
// ],
// ),
// ),
// );
// }
//}

View File

@ -20,7 +20,6 @@
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/ios/Flutter/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/flutter_assets/packages" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/flutter_assets/packages" />
</content> </content>
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

View File

@ -10,21 +10,12 @@ import Foundation
@objcMembers @objcMembers
public class InAppBrowserOptions: Options { public class InAppBrowserOptions: Options {
var useShouldOverrideUrlLoading = false
var useOnLoadResource = false
var openWithSystemBrowser = false;
var clearCache = false
var userAgent = ""
var javaScriptEnabled = true
var javaScriptCanOpenWindowsAutomatically = false
var hidden = false var hidden = false
var toolbarTop = true var toolbarTop = true
var toolbarTopBackgroundColor = "" var toolbarTopBackgroundColor = ""
var toolbarTopFixedTitle = ""
var hideUrlBar = false var hideUrlBar = false
var mediaPlaybackRequiresUserGesture = true
var isLocalFile = false
var disallowOverScroll = false
var toolbarBottom = true var toolbarBottom = true
var toolbarBottomBackgroundColor = "" var toolbarBottomBackgroundColor = ""
var toolbarBottomTranslucent = true var toolbarBottomTranslucent = true
@ -32,15 +23,6 @@ public class InAppBrowserOptions: Options {
var closeButtonColor = "" var closeButtonColor = ""
var presentationStyle = 0 //fullscreen var presentationStyle = 0 //fullscreen
var transitionStyle = 0 //crossDissolve var transitionStyle = 0 //crossDissolve
var enableViewportScale = false
//var keyboardDisplayRequiresUserAction = true
var suppressesIncrementalRendering = false
var allowsAirPlayForMediaPlayback = true
var allowsBackForwardNavigationGestures = true
var allowsLinkPreview = true
var ignoresViewportScaleLimits = false
var allowsInlineMediaPlayback = false
var allowsPictureInPictureMediaPlayback = true
var spinner = true var spinner = true
override init(){ override init(){

View File

@ -129,7 +129,7 @@ func convertToDictionary(text: String) -> [String: Any]? {
// //
//} //}
class WKWebView_IBWrapper: WKWebView { class InAppWebView_IBWrapper: InAppWebView {
required convenience init?(coder: NSCoder) { required convenience init?(coder: NSCoder) {
let config = WKWebViewConfiguration() let config = WKWebViewConfiguration()
self.init(frame: .zero, configuration: config) self.init(frame: .zero, configuration: config)
@ -139,7 +139,7 @@ class WKWebView_IBWrapper: WKWebView {
class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate, WKScriptMessageHandler { class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, UITextFieldDelegate, WKScriptMessageHandler {
@IBOutlet var webView: WKWebView_IBWrapper! @IBOutlet var webView: InAppWebView_IBWrapper!
@IBOutlet var closeButton: UIButton! @IBOutlet var closeButton: UIButton!
@IBOutlet var reloadButton: UIBarButtonItem! @IBOutlet var reloadButton: UIBarButtonItem!
@IBOutlet var backButton: UIBarButtonItem! @IBOutlet var backButton: UIBarButtonItem!
@ -159,6 +159,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
var currentURL: URL? var currentURL: URL?
var tmpWindow: UIWindow? var tmpWindow: UIWindow?
var browserOptions: InAppBrowserOptions? var browserOptions: InAppBrowserOptions?
var webViewOptions: InAppWebViewOptions?
var initHeaders: [String: String]? var initHeaders: [String: String]?
var isHidden = false var isHidden = false
var uuid: String = "" var uuid: String = ""
@ -216,7 +217,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
// Prevent crashes on closing windows // Prevent crashes on closing windows
deinit { deinit {
webView?.uiDelegate = nil webView.removeObserver(self, forKeyPath: "estimatedProgress")
webView.uiDelegate = nil
} }
override func viewWillDisappear (_ animated: Bool) { override func viewWillDisappear (_ animated: Bool) {
@ -231,6 +233,11 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
func prepareWebView() { func prepareWebView() {
//UIApplication.shared.statusBarStyle = preferredStatusBarStyle //UIApplication.shared.statusBarStyle = preferredStatusBarStyle
self.webView.addObserver(self,
forKeyPath: #keyPath(WKWebView.estimatedProgress),
options: .new,
context: nil)
self.webView.configuration.userContentController = WKUserContentController() self.webView.configuration.userContentController = WKUserContentController()
self.webView.configuration.preferences = WKPreferences() self.webView.configuration.preferences = WKPreferences()
@ -273,7 +280,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)! self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)!
// prevent webView from bouncing // prevent webView from bouncing
if (browserOptions?.disallowOverScroll)! { if (webViewOptions?.disallowOverScroll)! {
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) { if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
self.webView.scrollView.bounces = false self.webView.scrollView.bounces = false
} }
@ -286,7 +293,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
} }
} }
if (browserOptions?.enableViewportScale)! { if (webViewOptions?.enableViewportScale)! {
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);" let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true) let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
self.webView.configuration.userContentController.addUserScript(userScript) self.webView.configuration.userContentController.addUserScript(userScript)
@ -314,44 +321,44 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.webView.configuration.userContentController.add(self, name: "resourceLoaded") self.webView.configuration.userContentController.add(self, name: "resourceLoaded")
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
self.webView.configuration.mediaTypesRequiringUserActionForPlayback = ((browserOptions?.mediaPlaybackRequiresUserGesture)!) ? .all : [] self.webView.configuration.mediaTypesRequiringUserActionForPlayback = ((webViewOptions?.mediaPlaybackRequiresUserGesture)!) ? .all : []
} else { } else {
// Fallback on earlier versions // Fallback on earlier versions
self.webView.configuration.mediaPlaybackRequiresUserAction = (browserOptions?.mediaPlaybackRequiresUserGesture)! self.webView.configuration.mediaPlaybackRequiresUserAction = (webViewOptions?.mediaPlaybackRequiresUserGesture)!
} }
self.webView.configuration.allowsInlineMediaPlayback = (browserOptions?.allowsInlineMediaPlayback)! self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
//self.webView.keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction //self.webView.keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction
self.webView.configuration.suppressesIncrementalRendering = (browserOptions?.suppressesIncrementalRendering)! self.webView.configuration.suppressesIncrementalRendering = (webViewOptions?.suppressesIncrementalRendering)!
self.webView.allowsBackForwardNavigationGestures = (browserOptions?.allowsBackForwardNavigationGestures)! self.webView.allowsBackForwardNavigationGestures = (webViewOptions?.allowsBackForwardNavigationGestures)!
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.allowsLinkPreview = (browserOptions?.allowsLinkPreview)! self.webView.allowsLinkPreview = (webViewOptions?.allowsLinkPreview)!
} }
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
self.webView.configuration.ignoresViewportScaleLimits = (browserOptions?.ignoresViewportScaleLimits)! self.webView.configuration.ignoresViewportScaleLimits = (webViewOptions?.ignoresViewportScaleLimits)!
} }
self.webView.configuration.allowsInlineMediaPlayback = (browserOptions?.allowsInlineMediaPlayback)! self.webView.configuration.allowsInlineMediaPlayback = (webViewOptions?.allowsInlineMediaPlayback)!
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.configuration.allowsPictureInPictureMediaPlayback = (browserOptions?.allowsPictureInPictureMediaPlayback)! self.webView.configuration.allowsPictureInPictureMediaPlayback = (webViewOptions?.allowsPictureInPictureMediaPlayback)!
} }
self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (browserOptions?.javaScriptCanOpenWindowsAutomatically)! self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (webViewOptions?.javaScriptCanOpenWindowsAutomatically)!
self.webView.configuration.preferences.javaScriptEnabled = (browserOptions?.javaScriptEnabled)! self.webView.configuration.preferences.javaScriptEnabled = (webViewOptions?.javaScriptEnabled)!
if ((browserOptions?.userAgent)! != "") { if ((webViewOptions?.userAgent)! != "") {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.customUserAgent = (browserOptions?.userAgent)! self.webView.customUserAgent = (webViewOptions?.userAgent)!
} }
} }
if (browserOptions?.clearCache)! { if (webViewOptions?.clearCache)! {
clearCache() clearCache()
} }
@ -519,14 +526,14 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
if let url = navigationAction.request.url { if let url = navigationAction.request.url {
if url.absoluteString != self.currentURL?.absoluteString && (browserOptions?.useOnLoadResource)! { if url.absoluteString != self.currentURL?.absoluteString && (webViewOptions?.useOnLoadResource)! {
WKNavigationMap[url.absoluteString] = [ WKNavigationMap[url.absoluteString] = [
"startTime": currentTimeInMilliSeconds(), "startTime": currentTimeInMilliSeconds(),
"request": navigationAction.request "request": navigationAction.request
] ]
} }
if navigationAction.navigationType == .linkActivated && (browserOptions?.useShouldOverrideUrlLoading)! { if navigationAction.navigationType == .linkActivated && (webViewOptions?.useShouldOverrideUrlLoading)! {
if navigationDelegate != nil { if navigationDelegate != nil {
navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url) navigationDelegate?.shouldOverrideUrlLoading(uuid: self.uuid, webView: webView, url: url)
} }
@ -548,7 +555,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
decidePolicyFor navigationResponse: WKNavigationResponse, decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if (browserOptions?.useOnLoadResource)! { if (webViewOptions?.useOnLoadResource)! {
if let url = navigationResponse.response.url { if let url = navigationResponse.response.url {
if WKNavigationMap[url.absoluteString] != nil { if WKNavigationMap[url.absoluteString] != nil {
let startResourceTime = (WKNavigationMap[url.absoluteString]!["startTime"] as! Int) let startResourceTime = (WKNavigationMap[url.absoluteString]!["startTime"] as! Int)
@ -678,7 +685,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
navigationDelegate?.onConsoleMessage(uuid: self.uuid, sourceURL: "", lineNumber: 1, message: message.body as! String, messageLevel: messageLevel) navigationDelegate?.onConsoleMessage(uuid: self.uuid, sourceURL: "", lineNumber: 1, message: message.body as! String, messageLevel: messageLevel)
} }
} }
else if message.name == "resourceLoaded" && (browserOptions?.useOnLoadResource)! { else if message.name == "resourceLoaded" && (webViewOptions?.useOnLoadResource)! {
if let resource = convertToDictionary(text: message.body as! String) { if let resource = convertToDictionary(text: message.body as! String) {
let url = URL(string: resource["name"] as! String)! let url = URL(string: resource["name"] as! String)!
if !UIApplication.shared.canOpenURL(url) { if !UIApplication.shared.canOpenURL(url) {
@ -730,6 +737,9 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
func setOptions(newOptions: InAppBrowserOptions, newOptionsMap: [String: Any]) { func setOptions(newOptions: InAppBrowserOptions, newOptionsMap: [String: Any]) {
let newInAppWebViewOptions = InAppWebViewOptions()
newInAppWebViewOptions.parse(options: newOptionsMap)
if newOptionsMap["hidden"] != nil && browserOptions?.hidden != newOptions.hidden { if newOptionsMap["hidden"] != nil && browserOptions?.hidden != newOptions.hidden {
if newOptions.hidden { if newOptions.hidden {
self.navigationDelegate?.hide(uuid: self.uuid) self.navigationDelegate?.hide(uuid: self.uuid)
@ -784,93 +794,107 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: newOptions.transitionStyle)! self.modalTransitionStyle = UIModalTransitionStyle(rawValue: newOptions.transitionStyle)!
} }
if newOptionsMap["disallowOverScroll"] != nil && browserOptions?.disallowOverScroll != newOptions.disallowOverScroll { if newOptionsMap["disallowOverScroll"] != nil && webViewOptions?.disallowOverScroll != newInAppWebViewOptions.disallowOverScroll {
if self.webView.responds(to: #selector(getter: self.webView.scrollView)) { if self.webView.responds(to: #selector(getter: self.webView.scrollView)) {
self.webView.scrollView.bounces = !newOptions.disallowOverScroll self.webView.scrollView.bounces = !newInAppWebViewOptions.disallowOverScroll
} }
else { else {
for subview: UIView in self.webView.subviews { for subview: UIView in self.webView.subviews {
if subview is UIScrollView { if subview is UIScrollView {
(subview as! UIScrollView).bounces = !newOptions.disallowOverScroll (subview as! UIScrollView).bounces = !newInAppWebViewOptions.disallowOverScroll
} }
} }
} }
} }
if newOptionsMap["enableViewportScale"] != nil && browserOptions?.enableViewportScale != newOptions.enableViewportScale && newOptions.enableViewportScale { if newOptionsMap["enableViewportScale"] != nil && webViewOptions?.enableViewportScale != newInAppWebViewOptions.enableViewportScale && newInAppWebViewOptions.enableViewportScale {
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);" let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
self.webView.evaluateJavaScript(jscript, completionHandler: nil) self.webView.evaluateJavaScript(jscript, completionHandler: nil)
} }
if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && browserOptions?.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture { if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && webViewOptions?.mediaPlaybackRequiresUserGesture != newInAppWebViewOptions.mediaPlaybackRequiresUserGesture {
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
self.webView.configuration.mediaTypesRequiringUserActionForPlayback = (newOptions.mediaPlaybackRequiresUserGesture) ? .all : [] self.webView.configuration.mediaTypesRequiringUserActionForPlayback = (newInAppWebViewOptions.mediaPlaybackRequiresUserGesture) ? .all : []
} else { } else {
// Fallback on earlier versions // Fallback on earlier versions
self.webView.configuration.mediaPlaybackRequiresUserAction = newOptions.mediaPlaybackRequiresUserGesture self.webView.configuration.mediaPlaybackRequiresUserAction = newInAppWebViewOptions.mediaPlaybackRequiresUserGesture
} }
} }
if newOptionsMap["allowsInlineMediaPlayback"] != nil && browserOptions?.allowsInlineMediaPlayback != newOptions.allowsInlineMediaPlayback { if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
self.webView.configuration.allowsInlineMediaPlayback = newOptions.allowsInlineMediaPlayback self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
} }
// if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction { // if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction {
// self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction // self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction
// } // }
if newOptionsMap["suppressesIncrementalRendering"] != nil && browserOptions?.suppressesIncrementalRendering != newOptions.suppressesIncrementalRendering { if newOptionsMap["suppressesIncrementalRendering"] != nil && webViewOptions?.suppressesIncrementalRendering != newInAppWebViewOptions.suppressesIncrementalRendering {
self.webView.configuration.suppressesIncrementalRendering = newOptions.suppressesIncrementalRendering self.webView.configuration.suppressesIncrementalRendering = newInAppWebViewOptions.suppressesIncrementalRendering
} }
if newOptionsMap["allowsBackForwardNavigationGestures"] != nil && browserOptions?.allowsBackForwardNavigationGestures != newOptions.allowsBackForwardNavigationGestures { if newOptionsMap["allowsBackForwardNavigationGestures"] != nil && webViewOptions?.allowsBackForwardNavigationGestures != newInAppWebViewOptions.allowsBackForwardNavigationGestures {
self.webView.allowsBackForwardNavigationGestures = newOptions.allowsBackForwardNavigationGestures self.webView.allowsBackForwardNavigationGestures = newInAppWebViewOptions.allowsBackForwardNavigationGestures
} }
if newOptionsMap["allowsLinkPreview"] != nil && browserOptions?.allowsLinkPreview != newOptions.allowsLinkPreview { if newOptionsMap["allowsLinkPreview"] != nil && webViewOptions?.allowsLinkPreview != newInAppWebViewOptions.allowsLinkPreview {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.allowsLinkPreview = newOptions.allowsLinkPreview self.webView.allowsLinkPreview = newInAppWebViewOptions.allowsLinkPreview
} }
} }
if newOptionsMap["ignoresViewportScaleLimits"] != nil && browserOptions?.ignoresViewportScaleLimits != newOptions.ignoresViewportScaleLimits { if newOptionsMap["ignoresViewportScaleLimits"] != nil && webViewOptions?.ignoresViewportScaleLimits != newInAppWebViewOptions.ignoresViewportScaleLimits {
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
self.webView.configuration.ignoresViewportScaleLimits = newOptions.ignoresViewportScaleLimits self.webView.configuration.ignoresViewportScaleLimits = newInAppWebViewOptions.ignoresViewportScaleLimits
} }
} }
if newOptionsMap["allowsInlineMediaPlayback"] != nil && browserOptions?.allowsInlineMediaPlayback != newOptions.allowsInlineMediaPlayback { if newOptionsMap["allowsInlineMediaPlayback"] != nil && webViewOptions?.allowsInlineMediaPlayback != newInAppWebViewOptions.allowsInlineMediaPlayback {
self.webView.configuration.allowsInlineMediaPlayback = newOptions.allowsInlineMediaPlayback self.webView.configuration.allowsInlineMediaPlayback = newInAppWebViewOptions.allowsInlineMediaPlayback
} }
if newOptionsMap["allowsPictureInPictureMediaPlayback"] != nil && browserOptions?.allowsPictureInPictureMediaPlayback != newOptions.allowsPictureInPictureMediaPlayback { if newOptionsMap["allowsPictureInPictureMediaPlayback"] != nil && webViewOptions?.allowsPictureInPictureMediaPlayback != newInAppWebViewOptions.allowsPictureInPictureMediaPlayback {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.configuration.allowsPictureInPictureMediaPlayback = newOptions.allowsPictureInPictureMediaPlayback self.webView.configuration.allowsPictureInPictureMediaPlayback = newInAppWebViewOptions.allowsPictureInPictureMediaPlayback
} }
} }
if newOptionsMap["javaScriptCanOpenWindowsAutomatically"] != nil && browserOptions?.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically { if newOptionsMap["javaScriptCanOpenWindowsAutomatically"] != nil && webViewOptions?.javaScriptCanOpenWindowsAutomatically != newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically {
self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = newOptions.javaScriptCanOpenWindowsAutomatically self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = newInAppWebViewOptions.javaScriptCanOpenWindowsAutomatically
} }
if newOptionsMap["javaScriptEnabled"] != nil && browserOptions?.javaScriptEnabled != newOptions.javaScriptEnabled { if newOptionsMap["javaScriptEnabled"] != nil && webViewOptions?.javaScriptEnabled != newInAppWebViewOptions.javaScriptEnabled {
self.webView.configuration.preferences.javaScriptEnabled = newOptions.javaScriptEnabled self.webView.configuration.preferences.javaScriptEnabled = newInAppWebViewOptions.javaScriptEnabled
} }
if newOptionsMap["userAgent"] != nil && browserOptions?.userAgent != newOptions.userAgent && (newOptions.userAgent != "") { if newOptionsMap["userAgent"] != nil && webViewOptions?.userAgent != newInAppWebViewOptions.userAgent && (newInAppWebViewOptions.userAgent != "") {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
self.webView.customUserAgent = newOptions.userAgent self.webView.customUserAgent = newInAppWebViewOptions.userAgent
} }
} }
if newOptionsMap["clearCache"] != nil && newOptions.clearCache { if newOptionsMap["clearCache"] != nil && newInAppWebViewOptions.clearCache {
clearCache() clearCache()
} }
self.browserOptions = newOptions self.browserOptions = newOptions
self.webViewOptions = newInAppWebViewOptions
} }
func getOptions() -> [String: Any]? { func getOptions() -> [String: Any]? {
return (self.browserOptions != nil) ? self.browserOptions?.getHashMap() : nil if (self.browserOptions == nil || self.webViewOptions == nil) {
return nil
}
var optionsMap = self.browserOptions!.getHashMap()
optionsMap.merge(self.webViewOptions!.getHashMap(), uniquingKeysWith: { (current, _) in current })
return optionsMap
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?,
change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "estimatedProgress" {
let progress = Int(webView.estimatedProgress * 100)
self.navigationDelegate?.onProgressChanged(uuid: self.uuid, webView: self.webView, progress: progress)
}
} }
} }

View File

@ -0,0 +1,13 @@
//
// InAppWebView.swift
// flutter_inappbrowser
//
// Created by Lorenzo on 21/10/18.
//
import Foundation
import WebKit
public class InAppWebView: WKWebView {
}

View File

@ -0,0 +1,38 @@
//
// InAppWebViewOptions.swift
// flutter_inappbrowser
//
// Created by Lorenzo on 21/10/18.
//
import Foundation
@objcMembers
public class InAppWebViewOptions: Options {
var useShouldOverrideUrlLoading = false
var useOnLoadResource = false
var clearCache = false
var userAgent = ""
var javaScriptEnabled = true
var javaScriptCanOpenWindowsAutomatically = false
var mediaPlaybackRequiresUserGesture = true
var disallowOverScroll = false
var enableViewportScale = false
//var keyboardDisplayRequiresUserAction = true
var suppressesIncrementalRendering = false
var allowsAirPlayForMediaPlayback = true
var allowsBackForwardNavigationGestures = true
var allowsLinkPreview = true
var ignoresViewportScaleLimits = false
var allowsInlineMediaPlayback = false
var allowsPictureInPictureMediaPlayback = true
override init(){
super.init()
}
}

View File

@ -68,6 +68,9 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
case "loadUrl": case "loadUrl":
self.loadUrl(uuid: uuid, arguments: arguments!, result: result) self.loadUrl(uuid: uuid, arguments: arguments!, result: result)
break break
case "loadFile":
self.loadFile(uuid: uuid, arguments: arguments!, result: result)
break
case "close": case "close":
self.close(uuid: uuid) self.close(uuid: uuid)
result(true) result(true)
@ -205,29 +208,39 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let url: String = (arguments["url"] as? String)! let url: String = (arguments["url"] as? String)!
let headers = (arguments["headers"] as? [String: String])! let headers = (arguments["headers"] as? [String: String])!
let absoluteUrl = URL(string: url)?.absoluteURL var absoluteUrl = URL(string: url)?.absoluteURL
let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool)!
let useChromeSafariBrowser = (arguments["useChromeSafariBrowser"] as? Bool) if useChromeSafariBrowser {
if useChromeSafariBrowser! {
let uuidFallback = (arguments["uuidFallback"] as? String)! let uuidFallback = (arguments["uuidFallback"] as? String)!
let safariOptions = SafariBrowserOptions() let safariOptions = (arguments["options"] as? [String: Any])!
safariOptions.parse(options: (arguments["options"] as? [String: Any])!)
let optionsFallback = InAppBrowserOptions() let optionsFallback = (arguments["optionsFallback"] as? [String: Any])!
optionsFallback.parse(options: (arguments["optionsFallback"] as? [String: Any])!)
open(uuid: uuid, uuidFallback: uuidFallback, inAppBrowser: absoluteUrl!, headers: headers, withOptions: safariOptions, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback, result: result); open(uuid: uuid, uuidFallback: uuidFallback, inAppBrowser: absoluteUrl!, headers: headers, withOptions: safariOptions, useChromeSafariBrowser: true, withOptionsFallback: optionsFallback, result: result);
} }
else { else {
let options = InAppBrowserOptions() let options = (arguments["options"] as? [String: Any])!
options.parse(options: (arguments["options"] as? [String: Any])!)
let isLocalFile = (arguments["isLocalFile"] as? Bool)!
var openWithSystemBrowser = (arguments["openWithSystemBrowser"] as? Bool)!
if isLocalFile {
let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url)
let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
if assetURL == nil {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
return
}
absoluteUrl = assetURL!
}
if isSystemUrl(absoluteUrl!) { if isSystemUrl(absoluteUrl!) {
options.openWithSystemBrowser = true openWithSystemBrowser = true
} }
if (options.openWithSystemBrowser) { if (openWithSystemBrowser) {
open(inSystem: absoluteUrl!, result: result) open(inSystem: absoluteUrl!, result: result)
} }
else { else {
@ -236,7 +249,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
} }
} }
func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: Options, useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: Options?, result: @escaping FlutterResult) { func open(uuid: String, uuidFallback: String?, inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any], useChromeSafariBrowser: Bool, withOptionsFallback optionsFallback: [String: Any]?, result: @escaping FlutterResult) {
var uuid = uuid var uuid = uuid
@ -270,10 +283,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
self.tmpWindow?.makeKeyAndVisible() self.tmpWindow?.makeKeyAndVisible()
let browserOptions: InAppBrowserOptions let browserOptions: InAppBrowserOptions
let webViewOptions: InAppWebViewOptions
if useChromeSafariBrowser == true { if useChromeSafariBrowser == true {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
let safariOptions = options as! SafariBrowserOptions let safariOptions = SafariBrowserOptions()
safariOptions.parse(options: options)
let safari: SafariViewController let safari: SafariViewController
@ -310,23 +325,19 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
return return
} }
uuid = uuidFallback! uuid = uuidFallback!
browserOptions = optionsFallback as! InAppBrowserOptions browserOptions = InAppBrowserOptions()
browserOptions.parse(options: optionsFallback!)
webViewOptions = InAppWebViewOptions()
webViewOptions.parse(options: optionsFallback!)
} }
} }
else { else {
browserOptions = options as! InAppBrowserOptions browserOptions = InAppBrowserOptions()
} browserOptions.parse(options: options)
var currentURL = url webViewOptions = InAppWebViewOptions()
webViewOptions.parse(options: options)
if browserOptions.isLocalFile {
let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url.absoluteString)
let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
if assetURL == nil {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url.absoluteString + " asset file cannot be found!", details: nil))
return
}
currentURL = assetURL!
} }
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppBrowserFlutterPlugin.self)) let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppBrowserFlutterPlugin.self))
@ -335,9 +346,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
webViewController.uuid = uuid webViewController.uuid = uuid
webViewController.browserOptions = browserOptions webViewController.browserOptions = browserOptions
webViewController.webViewOptions = webViewOptions
webViewController.isHidden = browserOptions.hidden webViewController.isHidden = browserOptions.hidden
webViewController.tmpWindow = tmpWindow webViewController.tmpWindow = tmpWindow
webViewController.currentURL = currentURL webViewController.currentURL = url
webViewController.initHeaders = headers webViewController.initHeaders = headers
webViewController.navigationDelegate = self webViewController.navigationDelegate = self
@ -365,11 +377,29 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
public func loadUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) { public func loadUrl(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
let url: String? = (arguments["url"] as? String)! if let url = arguments["url"] as? String {
let headers = (arguments["headers"] as? [String: String])! let headers = (arguments["headers"] as? [String: String])!
let absoluteUrl = URL(string: url)!.absoluteURL
if url != nil { webViewController.loadUrl(url: absoluteUrl, headers: headers)
let absoluteUrl = URL(string: url!)!.absoluteURL }
else {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "url is empty", details: nil))
}
result(true)
}
public func loadFile(uuid: String, arguments: NSDictionary, result: @escaping FlutterResult) {
let webViewController: InAppBrowserWebViewController = self.webViewControllers[uuid] as! InAppBrowserWebViewController
if let url = arguments["url"] as? String {
let headers = (arguments["headers"] as? [String: String])!
let key = SwiftFlutterPlugin.registrar!.lookupKey(forAsset: url)
let assetURL = Bundle.main.url(forResource: key, withExtension: nil)
if assetURL == nil {
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: url + " asset file cannot be found!", details: nil))
return
}
let absoluteUrl = URL(string: url)!.absoluteURL
webViewController.loadUrl(url: absoluteUrl, headers: headers) webViewController.loadUrl(url: absoluteUrl, headers: headers)
} }
else { else {
@ -530,6 +560,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
} }
} }
func onProgressChanged(uuid: String, webView: WKWebView, progress: Int) {
if let webViewController = self.webViewControllers[uuid] {
channel.invokeMethod("onProgressChanged", arguments: ["uuid": uuid, "progress": progress])
}
}
func onLoadResource(uuid: String, webView: WKWebView, response: URLResponse, fromRequest request: URLRequest?, withData data: Data, startTime: Int, duration: Int) { func onLoadResource(uuid: String, webView: WKWebView, response: URLResponse, fromRequest request: URLRequest?, withData data: Data, startTime: Int, duration: Int) {
if self.webViewControllers[uuid] != nil { if self.webViewControllers[uuid] != nil {
var headersResponse = (response as! HTTPURLResponse).allHeaderFields as! [String: String] var headersResponse = (response as! HTTPURLResponse).allHeaderFields as! [String: String]

View File

@ -21,7 +21,7 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/> <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gA9-n8-qaQ" customClass="WKWebView_IBWrapper" customModule="flutter_inappbrowser"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gA9-n8-qaQ" customClass="InAppWebView_IBWrapper" customModule="flutter_inappbrowser">
<rect key="frame" x="0.0" y="66" width="414" height="626"/> <rect key="frame" x="0.0" y="66" width="414" height="626"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view> </view>
@ -96,7 +96,7 @@
<outlet property="toolbarTop" destination="vlz-kT-71x" id="WgC-80-Z28"/> <outlet property="toolbarTop" destination="vlz-kT-71x" id="WgC-80-Z28"/>
<outlet property="toolbarTop_BottomToWebViewTopConstraint" destination="Sjd-dV-din" id="vkO-Yu-xaE"/> <outlet property="toolbarTop_BottomToWebViewTopConstraint" destination="Sjd-dV-din" id="vkO-Yu-xaE"/>
<outlet property="urlField" destination="sy2-Vx-Cxd" id="MCW-lJ-Ehl"/> <outlet property="urlField" destination="sy2-Vx-Cxd" id="MCW-lJ-Ehl"/>
<outlet property="webView" destination="gA9-n8-qaQ" id="7JE-lp-bwe"/> <outlet property="webView" destination="gA9-n8-qaQ" id="439-rj-hHB"/>
</connections> </connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="cYA-mw-BIR" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="cYA-mw-BIR" userLabel="First Responder" sceneMemberID="firstResponder"/>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
name: flutter_inappbrowser name: flutter_inappbrowser
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser). description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
version: 0.4.1 version: 0.5.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com> author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser homepage: https://github.com/pichillilorenzo/flutter_inappbrowser