【发布时间】:2019-07-31 07:45:11
【问题描述】:
我已经使用 Flutter 的 web_view_plugin(webview) 构建了一个混合应用程序。
我们的一种支付方式需要打开一个 3rd 方应用程序(在本例中为 kakaotalk)。但是flutter webview插件没有提供这个功能,返回了net::ERR_UNKNOWN_URL_SCHEME。我做了一些研究,我知道问题在于url。如果url 不以http 或https 开头,则会导致此错误。
所以,为了解决这个问题,我不得不更改本机 Java 代码。现在我完全没有使用java 和android 的经验,因此修复本机代码非常困难。我知道我必须修改shouldOverrideUrlLoading 部分,以允许以intent:// 开头的url 并且我必须进行一些验证以检查应用程序是否已安装。(如果未安装用户应该被重定向到Playstore)
我添加的代码在shouldOverrideUrlLoading。
我还做了三个导入。剩下的就是代码,由flutter生成
package com.flutter_webview_plugin;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.os.Build;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Intent; //added import
import android.net.Uri; //added import
import android.content.ActivityNotFoundException; //added import
/**
* Created by lejard_h on 20/12/2017.
*/
public class BrowserClient extends WebViewClient {
private Pattern invalidUrlPattern = null;
public BrowserClient() {
this(null);
}
public BrowserClient(String invalidUrlRegex) {
super();
if (invalidUrlRegex != null) {
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
}
}
public void updateInvalidUrlRegex(String invalidUrlRegex) {
if (invalidUrlRegex != null) {
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
} else {
invalidUrlPattern = null;
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
data.put("type", "startLoad");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
FlutterWebviewPlugin.channel.invokeMethod("onUrlChanged", data);
data.put("type", "finishLoad");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// returning true causes the current WebView to abort loading the URL,
// while returning false causes the WebView to continue loading the URL as usual.
String url = request.getUrl().toString();
boolean isInvalid = checkInvalidUrl(url);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
data.put("type", isInvalid ? "abortLoad" : "shouldStart");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
return isInvalid;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// returning true causes the current WebView to abort loading the URL,
// while returning false causes the WebView to continue loading the URL as usual.
if (url.startsWith(INTENT_PROTOCOL_START)) {
final int customUrlStartIndex = INTENT_PROTOCOL_START.length();
final int customUrlEndIndex = url.indexOf(INTENT_PROTOCOL_INTENT);
if (customUrlEndIndex < 0) {
return false;
} else {
final String customUrl = url.substring(customUrlStartIndex, customUrlEndIndex);
try {
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(customUrl)));
} catch (ActivityNotFoundException e) {
final int packageStartIndex = customUrlEndIndex + INTENT_PROTOCOL_INTENT.length();
final int packageEndIndex = url.indexOf(INTENT_PROTOCOL_END);
final String packageName = url.substring(packageStartIndex, packageEndIndex < 0 ? url.length() : packageEndIndex);
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(GOOGLE_PLAY_STORE_PREFIX + packageName)));
}
return true;
}
} else {
return false;
}
// boolean isInvalid = checkInvalidUrl(url);
// Map<String, Object> data = new HashMap<>();
// data.put("url", url);
// data.put("type", isInvalid ? "abortLoad" : "shouldStart");
// FlutterWebviewPlugin.channel.invokeMethod("onState", data);
// return isInvalid;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
Map<String, Object> data = new HashMap<>();
data.put("url", request.getUrl().toString());
data.put("code", Integer.toString(errorResponse.getStatusCode()));
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Map<String, Object> data = new HashMap<>();
data.put("url", failingUrl);
data.put("code", errorCode);
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
}
private boolean checkInvalidUrl(String url) {
if (invalidUrlPattern == null) {
return false;
} else {
Matcher matcher = invalidUrlPattern.matcher(url);
return matcher.lookingAt();
}
}
}
代码编译,但当我尝试使用“3rd party app(kakaotalk)”付款时,它仍然返回相同的错误net::ERR_UNKNOWN_URL_SCHEME
【问题讨论】:
标签: java android flutter webview