Problem in google login in canva through webview in flutter - flutter

I wanted to upload pics through canva from my flutter app that is why I am using the flutter-webview-plugin for the first time and therefore I am not able to solve this issue.
Code for the same is:-
import 'package:flutter/material.dart';
import 'package:kf_drawer/kf_drawer.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
class SettingsPage extends KFDrawerContent {
#override
_SettingsPageState createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Center(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
....
],
),
Expanded(
child: Container(
height: 500,
child: WebView(
initialUrl: "https://shree-hari.github.io/laxmi_canva/index.html",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController){
_controller.complete(webViewController);
},
),
),
)
],
),
),
);
}
}
Please Help me to address this issue 🙄.

Google not allow native Flutter Web-Views to initiate OAuth.
For more info read Google Blog
In your case, I can suggest 3 Possible Solutions.
Try to Sign in with Email/Password instead of Google Sign In.
Use url_launcher to redirect the user to the browser.
If you don't want the user to leave your app
then you can use flutter_custom_tabs
this plugin use Chrome Custom Tabs to create a native experience inside the Flutter App.

You can add this userAgent :
WebView(
initialUrl: url,
userAgent: Platform.isIOS ? 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_2 like Mac OS X) AppleWebKit/605.1.15' +
' (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1' :
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36',
...

Use this package, it works like a charm
https://github.com/LinusU/flutter_web_auth
In the background, this plugin uses ASWebAuthenticationSession on iOS 12+ and macOS 10.15+, SFAuthenticationSession on iOS 11, Chrome Custom Tabs on Android and opens a new window on Web.
Your auth flow must land in the scheme you provide in callbackUrlScheme property. Then just parse the callback url and implement you own business logic around signin/signup
import 'package:flutter_web_auth/flutter_web_auth.dart';
// Present the dialog to the user
final result = await FlutterWebAuth.authenticate(url: "https://my-custom-app.com/connect", callbackUrlScheme: "my-custom-app");
// Extract token from resulting url
final token = Uri.parse(result).queryParameters['token']

https://stackoverflow.com/a/71297966/18723243
Using webview_flutter package you can fix the problem by adding userAgent: 'random', in the web view constructor. So, it will look like this:
WebView(
userAgent: 'random',
)

Related

Open Facebook app with url_launcher package in Flutter

I am trying to open the Facebook app on a company page in Flutter but it keeps opening it in the web browser instead.
It's just a simple widget that outputs a row of social media icons from a list:
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class SocialMediaLinks extends StatelessWidget {
SocialMediaLinks({Key? key}) : super(key: key);
final List<Map<dynamic, dynamic>> icons = [
{
'name': 'twitter',
'launchUrl': 'twitter://PAGENAME',
'backupUrl': 'https://twitter.com/PAGENAME',
},
{
'name': 'facebook',
'launchUrl': 'fb://page/PAGEID',
'backupUrl': 'https://www.facebook.com/PAGENAME',
},
{
'name': 'instagram',
'launchUrl': 'instagram://PAGENAME',
'backupUrl': 'https://www.instagram.com/PAGENAME',
}
];
#override
Widget build(BuildContext context) {
return Row(
children: [
for (Map i in icons)
IconButton(
onPressed: () async {
await canLaunch(i['launchUrl'])
? launch(
i['launchUrl'],
forceSafariVC: false,
forceWebView: false,
)
: launch(
i['backupUrl'],
forceSafariVC: false,
forceWebView: false,
);
},
splashRadius: 30.0,
iconSize: 38.0,
icon: Image.asset(
"assets/images/icons/${i['name']}.png",
color: Colors.white,
),
),
],
);
}
}
Twitter and Instagram work and open in their apps but Facebook still only opens in the web browser. I've tried tonnes of solutions on stackoverflow but to no avail. Am I missing something?
Thanks.
I've observed a limitation with the supported URLs configured in the Facebook app. In Android at least, while the Facebook app has support for facebook.com, I noticed that the Facebook app opens when it's a link to a specific post i.e. https://www.facebook.com/$profileId/posts/$postId
However, the Facebook app seems to be unable to handle direct links to the profile or page i.e. https://www.facebook.com/$profileId
If you're linking to a profile/page in Facebook, you can pin a post in the profile/page and share the link of the Facebook post as a workaround. This should successfully open the Facebook app installed on the device.

Flutter webivew not showing content from my site

