Is there any way to parse html created with javascript in flutter? - flutter

I would like to use metadata_fetch package to get the OGP.
The implementation of this package uses the html (parse) package. And it worked for most of the web pages.
However, there are some web pages, like this one, that cannot be fetched. I think this was because the html was generated by javascript. Is there any way to parse such a page as well?

You should be able to create a webview_flutter and inject some sort of Javascript that would walk the DOM for you and serialize it for return, which of course would happen after the page javascript has already built up the DOM. I haven't done that, but it might be a fun project.
EDIT: it might be as simple as capturing the string response of document.firstElementChild.outerHTML.

For the benefit of others, here's a source I made based on an idea from #Randal Schwartz.
const String url_unext = 'https://video.unext.jp/title/SID0050925';
WebViewController _controller;
Stack(
children: [
WebView(
onWebViewCreated: (controller) {
_controller = controller;
},
javascriptMode: JavascriptMode.unrestricted,
initialUrl: url_unext,
onPageFinished: (_) async {
html = await _controller.evaluateJavascript("window.document.firstElementChild.outerHTML;");
// Use Metadata_fetch to parse
final data = getOpenGraphDataFromResponse(html);
print(data);
},
),
// else widget here
Container(),
],
),
However, I am concerned about running a malicious script. If there is a better way, please let me know. I'm looking into the possibility of using oembed.
Once again, thank you very much, #Randal Schwartz.

Related

webView flutter loads white screen sometimes

I am working on app where I need to show certificate in pdf format inside WebView from specific URL. I am using webview_flutter plugin for webview.
Please consider the below mentioned code:
WebView(
debuggingEnabled: true,
initialUrl: Uri.encodeFull('https://docs.google.com/gview?embedded=true&url=${strUrl}'),
javascriptMode: JavascriptMode.unrestricted,
onProgress: (int progress) {
print('WebView is loading (progress : $progress%)');
},
onWebViewCreated: (webViewController) {
_controller.complete(webViewController);
webViewController.clearCache();
final cookieManager = CookieManager();
cookieManager.clearCookies();
},
),
Now on the progress log if the webview loads certificate properly then the progress shows like 10, 15, 30, 50, 80, 100. But in the case of white screen on no data loading progress went like 10, to directly 100. Logs are not working properly.
I couldn't use other libs or plugin, Is there any solution for same?
Progress in HTTP isn't an absolute so you cannot always expect a "smooth" progress. Sometimes data chunks will be received in buffers that are outside your control so this behavior isn't surprising.

Flutter WebView Location

I am creating a WebView of this website
https://nearxt.com/
which asks for location when opened but when i use this link to create a webview in flutter
then it can not take location
i have also defined location in the application but webview cant recieve location
SafeArea(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl: flutterUrl,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
),
),
This is unsupported in flutter. Even if you try to ask for location access using permission handler the app will deny it and still if you manually give the location permission to the app from your phone it still won't catch the real time location. Suggestion is to use plain old java for it you can find a lot of help around the internet about webview in java with location access it works perfect.
Use flutter_inappwebview to get users location
InAppWebView(
initialUrlRequest:
URLRequest(url: Uri.parse('your link here')),
androidOnGeolocationPermissionsShowPrompt:
(InAppWebViewController controller, String origin) async {
return GeolocationPermissionShowPromptResponse(
origin: origin,
allow: true,
retain: true
);
},
)

Flutter Web View blank screen on Release Mode

