Flutter, how to make 'webview_flutter' set to chrome - flutter

I want to make "webview_flutter" package run only on the chrome browser.
But I don't know if this is possible or not.
Or if I'm misunderstanding something, please let me know as well.

You can try the plugin flutter_inappwebview. To do that, you need to use the ChromeSafariBrowser class.
It uses Chrome Custom Tabs on Android and SFSafariViewController on iOS.
You can initialize the ChromeSafariBrowser instance with an InAppBrowser fallback instance.
an exemple :
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class MyInAppBrowser extends InAppBrowser {
#override
Future onLoadStart(String url) async {
print("\n\nStarted $url\n\n");
}
#override
Future onLoadStop(String url) async {
print("\n\nStopped $url\n\n");
}
#override
void onLoadError(String url, int code, String message) {
print("\n\nCan't load $url.. Error: $message\n\n");
}
#override
void onExit() {
print("\n\nBrowser closed!\n\n");
}
}
class MyChromeSafariBrowser extends ChromeSafariBrowser {
MyChromeSafariBrowser(browserFallback) : super(bFallback:
browserFallback);
#override
void onOpened() {
print("ChromeSafari browser opened");
}
#override
void onLoaded() {
print("ChromeSafari browser loaded");
}
#override
void onClosed() {
print("ChromeSafari browser closed");
}
}
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
final ChromeSafariBrowser browser = new MyChromeSafariBrowser(new
MyInAppBrowser());
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('ChromeSafariBrowser Example'),
),
body: Center(
child: RaisedButton(
onPressed: () async {
await widget.browser.open(
url: "https://flutter.dev/",
options: ChromeSafariBrowserClassOptions(
androidChromeCustomTabsOptions:
AndroidChromeCustomTabsOptions(addShareButton:
false),
iosSafariOptions:
IosSafariOptions(barCollapsingEnabled: true)));
},
child: Text("Open Chrome Safari Browser")),
),
),
);
}
}
or you can make your own browser follow this exemple :
https://inappwebview.dev/docs/in-app-webview/basic-usage/

Related

Code execution stopped at await in async function in flutter while implementing Text to Speech

I am trying the text to speech feature in a flutter, but it is not working.
I tried many code examples from the internet and googled but did not find why not working in my project.
To keep it simple I was trying in one simple file but still, it is not working.
On click of a button, the first print statement is executing but after that not get anything.
Below is the code
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late FlutterTts flutterTts;
#override
initState() {
super.initState();
initTts();
}
initTts() {
flutterTts = FlutterTts();
}
#override
void dispose() {
super.dispose();
flutterTts.stop();
}
Future _speak() async {
print("1");
await flutterTts.speak("Hello");
print("2");
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter TTS'),
),
body: InkWell(
onTap: _speak,
child: Text("Click"),
)
),
);
}
}
The console output is
Performing hot reload...
Syncing files to device Android SDK built for x86...
Reloaded 1 of 568 libraries in 544ms.
I/flutter (21300): 1

flutte app run in background only if device is connected to usb charger

I try to validate simple task => persiste the vibration when device is horizontal (user sitdown)
Currently it's work when the screen is off only if device is connected to the laptop or usb charger. I try workmanager and android_alarm_manager but I have same issue. I'm doing something wrong ? or it's Impossible ?
Here is a simple reproduce code to test timer and vibration in background when device is connected and not connected.
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'dart:async';
main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Timer _timer;
test_vibration() {
_timer= Timer.periodic(const Duration(seconds: 1), (timer) {
Vibration.vibrate();
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
AndroidAlarmManager.periodic(Duration(seconds: 1), 0, test_vibration());
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center()
),
);
}
}
here is more complet example with accelerometer
import 'package:sensors/sensors.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'dart:async';
main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<double> _accelerometerValues;
List<StreamSubscription<dynamic>> _streamSubscriptions =
<StreamSubscription<dynamic>>[];
test_vibration() {
_streamSubscriptions.add(accelerometerEvents.listen((AccelerometerEvent event) { // Stream accelerometre
_accelerometerValues = <double>[event.y]; read accelerometer y
if (event.y>6.0||event.y<-6.0){ //device vertical
}else{ // device horizontal
Vibration.vibrate();
}
}));
}
#override
void initState() {
// TODO: implement initState
super.initState();
_streamSubscriptions.add(accelerometerEvents.listen((AccelerometerEvent event) {
setState(() {
_accelerometerValues = <double>[event.y];
});
AndroidAlarmManager.periodic(Duration(seconds: 1), 0, test_vibration());
}));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center()
),
);
}
}
solution I found :
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

How to check if user is SignedIn in Flutter Firebase

