Commit 99ff84c6 authored by pichillilorenzo's avatar pichillilorenzo

v0.4.1

parent ea6134d1
This diff is collapsed.
## 0.4.1
- added `InAppBrowser.takeScreenshot()`
- added `InAppBrowser.setOptions()`
- added `InAppBrowser.getOptions()`
## 0.4.0
- removed `target` parameter to `InAppBrowser.open()` method. To open the url on the system browser, use the `openWithSystemBrowser: true` option
......@@ -7,6 +13,7 @@
- added `InAppBrowser.openWithSystemBrowser` method
- added `InAppBrowser.openOnLocalhost` method
- added `InAppBrowser.loadFile` method
- added `InAppBrowser.isOpened` method
## 0.3.2
......
......@@ -9,6 +9,14 @@
A Flutter plugin that allows you to open an in-app browser window.
This plugin is inspired by the popular [cordova-plugin-inappbrowser](https://github.com/apache/cordova-plugin-inappbrowser)!
### IMPORTANT Note for iOS
To be able to use this plugin on iOS, you need to create the Flutter App with `flutter create -i swift` (see [flutter/flutter#13422 (comment)](https://github.com/flutter/flutter/issues/13422#issuecomment-392133780)), otherwise, you will get this message:
```
=== BUILD TARGET flutter_inappbrowser OF PROJECT Pods WITH CONFIGURATION Debug ===
The “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift. Supported values are: 3.0, 4.0, 4.2. This setting can be set in the build settings editor.
```
that is not true! The Swift version that I have used is already a supported value: 4.0.
## Getting Started
For help getting started with Flutter, view our online
......@@ -334,7 +342,7 @@ inAppBrowser.loadUrl(String url, {Map<String, String> headers = const {}});
Loads the given `assetFilePath` with optional `headers` specified as a map from name to value.
To be able to load your local files (assets, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found!
To be able to load your local files (html, js, css, etc.), you need to add them in the `assets` section of the `pubspec.yaml` file, otherwise they cannot be found!
Example of a `pubspec.yaml` file:
```yaml
......@@ -493,6 +501,35 @@ Returns `true` if the callback is removed, otherwise `false`.
inAppBrowser.removeJavaScriptHandler(String handlerName, int index);
```
#### Future\<Uint8List\> InAppBrowser.takeScreenshot
Takes a screenshot (in PNG format) of the view's visible viewport and returns a `Uint8List`. Returns `null` if it wasn't be able to take it.
**NOTE for iOS**: available from iOS 11.0+.
```dart
inAppBrowser.takeScreenshot();
```
#### Future\<void\> InAppBrowser.setOptions
Sets the InAppBrowser options with the new `options` and evaluates them.
```dart
inAppBrowser.setOptions(Map<String, dynamic> options);
```
#### Future\<Map\<String, dynamic\>\> InAppBrowser.getOptions
Gets the current InAppBrowser options. Returns `null` if the options are not setted yet.
```dart
inAppBrowser.getOptions();
```
#### bool InAppBrowser.isOpened
Returns `true` if the `InAppBrowser` instance is opened, otherwise `false`.
```dart
inAppBrowser.isOpened();
```
### `ChromeSafariBrowser` class
[Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android / [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
......
......@@ -31,6 +31,7 @@ import android.provider.Browser;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Base64;
import android.util.JsonReader;
import android.util.JsonToken;
import android.webkit.MimeTypeMap;
......@@ -247,6 +248,28 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
case "isHidden":
result.success(isHidden(uuid));
break;
case "takeScreenshot":
result.success(takeScreenshot(uuid));
break;
case "setOptions":
{
String optionsType = (String) call.argument("optionsType");
switch (optionsType){
case "InAppBrowserOptions":
InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions();
HashMap<String, Object> inAppBroeserOptionsMap = (HashMap<String, Object>) call.argument("options");
inAppBrowserOptions.parse(inAppBroeserOptionsMap);
setOptions(uuid, inAppBrowserOptions, inAppBroeserOptionsMap);
break;
default:
result.error(LOG_TAG, "Options " + optionsType + " not available.", null);
}
}
result.success(true);
break;
case "getOptions":
result.success(getOptions(uuid));
break;
default:
result.notImplemented();
}
......@@ -580,4 +603,25 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
result.success(true);
}
}
public byte[] takeScreenshot(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.takeScreenshot();
return null;
}
public void setOptions(String uuid, InAppBrowserOptions options, HashMap<String, Object> optionsMap) {
WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
webViewActivity.setOptions(options, optionsMap);
}
public HashMap<String, Object> getOptions(String uuid) {
WebViewActivity webViewActivity = webViewActivities.get(uuid);
if (webViewActivity != null)
return webViewActivity.getOptions();
return null;
}
}
package com.pichillilorenzo.flutter_inappbrowser;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.support.v7.app.ActionBar;
......@@ -12,6 +15,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
......@@ -19,6 +23,10 @@ import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.SearchView;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
......@@ -31,6 +39,7 @@ public class WebViewActivity extends AppCompatActivity {
String uuid;
WebView webView;
ActionBar actionBar;
Menu menu;
InAppBrowserWebViewClient inAppBrowserWebViewClient;
InAppBrowserWebChromeClient inAppBrowserWebChromeClient;
SearchView searchView;
......@@ -182,8 +191,12 @@ public class WebViewActivity extends AppCompatActivity {
else
settings.setTextZoom(100);
if (options.progressBar)
progressBar = findViewById(R.id.progressBar);
progressBar = findViewById(R.id.progressBar);
if (!options.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
actionBar.setDisplayShowTitleEnabled(!options.hideTitleBar);
......@@ -199,7 +212,9 @@ public class WebViewActivity extends AppCompatActivity {
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
public boolean onCreateOptionsMenu(Menu m) {
menu = m;
MenuInflater inflater = getMenuInflater();
// Inflate menu to add items to action bar if it is present.
inflater.inflate(R.menu.menu_main, menu);
......@@ -366,9 +381,11 @@ public class WebViewActivity extends AppCompatActivity {
}
private void clearCache() {
webView.clearCache(true);
clearCookies();
webView.clearFormData();
if (webView != null) {
webView.clearCache(true);
clearCookies();
webView.clearFormData();
}
}
public void goBackButtonClicked(MenuItem item) {
......@@ -394,4 +411,107 @@ public class WebViewActivity extends AppCompatActivity {
InAppBrowserFlutterPlugin.close(uuid, null);
}
public byte[] takeScreenshot() {
if (webView != null) {
Picture picture = webView.capturePicture();
Bitmap b = Bitmap.createBitmap( webView.getWidth(),
webView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
picture.draw(c);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toByteArray();
}
return null;
}
public void setOptions(InAppBrowserOptions newOptions, HashMap<String, Object> newOptionsMap) {
WebSettings settings = webView.getSettings();
if (newOptionsMap.get("hidden") != null && options.hidden != newOptions.hidden) {
if (newOptions.hidden)
hide();
else
show();
}
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
if (newOptionsMap.get("builtInZoomControls") != null && options.builtInZoomControls != newOptions.builtInZoomControls)
settings.setBuiltInZoomControls(newOptions.builtInZoomControls);
if (newOptionsMap.get("safeBrowsingEnabled") != null && options.safeBrowsingEnabled != newOptions.safeBrowsingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
settings.setSafeBrowsingEnabled(newOptions.safeBrowsingEnabled);
if (newOptionsMap.get("mediaPlaybackRequiresUserGesture") != null && options.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture)
settings.setMediaPlaybackRequiresUserGesture(newOptions.mediaPlaybackRequiresUserGesture);
if (newOptionsMap.get("databaseEnabled") != null && options.databaseEnabled != newOptions.databaseEnabled)
settings.setDatabaseEnabled(newOptions.databaseEnabled);
if (newOptionsMap.get("domStorageEnabled") != null && options.domStorageEnabled != newOptions.domStorageEnabled)
settings.setDomStorageEnabled(newOptions.domStorageEnabled);
if (newOptionsMap.get("userAgent") != null && options.userAgent != newOptions.userAgent && !newOptions.userAgent.isEmpty())
settings.setUserAgentString(newOptions.userAgent);
if (newOptionsMap.get("clearCache") != null && newOptions.clearCache)
clearCache();
else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache)
CookieManager.getInstance().removeSessionCookie();
if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort)
settings.setUseWideViewPort(newOptions.useWideViewPort);
if (newOptionsMap.get("supportZoom") != null && options.supportZoom != newOptions.supportZoom)
settings.setSupportZoom(newOptions.supportZoom);
if (newOptionsMap.get("progressBar") != null && options.progressBar != newOptions.progressBar && progressBar != null) {
if (newOptions.progressBar)
progressBar.setMax(0);
else
progressBar.setMax(100);
}
if (newOptionsMap.get("hideTitleBar") != null && options.hideTitleBar != newOptions.hideTitleBar)
actionBar.setDisplayShowTitleEnabled(!newOptions.hideTitleBar);
if (newOptionsMap.get("toolbarTop") != null && options.toolbarTop != newOptions.toolbarTop) {
if (!newOptions.toolbarTop)
actionBar.hide();
else
actionBar.show();
}
if (newOptionsMap.get("toolbarTopBackgroundColor") != null && options.toolbarTopBackgroundColor != newOptions.toolbarTopBackgroundColor && !newOptions.toolbarTopBackgroundColor.isEmpty())
actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor(newOptions.toolbarTopBackgroundColor)));
if (newOptionsMap.get("toolbarTopFixedTitle") != null && options.toolbarTopFixedTitle != newOptions.toolbarTopFixedTitle && !newOptions.toolbarTopFixedTitle.isEmpty())
actionBar.setTitle(newOptions.toolbarTopFixedTitle);
if (newOptionsMap.get("hideUrlBar") != null && options.hideUrlBar != newOptions.hideUrlBar) {
if (newOptions.hideUrlBar)
menu.findItem(R.id.menu_search).setVisible(false);
else
menu.findItem(R.id.menu_search).setVisible(true);
}
options = newOptions;
}
public HashMap<String, Object> getOptions() {
return (options != null) ? options.getHashMap() : null;
}
}
......@@ -91,4 +91,5 @@ public class ChromeCustomTabsActivity extends Activity {
InAppBrowserFlutterPlugin.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
}
}
}
......@@ -2,6 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
......
......@@ -25,7 +25,7 @@ dev_dependencies:
sdk: flutter
flutter_inappbrowser:
path: ../
path: ../
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
......
......@@ -20,6 +20,7 @@
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappbrowser/example/ios/Flutter/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/flutter_assets/packages" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
......
......@@ -14,7 +14,7 @@ public class Options: NSObject {
super.init()
}
public func parse(options: [String: Any]) -> Options {
func parse(options: [String: Any]) -> Options {
for (key, value) in options {
if self.responds(to: Selector(key)) {
self.setValue(value, forKey: key)
......@@ -22,5 +22,20 @@ public class Options: NSObject {
}
return self
}
func getHashMap() -> [String: Any] {
var options: [String: Any] = [:]
var counts = UInt32();
let properties = class_copyPropertyList(object_getClass(self), &counts);
for i in 0..<counts {
let property = properties?.advanced(by: Int(i)).pointee;
let cName = property_getName(property!);
let name = String(cString: cName)
options[name] = self.value(forKey: name)
}
free(properties)
return options
}
}
......@@ -59,7 +59,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
let uuid: String = (arguments!["uuid"] as? String)!
let uuid: String = arguments!["uuid"] as! String
switch call.method {
case "open":
......@@ -151,6 +151,33 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
self.injectStyleFile(uuid: uuid, arguments: arguments!, result: nil)
result(true)
break
case "takeScreenshot":
if let webViewController = self.webViewControllers[uuid] {
webViewController?.takeScreenshot(completionHandler: { (screenshot) -> Void in
result(screenshot)
})
}
else {
result(nil)
}
break
case "setOptions":
let optionsType = arguments!["optionsType"] as! String;
switch (optionsType){
case "InAppBrowserOptions":
let inAppBrowserOptions = InAppBrowserOptions();
let inAppBroeserOptionsMap = arguments!["options"] as! [String: Any];
inAppBrowserOptions.parse(options: inAppBroeserOptionsMap);
self.setOptions(uuid: uuid, options: inAppBrowserOptions, optionsMap: inAppBroeserOptionsMap);
break;
default:
result(FlutterError(code: "InAppBrowserFlutterPlugin", message: "Options " + optionsType + " not available.", details: nil))
}
result(true)
break
case "getOptions":
result(self.getOptions(uuid: uuid))
break
default:
result(FlutterMethodNotImplemented)
break
......@@ -594,4 +621,17 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func setOptions(uuid: String, options: InAppBrowserOptions, optionsMap: [String: Any]) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.setOptions(newOptions: options, newOptionsMap: optionsMap)
}
}
func getOptions(uuid: String) -> [String: Any]? {
if let webViewController = self.webViewControllers[uuid] {
return webViewController!.getOptions()
}
return nil
}
}
......@@ -92,7 +92,9 @@
<outlet property="shareButton" destination="skL-Lw-jYB" id="8hu-WC-OM0"/>
<outlet property="spinner" destination="HWt-17-FMf" id="c2Y-Tb-XfA"/>
<outlet property="toolbarBottom" destination="8Pf-5R-cFf" id="Og7-Xw-2sq"/>
<outlet property="toolbarBottom_TopToWebViewBottomConstraint" destination="KeI-jL-Qoi" id="jKQ-OC-jpD"/>
<outlet property="toolbarTop" destination="vlz-kT-71x" id="WgC-80-Z28"/>
<outlet property="toolbarTop_BottomToWebViewTopConstraint" destination="Sjd-dV-din" id="vkO-Yu-xaE"/>
<outlet property="urlField" destination="sy2-Vx-Cxd" id="MCW-lJ-Ehl"/>
<outlet property="webView" destination="gA9-n8-qaQ" id="7JE-lp-bwe"/>
</connections>
......
......@@ -579,7 +579,38 @@ class InAppBrowser {
}
///Returns `true` if the browser is opened, otherwise `false`.
///Takes a screenshot (in PNG format) of the WebView's visible viewport and returns a `Uint8List`. Returns `null` if it wasn't be able to take it.
///
///**NOTE for iOS**: available from iOS 11.0+.
Future<Uint8List> takeScreenshot() async {
this._throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
return await _ChannelManager.channel.invokeMethod('takeScreenshot', args);
}
///Sets the [InAppBrowser] options with the new [options] and evaluates them.
Future<void> setOptions(Map<String, dynamic> options) async {
this._throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('options', () => options);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
await _ChannelManager.channel.invokeMethod('setOptions', args);
}
///Gets the current [InAppBrowser] options. Returns `null` if the options are not setted yet.
Future<Map<String, dynamic>> getOptions() async {
this._throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
Map<dynamic, dynamic> options = await _ChannelManager.channel.invokeMethod('getOptions', args);
options = options.cast<String, dynamic>();
return options;
}
///Returns `true` if the [InAppBrowser] instance is opened, otherwise `false`.
bool isOpened() {
return this._isOpened;
}
......
name: flutter_inappbrowser
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
version: 0.4.0
version: 0.4.1
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