I have an issue where the Flutter WebView is rendering blank on the release version of my Android App on the Playstore.
Users are complaining that a page is not loading, but this page was loading very fine in debug mode.
Here is what I am doing. I am loading a local html file from my assets folder as shown in the code below:
import 'package:webview_flutter/webview_flutter.dart';
class _InvoicePageState extends ResumableState<InvoicePage>
with SingleTickerProviderStateMixin {
WebViewController? _webViewController;
#override
initState() {
super.initState();
}
void loadPage()async{
String html = await rootBundle.loadString('assets/html/invoice.html');
_webViewController?.loadUrl(Uri.dataFromString(html ,
mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString());
}
//Then in my build Method I have this
....
WebView(
onWebViewCreated:
(WebViewController webViewController) {
_webViewController = webViewController;
loadPage();
},
),
What could be wrong, why is it loading in debug mode but not loading in release mode?
My users are already dropping really bad reviews.
Please help.
Thank you.
The library's official example has InAppWebView embedded inside Stack which is further embedded inside Expanded. That is causing the issue. Try removing the Stack and Expanded or if you really want Stack, then first embed InAppWebView inside Expanded and then remove the parent Expanded.

How to implement reCaptcha into a flutter app

I am trying to implement the reCaptcha function to my flutter app, but in the captcha registration I need to provide a domain which I don't have one for a mobile app. I have browsed several guides teaching how to implement reCaptcha into a mobile app, yet those guides registered their reCaptcha with package names but not domains. What is the correct way to implement reCaptcha in a flutter app, or any mobile app in 2020?
You can use this plugin, flutter_recaptcha.
For the domain, I had the same issue. I first found that I needed to use the "I'm not a robot" checkbox option from here and I had to check the github repository to find this information, "!!! Remember to add this domain into the reCaptcha setting: recaptcha-flutter-plugin.firebaseapp.com," which explains it.
I was lost for a bit after not seeing that on the main page, but now it makes sense. Hopefully it helps.
Edit
I noticed something after trying it out, that I'd like to mention. The plugin does not provide a captcha response for using to authenticate the user server-side, so it does not seem very useful as it is. However, it is a simple plugin, so it may be possible to use it as an example. The steps, I think, would be to create a webpage with the captcha. As with the plugin, use a webview to open the page, then capture the post output of the form and ip address of user submitting the form, using something like this, then send it to flutter and then submit your request with that information, and use the Google library to verify the captcha.
Instructions
I just finished implementing this and I found a good way that works.
First, create an html page, like this:
<html>
<head>
<title>reCAPTCHA</title>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body style='background-color: aqua;'>
<div style='height: 60px;'></div>
<form action="?" method="POST">
<div class="g-recaptcha"
data-sitekey="YOUR-SITE-KEY"
data-callback="captchaCallback"></div>
</form>
<script>
function captchaCallback(response){
//console.log(response);
if(typeof Captcha!=="undefined"){
Captcha.postMessage(response);
}
}
</script>
</body>
</html>
Then, host that on your domain, say example.com/captcha.
Then, create a flutter Widget, like this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class Captcha extends StatefulWidget{
Function callback;
Captcha(this.callback);
#override
State<StatefulWidget> createState() {
return CaptchaState();
}
}
class CaptchaState extends State<Captcha>{
WebViewController webViewController;
#override
initState(){
super.initState();
}
#override
Widget build(BuildContext context) {
return Center(
child: WebView(
initialUrl: "https://example.com/captcha.html",
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: 'Captcha',
onMessageReceived: (JavascriptMessage message) {
//This is where you receive message from
//javascript code and handle in Flutter/Dart
//like here, the message is just being printed
//in Run/LogCat window of android studio
//print(message.message);
widget.callback(message.message);
Navigator.of(context).pop();
})
]),
onWebViewCreated: (WebViewController w) {
webViewController = w;
},
)
);
}
}
Make sure you registered for a captcha key at https://www.google.com/recaptcha (click on "Admin Console" at the top-right).
Then, you have the front-end built. To call a captcha, just run:
Navigator.of(context).push(
MaterialPageRoute(
builder: (context){
return Captcha((String code)=>print("Code returned: "+code));
}
),
);
You can use whatever callback you want to, like this:
class GenericState extends State<Generic>{
void methodWithCaptcha(String captchaCode){
// Do something with captchaCode
}
#override
Widget build(BuildContext context) {
return Center(child:FlatButton(
child: Text("Click here!"),
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context){
return Captcha(methodWithCaptcha);
}
),
);
}
}
}
Server-side, you can follow the instructions here (I followed the sections "Direct Download" and "Usage"). I found that for the usage, I could simply use the code:
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
// Verified!
} else {
$errors = $resp->getErrorCodes();
}
Using setExpectedHostname, like in the example, was unnecessary.
After that, everything works! I think this is currently the best way to implement Google reCaptcha V2 in flutter (for both iOS and Android).
If you are looking for Flutter WEB, You can try g_recaptcha_v3 package
Note:
it supports reCAPTCHA V3 only and not V2
its for Flutter Web only and no other platform supports
I've improved #JVE999 approach and created a new package:
flutter_firebase_recaptcha
The package uses InAppWebView for recapcha HTML rendering, so you don't need separate web page anymore.
My widget supports 'visible' and 'invisible' recapcha. Invisible recapcha allows you try to get recapcha token without showing anything to your user.

flutter:I can't load image through plugin webview_flutter

I wanna load HTML string through plugin webview_flutter, I try it like those:
But I couldn't load an image in my HTML string, meanwhile, I made WebView as a child for SizedBox, its height and width were adapted to device screen. Even though, it still exceeded device's width. I check the official demo, but it was futile
return WebView(
initialUrl: '',
onWebViewCreated: (controller) async {
String content = base64Encode(Utf8Encoder().convert(html));
controller.loadUrl('data:text/html;base64,$content');
},
);