When I want to display API data on the iOS Flutter webview, the page takes about 10 seconds to load. Are there any specific settings for that?
the following code that I use
child: WebView(
// controller: _webViewController,
initialUrl: new Uri
.dataFromString(
"<meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1'/>" //IOS KONFIGURASI TEXT NORMAL DI EBVIEW
"${widget.s_content}",
mimeType: 'text/html')
.toString(),
//initialUrl: '${dataQuestions["list_question"][_counter]["data_option"][loop]["option_text"]}',
javascriptMode:
JavascriptMode.unrestricted,
onPageFinished: (finish) {
setState(() {
isLoading = false;
});
},
)
EDIT:
On real device the data loads fast but only in the emulator takes time to load.
Related
In Flutter, I am using Navigator 2.0 using go_router.
I want deeplink in my app to work properly and my app has some properties which needs to be initialized before going to any screen so I have put my MaterialApp.router(...) in a conditional boolean and Splash screen is shown while app is being initialized.
But deeplink doesn't redirect to given path when app is closed on iOS, it just opens the app.
Everything is working fine in android.
It starts working fine in iOS too when I remove async app initialization function from MaterialApp.
What am I doing wrong? Is there better way to initialze app instead of a conditional check in MaterialApp.
I have created a basic reproducible code repo https://github.com/sgshivamgarg8/testapp. Please try it out. To test deeplinks I have put required scripts in scripts/ folder.
Future<void> _appInit() async {
setState(() {
isLoading = true;
});
await Future.delayed(
const Duration(seconds: 1)); // commenting this line solves the issue
setState(() {
isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return isLoading
? const CircularProgressIndicator()
: MaterialApp.router(
routerConfig: _router,
title: 'Test',
theme: ThemeData.light(),
debugShowCheckedModeBanner: false,
);
Below the code loads several tweets in WebViews. This code works flawlessly in Android but produces a different result in iOS Simulator. No errors are produced in logs and nothing in flutter analyze pertain to this page and its classes.
Included <key>io.flutter.embedded_views_preview</key><true/> in info.plist
Widget build(BuildContext context) {
var child;
//print(_tweetHTML);
if (_tweetHTML != '' && _tweetHTML.length > 0) {
final downloadUrl = Uri.file(_filename).toString();
print(downloadUrl); //This prints the expected HTML file
// Create the WebView to contian the tweet HTML
final webView = WebView(
initialUrl: downloadUrl,
javascriptMode: JavascriptMode.unrestricted,
gestureNavigationEnabled: true,
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith(downloadUrl)) {
//print('allowing navigation to $request');
return NavigationDecision.navigate;
} else if (request.isForMainFrame) {
//print('allowing navigation to $request');
_launchURL(request.url);
return NavigationDecision.prevent;
} else {
//print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
},);
final box = LimitedBox(
maxHeight: 500.0,
child: webView,
);
child = box;
} else {
child = Text('Loading...');
}
return Container(child: child);
}
Expected results:
As you can see this works in Android:
Actual results:
However on iOS:
Option 1: add this to html body
<script id="twitter-wjs" type="text/javascript" async defer src="//platform.twitter.com/widgets.js"></script>
Option 2: Check out this widget on github TweetWebView for Flutter
Option 3: use Flutter WebView Plugin by fluttercommunity.dev, BUT This webview is not integrated in the widget tree, it is a native view on top of the flutter view. You won't be able see snackbars, dialogs, or other flutter widgets that would overlap with the region of the screen taken up by the webview.
In order to use SFSafariViewController in my Flutter app, I am using this package: flutter_inappwebview: ^3.3.0+3
While this works, there is a bug in the animation through which the SFSafariViewController appears.
Notice this:
Actual Behaviour
Expected Behaviour
Notice how in the second GIF, the app itself is pushed back, whereas in the first GIF, we can see a semi-transparent view created instead of the native push back animation for the app.
Here's the code that I am using:
final ChromeSafariBrowser browser =
MyChromeSafariBrowser(MyInAppBrowser());
await browser.open(
url: 'https://google.com',
options: ChromeSafariBrowserClassOptions(
ios: IOSSafariOptions(
barCollapsingEnabled: true,
presentationStyle: IOSUIModalPresentationStyle.POPOVER)));
Here's the Gist for the MyChromeSafariBrowser and MyInAppBrowser class.
Can you please help me with this?
You should submit an issue to flutter_inappwebview. The package uses a native modal presentations and it looks like it is not doing it correctly.
If you want to use the modal_bottom_sheet package as the gif you attached, then you can't use ChromeSafariBrowser, and you would need to use InAppWebView instead.
ChromeSafariBrowser is a native activity outside Flutter while InAppWebView is a native view wrapped inside Flutter.
InAppWebView(
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
),
This was fixed in the release v4.0.0 and it is now possible to get the expected behaviour by setting
presentationStyle: IOSUIModalPresentationStyle.POPOVER
More information here: https://pub.dev/packages/flutter_inappwebview#-changelog-tab-
I want to open a bunch of music app links using links data I have in firebase. I want to open, amazonPrimeMusic, Ganna, Spotify, Wynk, JioSavaan to name some.
Widget buildResultCard(data) {
List items = [Text(data['Ganna']),
IconButton(icon:Icon(Icons.all_inclusive),
onPressed: ()=> {Text("Ganna")}
),
Text(data['Wynk']),
IconButton(icon:Icon(Icons.all_inclusive),
onPressed: ()=> {Text("Ganna")}
),
Text(data['JioSavaan']),
IconButton(icon:Icon(Icons.all_inclusive),
onPressed: ()=> {Text("Ganna")}
),
Text(data['PrimeMusic']),
IconButton(icon:Icon(Icons.all_inclusive),
onPressed: ()=> {Text("Ganna")}
)
];
return ListView.builder(
padding: EdgeInsets.only(top: 20),
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
return items[index];
},
);
}
when I tap the button in the list it should open up the particular app for which the link is, for example for AmazonPrimeMusic link, it should open the Amazon music app.
add this to the pubspec.yaml file under dependencies-
device_apps:
android_intent:
url_launcher:
and add these to the top -
import 'package:device_apps/device_apps.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:android_intent/android_intent.dart';
and here is the sample code -
_openJioSavaan (data) async
{String dt = data['JioSavaan'] as String;
bool isInstalled = await DeviceApps.isAppInstalled('com.jio.media.jiobeats');
if (isInstalled != false)
{
AndroidIntent intent = AndroidIntent(
action: 'action_view',
data: dt
);
await intent.launch();
}
else
{
String url = dt;
if (await canLaunch(url))
await launch(url);
else
throw 'Could not launch $url';
}
}
You can use flutter_appavailability package. This plugin allows you to check if an app is installed in mobile and using this plugin you can launch an app.
If already installed then launch otherwise open link in WebView using url_launcher.
Hello you actually need two packages. Check the versions before you use them. First of all you need the id of the app. For example for facebook lite the id is com.facebook.lite. You acn find the id if you go to playstore click share and cope the link. The link for facebook lite is https://play.google.com/store/apps/details?id=com.facebook.lite from this one you can easily understand that the id is after "id=". Its the same on the other apps too.
device_apps: ^2.1.1
url_launcher: ^6.0.3
try {
///checks if the app is installed on your mobile device
bool isInstalled = await DeviceApps.isAppInstalled('si.modula.android.instantheartrate');
if (isInstalled) {
DeviceApps.openApp("si.modula.android.instantheartrate");
} else {
///if the app is not installed it lunches google play store so you can install it from there
launch("market://details?id=" +"si.modula.android.instantheartrate");
}
} catch (e) {
print(e);
}
so the code above check if you have already installed the application. If you have done it it will lunch the application if not it is going to open google playstore so you can see it there. It works only for android devices.
Updated :
url_launcher: ^6.1.4
void launchAnotherApp() async {
if (!await launchUrl(Uri.parse("https://www.instagram.com/username/"),
mode: LaunchMode.externalApplication)) {
throw 'Could not launch ';
}
}
It opens another app on your phone. If targeted app not installed on your device it will open in webview.
I think you can use external_app_launcher: ^3.0.0
https://pub.dev/packages/external_app_launcher
You can easily do it with the help of external_app_launcher.
A Flutter plugin that helps you to open another app from your app. The package asks you for four parameters out of which two are mandatory.
Example code:
RaisedButton(
color: Colors.blue,
onPressed: () {
LaunchApp.openApp(
androidPackageName: 'net.pulsesecure.pulsesecure',
iosUrlScheme: 'pulsesecure://',
appStoreLink: 'itms-apps://itunes.apple.com/us/app/pulse-secure/id945832041',
);
// Enter the package name of the App you want to open and for iOS add the URLscheme to the Info.plist file.
// The `openStore` argument decides whether the app redirects to PlayStore or AppStore.
// For testing purpose you can enter com.instagram.android
},
child: Container(
child: Center(
child: Text("Open",
textAlign: TextAlign.center,
),
),
),
)
Is there a way to block ads in an flutter WebView? I am building app that lets users browse web pages, but need to block ads. Its basically a custom browser, but I need to get rid of ads.
navigationDelegate: (NavigationRequest request) {
return NavigationDecision.prevent;}
I added that to the Webview to prevent navigation to other screens in case they accidentally click on those ads.
WebView(
initialUrl: widget.url,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
javascriptChannels: <JavascriptChannel>[
_toasterJavascriptChannel(context),
].toSet(),
navigationDelegate: (NavigationRequest request) {
return NavigationDecision.prevent;
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
},
gestureNavigationEnabled: true,
);
The webview_flutter plugin, currently, doesn't offer such feature.
However, to block ads, you can use the flutter_inappwebview plugin (I'm the author). It offers the content blocking feature through the ContentBlocker class!
I have written an article that explains it in more detail and can be found here.
Also, I have created a full project example on GitHub here (webview_ad_blocker) that uses the ContentBlocker class to block the loading of ads, such as Google Ads.