Commit 5fc1d405 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

updated plugin version, added new options to hide/show scrollbars #165,...

updated plugin version, added new options to hide/show scrollbars #165, initial support for DownloadManager in Android and iOS
parent 9470a529
This diff is collapsed.
## 1.3.0
- Merge
- Merge
- Merge
- Merge
- Merge
- Merge
- Added `horizontalScrollBarEnabled` and `verticalScrollBarEnabled` options to enable/disable the corresponding scrollbar of the WebView [#165](https://github.com/pichillilorenzo/flutter_inappbrowser/issues/165)
## 1.2.1
- Merge "Add new option to control the contentMode in Android platform" [#101](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/101) (thanks to [DreamBuddy](https://github.com/DreamBuddy))
......
......@@ -8,7 +8,6 @@
[![Donate to this project using Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://www.patreon.com/bePatron?u=9269604)
A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
This plugin is inspired by the popular [cordova-plugin-inappbrowser](https://github.com/apache/cordova-plugin-inappbrowser)!
### Requirements
- Dart sdk: ">=2.1.0-dev.7.1 <3.0.0"
......
......@@ -3,6 +3,7 @@
package="com.pichillilorenzo.flutter_inappbrowser">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
<activity android:theme="@style/AppTheme" android:name=".InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
......
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.Manifest;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.JsonReader;
import android.util.JsonToken;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
import android.webkit.WebBackForwardList;
import android.webkit.WebHistoryItem;
......@@ -21,6 +31,7 @@ import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappbrowser.RequestPermissionHandler;
import com.pichillilorenzo.flutter_inappbrowser.Util;
import java.io.ByteArrayOutputStream;
......@@ -36,6 +47,8 @@ import io.flutter.plugin.common.PluginRegistry;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import static android.content.Context.DOWNLOAD_SERVICE;
public class InAppWebView extends WebView {
static final String LOG_TAG = "InAppWebView";
......@@ -110,6 +123,8 @@ public class InAppWebView extends WebView {
public void prepare() {
final Activity activity = (inAppBrowserActivity != null) ? inAppBrowserActivity : registrar.activity();
boolean isFromInAppBrowserActivity = inAppBrowserActivity != null;
httpClient = new OkHttpClient().newBuilder().cache(new Cache(getContext().getCacheDir(), okHttpClientCacheSize)).build();
......@@ -122,39 +137,43 @@ public class InAppWebView extends WebView {
inAppWebViewClient = new InAppWebViewClient((isFromInAppBrowserActivity) ? inAppBrowserActivity : flutterWebView);
setWebViewClient(inAppWebViewClient);
// final Activity activity = this;
//
// webView.setDownloadListener(new DownloadListener() {
// @Override
// public void onDownloadStart(final String url, final String userAgent,
// final String contentDisposition, final String mimetype,
// final long contentLength) {
//
// RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
// @Override
// public void run(){
// DownloadManager.Request request = new DownloadManager.Request(
// Uri.parse(url));
//
// final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
// request.allowScanningByMediaScanner();
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
// request.setVisibleInDownloadsUi(true);
// request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
// DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
// if (dm != null) {
// dm.enqueue(request);
// Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
// Toast.LENGTH_LONG).show();
// }
// else {
// Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
// Toast.LENGTH_LONG).show();
// }
// }
// });
// }
// });
activity.registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(final String url, final String userAgent,
final String contentDisposition, final String mimetype,
final long contentLength) {
RequestPermissionHandler.checkAndRun(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, RequestPermissionHandler.REQUEST_CODE_WRITE_EXTERNAL_STORAGE, new Runnable(){
@Override
public void run(){
Log.e(LOG_TAG, url);
Log.e(LOG_TAG, contentDisposition);
Log.e(LOG_TAG, mimetype);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
request.setVisibleInDownloadsUi(true);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
DownloadManager dm = (DownloadManager) activity.getSystemService(DOWNLOAD_SERVICE);
if (dm != null) {
dm.enqueue(request);
//Toast.makeText(getApplicationContext(), "Downloading File: " + filename, //To notify the Client that the file is being downloaded
// Toast.LENGTH_LONG).show();
}
else {
//Toast.makeText(getApplicationContext(), "Cannot Download File: " + filename, //To notify the Client that the file cannot be downloaded
// Toast.LENGTH_LONG).show();
}
}
});
}
});
WebSettings settings = getSettings();
......@@ -187,6 +206,8 @@ public class InAppWebView extends WebView {
settings.setUseWideViewPort(options.useWideViewPort);
settings.setSupportZoom(options.supportZoom);
settings.setTextZoom(options.textZoom);
setVerticalScrollBarEnabled(options.verticalScrollBarEnabled);
setHorizontalScrollBarEnabled(options.horizontalScrollBarEnabled);
if (options.transparentBackground) {
setBackgroundColor(Color.TRANSPARENT);
......@@ -205,6 +226,19 @@ public class InAppWebView extends WebView {
}
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (1 == id) { // test
//if (downloadID == id) {
//Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
}
}
};
public void loadUrl(String url, MethodChannel.Result result) {
if (!url.isEmpty()) {
loadUrl(url);
......@@ -367,6 +401,12 @@ public class InAppWebView extends WebView {
if (newOptionsMap.get("textZoom") != null && options.textZoom != newOptions.textZoom)
settings.setTextZoom(newOptions.textZoom);
if (newOptionsMap.get("verticalScrollBarEnabled") != null && options.verticalScrollBarEnabled != newOptions.verticalScrollBarEnabled)
setVerticalScrollBarEnabled(newOptions.verticalScrollBarEnabled);
if (newOptionsMap.get("horizontalScrollBarEnabled") != null && options.horizontalScrollBarEnabled != newOptions.horizontalScrollBarEnabled)
setHorizontalScrollBarEnabled(newOptions.horizontalScrollBarEnabled);
if (newOptionsMap.get("transparentBackground") != null && options.transparentBackground != newOptions.transparentBackground) {
if (newOptions.transparentBackground) {
setBackgroundColor(Color.TRANSPARENT);
......@@ -524,4 +564,11 @@ public class InAppWebView extends WebView {
private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.channel : flutterWebView.channel;
}
@Override
public void destroy() {
final Activity activity = (inAppBrowserActivity != null) ? inAppBrowserActivity : registrar.activity();
activity.unregisterReceiver(onDownloadComplete);
super.destroy();
}
}
......@@ -14,6 +14,8 @@ public class InAppWebViewOptions extends Options {
public boolean javaScriptCanOpenWindowsAutomatically = false;
public boolean mediaPlaybackRequiresUserGesture = true;
public int textZoom = 100;
public boolean verticalScrollBarEnabled = true;
public boolean horizontalScrollBarEnabled = true;
public boolean clearSessionCache = false;
public boolean builtInZoomControls = false;
......
......@@ -15,6 +15,8 @@ public abstract class RequestPermissionHandler implements ActivityCompat.OnReque
private static Map<Integer, List<Runnable>> actionDictionary = new HashMap<>();
public static int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1;
public static void checkAndRun(Activity activity, String permission, int requestCode, Runnable runnable) {
int permissionCheck = ContextCompat.checkSelfPermission(activity.getApplicationContext(), permission);
......
......@@ -55,8 +55,8 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView(
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
//initialUrl: "https://flutter.dev/",
initialFile: "assets/index.html",
initialUrl: "https://flutter.dev/",
//initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: {
//"mediaPlaybackRequiresUserGesture": false,
......
......@@ -82,8 +82,8 @@ window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() {
let platformReadyJS = "window.dispatchEvent(new Event('flutterInAppBrowserPlatformReady'));";
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, URLSessionDownloadDelegate {
var IABController: InAppBrowserWebViewController?
var IAWController: FlutterWebViewController?
var options: InAppWebViewOptions?
......@@ -180,6 +180,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
configuration.preferences.javaScriptEnabled = (options?.javaScriptEnabled)!
scrollView.showsVerticalScrollIndicator = (options?.verticalScrollBarEnabled)!
scrollView.showsHorizontalScrollIndicator = (options?.horizontalScrollBarEnabled)!
if ((options?.userAgent)! != "") {
if #available(iOS 9.0, *) {
customUserAgent = (options?.userAgent)!
......@@ -388,6 +391,13 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
configuration.preferences.javaScriptEnabled = newOptions.javaScriptEnabled
}
if newOptionsMap["verticalScrollBarEnabled"] != nil && options?.verticalScrollBarEnabled != newOptions.verticalScrollBarEnabled {
scrollView.showsVerticalScrollIndicator = newOptions.verticalScrollBarEnabled
}
if newOptionsMap["horizontalScrollBarEnabled"] != nil && options?.horizontalScrollBarEnabled != newOptions.horizontalScrollBarEnabled {
scrollView.showsHorizontalScrollIndicator = newOptions.horizontalScrollBarEnabled
}
if newOptionsMap["userAgent"] != nil && options?.userAgent != newOptions.userAgent && (newOptions.userAgent != "") {
if #available(iOS 9.0, *) {
customUserAgent = newOptions.userAgent
......@@ -514,9 +524,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
public func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url {
if url.absoluteString != url.absoluteString && (options?.useOnLoadResource)! {
WKNavigationMap[url.absoluteString] = [
"startTime": currentTimeInMilliSeconds(),
......@@ -556,6 +565,17 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
}
let mimeType = navigationResponse.response.mimeType
if let url = navigationResponse.response.url {
if mimeType != nil && !mimeType!.starts(with: "text/") {
Downloader.load(delegate: self, url: url, completion: { (destinationUrl: URL) in
print(destinationUrl)
})
decisionHandler(.cancel)
return
}
}
decisionHandler(.allow)
}
......@@ -647,6 +667,20 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
setNeedsLayout()
}
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
}
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
guard
let url = downloadTask.originalRequest?.url
else {
return
}
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)
}
public func onLoadStart(url: String) {
var arguments: [String: Any] = ["url": url]
if IABController != nil {
......@@ -839,3 +873,47 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
return (IABController != nil) ? SwiftFlutterPlugin.channel! : ((IAWController != nil) ? IAWController!.channel! : nil);
}
}
class Downloader {
class func load(delegate: URLSessionDelegate, url: URL, completion: @escaping (_ destinationUrl: URL) -> ()) {
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last as! URL
let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("file already exists [\(destinationUrl.path)]")
//completion(path: destinationUrl.path!, error:nil)
return
}
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: delegate, delegateQueue: nil)
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
if statusCode == 200 {
do {
try FileManager.default.moveItem(at: tempLocalUrl, to: destinationUrl)
completion(destinationUrl)
} catch (let writeError) {
print("error writing file \(destinationUrl) : \(writeError)")
//completion(path: destinationUrl.path!, error:nil)
}
} else {
//completion(path: destinationUrl.path!, error:nil)
}
} else {
//completion(path: destinationUrl.path!, error:nil)
}
} else {
print("Failure: %@", error?.localizedDescription);
//completion(path: destinationUrl.path!, error:nil)
}
}
task.resume()
}
}
......@@ -17,6 +17,8 @@ public class InAppWebViewOptions: Options {
var javaScriptEnabled = true
var javaScriptCanOpenWindowsAutomatically = false
var mediaPlaybackRequiresUserGesture = true
var verticalScrollBarEnabled = true
var horizontalScrollBarEnabled = true
var disallowOverScroll = false
var enableViewportScale = false
......
name: flutter_inappbrowser
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window (inspired by the popular cordova-plugin-inappbrowser).
version: 1.2.1
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
version: 1.3.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment