updated android code, code cleanup, added new API
This commit is contained in:
parent
e0982e369c
commit
9c30ed7781
|
@ -7,31 +7,18 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/res/drawable/ic_more_vert_black_24dp.xml" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/res/layout/activity_web_view.xml" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/res/values/strings.xml" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/res/values/styles.xml" />
|
||||
<change beforePath="" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebChromeClient.java" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
|
||||
<change beforePath="$PROJECT_DIR$/android/build.gradle" afterPath="$PROJECT_DIR$/android/build.gradle" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" afterPath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-hdpi/ic_action_next_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-hdpi/ic_action_previous_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-hdpi/ic_action_remove.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-mdpi/ic_action_next_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-mdpi/ic_action_previous_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-mdpi/ic_action_remove.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xhdpi/ic_action_next_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xhdpi/ic_action_previous_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xhdpi/ic_action_remove.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xxhdpi/ic_action_next_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xxhdpi/ic_action_previous_item.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable-xxhdpi/ic_action_remove.png" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/example/android/app/build.gradle" afterPath="$PROJECT_DIR$/example/android/app/build.gradle" />
|
||||
<change beforePath="$PROJECT_DIR$/example/ios/Runner/WebView.storyboard" afterPath="$PROJECT_DIR$/example/ios/Runner/WebView.storyboard" />
|
||||
<change beforePath="$PROJECT_DIR$/example/lib/main.dart" afterPath="$PROJECT_DIR$/example/lib/main.dart" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserClient.java" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserDialog.java" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/drawable/ic_more_vert_black_24dp.xml" afterPath="" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/layout/activity_web_view.xml" afterPath="$PROJECT_DIR$/android/src/main/res/layout/activity_web_view.xml" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/menu/menu_main.xml" afterPath="$PROJECT_DIR$/android/src/main/res/menu/menu_main.xml" />
|
||||
<change beforePath="$PROJECT_DIR$/android/src/main/res/values/strings.xml" afterPath="$PROJECT_DIR$/android/src/main/res/values/strings.xml" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" />
|
||||
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" />
|
||||
|
@ -52,11 +39,11 @@
|
|||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<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="true">
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="347">
|
||||
<caret line="154" column="3" lean-forward="false" selection-start-line="154" selection-start-column="3" selection-end-line="154" selection-end-column="3" />
|
||||
<state relative-caret-position="-82">
|
||||
<caret line="129" column="52" lean-forward="false" selection-start-line="129" selection-start-column="52" selection-end-line="129" selection-end-column="52" />
|
||||
<folding>
|
||||
<element signature="e#814#834#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -64,11 +51,11 @@
|
|||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="main.dart" pinned="false" current-in-tab="true">
|
||||
<file leaf-file-name="main.dart" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="196">
|
||||
<caret line="20" column="0" lean-forward="false" selection-start-line="20" selection-start-column="0" selection-end-line="20" selection-end-column="0" />
|
||||
<state relative-caret-position="195">
|
||||
<caret line="15" column="34" lean-forward="false" selection-start-line="15" selection-start-column="34" selection-end-line="15" selection-end-column="34" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
@ -155,15 +142,15 @@
|
|||
<option value="$PROJECT_DIR$/README.md" />
|
||||
<option value="$PROJECT_DIR$/android/build.gradle" />
|
||||
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" />
|
||||
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
||||
<option value="$PROJECT_DIR$/example/lib/main.dart" />
|
||||
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="x" value="650" />
|
||||
<option name="x" value="362" />
|
||||
<option name="y" value="23" />
|
||||
<option name="width" value="1270" />
|
||||
<option name="width" value="1554" />
|
||||
<option name="height" value="1057" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
|
@ -190,6 +177,32 @@
|
|||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="android" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="android" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="app" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="android" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="app" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="main" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
|
@ -227,6 +240,7 @@
|
|||
<property name="Downloaded.Files.Path.Enabled" value="true" />
|
||||
<property name="Repository.Attach.JavaDocs" value="false" />
|
||||
<property name="Repository.Attach.Sources" value="false" />
|
||||
<property name="settings.editor.selected.configurable" value="configurable.group.language" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
|
@ -400,7 +414,7 @@
|
|||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="650" y="23" width="1270" height="1057" extended-state="0" />
|
||||
<frame x="362" y="23" width="1554" height="1057" extended-state="0" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Android Profiler" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
|
@ -409,17 +423,17 @@
|
|||
<window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.31735888" sideWeight="0.5026455" order="7" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Dart Analysis" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3290735" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.3024494" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.3024494" sideWeight="0.4973545" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.31735888" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Flutter Outline" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32977968" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.31735888" sideWeight="0.4973545" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Flutter Outline" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32936507" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Logcat" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2801303" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.22751322" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Device File Explorer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
|
@ -674,13 +688,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
|
@ -814,24 +821,32 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<entry file="file://$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="347">
|
||||
<caret line="154" column="3" lean-forward="false" selection-start-line="154" selection-start-column="3" selection-end-line="154" selection-end-column="3" />
|
||||
<folding>
|
||||
<element signature="e#814#834#0" expanded="true" />
|
||||
</folding>
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="196">
|
||||
<caret line="20" column="0" lean-forward="false" selection-start-line="20" selection-start-column="0" selection-end-line="20" selection-end-column="0" />
|
||||
<state relative-caret-position="195">
|
||||
<caret line="15" column="34" lean-forward="false" selection-start-line="15" selection-start-column="34" selection-end-line="15" selection-end-column="34" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-82">
|
||||
<caret line="129" column="52" lean-forward="false" selection-start-line="129" selection-start-column="52" selection-end-line="129" selection-end-column="52" />
|
||||
<folding>
|
||||
<element signature="e#814#834#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".WebViewActivity"></activity>
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity android:name=".WebViewActivity" android:configChanges="orientation|screenSize"></activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -24,54 +24,21 @@ package com.pichillilorenzo.flutter_inappbrowser;
|
|||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Browser;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.text.InputType;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.util.Log;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
@ -90,60 +57,12 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
|
||||
private static final String NULL = "null";
|
||||
protected static final String LOG_TAG = "InAppBrowser";
|
||||
private static final String SELF = "_self";
|
||||
private static final String SYSTEM = "_system";
|
||||
private static final String EXIT_EVENT = "exit";
|
||||
private static final String LOCATION = "location";
|
||||
private static final String ZOOM = "zoom";
|
||||
private static final String HIDDEN = "hidden";
|
||||
private static final String CLEAR_ALL_CACHE = "clearcache";
|
||||
private static final String CLEAR_SESSION_CACHE = "clearsessioncache";
|
||||
private static final String HARDWARE_BACK_BUTTON = "hardwareback";
|
||||
private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction";
|
||||
private static final String SHOULD_PAUSE = "shouldPauseOnSuspend";
|
||||
private static final Boolean DEFAULT_HARDWARE_BACK = true;
|
||||
private static final String USER_WIDE_VIEW_PORT = "useWideViewPort";
|
||||
private static final String TOOLBAR_COLOR = "toolbarcolor";
|
||||
private static final String CLOSE_BUTTON_CAPTION = "closebuttoncaption";
|
||||
private static final String CLOSE_BUTTON_COLOR = "closebuttoncolor";
|
||||
private static final String HIDE_NAVIGATION = "hidenavigationbuttons";
|
||||
private static final String NAVIGATION_COLOR = "navigationbuttoncolor";
|
||||
private static final String HIDE_URL = "hideurlbar";
|
||||
private static final String FOOTER = "footer";
|
||||
private static final String FOOTER_COLOR = "footercolor";
|
||||
|
||||
private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
|
||||
|
||||
private InAppBrowserDialog dialog;
|
||||
private WebView inAppWebView;
|
||||
private EditText edittext;
|
||||
private boolean showLocationBar = true;
|
||||
private boolean showZoomControls = true;
|
||||
private boolean openWindowHidden = false;
|
||||
private boolean clearAllCache = false;
|
||||
private boolean clearSessionCache = false;
|
||||
private boolean hadwareBackButton = true;
|
||||
private boolean mediaPlaybackRequiresUserGesture = false;
|
||||
private boolean shouldPauseInAppBrowser = false;
|
||||
private boolean useWideViewPort = true;
|
||||
private ValueCallback<Uri> mUploadCallback;
|
||||
private ValueCallback<Uri[]> mUploadCallbackLollipop;
|
||||
private final static int FILECHOOSER_REQUESTCODE = 1;
|
||||
private final static int FILECHOOSER_REQUESTCODE_LOLLIPOP = 2;
|
||||
private String closeButtonCaption = "";
|
||||
private String closeButtonColor = "";
|
||||
private int toolbarColor = android.graphics.Color.LTGRAY;
|
||||
private boolean hideNavigationButtons = false;
|
||||
private String navigationButtonColor = "";
|
||||
private boolean hideUrlBar = false;
|
||||
private boolean showFooter = false;
|
||||
private String footerColor = "";
|
||||
private String[] allowedSchemes;
|
||||
|
||||
public InAppBrowser(Registrar registrar, Activity activity) {
|
||||
this.registrar = registrar;
|
||||
public InAppBrowser(Registrar r, Activity activity) {
|
||||
registrar = r;
|
||||
this.activity = activity;
|
||||
this.channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
|
||||
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
|
||||
}
|
||||
|
||||
/** Plugin registration. */
|
||||
|
@ -165,9 +84,10 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
|
||||
String t = call.argument("target").toString();
|
||||
if (t == null || t.equals("") || t.equals(NULL)) {
|
||||
t = SELF;
|
||||
t = "_self";
|
||||
}
|
||||
final String target = t;
|
||||
|
||||
final InAppBrowserOptions options = new InAppBrowserOptions();
|
||||
options.parse((HashMap<String, Object>) call.argument("options"));
|
||||
|
||||
|
@ -176,9 +96,7 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
this.activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String r = "";
|
||||
// SELF
|
||||
if (SELF.equals(target)) {
|
||||
if ("_self".equals(target)) {
|
||||
Log.d(LOG_TAG, "in self");
|
||||
|
||||
//Load the dialer
|
||||
|
@ -196,26 +114,29 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
// load in InAppBrowser
|
||||
else {
|
||||
Log.d(LOG_TAG, "loading in InAppBrowser");
|
||||
r = showWebPage(url, options);
|
||||
open(url, options);
|
||||
}
|
||||
}
|
||||
// SYSTEM
|
||||
else if (SYSTEM.equals(target)) {
|
||||
else if ("_system".equals(target)) {
|
||||
Log.d(LOG_TAG, "in system");
|
||||
r = openExternal(url);
|
||||
openExternal(url, result);
|
||||
}
|
||||
// BLANK - or anything else
|
||||
else {
|
||||
Log.d(LOG_TAG, "in blank");
|
||||
r = showWebPage(url, options);
|
||||
open(url, options);
|
||||
}
|
||||
|
||||
result.success(r);
|
||||
result.success(true);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "loadUrl":
|
||||
loadUrl(call.argument("url").toString(), (Map<String, String>) call.argument("headers"), result);
|
||||
break;
|
||||
case "close":
|
||||
closeDialog();
|
||||
close();
|
||||
result.success(true);
|
||||
break;
|
||||
case "injectScriptCode":
|
||||
|
@ -243,21 +164,36 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
result.success(true);
|
||||
break;
|
||||
case "show":
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
show();
|
||||
result.success(true);
|
||||
break;
|
||||
case "hide":
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.hide();
|
||||
}
|
||||
});
|
||||
hide();
|
||||
result.success(true);
|
||||
break;
|
||||
case "reload":
|
||||
reload();
|
||||
result.success(true);
|
||||
break;
|
||||
case "goBack":
|
||||
goBack();
|
||||
result.success(true);
|
||||
break;
|
||||
case "canGoBack":
|
||||
result.success(canGoBack());
|
||||
break;
|
||||
case "goForward":
|
||||
goForward();
|
||||
result.success(true);
|
||||
break;
|
||||
case "canGoForward":
|
||||
result.success(canGoForward());
|
||||
break;
|
||||
case "isLoading":
|
||||
result.success(isLoading());
|
||||
break;
|
||||
case "stopLoading":
|
||||
stopLoading();
|
||||
result.success(true);
|
||||
break;
|
||||
default:
|
||||
|
@ -283,7 +219,7 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
* which should be executed directly.
|
||||
*/
|
||||
private void injectDeferredObject(String source, String jsWrapper) {
|
||||
if (inAppWebView!=null) {
|
||||
if (webViewActivity!=null) {
|
||||
String scriptToInject;
|
||||
if (jsWrapper != null) {
|
||||
org.json.JSONArray jsonEsc = new org.json.JSONArray();
|
||||
|
@ -301,9 +237,9 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
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
|
||||
inAppWebView.loadUrl("javascript:" + finalScriptToInject);
|
||||
webViewActivity.webView.loadUrl("javascript:" + finalScriptToInject);
|
||||
} else {
|
||||
inAppWebView.evaluateJavascript(finalScriptToInject, null);
|
||||
webViewActivity.webView.evaluateJavascript(finalScriptToInject, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -327,9 +263,9 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
* @param url the url to load.
|
||||
* @return "" if ok, or error message.
|
||||
*/
|
||||
public String openExternal(String url) {
|
||||
public void openExternal(String url, Result result) {
|
||||
try {
|
||||
Intent intent = null;
|
||||
Intent intent;
|
||||
intent = new Intent(Intent.ACTION_VIEW);
|
||||
// Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
|
||||
// Adding the MIME type to http: URLs causes them to not be handled by the downloader.
|
||||
|
@ -341,16 +277,14 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
}
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
|
||||
activity.startActivity(intent);
|
||||
return "";
|
||||
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
|
||||
} catch (java.lang.RuntimeException e) {
|
||||
Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
|
||||
return e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(8)
|
||||
private String showWebPage(final String url, InAppBrowserOptions options) {
|
||||
private void open(final String url, InAppBrowserOptions options) {
|
||||
Intent intent = new Intent(activity, WebViewActivity.class);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
|
@ -361,11 +295,7 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
|
||||
activity.startActivity(intent);
|
||||
|
||||
//webViewActivity.loadUrl(url);
|
||||
|
||||
return "";
|
||||
|
||||
// Determine if we should hide the location bar.
|
||||
// Determine if we should hide the location bar.
|
||||
// showLocationBar = true;
|
||||
// showZoomControls = true;
|
||||
// openWindowHidden = false;
|
||||
|
@ -802,162 +732,87 @@ public class InAppBrowser implements MethodCallHandler {
|
|||
//return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the list of features into a hash map
|
||||
*
|
||||
* @param optString
|
||||
* @return
|
||||
*/
|
||||
private HashMap<String, String> parseFeature(String optString) {
|
||||
if (optString.equals(NULL)) {
|
||||
return null;
|
||||
} else {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
StringTokenizer features = new StringTokenizer(optString, ",");
|
||||
StringTokenizer option;
|
||||
while(features.hasMoreElements()) {
|
||||
option = new StringTokenizer(features.nextToken(), "=");
|
||||
if (option.hasMoreElements()) {
|
||||
String key = option.nextToken();
|
||||
String value = option.nextToken();
|
||||
if (!customizableOptions.contains(key)){
|
||||
value = value.equals("yes") || value.equals("no") ? value : "yes";
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
public void loadUrl(String url, Map<String, String> headers, Result result) {
|
||||
if (webViewActivity != null) {
|
||||
if (headers != null)
|
||||
webViewActivity.loadUrl(url, headers, result);
|
||||
else
|
||||
webViewActivity.loadUrl(url, result);
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.show();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.hide();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.reload();
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
if (webViewActivity != null)
|
||||
return webViewActivity.isLoading();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stopLoading() {
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.stopLoading();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if it is possible to go back one page in history, then does so.
|
||||
*/
|
||||
public void goBack() {
|
||||
if (this.inAppWebView.canGoBack()) {
|
||||
this.inAppWebView.goBack();
|
||||
}
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the web browser go back?
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean canGoBack() {
|
||||
return this.inAppWebView.canGoBack();
|
||||
if (webViewActivity != null)
|
||||
return webViewActivity.canGoBack();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the user set the hardware back button to go back
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean hardwareBack() {
|
||||
return hadwareBackButton;
|
||||
public void goForward() {
|
||||
if (webViewActivity != null)
|
||||
webViewActivity.goForward();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if it is possible to go forward one page in history, then does so.
|
||||
*/
|
||||
private void goForward() {
|
||||
if (this.inAppWebView.canGoForward()) {
|
||||
this.inAppWebView.goForward();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the new page
|
||||
*
|
||||
* @param url to load
|
||||
*/
|
||||
@TargetApi(3)
|
||||
private void navigate(String url) {
|
||||
InputMethodManager imm = (InputMethodManager)this.activity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
|
||||
|
||||
if (!url.startsWith("http") && !url.startsWith("file:")) {
|
||||
this.inAppWebView.loadUrl("http://" + url);
|
||||
} else {
|
||||
this.inAppWebView.loadUrl(url);
|
||||
}
|
||||
this.inAppWebView.requestFocus();
|
||||
public boolean canGoForward() {
|
||||
if (webViewActivity != null)
|
||||
return webViewActivity.canGoForward();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should we show the location bar?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean getShowLocationBar() {
|
||||
return this.showLocationBar;
|
||||
}
|
||||
|
||||
private InAppBrowser getInAppBrowser(){
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the dialog
|
||||
*/
|
||||
public void closeDialog() {
|
||||
public void close() {
|
||||
this.activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final WebView childView = inAppWebView;
|
||||
// The JS protects against multiple calls, so this should happen only when
|
||||
// closeDialog() is called by other native code.
|
||||
if (childView == null) {
|
||||
// close() is called by other native code.
|
||||
if (webViewActivity == null)
|
||||
return;
|
||||
}
|
||||
|
||||
childView.setWebViewClient(new WebViewClient() {
|
||||
webViewActivity.webView.setWebViewClient(new WebViewClient() {
|
||||
// NB: wait for about:blank before dismissing
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
if (dialog != null) {
|
||||
dialog.dismiss();
|
||||
dialog = null;
|
||||
}
|
||||
webViewActivity.close();
|
||||
}
|
||||
});
|
||||
// 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."
|
||||
// http://developer.android.com/guide/webapps/migrating.html#Threads
|
||||
childView.loadUrl("about:blank");
|
||||
webViewActivity.webView.loadUrl("about:blank");
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", EXIT_EVENT);
|
||||
channel.invokeMethod(EXIT_EVENT, obj);
|
||||
channel.invokeMethod("exit", obj);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by AccelBroker when listener is to be shut down.
|
||||
* Stop listener.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.pichillilorenzo.flutter_inappbrowser;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
|
||||
public class InAppBrowserDialog extends Dialog {
|
||||
Context context;
|
||||
InAppBrowser inAppBrowser = null;
|
||||
|
||||
public InAppBrowserDialog(Context context, int theme) {
|
||||
super(context, theme);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setInAppBroswer(InAppBrowser browser) {
|
||||
this.inAppBrowser = browser;
|
||||
}
|
||||
|
||||
public void onBackPressed () {
|
||||
if (this.inAppBrowser == null) {
|
||||
this.dismiss();
|
||||
} else {
|
||||
// better to go through the in inAppBrowser
|
||||
// because it does a clean up
|
||||
if (this.inAppBrowser.hardwareBack() && this.inAppBrowser.canGoBack()) {
|
||||
this.inAppBrowser.goBack();
|
||||
} else {
|
||||
this.inAppBrowser.closeDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,23 +13,21 @@ public class InAppBrowserOptions {
|
|||
|
||||
boolean clearCache = false;
|
||||
boolean clearSessionCache = false;
|
||||
String userAgent = "";
|
||||
boolean spinner = true;
|
||||
boolean hidden = false;
|
||||
boolean toolbarTop = true;
|
||||
String toolbarTopColor = "toolbarTopColor";
|
||||
boolean hideUrlBar = false;
|
||||
boolean enableViewportScale = false;
|
||||
boolean keyboardDisplayRequiresUserAction = true;
|
||||
boolean suppressesIncrementalRendering = false;
|
||||
boolean allowsAirPlayForMediaPlayback = true;
|
||||
boolean mediaTypesRequiringUserActionForPlayback = true;
|
||||
boolean allowsBackForwardNavigationGestures = true;
|
||||
boolean allowsLinkPreview = true;
|
||||
boolean ignoresViewportScaleLimits = false;
|
||||
boolean allowsInlineMediaPlayback = false;
|
||||
boolean allowsPictureInPictureMediaPlayback = true;
|
||||
boolean mediaPlaybackRequiresUserGesture = true;
|
||||
boolean javaScriptCanOpenWindowsAutomatically = false;
|
||||
boolean javaScriptEnabled = true;
|
||||
boolean builtInZoomControls = false;
|
||||
boolean supportZoom = true;
|
||||
boolean databaseEnabled = true;
|
||||
boolean domStorageEnabled = true;
|
||||
boolean useWideViewPort = true;
|
||||
boolean safeBrowsingEnabled = true;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public void parse(HashMap<String, Object> options) {
|
||||
|
@ -42,7 +40,6 @@ public class InAppBrowserOptions {
|
|||
// silent
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public HashMap<String, Object> getHashMap() {
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
package com.pichillilorenzo.flutter_inappbrowser;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
|
||||
public class InAppBrowserWebChromeClient extends WebChromeClient {
|
||||
|
||||
protected static final String LOG_TAG = "IABWebChromeClient";
|
||||
private WebViewActivity activity;
|
||||
private ValueCallback<Uri[]> mUploadMessageArray;
|
||||
private ValueCallback<Uri> mUploadMessage;
|
||||
private final static int FILECHOOSER_RESULTCODE=1;
|
||||
|
||||
public InAppBrowserWebChromeClient(WebViewActivity activity) {
|
||||
super();
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int progress) {
|
||||
if (activity.progressBar != null) {
|
||||
activity.progressBar.setVisibility(View.VISIBLE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
activity.progressBar.setProgress(progress, true);
|
||||
}
|
||||
else {
|
||||
activity.progressBar.setProgress(progress);
|
||||
}
|
||||
if (progress == 100) {
|
||||
activity.progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
super.onProgressChanged(view, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (activity.getSupportActionBar() != null)
|
||||
activity.getSupportActionBar().setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedIcon(WebView view, Bitmap icon) {
|
||||
super.onReceivedIcon(view, icon);
|
||||
}
|
||||
|
||||
//The undocumented magic method override
|
||||
//Eclipse will swear at you if you try to put @Override here
|
||||
// For Android 3.0+
|
||||
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
|
||||
|
||||
mUploadMessage = uploadMsg;
|
||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
i.setType("image/*");
|
||||
activity.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE);
|
||||
|
||||
}
|
||||
|
||||
// For Android 3.0+
|
||||
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
|
||||
mUploadMessage = uploadMsg;
|
||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
i.setType("*/*");
|
||||
activity.startActivityForResult(
|
||||
Intent.createChooser(i, "File Browser"),
|
||||
FILECHOOSER_RESULTCODE);
|
||||
}
|
||||
|
||||
//For Android 4.1
|
||||
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
|
||||
mUploadMessage = uploadMsg;
|
||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
i.setType("image/*");
|
||||
activity.startActivityForResult( Intent.createChooser( i, "File Chooser" ), FILECHOOSER_RESULTCODE );
|
||||
|
||||
}
|
||||
|
||||
//For Android 5.0+
|
||||
public boolean onShowFileChooser(
|
||||
WebView webView, ValueCallback<Uri[]> filePathCallback,
|
||||
FileChooserParams fileChooserParams){
|
||||
if(mUploadMessageArray != null){
|
||||
mUploadMessageArray.onReceiveValue(null);
|
||||
}
|
||||
mUploadMessageArray = filePathCallback;
|
||||
|
||||
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
contentSelectionIntent.setType("*/*");
|
||||
Intent[] intentArray;
|
||||
intentArray = new Intent[0];
|
||||
|
||||
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
|
||||
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
|
||||
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
|
||||
activity.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,84 +1,31 @@
|
|||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.pichillilorenzo.flutter_inappbrowser;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.HttpAuthHandler;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.EditText;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
public class InAppBrowserWebViewClient extends WebViewClient {
|
||||
|
||||
/**
|
||||
* The webview client receives notifications about appView
|
||||
*/
|
||||
public class InAppBrowserClient extends WebViewClient {
|
||||
protected static final String LOG_TAG = "IABWebViewClient";
|
||||
private WebViewActivity activity;
|
||||
|
||||
protected static final String LOG_TAG = "InAppBrowser";
|
||||
private static final String LOAD_START_EVENT = "loadstart";
|
||||
private static final String LOAD_STOP_EVENT = "loadstop";
|
||||
private static final String LOAD_ERROR_EVENT = "loaderror";
|
||||
|
||||
private String[] allowedSchemes;
|
||||
|
||||
private EditText edittext;
|
||||
private Activity activity;
|
||||
private final MethodChannel channel;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mEditText
|
||||
* @param activity
|
||||
*/
|
||||
public InAppBrowserClient(EditText mEditText, Activity activity, MethodChannel channel) {
|
||||
this.edittext = mEditText;
|
||||
public InAppBrowserWebViewClient(WebViewActivity activity) {
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the URL that should be loaded
|
||||
*
|
||||
* This handles a small subset of all the URIs that would be encountered.
|
||||
*
|
||||
* @param webView
|
||||
* @param url
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
|
||||
|
||||
if (url.startsWith(WebView.SCHEME_TEL)) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_DIAL);
|
||||
|
@ -88,7 +35,8 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
} catch (android.content.ActivityNotFoundException e) {
|
||||
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
|
||||
}
|
||||
} else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:") || url.startsWith("intent:")) {
|
||||
}
|
||||
else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:") || url.startsWith("intent:")) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
|
@ -104,7 +52,7 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
// Get address
|
||||
String address = null;
|
||||
String address;
|
||||
int parmIndex = url.indexOf('?');
|
||||
if (parmIndex == -1) {
|
||||
address = url.substring(4);
|
||||
|
@ -129,25 +77,8 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
|
||||
}
|
||||
}
|
||||
// Test for whitelisted custom scheme names like mycoolapp:// or twitteroauthresponse:// (Twitter Oauth Response)
|
||||
else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^[A-Za-z0-9+.-]*://.*?$")) {
|
||||
if (allowedSchemes == null) {
|
||||
String allowed = activity.getPreferences(0).getString("AllowedSchemes", null);
|
||||
if(allowed != null) {
|
||||
allowedSchemes = allowed.split(",");
|
||||
}
|
||||
}
|
||||
if (allowedSchemes != null) {
|
||||
for (String scheme : allowedSchemes) {
|
||||
if (url.startsWith(scheme)) {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", "customscheme");
|
||||
obj.put("url", url);
|
||||
channel.invokeMethod("customscheme", obj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return super.shouldOverrideUrlLoading(webView, url);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -164,27 +95,16 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
String newloc = "";
|
||||
if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
|
||||
newloc = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume that everything is HTTP at this point, because if we don't specify,
|
||||
// it really should be. Complain loudly about this!!!
|
||||
Log.e(LOG_TAG, "Possible Uncaught/Unknown URI");
|
||||
newloc = "http://" + url;
|
||||
}
|
||||
|
||||
// Update the UI if we haven't already
|
||||
if (!newloc.equals(edittext.getText().toString())) {
|
||||
edittext.setText(newloc);
|
||||
activity.isLoading = true;
|
||||
|
||||
if (activity.searchView != null && !url.equals(activity.searchView.getQuery().toString())) {
|
||||
activity.searchView.setQuery(url, false);
|
||||
}
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", LOAD_START_EVENT);
|
||||
obj.put("url", newloc);
|
||||
channel.invokeMethod(LOAD_START_EVENT, obj);
|
||||
obj.put("url", url);
|
||||
InAppBrowser.channel.invokeMethod("loadstart", obj);
|
||||
}
|
||||
|
||||
|
||||
|
@ -192,6 +112,8 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
activity.isLoading = false;
|
||||
|
||||
// CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
CookieManager.getInstance().flush();
|
||||
|
@ -204,20 +126,20 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
view.requestFocus();
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", LOAD_STOP_EVENT);
|
||||
obj.put("url", url);
|
||||
channel.invokeMethod(LOAD_STOP_EVENT, obj);
|
||||
InAppBrowser.channel.invokeMethod("loadstop", obj);
|
||||
}
|
||||
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
|
||||
activity.isLoading = false;
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("type", LOAD_ERROR_EVENT);
|
||||
obj.put("url", failingUrl);
|
||||
obj.put("code", errorCode);
|
||||
obj.put("message", description);
|
||||
channel.invokeMethod(LOAD_ERROR_EVENT, obj);
|
||||
InAppBrowser.channel.invokeMethod("loaderror", obj);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,4 +150,4 @@ public class InAppBrowserClient extends WebViewClient {
|
|||
// By default handle 401 like we'd normally do!
|
||||
super.onReceivedHttpAuthRequest(view, handler, host, realm);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.pichillilorenzo.flutter_inappbrowser;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
@ -8,37 +9,98 @@ import android.support.annotation.RequiresApi;
|
|||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SearchView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class WebViewActivity extends AppCompatActivity {
|
||||
|
||||
WebView wv;
|
||||
WebView webView;
|
||||
InAppBrowserWebViewClient inAppBrowserWebViewClient;
|
||||
InAppBrowserWebChromeClient inAppBrowserWebChromeClient;
|
||||
SearchView searchView;
|
||||
InAppBrowserOptions options;
|
||||
ProgressBar progressBar;
|
||||
public boolean isLoading = false;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_web_view);
|
||||
|
||||
webView = findViewById(R.id.webView);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
progressBar.setMax(100);
|
||||
|
||||
Bundle b = getIntent().getExtras();
|
||||
String url = b.getString("url");
|
||||
|
||||
options = new InAppBrowserOptions();
|
||||
options.parse((HashMap<String, Object>) b.getSerializable("options"));
|
||||
|
||||
setContentView(R.layout.activity_web_view);
|
||||
wv = (WebView) findViewById(R.id.webView);
|
||||
|
||||
InAppBrowser.webViewActivity = this;
|
||||
|
||||
wv.loadUrl(url);
|
||||
getSupportActionBar().setTitle(wv.getTitle());
|
||||
prepareWebView();
|
||||
|
||||
webView.loadUrl(url);
|
||||
|
||||
}
|
||||
|
||||
public void prepareWebView() {
|
||||
|
||||
inAppBrowserWebChromeClient = new InAppBrowserWebChromeClient(this);
|
||||
webView.setWebChromeClient(inAppBrowserWebChromeClient);
|
||||
|
||||
inAppBrowserWebViewClient = new InAppBrowserWebViewClient(this);
|
||||
webView.setWebViewClient(inAppBrowserWebViewClient);
|
||||
|
||||
WebSettings settings = webView.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) {
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -49,13 +111,13 @@ public class WebViewActivity extends AppCompatActivity {
|
|||
inflater.inflate(R.menu.menu_main, menu);
|
||||
|
||||
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
|
||||
searchView.setQuery(wv.getUrl(), false);
|
||||
getSupportActionBar().setTitle(wv.getTitle());
|
||||
searchView.setQuery(webView.getUrl(), false);
|
||||
getSupportActionBar().setTitle(webView.getTitle());
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
wv.loadUrl(query);
|
||||
webView.loadUrl(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -68,4 +130,131 @@ public class WebViewActivity extends AppCompatActivity {
|
|||
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 boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
|
||||
goBack();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
// @TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
// void eval(MethodCall call, final MethodChannel.Result result) {
|
||||
// String code = call.argument("code");
|
||||
//
|
||||
// webView.evaluateJavascript(code, new ValueCallback<String>() {
|
||||
// @Override
|
||||
// public void onReceiveValue(String value) {
|
||||
// result.success(value);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
public void close() {
|
||||
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() {
|
||||
if (webView != null)
|
||||
webView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
public void show() {
|
||||
if (webView != null)
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
if (webView != null)
|
||||
return isLoading;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stopLoading(){
|
||||
if (webView != null)
|
||||
webView.stopLoading();
|
||||
}
|
||||
|
||||
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() {
|
||||
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) {
|
||||
close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
|
@ -8,6 +8,15 @@
|
|||
android:orientation="vertical"
|
||||
tools:context=".WebViewActivity">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="@android:style/Widget.Holo.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="top"
|
||||
android:progress="0"
|
||||
android:visibility="gone" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webView"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,18 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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"
|
||||
tools:context=".WebViewActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
android:id="@+id/action_go_back"
|
||||
android:onClick="goBackButtonClicked"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_go_back"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_go_forward"
|
||||
android:title="@string/action_go_forward"
|
||||
android:orderInCategory="101"
|
||||
android:onClick="goForwardButtonClicked"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_share"
|
||||
android:title="@string/action_share"
|
||||
android:orderInCategory="102"
|
||||
android:onClick="shareButtonClicked"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reload"
|
||||
android:title="@string/action_reload"
|
||||
android:orderInCategory="103"
|
||||
android:onClick="reloadButtonClicked"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_close"
|
||||
android:title="@string/action_close"
|
||||
android:orderInCategory="104"
|
||||
android:onClick="closeButtonClicked"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_search"
|
||||
android:title="@string/menu_search"
|
||||
appcompat:actionViewClass="android.widget.SearchView"
|
||||
appcompat:showAsAction="always" />
|
||||
appcompat:showAsAction="ifRoom" />
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="action_go_back">Go Back</string>
|
||||
<string name="action_go_forward">Go Forward</string>
|
||||
<string name="action_reload">Reload</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="action_close">Close</string>
|
||||
<string name="menu_search">Search</string>
|
||||
</resources>
|
||||
|
|
|
@ -9,10 +9,11 @@ import Foundation
|
|||
|
||||
@objcMembers
|
||||
public class InAppBrowserOptions: NSObject {
|
||||
|
||||
var closeButtonCaption = ""
|
||||
var closeButtonColor = ""
|
||||
var clearCache = false
|
||||
var clearSessionCache = false
|
||||
var userAgent = ""
|
||||
var spinner = true
|
||||
var hidden = false
|
||||
var disallowOverScroll = false
|
||||
|
@ -38,6 +39,10 @@ public class InAppBrowserOptions: NSObject {
|
|||
var javaScriptCanOpenWindowsAutomatically = false
|
||||
var javaScriptEnabled = true
|
||||
|
||||
override init(){
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func parse(options: [String: Any]) {
|
||||
for (key, value) in options {
|
||||
if self.value(forKey: key) != nil {
|
||||
|
|
|
@ -78,6 +78,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
var currentURL: URL?
|
||||
var tmpWindow: UIWindow?
|
||||
var browserOptions: InAppBrowserOptions?
|
||||
var initHeaders: [String: String]?
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)!
|
||||
|
@ -117,7 +118,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
spinner.isHidden = false
|
||||
spinner.stopAnimating()
|
||||
|
||||
navigate(to: self.currentURL!)
|
||||
loadUrl(url: self.currentURL!, headers: self.initHeaders)
|
||||
}
|
||||
|
||||
// Prevent crashes on closing windows
|
||||
|
@ -223,6 +224,7 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
self.webView.configuration.mediaPlaybackRequiresUserAction = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,6 +250,33 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
}
|
||||
self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = (browserOptions?.javaScriptCanOpenWindowsAutomatically)!
|
||||
self.webView.configuration.preferences.javaScriptEnabled = (browserOptions?.javaScriptEnabled)!
|
||||
|
||||
if ((browserOptions?.userAgent)! != "") {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.webView.customUserAgent = (browserOptions?.userAgent)!
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
}
|
||||
|
||||
if (browserOptions?.clearCache)! {
|
||||
clearCache()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func loadUrl(url: URL, headers: [String: String]?) {
|
||||
var request = URLRequest(url: url)
|
||||
currentURL = url
|
||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
|
||||
if headers != nil {
|
||||
for (key, value) in headers! {
|
||||
request.setValue(value, forHTTPHeaderField: key)
|
||||
}
|
||||
}
|
||||
|
||||
webView.load(request)
|
||||
}
|
||||
|
||||
// Load user requested url
|
||||
|
@ -270,6 +299,24 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
webView.frame = frame
|
||||
}
|
||||
|
||||
func clearCache() {
|
||||
if #available(iOS 9.0, *) {
|
||||
//let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
|
||||
let date = NSDate(timeIntervalSince1970: 0)
|
||||
WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: date as Date, completionHandler:{ })
|
||||
} else {
|
||||
var libraryPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, false).first!
|
||||
libraryPath += "/Cookies"
|
||||
|
||||
do {
|
||||
try FileManager.default.removeItem(atPath: libraryPath)
|
||||
} catch {
|
||||
print("can't clear cache")
|
||||
}
|
||||
URLCache.shared.removeAllCachedResponses()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func reload () {
|
||||
webView.reload()
|
||||
}
|
||||
|
@ -305,22 +352,23 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
|
|||
})
|
||||
}
|
||||
|
||||
func navigate(to url: URL) {
|
||||
let request = URLRequest(url: url)
|
||||
currentURL = url
|
||||
updateUrlTextField(url: (currentURL?.absoluteString)!)
|
||||
webView.load(request)
|
||||
func canGoBack() -> Bool {
|
||||
return webView.canGoBack
|
||||
}
|
||||
|
||||
@objc func goBack() {
|
||||
if webView.canGoBack {
|
||||
if canGoBack() {
|
||||
webView.goBack()
|
||||
updateUrlTextField(url: (webView?.url?.absoluteString)!)
|
||||
}
|
||||
}
|
||||
|
||||
func canGoForward() -> Bool {
|
||||
return webView.canGoForward
|
||||
}
|
||||
|
||||
@objc func goForward() {
|
||||
if webView.canGoForward {
|
||||
if canGoForward() {
|
||||
webView.goForward()
|
||||
updateUrlTextField(url: (webView?.url?.absoluteString)!)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
case "open":
|
||||
self.open(arguments: arguments!, result: result)
|
||||
break
|
||||
case "loadUrl":
|
||||
self.loadUrl(arguments: arguments!, result: result)
|
||||
break
|
||||
case "close":
|
||||
self.close()
|
||||
result(true)
|
||||
|
@ -67,12 +70,18 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
self.webViewController?.goBack()
|
||||
result(true)
|
||||
break
|
||||
case "canGoBack":
|
||||
result(self.webViewController?.canGoBack() ?? false)
|
||||
break
|
||||
case "goForward":
|
||||
self.webViewController?.goForward()
|
||||
result(true)
|
||||
break
|
||||
case "canGoForward":
|
||||
result(self.webViewController?.canGoForward() ?? false)
|
||||
break
|
||||
case "isLoading":
|
||||
result(self.webViewController?.webView.isLoading == true)
|
||||
result((self.webViewController?.webView.isLoading ?? false) == true)
|
||||
break
|
||||
case "stopLoading":
|
||||
self.webViewController?.webView.stopLoading()
|
||||
|
@ -117,6 +126,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
|
||||
public func open(arguments: NSDictionary, result: @escaping FlutterResult) {
|
||||
let url: String? = (arguments["url"] as? String)!
|
||||
let headers = (arguments["headers"] as? [String: String])!
|
||||
var target: String? = (arguments["target"] as? String)!
|
||||
target = target != nil ? target : "_self"
|
||||
let options = (arguments["options"] as? [String: Any])!
|
||||
|
@ -129,45 +139,42 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
}
|
||||
|
||||
if (target == "_self" || target == "_target") {
|
||||
openIn(inAppBrowser: absoluteUrl!, withOptions: options)
|
||||
open(inAppBrowser: absoluteUrl!, headers: headers, withOptions: options)
|
||||
}
|
||||
else if (target == "_system") {
|
||||
open(inSystem: absoluteUrl!)
|
||||
}
|
||||
else {
|
||||
// anything else
|
||||
openIn(inAppBrowser: absoluteUrl!, withOptions: options)
|
||||
open(inAppBrowser: absoluteUrl!, headers: headers,withOptions: options)
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("url is empty")
|
||||
result(false)
|
||||
}
|
||||
result(true)
|
||||
}
|
||||
|
||||
func openIn(inAppBrowser url: URL, withOptions options: [String: Any]) {
|
||||
public func loadUrl(arguments: NSDictionary, result: @escaping FlutterResult) {
|
||||
let url: String? = (arguments["url"] as? String)!
|
||||
let headers = (arguments["headers"] as? [String: String])!
|
||||
|
||||
if url != nil {
|
||||
let absoluteUrl = URL(string: url!)!.absoluteURL
|
||||
webViewController?.loadUrl(url: absoluteUrl, headers: headers)
|
||||
}
|
||||
else {
|
||||
print("url is empty")
|
||||
result(false)
|
||||
}
|
||||
result(true)
|
||||
}
|
||||
|
||||
func open(inAppBrowser url: URL, headers: [String: String], withOptions options: [String: Any]) {
|
||||
|
||||
let browserOptions = InAppBrowserOptions()
|
||||
browserOptions.parse(options: options)
|
||||
|
||||
if browserOptions.clearCache {
|
||||
let _: HTTPCookie?
|
||||
let storage = HTTPCookieStorage.shared
|
||||
for cookie in storage.cookies! {
|
||||
if !(cookie.domain.isEqual(".^filecookies^") ) {
|
||||
storage.deleteCookie(cookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if browserOptions.clearSessionCache {
|
||||
let storage = HTTPCookieStorage.shared
|
||||
for cookie in storage.cookies! {
|
||||
if !(cookie.domain.isEqual(".^filecookies^") && cookie.isSessionOnly) {
|
||||
storage.deleteCookie(cookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if webViewController == nil {
|
||||
|
||||
|
@ -182,6 +189,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
webViewController?.browserOptions = browserOptions
|
||||
webViewController?.tmpWindow = tmpWindow
|
||||
webViewController?.currentURL = url
|
||||
webViewController?.initHeaders = headers
|
||||
webViewController?.navigationDelegate = self
|
||||
}
|
||||
|
||||
|
@ -258,18 +266,18 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
//
|
||||
// If no wrapper is supplied, then the source string is executed directly.
|
||||
func injectDeferredObject(_ source: String, withWrapper jsWrapper: String) {
|
||||
if jsWrapper != nil {
|
||||
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: [source], options: [])
|
||||
let sourceArrayString = String(data: jsonData!, encoding: String.Encoding.utf8)
|
||||
if sourceArrayString != nil {
|
||||
let sourceString: String? = (sourceArrayString! as NSString).substring(with: NSRange(location: 1, length: (sourceArrayString?.characters.count ?? 0) - 2))
|
||||
let jsToInject = String(format: jsWrapper, sourceString!)
|
||||
webViewController?.webView?.evaluateJavaScript(jsToInject)
|
||||
}
|
||||
}
|
||||
else {
|
||||
webViewController?.webView?.evaluateJavaScript(source)
|
||||
//if jsWrapper != nil {
|
||||
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: [source], options: [])
|
||||
let sourceArrayString = String(data: jsonData!, encoding: String.Encoding.utf8)
|
||||
if sourceArrayString != nil {
|
||||
let sourceString: String? = (sourceArrayString! as NSString).substring(with: NSRange(location: 1, length: (sourceArrayString?.characters.count ?? 0) - 2))
|
||||
let jsToInject = String(format: jsWrapper, sourceString!)
|
||||
webViewController?.webView?.evaluateJavaScript(jsToInject)
|
||||
}
|
||||
//}
|
||||
//else {
|
||||
// webViewController?.webView?.evaluateJavaScript(source)
|
||||
//}
|
||||
}
|
||||
|
||||
public func injectScriptCode(arguments: NSDictionary) {
|
||||
|
@ -294,23 +302,23 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
|
||||
func webViewDidStartLoad(_ webView: WKWebView) {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
channel.invokeMethod("loadstart", arguments: ["type": "loadstart", "url": url])
|
||||
channel.invokeMethod("loadstart", arguments: ["url": url])
|
||||
}
|
||||
|
||||
func webViewDidFinishLoad(_ webView: WKWebView) {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
channel.invokeMethod("loadstop", arguments: ["type": "loadstop", "url": url])
|
||||
channel.invokeMethod("loadstop", arguments: ["url": url])
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFailLoadWithError error: Error) {
|
||||
let url: String = webViewController!.currentURL!.absoluteString
|
||||
let arguments = ["type": "loaderror", "url": url, "code": error._code, "message": error.localizedDescription] as [String : Any]
|
||||
let arguments = ["url": url, "code": error._code, "message": error.localizedDescription] as [String : Any]
|
||||
channel.invokeMethod("loaderror", arguments: arguments)
|
||||
}
|
||||
|
||||
func browserExit() {
|
||||
|
||||
channel.invokeMethod("exit", arguments: ["type": "exit"])
|
||||
channel.invokeMethod("exit", arguments: [])
|
||||
|
||||
// Set navigationDelegate to nil to ensure no callbacks are received from it.
|
||||
webViewController?.navigationDelegate = nil
|
||||
|
|
|
@ -51,10 +51,6 @@ class InAppBrowser {
|
|||
case "exit":
|
||||
onExit();
|
||||
break;
|
||||
case "customscheme":
|
||||
String url = call.arguments["url"];
|
||||
onCustomScheme(url);
|
||||
break;
|
||||
}
|
||||
return new Future.value("");
|
||||
}
|
||||
|
@ -121,14 +117,22 @@ class InAppBrowser {
|
|||
/// - __transitionstyle__: Set to `fliphorizontal`, `crossdissolve` or `coververtical` to set the [transition style](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/modalTransitionStyle) (defaults to `coververtical`).
|
||||
/// - __toolbarposition__: Set to `top` or `bottom` (default is `bottom`). Causes the toolbar to be at the top or bottom of the window.
|
||||
/// - __hidespinner__: Set to `yes` or `no` to change the visibility of the loading indicator (defaults to `no`).
|
||||
Future<void> open(String url, {String target = "_self", Map<String, dynamic> options = const {}}) async {
|
||||
Future<void> open(String url, {Map<String, String> headers = const {}, String target = "_self", Map<String, dynamic> options = const {}}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('target', () => target);
|
||||
args.putIfAbsent('options', () => options);
|
||||
return await _channel.invokeMethod('open', args);
|
||||
}
|
||||
|
||||
Future<void> loadUrl(String url, {Map<String, String> headers = const {}}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url);
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
return await _channel.invokeMethod('loadUrl', args);
|
||||
}
|
||||
|
||||
///Displays an [InAppBrowser] window that was opened hidden. Calling this has no effect if the [InAppBrowser] was already visible.
|
||||
Future<void> show() async {
|
||||
return await _channel.invokeMethod('show');
|
||||
|
|
Loading…
Reference in New Issue