Hy here everyone. I am new to flutter and i want to check if User is SignedIn. If so the user navigate to HomeScreen else SplashScreen.
Here is my main.dart
void main() async{
runApp(MyApp());
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Instant Tasker',
theme: theme(),
initialRoute: SplashScreen.routeName,
routes: routes,
);
}
}
Here is Splash Screen
class SplashScreen extends StatefulWidget {
static String routeName = "/splash";
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
startTime() async {
var _duration = new Duration(seconds: 2);
return new Timer(_duration, navigationPage);
}
void navigationPage() {
var auth = FirebaseAuth.instance;
// ignore: deprecated_member_use
auth.onAuthStateChanged.listen((user) {
if (user != null) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => MainScreen()),
(Route<dynamic> route) => false);
} else {}
});
}
#override
void initState() {
super.initState();
startTime();
}
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
body: Body()
);
}
}
However i achieved to check user at splash screen but it stays at splash screen to check user then move to HomeScreen which doesn't seems to be good.
Or can anybody suggest how to show CircularProgressIndicator instead of Splash Screen body when it is checking for user
You can achieve it using StreamProvder
Implementation
Steps
Create a CustomUser Data model.
class CustomUser {
final String userId;
CustomUser({this.userId});
}
Create a class named FirebaseAuthService and create a stream to listen to Firebase AuthStateChanges
import 'package:firebase_auth/firebase_auth.dart';
class FirebaseAuthService {
final FirebaseAuth auth = FirebaseAuth.instance;
// create user obj based on firebase user
CustomUser _userFromFirebaseUser(User user) {
return user != null ? CustomUser(userId: user.uid) : null;
}
// auth change user stream
//Required stream
Stream<CustomUser> get user {
return auth.authStateChanges().map(_userFromFirebaseUser);
}
}
}
Add a StreamProvider on top of the widget tree where you want to check for the AuthState.
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<CustomUser>.value(
value: FirebaseAuthService().user,
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Instant Tasker',
theme: theme(),
initialRoute: SplashScreen.routeName,
routes: routes,
)
);
}
}
Create a Wrapper and return SplashScreen or HomeScreen based on AuthState.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
#override
Widget build(BuildContext context) {
final user = Provider.of<CustomUser>(context);
if (user == null) {
return SplashScreen();
}
return HomeScreen();
}
}
Now you can use final user = Provider.of<CustomUser>(context);
in the widget tree to check if the user is null.
https://www.youtube.com/watch?v=z05m8nlPRxk&list=PL4cUxeGkcC9j--TKIdkb3ISfRbJeJYQwC&index=3

Flutter | how can i record the time user spend in my app in flutter?

I have developed and app and the client want me to store the total time spend by the user inside the app
how can I achieve that
I have tried using this App_usage package in flutter but its showing me Star Activity error
if you guys have any solution please let me know
thanks in advance :)
Have some variable that tracks the start time and end/ pause time of the app and persist the difference. You will have to hook that up to the app lifecycle to listen to events such as pausing/ resuming the app. (e.g. How to handle onPause/onResume in Flutter App?)
Something like this:
class AppLifecycleReactor extends StatefulWidget {
const AppLifecycleReactor({Key key}) : super(key: key);
#override
_AppLifecycleReactorState createState() => _AppLifecycleReactorState();
}
class _AppLifecycleReactorState extends State<AppLifecycleReactor>
with WidgetsBindingObserver {
DateTime startTime;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
startTime = DateTime.now();
}
if (state == AppLifecycleState.detached ||
state == AppLifecycleState.paused) {
var usageTime = DateTime.now().difference(startTime);
// do whatever with the usageTime
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: MyContent(),
);
}
}
like Chris Marx said, you can use the counter to store usage time. and to handle the sync operation to server, you can use shared preferenceq to store data and when the app launched again you do sync(update) with the server.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(new HomePage());
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String? docId;
addTime() async {
docId = await TimeHomePageUsage.addUserStartTime();
}
#override
void initState() {
// TODO: implement initState
super.initState();
addTime();
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
TimeHomePageUsage.addUserEndTime(docId);
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Home Page'),
),
);
}
}
class TimeHomePageUsage {
static Future<String?> addUserStartTime() async {
String? docId;
await FirebaseFirestore.instance
.collection('timeUsage')
.add({'startTime': DateTime.now().toString()})
.then((doc) => print("Start Time added ${docId = doc.id} "))
.catchError((error) => print("Failed to add Start Time: $error"));
return docId;
}
static Future<void> addUserEndTime(String? docId) async {
await FirebaseFirestore.instance
.collection('timeUsage')
.doc(docId)
.update({"endTime": DateTime.now().toString()})
.then((value) => print("End Time added "))
.catchError((error) => print("Failed to add End Time: $error"));
}
}

How can I prevent my Build Method from looping?

I am learning Flutter. I wrote small app to getting key from API and print it on screen. The problem is that my getApiKey() method is looping.
Why? And How I can prevent it?
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider<TenderApiData>(
builder: (_) => TenderApiData(), child: HomePage()),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(), body: MyContainer());
}
}
class MyContainer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[MyTestWidget()],
);
}
}
class TenderApiData with ChangeNotifier {
String access_token;
String url = "https://";
getApiKey() async
{
var response = await http.post(url, headers: {"Accept": "application/json"});
// await Future.delayed(Duration(seconds: 25));
if (response.statusCode == 200)
{
access_token = json.decode(response.body)['access_token'];
notifyListeners();
}
}
}
class MyTestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
Provider.of<TenderApiData>(context).getApiKey();
var result = Provider.of<TenderApiData>(context).access_token;
return Row(
children: <Widget>[
Flexible(child: Text("Data: $result"))
],
);
}
}
The reason this happens is because you are notifying listeners in your getApiKey function and then calling getApiKey in your build method. The build method is called when you notify your listeners, see why this loops?
Anyways, to prevent it, you simply convert your StatelessWidget to a StatefulWidget and only call getApiKey in State.didChangeDependencies (not in initState because you need access to the BuildContext):
class MyTestWidget extends StatefulWidget {
#override
_MyTestWidgetState createState() => _MyTestWidgetState();
}
class _MyTestWidgetState extends State<MyTestWidget> {
bool apiKeyLoaded;
#override
void initState() {
apiKeyLoaded = false;
super.initState();
}
#override
void didChangeDependencies() {
if (!apiKeyLoaded) {
Provider.of<TenderApiData>(context).getApiKey();
apiKeyLoaded = true;
}
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
var result = Provider
.of<TenderApiData>(context)
.access_token;
return Row(
children: <Widget>[
Flexible(child: Text("Data: $result"))
],
);
}
}