I am trying to load my website content in my flutter application.
I have a link https://dev.demo.hello.example.com/id/4
I have tried using flutter_webview_plugin & webview_flutter both plugins but on both plugins i am getting below error :
WF: === Starting WebFilter logging for process Runner
WF: _userSettingsForUser mobile: {
filterBlacklist = (
);
filterWhitelist = (
);
restrictWeb = 1;
useContentFilter = 0;
useContentFilterOverrides = 0;
whitelistEnabled = 0;
}
WF: _WebFilterIsActive returning: NO
I have also tried mentioned ATS related things in info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
But still facing the same issue. I have https in my link.
Is there any work around ?
In my case, I was setting a navigationDelegate to prevent all further navigation :
WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (navigation) => navigation.url == url ? NavigationDecision.navigate : NavigationDecision.prevent,
),
It works fine on Android, the initialUrl gets loaded, and any further navigation is blocked.
But on iOS I had to change this code as it was blocking even initialUrl :
WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (navigation) => navigation.url == url ? NavigationDecision.navigate : NavigationDecision.prevent,
),
Yes, just put this code to your navigationDelegate in WebView widget
navigationDelegate: (NavigationRequest request) {
if (request.url == get.url) {
return NavigationDecision.navigate;
}
return NavigationDecision.prevent;
}
it work for me on IoS & Android

flutter webview disallowed user agent

I am trying to openning sign-in google with webview in flutter application. I installed flutter_inappwebview: ^3.1.0 and this is my code:
child: InAppWebView(
initialUrl: url.toString(),
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
debuggingEnabled: true,
)),
but when i open google sin in page i got this error:
Using webview_flutter package you can fix the problem by adding userAgent: 'random', in the web view constructor. So, it will look like this:
WebView(
initialUrl: 'https://abdulrazakzakieh.com/',
userAgent: 'random',
)
change userAgent to random like -> userAgent: "random". works perfectly! but then it will most likely low end mobile interface for google page. that's the only drawback. else works perfectly fine !
For my case, It worked for this-
InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse("www.myurl.com")),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(userAgent: "random"),)
...)

Embedding a Youtube video in Flutter Web

Is it possible to embed a Youtube video in a Flutter web page? I tried the following code to have a Youtube embedded in my Flutter website, but nothing appears on the page without any error message.
import 'package:flutter_html_view/flutter_html_view.dart';
Container(child: HtmlView(data: """
<iframe src="https://www.youtube.com/embed/xMzkWfIR9Pk" width="560" height="315"></iframe>
""")),
Also tried the solution recommended here (WebView in Flutter Web) but that doesn't work either.
import 'dart:ui' as ui
//ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => html.IFrameElement()
..width = '640'
..height = '360'
..src = 'https://www.youtube.com/embed/IyFZznAk69U'
..style.border = 'none');
I used to package called flutter_html
But this gave me some scrolling issues.
Html(
data: '<iframe width="560" height="315" src="https://www.youtube.com/embed/D_mCZlQZg9Y" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
)
You should go like this
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:ui' as ui;
String viewID = "your-view-id";
#override
Widget build(BuildContext context) {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
viewID,
(int id) => html.IFrameElement()
..width = MediaQuery.of(context).size.width.toString()
..height = MediaQuery.of(context).size.height.toString()
..src = 'https://www.youtube.com/embed/IyFZznAk69U'
..style.border = 'none');
return SizedBox(
height: 500,
child: HtmlElementView(
viewType: viewID,
),
);
}
You can use the youtube_player_iframe
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'K18cpp_-gP8',
params: YoutubePlayerParams(
playlist: ['nPt8bK2gbaU', 'gQDByCdjUXw'], // Defining custom playlist
startAt: Duration(seconds: 30),
showControls: true,
showFullscreenButton: true,
),
);
YoutubePlayerIFrame(
controller: _controller,
aspectRatio: 16 / 9,
),
ext_video_player supports Android, iOS and web for YouTube. You can try running sample code from ext_video_player repo.
I tested with different browsers of different OS. Android, Mac, Windows browsers are working fine with ext_video_player. But it's not playing with iOS browser.
There are, at least, two solutions:
a) video_player package now works fine in the three main platforms: android, ios and web
b) This article explains a good way to embed video source in a flutter web widget, even when the article is for local files, the final procedure works fine for web sources, like youtube, too: https://vermahitesh.medium.com/play-local-video-on-flutter-web-d757bab0141c

How do I open a web browser (URL) from my Flutter code?

