Skip to content

Commit

Permalink
updated plugin version, added new options to hide/show scrollbars #165,…
Browse files Browse the repository at this point in the history
… initial support for DownloadManager in Android and iOS
  • Loading branch information
pichillilorenzo committed Oct 25, 2019
1 parent 9470a52 commit 5fc1d40
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 174 deletions.
216 changes: 84 additions & 132 deletions .idea/workspace.xml

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 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))
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
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;
Expand All @@ -21,6 +31,7 @@
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;
Expand All @@ -36,6 +47,8 @@
import okhttp3.Cache;
import okhttp3.OkHttpClient;

import static android.content.Context.DOWNLOAD_SERVICE;

public class InAppWebView extends WebView {

static final String LOG_TAG = "InAppWebView";
Expand Down Expand Up @@ -110,6 +123,8 @@ public void reload() {

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();
Expand All @@ -122,39 +137,43 @@ public void prepare() {
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();

Expand Down Expand Up @@ -187,6 +206,8 @@ else if (options.clearSessionCache)
settings.setUseWideViewPort(options.useWideViewPort);
settings.setSupportZoom(options.supportZoom);
settings.setTextZoom(options.textZoom);
setVerticalScrollBarEnabled(options.verticalScrollBarEnabled);
setHorizontalScrollBarEnabled(options.horizontalScrollBarEnabled);

if (options.transparentBackground) {
setBackgroundColor(Color.TRANSPARENT);
Expand All @@ -205,6 +226,19 @@ else if (options.clearSessionCache)
}
}

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);
Expand Down Expand Up @@ -367,6 +401,12 @@ else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessi
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);
Expand Down Expand Up @@ -524,4 +564,11 @@ protected void onScrollChanged (int l,
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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions example/lib/inline_example.screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
86 changes: 82 additions & 4 deletions ios/Classes/InAppWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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)!
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
}
}
2 changes: 2 additions & 0 deletions ios/Classes/InAppWebViewOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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 <[email protected]>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser

Expand Down

0 comments on commit 5fc1d40

Please sign in to comment.