Skip to content

Commit 92baafb

Browse files
authored
Merge pull request #1 from fluttercommunity/master
pull
2 parents 75831d2 + e074dd0 commit 92baafb

File tree

13 files changed

+181
-20
lines changed

13 files changed

+181
-20
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# 0.3.3
2+
3+
- BREAKING CHANGE - AndroidX support
4+
5+
# 0.3.2
6+
7+
- enable Javascript in iOS, support abort loading specific URLs
8+
- add resizeToAvoidBottomInset to WebviewScaffold; #301
9+
10+
# 0.3.1
11+
12+
- Add support for geolocation Android
13+
- fix No269: Can't load target="_blank" links on iOS
14+
- fix: reloadUrl will not return Future
15+
- Fix height of keyboard
16+
- Fix Hide/Show WebView
17+
- hotfix widget back to initialChild after webview is tapped on Android
18+
119
# 0.3.0
220

321
- Fixes rect capture issue. Ensures WebView remains in the correct place on screen even when keyboard appears.

android/build.gradle

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
group 'com.flutter_webview_plugin'
22
version '1.0-SNAPSHOT'
33

4+
def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning";
5+
gradle.buildFinished { buildResult ->
6+
if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) {
7+
println ' *********************************************************'
8+
println 'WARNING: This version of flutter_webview_plugin will break your Android build if it or its dependencies aren\'t compatible with AndroidX.'
9+
println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.'
10+
println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.'
11+
println ' *********************************************************'
12+
rootProject.ext.set(ANDROIDX_WARNING, true);
13+
}
14+
}
15+
416
buildscript {
517
repositories {
618
google()
719
jcenter()
820
}
921

1022
dependencies {
11-
classpath 'com.android.tools.build:gradle:3.2.1'
23+
classpath 'com.android.tools.build:gradle:3.3.2'
1224
}
1325
}
1426

@@ -21,10 +33,10 @@ allprojects {
2133
apply plugin: 'com.android.library'
2234

2335
android {
24-
compileSdkVersion 27
36+
compileSdkVersion 28
2537

2638
defaultConfig {
27-
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
39+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2840
// NOTE(jeffmikels): When targetSdkVersion or minSdkVersion is not set or < 4, gradle adds
2941
// additional scary permissions such as WRITE_EXTERNAL_STORAGE and READ_PHONE_STATE.
3042
minSdkVersion 16

android/src/main/java/com/flutter_webview_plugin/BrowserClient.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
package com.flutter_webview_plugin;
22

3+
import android.annotation.TargetApi;
34
import android.graphics.Bitmap;
5+
import android.os.Build;
46
import android.webkit.WebResourceRequest;
57
import android.webkit.WebResourceResponse;
68
import android.webkit.WebView;
79
import android.webkit.WebViewClient;
810

911
import java.util.HashMap;
1012
import java.util.Map;
13+
import java.util.regex.Matcher;
14+
import java.util.regex.Pattern;
1115

1216
/**
1317
* Created by lejard_h on 20/12/2017.
1418
*/
1519

1620
public class BrowserClient extends WebViewClient {
21+
private Pattern invalidUrlPattern = null;
22+
1723
public BrowserClient() {
24+
this(null);
25+
}
26+
27+
public BrowserClient(String invalidUrlRegex) {
1828
super();
29+
if (invalidUrlRegex != null) {
30+
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
31+
}
32+
}
33+
34+
public void updateInvalidUrlRegex(String invalidUrlRegex) {
35+
if (invalidUrlRegex != null) {
36+
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
37+
} else {
38+
invalidUrlPattern = null;
39+
}
1940
}
2041

2142
@Override
@@ -40,6 +61,35 @@ public void onPageFinished(WebView view, String url) {
4061

4162
}
4263

64+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
65+
@Override
66+
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
67+
// returning true causes the current WebView to abort loading the URL,
68+
// while returning false causes the WebView to continue loading the URL as usual.
69+
String url = request.getUrl().toString();
70+
boolean isInvalid = checkInvalidUrl(url);
71+
Map<String, Object> data = new HashMap<>();
72+
data.put("url", url);
73+
data.put("type", isInvalid ? "abortLoad" : "shouldStart");
74+
75+
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
76+
return isInvalid;
77+
}
78+
79+
@Override
80+
public boolean shouldOverrideUrlLoading(WebView view, String url) {
81+
// returning true causes the current WebView to abort loading the URL,
82+
// while returning false causes the WebView to continue loading the URL as usual.
83+
boolean isInvalid = checkInvalidUrl(url);
84+
Map<String, Object> data = new HashMap<>();
85+
data.put("url", url);
86+
data.put("type", isInvalid ? "abortLoad" : "shouldStart");
87+
88+
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
89+
return isInvalid;
90+
}
91+
92+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
4393
@Override
4494
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
4595
super.onReceivedHttpError(view, request, errorResponse);
@@ -48,4 +98,22 @@ public void onReceivedHttpError(WebView view, WebResourceRequest request, WebRes
4898
data.put("code", Integer.toString(errorResponse.getStatusCode()));
4999
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
50100
}
101+
102+
@Override
103+
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
104+
super.onReceivedError(view, errorCode, description, failingUrl);
105+
Map<String, Object> data = new HashMap<>();
106+
data.put("url", failingUrl);
107+
data.put("code", errorCode);
108+
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
109+
}
110+
111+
private boolean checkInvalidUrl(String url) {
112+
if (invalidUrlPattern == null) {
113+
return false;
114+
} else {
115+
Matcher matcher = invalidUrlPattern.matcher(url);
116+
return matcher.lookingAt();
117+
}
118+
}
51119
}

android/src/main/java/com/flutter_webview_plugin/FlutterWebviewPlugin.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ private void openUrl(MethodCall call, MethodChannel.Result result) {
9999
Map<String, String> headers = call.argument("headers");
100100
boolean scrollBar = call.argument("scrollBar");
101101
boolean allowFileURLs = call.argument("allowFileURLs");
102+
boolean useWideViewPort = call.argument("useWideViewPort");
103+
String invalidUrlRegex = call.argument("invalidUrlRegex");
102104
boolean geolocationEnabled = call.argument("geolocationEnabled");
103105

104106
if (webViewManager == null || webViewManager.closed == true) {
@@ -122,6 +124,8 @@ private void openUrl(MethodCall call, MethodChannel.Result result) {
122124
supportMultipleWindows,
123125
appCacheEnabled,
124126
allowFileURLs,
127+
useWideViewPort,
128+
invalidUrlRegex,
125129
geolocationEnabled
126130
);
127131
result.success(null);

android/src/main/java/com/flutter_webview_plugin/WebviewManager.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import android.content.Intent;
44
import android.net.Uri;
5-
import android.util.Log;
65
import android.annotation.TargetApi;
76
import android.app.Activity;
87
import android.content.Context;
@@ -16,7 +15,6 @@
1615
import android.webkit.WebChromeClient;
1716
import android.webkit.WebSettings;
1817
import android.webkit.WebView;
19-
import android.webkit.WebViewClient;
2018
import android.widget.FrameLayout;
2119
import android.provider.MediaStore;
2220
import android.support.v4.content.FileProvider;
@@ -90,6 +88,7 @@ public boolean handleResult(int requestCode, int resultCode, Intent intent){
9088
boolean closed = false;
9189
WebView webView;
9290
Activity activity;
91+
BrowserClient webViewClient;
9392
ResultHandler resultHandler;
9493
Context context;
9594

@@ -98,7 +97,7 @@ public boolean handleResult(int requestCode, int resultCode, Intent intent){
9897
this.activity = activity;
9998
this.context = context;
10099
this.resultHandler = new ResultHandler();
101-
WebViewClient webViewClient = new BrowserClient();
100+
webViewClient = new BrowserClient();
102101
webView.setOnKeyListener(new View.OnKeyListener() {
103102
@Override
104103
public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -308,6 +307,8 @@ void openUrl(
308307
boolean supportMultipleWindows,
309308
boolean appCacheEnabled,
310309
boolean allowFileURLs,
310+
boolean useWideViewPort,
311+
String invalidUrlRegex,
311312
boolean geolocationEnabled
312313
) {
313314
webView.getSettings().setJavaScriptEnabled(withJavascript);
@@ -323,6 +324,10 @@ void openUrl(
323324
webView.getSettings().setAllowFileAccessFromFileURLs(allowFileURLs);
324325
webView.getSettings().setAllowUniversalAccessFromFileURLs(allowFileURLs);
325326

327+
webView.getSettings().setUseWideViewPort(useWideViewPort);
328+
329+
webViewClient.updateInvalidUrlRegex(invalidUrlRegex);
330+
326331
if (geolocationEnabled) {
327332
webView.getSettings().setGeolocationEnabled(true);
328333
webView.setWebChromeClient(new WebChromeClient() {

example/android/app/build.gradle

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ apply plugin: 'com.android.application'
1515
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
1616

1717
android {
18-
compileSdkVersion 27
18+
compileSdkVersion 28
1919

2020
lintOptions {
2121
disable 'InvalidPackage'
@@ -25,6 +25,7 @@ android {
2525
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
2626
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
2727
applicationId "com.yourcompany.flutter_webview_plugin_example"
28+
minSdkVersion 16
2829
}
2930

3031
buildTypes {
@@ -41,7 +42,7 @@ flutter {
4142
}
4243

4344
dependencies {
44-
androidTestImplementation 'com.android.support:support-annotations:27.0.0'
45-
androidTestImplementation 'com.android.support.test:runner:1.0.2'
46-
androidTestImplementation 'com.android.support.test:rules:1.0.2'
45+
androidTestImplementation 'androidx.annotation:annotation:1.0.2'
46+
androidTestImplementation 'androidx.test:runner:1.1.1'
47+
androidTestImplementation 'androidx.test:rules:1.1.1'
4748
}

example/android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:3.2.1'
11+
classpath 'com.android.tools.build:gradle:3.3.2'
1212
}
1313
}
1414

@@ -33,5 +33,5 @@ task clean(type: Delete) {
3333
}
3434

3535
task wrapper(type: Wrapper) {
36-
gradleVersion = '2.14.1'
36+
gradleVersion = '4.10.2'
3737
}

example/android/gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
org.gradle.jvmargs=-Xmx1536M
2+
android.useAndroidX=true
3+
android.enableJetifier=false

example/lib/main.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class _MyHomePageState extends State<MyHomePage> {
201201
selectedUrl,
202202
rect: Rect.fromLTWH(0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
203203
userAgent: kAndroidUserAgent,
204+
invalidUrlRegex: r'^(https).+(twitter)', // prevent redirecting to twitter when user click on its icon in flutter website
204205
);
205206
},
206207
child: const Text('Open Webview (rect)'),

ios/Classes/FlutterWebviewPlugin.m

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@interface FlutterWebviewPlugin() <WKNavigationDelegate, UIScrollViewDelegate, WKUIDelegate> {
77
BOOL _enableAppScheme;
88
BOOL _enableZoom;
9+
NSString* _invalidUrlRegex;
910
}
1011
@end
1112

@@ -83,6 +84,8 @@ - (void)initWebview:(FlutterMethodCall*)call {
8384
NSString *userAgent = call.arguments[@"userAgent"];
8485
NSNumber *withZoom = call.arguments[@"withZoom"];
8586
NSNumber *scrollBar = call.arguments[@"scrollBar"];
87+
NSNumber *withJavascript = call.arguments[@"withJavascript"];
88+
_invalidUrlRegex = call.arguments[@"invalidUrlRegex"];
8689

8790
if (clearCache != (id)[NSNull null] && [clearCache boolValue]) {
8891
[[NSURLCache sharedURLCache] removeAllCachedResponses];
@@ -112,9 +115,18 @@ - (void)initWebview:(FlutterMethodCall*)call {
112115
self.webview.scrollView.showsHorizontalScrollIndicator = [scrollBar boolValue];
113116
self.webview.scrollView.showsVerticalScrollIndicator = [scrollBar boolValue];
114117

118+
WKPreferences* preferences = [[self.webview configuration] preferences];
119+
if ([withJavascript boolValue]) {
120+
[preferences setJavaScriptEnabled:YES];
121+
} else {
122+
[preferences setJavaScriptEnabled:NO];
123+
}
124+
115125
_enableZoom = [withZoom boolValue];
116126

117-
[self.viewController.view addSubview:self.webview];
127+
UIViewController* presentedViewController = self.viewController.presentedViewController;
128+
UIViewController* currentViewController = presentedViewController != nil ? presentedViewController : self.viewController;
129+
[currentViewController.view addSubview:self.webview];
118130

119131
[self navigate:call];
120132
}
@@ -235,18 +247,37 @@ - (void)cleanCookies {
235247
}];
236248
}
237249

250+
- (bool)checkInvalidUrl:(NSURL*)url {
251+
NSString* urlString = url != nil ? [url absoluteString] : nil;
252+
if (_invalidUrlRegex != [NSNull null] && urlString != nil) {
253+
NSError* error = NULL;
254+
NSRegularExpression* regex =
255+
[NSRegularExpression regularExpressionWithPattern:_invalidUrlRegex
256+
options:NSRegularExpressionCaseInsensitive
257+
error:&error];
258+
NSTextCheckingResult* match = [regex firstMatchInString:urlString
259+
options:0
260+
range:NSMakeRange(0, [urlString length])];
261+
return match != nil;
262+
} else {
263+
return false;
264+
}
265+
}
266+
238267
#pragma mark -- WkWebView Delegate
239268
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
240269
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
241270

271+
BOOL isInvalid = [self checkInvalidUrl: navigationAction.request.URL];
272+
242273
id data = @{@"url": navigationAction.request.URL.absoluteString,
243-
@"type": @"shouldStart",
274+
@"type": isInvalid ? @"abortLoad" : @"shouldStart",
244275
@"navigationType": [NSNumber numberWithInt:navigationAction.navigationType]};
245276
[channel invokeMethod:@"onState" arguments:data];
246277

247278
if (navigationAction.navigationType == WKNavigationTypeBackForward) {
248279
[channel invokeMethod:@"onBackPressed" arguments:nil];
249-
} else {
280+
} else if (!isInvalid) {
250281
id data = @{@"url": navigationAction.request.URL.absoluteString};
251282
[channel invokeMethod:@"onUrlChanged" arguments:data];
252283
}
@@ -255,7 +286,11 @@ - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigati
255286
([webView.URL.scheme isEqualToString:@"http"] ||
256287
[webView.URL.scheme isEqualToString:@"https"] ||
257288
[webView.URL.scheme isEqualToString:@"about"])) {
258-
decisionHandler(WKNavigationActionPolicyAllow);
289+
if (isInvalid) {
290+
decisionHandler(WKNavigationActionPolicyCancel);
291+
} else {
292+
decisionHandler(WKNavigationActionPolicyAllow);
293+
}
259294
} else {
260295
decisionHandler(WKNavigationActionPolicyCancel);
261296
}

0 commit comments

Comments
 (0)