I am building a Flutter app, and I'd like to open a URL into a web browser or browser window (in response to a button tap). How can I do this?
TL;DR
This is now implemented as Plugin
const url = "https://flutter.io";
if (await canLaunchUrl(url))
await launchUrl(url);
else
// can't launch url, there is some error
throw "Could not launch $url";
Full example:
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(new Scaffold(
body: new Center(
child: new RaisedButton(
onPressed: _launchURL,
child: new Text('Show Flutter homepage'),
),
),
));
}
_launchURL() async {
const url = 'https://flutter.io';
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
} else {
throw 'Could not launch $url';
}
}
In pubspec.yaml
dependencies:
url_launcher: ^6.1.7
Check out the latest url_launcher package.
Special Characters:
If the url value contains spaces or other values that are now allowed in URLs, use
Uri.encodeFull(urlString) or Uri.encodeComponent(urlString) and pass the resulting value instead.
If you target sdk 30 or above canLaunch will return false by default due to package visibility changes: https://developer.android.com/training/basics/intents/package-visibility
in the androidManifest.xml you'll need to add the following directly under <manifest>:
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
</queries>
Then the following should word - for flutter 3 upwards:
const uri = Uri.parse("https://flutter.io");
if (await canLaunchUrl(uri)){
await launchUrl(uri);
} else {
// can't launch url
}
or for older versions of flutter use this instead:
const url = "https://flutter.io";
if (await canLaunch(url)){
await launch(url);
} else {
// can't launch url
}
launchUrl has a mode parameter which can be used to control where the url gets launched.
So, passing in launchUrl(uri, mode: LaunchMode.platformDefault) leaves the decision of how to launch the URL to the platform
implementation. But you can also specify
LaunchMode.inAppWebView which will use an in-app web view
LaunchMode.externalApplication for it to be handled by an external application
Or LaunchMode.externalNonBrowserApplication to be handled by a non-browser application.
For Flutter:
As described above by Günter Zöchbauer
For Flutter Web:
import 'dart:html' as html;
Then use:
html.window.open(url, name);
Make sure that you run flutter clean if the import doesn't resolve.
For those who wants to implement LAUNCH BROWSER AND EXIT APP by using url_launcher. Remember to use (forceSafariVC: false) to open the url in default browser of the phone. Otherwise, the launched browser exit along with your APP.
await launch(URL, forceSafariVC: false);
The best way is to use url_launcher package .
Add url_launcher as a dependency in your pubspec.yaml file.
dependencies:
url_launcher:
An example of how to use it :
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Flutter is beautiful'),),
body: Center(
child: RaisedButton(
onPressed: _launchURL,
child: Text('Show Flutter homepage'),
),
),
)),
);
}
_launchURL() async {
const url = 'https://flutter.dev';
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
} else {
throw 'Could not launch $url';
}
}
Output :
The launch method takes a string argument containing a URL .
By default, Android opens up a browser when handling URLs. You can
pass forceWebView: true parameter to tell the plugin to open a WebView
instead. If you do this for a URL of a page containing JavaScript,
make sure to pass in enableJavaScript: true, or else the launch method
will not work properly. On iOS, the default behavior is to open all
web URLs within the app. Everything else is redirected to the app
handler.
This is now implemented as Plugin
const url = "https://flutter.io";
final Uri _url = Uri.parse(url);
await launchUrl(_url,mode: LaunchMode.externalApplication);
pubspec.yaml
Add dependencies
dependencies: url_launcher: ^6.0.12
Output
If you want to use url_launcher than please use it in this form
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
url_launcher: ^5.0.2
flutter:
sdk: flutter
This answer is also for absolute beginners: They are thinking behind the flutter sdk.
No that was a failure. The packages were extras and not in the flutter Sdk. These were secondary packages (single small framework helpers).
The PLUGIN plugin works great, as you explain in your examples.
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
final Uri _url = Uri.parse('https://flutter.dev');
void main() => runApp(
const MaterialApp(
home: Material(
child: Center(
child: ElevatedButton(
onPressed: launchUrlStart(url: "https://flutter.dev"),
child: Text('Show Flutter homepage'),
),
),
),
),
);
Future<void> launchUrlStart({required String url}) async {
if (!await launchUrl(Uri.parse(url))) {
throw 'Could not launch $url';
}
}
But when trying to open PDF https://www.orimi.com/pdf-test.pdf it remained blank, the problem was that the browser handled it in its own way. Therefore the solution was to tell it to open with an external application and it worked as expected.
Future<void> launchUrlStart({required String url}) async {
if (!await launchUrl(Uri.parse(url),mode: LaunchMode.externalApplication)) {
throw 'Could not launch $url';
}
}
In pubspec.yaml
#https://pub.dev/packages/url_launcher
url_launcher: ^6.1.5
using the url_launcher package to do the following:
dependencies:
url_launcher: ^latest_version
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
}
Note: Ensure you are trying to open a URI, not a String.