Share Content with the React Library, Flutter Share and inappwebview Plugins

Nagi
IceApple Tech Talks
4 min readOct 9, 2023

When react application is running through flutter app, we can use flutter share and inappwebview plugins to share the content. In this article we can learn to how to communicate between the react application and inappwebview (inline web view) and share the content to multiple social medias like whats app, face book, twitter, mail etc.. which are installed in phone.

Step 1: Setup the react environment. Follow this link for environment setup https://create-react-app.dev/docs/adding-typescript. Create a new project by running the below command.

npx create-react-app share-app - template typescript

Step 2: Create app.tsx, add below code and run the react project


type MyButtonProps = {
children: string;
onClick: () => void;
};

const MyButton = ({ children, onClick }: MyButtonProps): JSX.Element => (
<button onClick={onClick}>{children}</button>
);

const handleShare = () => {
console.log("Native calling share");
if (!(window as any).flutter_inappwebview) return;
(window as any).flutter_inappwebview
.callHandler(
"share",
"Hello I am a sharing content", "https://www.google.com/"
)
.then((result: any) => {
console.log(result);
});
}

export default function App() {
return (
<div className="App">
<h1>Hello I am sharing content</h1>
<MyButton onClick={() => handleShare()}>Share!</MyButton>
</div>
);
}

Step 3: Setup the flutter environment. Follow this link for environment setup. https://docs.flutter.dev/get-started/install. After environment setup, create a new project by running the below command.

flutter create flutter_share_demo

Step 4: Add the following Flutter package dependency in pubspec.yaml file.

  flutter_inappwebview: ^5.7.2+3
double_back_to_close_app: ^2.1.0
permission_handler: ^10.2.0

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
url_launcher: ^6.1.5
share: ^2.0.4

Step 5: Create home.dart file and add the below code

import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:share/share.dart';

class WebViewHost extends StatefulWidget {
@override
WebViewHostState createState() => WebViewHostState();
}

class WebViewHostState extends State<WebViewHost> {
final GlobalKey webViewKey = GlobalKey();

InAppWebViewController? webViewController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
javaScriptCanOpenWindowsAutomatically: true,
javaScriptEnabled: true,
useOnDownloadStart: true,
useOnLoadResource: true,
preferredContentMode: UserPreferredContentMode.MOBILE,
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: true,
allowFileAccessFromFileURLs: true,
allowUniversalAccessFromFileURLs: true,
verticalScrollBarEnabled: false,
supportZoom: false,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
ios: IOSInAppWebViewOptions(
allowsAirPlayForMediaPlayback: true,
suppressesIncrementalRendering: true,
ignoresViewportScaleLimits: true,
selectionGranularity: IOSWKSelectionGranularity.DYNAMIC,
enableViewportScale: true,
sharedCookiesEnabled: true,
automaticallyAdjustsScrollIndicatorInsets: true,
useOnNavigationResponse: true,
allowsInlineMediaPlayback: true,
));

String url = "http://127.0.0.1:3000/";
double progress = 0;
final urlController = TextEditingController();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child:
InAppWebView(
key: webViewKey,
gestureRecognizers: Set()..add(Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())),
initialUrlRequest:
URLRequest(url: Uri.parse("http://127.0.0.1:3000/")),
initialOptions: options,
onWebViewCreated: (controller) {
webViewController = controller;
controller.addJavaScriptHandler(handlerName: "share", callback: (args) {
print(args);
Share.share(args[0]+" "+args[1], subject: args[0]);
return true;
});
controller.addJavaScriptHandler(handlerName: "isAndroid", callback: (args) {
return Platform.isAndroid;
});
controller.addJavaScriptHandler(handlerName: "isIos", callback: (args) {
return Platform.isIOS;
});
},
onLoadStart: (controller, url) {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
androidOnPermissionRequest: (controller, origin, resources) async {
return PermissionRequestResponse(
resources: resources,
action: PermissionRequestResponseAction.GRANT);
},
iosOnNavigationResponse: (controller, response) async {
return IOSNavigationResponseAction.ALLOW;
},
onLoadStop: (controller, url) async {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
onLoadError: (controller, url, code, message) {
},
onProgressChanged: (controller, progress) {
if (progress == 100) {
}
setState(() {
this.progress = progress / 100;
urlController.text = this.url;
});
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
},

shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async {
var url = shouldOverrideUrlLoadingRequest.request.url;

if ((url.toString()).startsWith('http://127.0.0.1:3000/')) {
return NavigationActionPolicy.ALLOW;
}else {
launchUrl(Uri.parse(url.toString()));
return NavigationActionPolicy.CANCEL;
}
},
)

)
);

}
}

The web controller handler called “addJavaScriptHandler” is used to communicate between react library and flutter native code. The event handler “share” is created to emit when it called from react library. we can pass more number of arguments in array form to share handler.

Once the share content has been received from react app, the below code will take care of sharing the content through multiple social platforms including whats app, face book, mail etc..

Share.share(args[0]+" "+args[1], subject: args[0]);

To read the about the share plugin, go to https://pub.dev/packages/share.

we can able to send images, videos and text content from share plugin.

Note: In the above code, We should replace with url “http://127.0.0.1:3000” with hosted react url. For local testing, we should use the ip instead of 127.0.0.1 and both flutter & react app should run in same network.

Step 6: Add the below code in main.dart file and run the flutter project to test in emulators.

import 'package:double_back_to_close_app/double_back_to_close_app.dart';
import 'package:flutter/material.dart';
import 'home.dart';
import 'package:permission_handler/permission_handler.dart';

void main() async=> {
WidgetsFlutterBinding.ensureInitialized(),
await Permission.camera.request(),
runApp(MaterialApp(
home: Scaffold(
body: DoubleBackToCloseApp(
child: WebViewHost(),
snackBar: const SnackBar(
content: Text('Tap back again to close'),
),
),
),
debugShowCheckedModeBanner: false,
theme:ThemeData(
primarySwatch: Colors.blue
)
))
};

The app will work for both android and IOS platforms.

Happy sharing.

--

--