Skip to content

Commit

Permalink
iOS web view plugin
Browse files Browse the repository at this point in the history
- Fixed crash with clearCookies
- Added flag to toggle full screen mode
- Updated README
- Updated pubspec.yaml authors section
  • Loading branch information
Toufik Zitouni authored and Toufik Zitouni committed Jun 20, 2017
1 parent b0d9458 commit 4e3488b
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ build/
ios/.generated/
packages
pubspec.lock

example/ios/Podfile.lock
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
Plugin that allow Flutter to communicate with a native Webview.


***It will launch a new Activity inside the App with the Webview inside. Does not allow to integrate a Webview inside a Flutter Widget***
***For Android, it will launch a new Activity inside the App with the Webview inside. Does not allow to integrate a Webview inside a Flutter Widget***

TODO:
***For IOS, it will launch a new UIViewController inside the App with the UIWebView inside. Does not allow to integrate a Webview inside a Flutter Widget***

- [x] Android
- [ ] [IOS](https://github.com/dart-flitter/flutter_webview_plugin/issues/1)
- [x] IOS


## Getting Started
Expand All @@ -32,3 +32,7 @@ Add the Activity to you `AndroidManifest.xml`
<activity android:name="com.flutter_webview_plugin.WebviewActivity"
android:parentActivityName=".MainActivity"/>
```

### IOS

No extra configuration is needed
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.flutter.plugins;

import io.flutter.plugin.common.PluginRegistry;
import com.flutter_webview_plugin.FlutterWebviewPlugin;

/**
* Generated file. Do not edit.
*/
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
FlutterWebviewPlugin.registerWith(registry.registrarFor("com.flutter_webview_plugin.FlutterWebviewPlugin"));
}
}
3 changes: 0 additions & 3 deletions example/ios/Podfile.lock

This file was deleted.

22 changes: 11 additions & 11 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* PluginRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* PluginRegistry.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
945777F11EF64758001C8557 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 945777F01EF64758001C8557 /* GeneratedPluginRegistrant.m */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
Expand All @@ -21,7 +21,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
B1F3D14E8117A6C9F65810E0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D558BB7489B1C82B42A9097 /* libPods-Runner.a */; };
C1AB67DD965258C508BF745D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A3CDD044DB4E60255722586 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -40,14 +40,13 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* PluginRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PluginRegistry.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* PluginRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PluginRegistry.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
4D558BB7489B1C82B42A9097 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
945777EF1EF64758001C8557 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
945777F01EF64758001C8557 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = "<group>"; };
Expand All @@ -58,6 +57,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9A3CDD044DB4E60255722586 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -67,7 +67,7 @@
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
B1F3D14E8117A6C9F65810E0 /* libPods-Runner.a in Frameworks */,
C1AB67DD965258C508BF745D /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -117,15 +117,15 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
945777EF1EF64758001C8557 /* GeneratedPluginRegistrant.h */,
945777F01EF64758001C8557 /* GeneratedPluginRegistrant.m */,
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* PluginRegistry.h */,
1498D2331E8E89220040F4C2 /* PluginRegistry.m */,
);
path = Runner;
sourceTree = "<group>";
Expand All @@ -141,7 +141,7 @@
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */ = {
isa = PBXGroup;
children = (
4D558BB7489B1C82B42A9097 /* libPods-Runner.a */,
9A3CDD044DB4E60255722586 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
Expand Down Expand Up @@ -292,7 +292,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
Expand All @@ -304,7 +304,7 @@
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* PluginRegistry.m in Sources */,
945777F11EF64758001C8557 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
30 changes: 30 additions & 0 deletions example/ios/Runner.xcworkspace/xcshareddata/Runner.xcscmblueprint
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "089954AE9FE84C565F8189CE7B1E08C8949FC40C",
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {

},
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
"B9BC852104FA5F3F91D8B12EB80D37232CB3B40D" : 9223372036854775807,
"089954AE9FE84C565F8189CE7B1E08C8949FC40C" : 9223372036854775807
},
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "9839F02E-853D-4357-B537-73CD5272EC87",
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
"B9BC852104FA5F3F91D8B12EB80D37232CB3B40D" : "..\/..\/flutter",
"089954AE9FE84C565F8189CE7B1E08C8949FC40C" : "flutter_webview_plugin\/"
},
"DVTSourceControlWorkspaceBlueprintNameKey" : "Runner",
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "example\/ios\/Runner.xcworkspace",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/dart-flitter\/flutter_webview_plugin.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "089954AE9FE84C565F8189CE7B1E08C8949FC40C"
},
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/flutter\/flutter.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "B9BC852104FA5F3F91D8B12EB80D37232CB3B40D"
}
]
}
11 changes: 5 additions & 6 deletions example/ios/Runner/AppDelegate.m
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#include "AppDelegate.h"
#include "PluginRegistry.h"
#include "GeneratedPluginRegistrant.h"

@implementation AppDelegate {
PluginRegistry *plugins;
GeneratedPluginRegistrant *plugins;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
FlutterViewController *flutterController =
(FlutterViewController *)self.window.rootViewController;
plugins = [[PluginRegistry alloc] initWithController:flutterController];
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}

Expand Down
14 changes: 14 additions & 0 deletions example/ios/Runner/GeneratedPluginRegistrant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Generated file. Do not edit.
//

#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h

#import <Flutter/Flutter.h>

@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end

#endif /* GeneratedPluginRegistrant_h */
14 changes: 14 additions & 0 deletions example/ios/Runner/GeneratedPluginRegistrant.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Generated file. Do not edit.
//

#import "GeneratedPluginRegistrant.h"
#import <flutter_webview_plugin/FlutterWebviewPlugin.h>

@implementation GeneratedPluginRegistrant

+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FlutterWebviewPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterWebviewPlugin"]];
}

@end
7 changes: 6 additions & 1 deletion ios/Classes/FlutterWebviewPlugin.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
#import <Flutter/Flutter.h>
#import "WebviewController.h"

static FlutterMethodChannel *channel;

@interface FlutterWebviewPlugin : NSObject<FlutterPlugin>
@end
@property (nonatomic, retain) UIViewController *viewController;
@property (nonatomic, retain) WebviewController *webviewController;
@end
50 changes: 42 additions & 8 deletions ios/Classes/FlutterWebviewPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,50 @@
static NSString *const CHANNEL_NAME = @"flutter_webview_plugin";

@implementation FlutterWebviewPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
channel = [FlutterMethodChannel
methodChannelWithName:CHANNEL_NAME
binaryMessenger:[registrar messenger]];
UIViewController *viewController = (UIViewController *)registrar.messenger;
FlutterWebviewPlugin* instance = [[FlutterWebviewPlugin alloc] initWithViewController:viewController];
[registrar addMethodCallDelegate:instance channel:channel];
}

- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
self.viewController = viewController;
}
return self;
}

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:CHANNEL_NAME binaryMessenger:registrar.messenger];
[channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
NSString *method = [call method];
NSDictionary *arguments = [call arguments];
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"launch" isEqualToString:call.method]) {
[self showWebView:call];
result(nil);
} else if ([@"close" isEqualToString:call.method]) {
[self closeWebView];
result(nil);
} else {
result(FlutterMethodNotImplemented);
}
}

- (void)showWebView:(FlutterMethodCall*)call {
NSString *url = call.arguments[@"url"];
NSNumber *withJavascript = call.arguments[@"withJavascript"];
NSNumber *clearCache = call.arguments[@"clearCache"];
NSNumber *clearCookies = call.arguments[@"clearCookies"];
NSNumber *fullScreen = call.arguments[@"fullScreen"];

self.webviewController = [[WebviewController alloc] initWithUrl:url withJavascript:withJavascript clearCache:clearCache clearCookes:clearCookies fullScreen:fullScreen];

UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:self.webviewController];
[_viewController presentModalViewController:navigation animated:YES];
}

result(FlutterMethodNotImplemented);
}];
- (void)closeWebView {
[self.webviewController dismissViewControllerAnimated:YES completion:nil];
}

@end
13 changes: 13 additions & 0 deletions ios/Classes/WebviewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// WebviewController.h
// Pods
//
// Created by Toufik Zitouni on 6/17/17.
//
//

#import <UIKit/UIKit.h>

@interface WebviewController : UIViewController
- (instancetype)initWithUrl:(NSString *)url withJavascript:(NSNumber *)withJavascript clearCache:(NSNumber *)clearCache clearCookes:(NSNumber *)clearCookies fullScreen:(NSNumber *)fullScreen;
@end
74 changes: 74 additions & 0 deletions ios/Classes/WebviewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// WebviewController.m
// Pods
//
// Created by Toufik Zitouni on 6/17/17.
//
//

#import "WebviewController.h"
#import "FlutterWebviewPlugin.h"

@interface WebviewController ()
@property (nonatomic, retain) NSString *url;
@property NSNumber *withJavascript;
@property NSNumber *clearCache;
@property NSNumber *clearCookies;
@property NSNumber *fullScreen;
@end

@implementation WebviewController

- (instancetype)initWithUrl:(NSString *)url withJavascript:(NSNumber *)withJavascript clearCache:(NSNumber *)clearCache clearCookes:(NSNumber *)clearCookies fullScreen:(NSNumber *)fullScreen {
self = [super init];
if (self) {
self.url = url;
self.withJavascript = withJavascript;
self.clearCache = clearCache;
self.clearCookies = clearCookies;
self.fullScreen = fullScreen;
}
return self;
}

- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(backButtonPressed:)];
self.navigationItem.leftBarButtonItem = backButton;

UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.frame];

if ([self.clearCache boolValue]) {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}

if ([self.clearCookies boolValue]) {
[[NSURLSession sharedSession] resetWithCompletionHandler:^{

}];
}

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]];

webView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:webView];
}

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

if ([self.fullScreen boolValue]) {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
}
}

- (IBAction)backButtonPressed:(id)sender {
[channel invokeMethod:@"onBackPressed" arguments:nil];
[self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc {
[channel invokeMethod:@"onDestroy" arguments:nil];
}

@end
Loading

0 comments on commit 4e3488b

Please sign in to comment.