Hello I am new in flutter. I created a webapp with webview. Now i want that if there is not internet connection the splash screen should display that there is no internet connection other wise it should load the web page.
in this code in initstate of stateful widget it will check if internet is available using isInternetAvailable then it will show webview else it will show text with Internet not available.
import 'package:flutter/material.dart';
import 'dart:io';
class SplashScreen extends StatefulWidget {
#override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
bool isInternetAvailable = false;
#override
void initState() {
isInternetConnected().then((value){
setState(() {
isInternetAvailable = value;
});
});
super.initState();
}
Future<bool> isInternetConnected() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
return true;
} else {
return false;
}
} on SocketException catch (_) {
print('not connected');
return false;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: isInternetAvailable ? Webview() : Center(
child: Text('Internet not available'),
)
);
}
}
Related
So I am trying to get my camera preview working on iOS and Android, so that it can take a photo, however, I am receiving this error when trying to access my camera from the bottom navigation.
NoSuchMethodError: The Method '[]' was called on Null.
Receiver: null
Tried calling: [](0)
This is the camera I am using, and according to docs, this should be working correctly.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:stumble/main.dart';
import 'dart:async';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(MyApp());
}
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
I have tried various methods of troubleshooting and to no avail. Am I missing an asset entirely? How can I rectify? This is building on my initial question located here: Camera preview stretched in flutter
Edit:
New code re: answers
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:stumble/main.dart';
import 'dart:async';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(MyApp());
}
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
if (cameras.isNotEmpty) {
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
Edit:
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Camera(setData: (File file) {
_imageArray.add(file);
print("_imageArray-- " + _imageArray.length.toString());
setState(() {});
}),
));
It seems like the error indicates that you do not have any available cameras. You should check if you have available cameras like this:
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
if(cameras.isNotEmpty) {
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if(cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
The error indicates that there is no available cameras in your current environment. Are you trying this out on a simulator? If so, that might be the cause.
Try to set a breakpoint to check the value of the cameras variable or print the length of it afterwards like this:
cameras = await availableCameras();
print(cameras.length);
If you get 0 as the length, that means there is no available cameras.
Could you see if this minimal sample works?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
print(cameras.length); // Confirm here that more than 1 cameras do exist
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Camera(),
);
}
}
class Camera extends StatefulWidget {
Camera({Key key}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController _controller;
#override
void initState() {
super.initState();
print(cameras.length); // Confirm here that cameras.length did not change from above
if (cameras.isNotEmpty) {
_controller = CameraController(cameras[0], ResolutionPreset.max);
_controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
_controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!_controller.value.isInitialized) {
return Container();
}
return CameraPreview(_controller);
}
}
I am a newbie , and I am facing a problem beyond my little knowledge.
I am making a test project, where I want to use a splashscreen, as a newbie, I used flutter_native_splash to create splash screen; it is working fine, but now I want to hold the splash screen and show an AlertDialog about internet connectivity.
I don't know how to use it :(
extra Q. is there any way to use an button to the AlertDialog, which will reopen / resume the process if the internet connection restore?
Try this package data_connection_checker
class InitialScreen extends StatefullWidget {
#override
_InitialScreenState createState() => _InitialScreenState();
}
class _InitialScreenState extends State<InitialScreen> {
bool hasConnection;
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
setState(() {
hasConnection = await DataConnectionChecker().hasConnection;
});
});
}
#override
Widget build(BuildContext) {
if(hasConnection) {
return Text('hasConnection');
} else {
return Text('Connection error');
}
}
}
Hours of researching with noob knowledge, I maybe found a solution of my problem -->
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
class SplashScreen extends StatefulWidget {
SplashScreen({Key key}) : super(key: key);
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
int internetValue = 0;
Future<bool> asyncNetCheck() async {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return Future<bool>.value(true);
}
}
#override
void initState () {
super.initState();
new Future.delayed(const Duration(seconds: 3),(){
setState(() {
internetValue = 2;
asyncNetCheck().then((value) {
internetValue = 1;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
});
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: GlobalColor.splashColorFill,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/splash.png"),
),
),
child: internetValue == 0 ? Container(): internetValue == 2? Container(child: Center(child: Text("checking Internet..."),),) : Container()
)
);
}
}
but still there is a problem though, if internet connection is slow or the process is slowing the thread; the "checking internet..." text splash for a few moment, hope I can fix that too!and to my extra question, I will place an button in space of text, and will call the initstate, hope that will cover at least minimum area!
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"));
}
}
In other words, instead of fixed 15 seconds, is there a way to, to tell it to stop showing when my async function is finished?
If you are using a separate screen for Splash screen, you can simply await the async function you have and the use Navigator.pushReplacement() to open your Main Screen
Example:
class SplashScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return SplashScreenState();
}
}
class SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
handleSplashscreen();
}
void handleSplashscreen() async {
// Wait for async to complete
await someAsyncFunction();
// Open Main page
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomePage(user: null)));
}
Future<void> someAsyncFunction() async {
// Do some Network or other stuff
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text("Loading...")),
);
}
}
If you are simply showing a loader in the same screen while async operation is being done, you can use a FutureBuilder as others suggested.
Or you can conditionally show loader and Main UI using a boolean and setState().
Example:
class MainPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MainPageState();
}
}
class MainPageState extends State<MainPage> {
// Boolean to show/ hide loader
bool isLoading = true;
#override
void initState() {
super.initState();
handleAsync();
}
void handleAsync() async {
// Wait for async to complete
await someAsyncFunction();
// Open Main page
setState(() {
isLoading = false;
});
}
Future<void> someAsyncFunction() async {
// Do some Network or other stuff
}
#override
Widget build(BuildContext context) {
// Using isLoading to check whether async function is complete
return isLoading
? Container(
child: Center(child: Text("Loading...")),
)
: Container(
child: Text("The Actual screen"),
);
}
}
Hope it helps.
Use FutureBuilder from here in the page and show splash screen image when the data is not loaded.
Hi iam using flutter cameraPreview to capture photo, the camera preview works fine but when the camera screen goes to background, while on resumed on that screen the camera screen is frezzed, cant able to view cameraPrview onResume.
mycode:
Future<void> _initializeCamera() async {
final cameras = await availableCameras();
final firstCamera = cameras.first;
_controller = CameraController(firstCamera, ResolutionPreset.high);
_initializeControllerFuture = _controller.initialize();
if (!mounted) {
return;
}
setState(() {
isCameraReady = true;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: Stack(children: <Widget>[
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
return Center(
child:
CircularProgressIndicator()); // Otherwise, display a loading indicator.
}
},
),],),);
controller is disposed prpoperly.
I want to know why camera preview is disposed while pause.
Issue is solved by initialised cameraPreview onResume
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_controller != null
? _initializeControllerFuture = _controller.initialize()
: null; //on pause camera disposed so we need call again "issue is only for android"
}
}
On resuming to the page, _controller.initialize will call, so that cameraPreview will works fine.
This is due to cameraPreview runs for long on onPause, it will be disposed..onAndroid i think so..
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
late List<CameraDescription> _cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
_cameras = await availableCameras();
runApp(const CameraApp());
}
/// CameraApp is the Main Application.
class CameraApp extends StatefulWidget {
/// Default Constructor
const CameraApp({Key? key}) : super(key: key);
#override
State<CameraApp> createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> with WidgetsBindingObserver {
late CameraController controller;
// late AppLifecycleState _appLifecycleState;
#override
void initState() {
super.initState();
// _appLifecycleState = AppLifecycleState.resumed;
WidgetsBinding.instance.addObserver(this);
controller = CameraController(_cameras[0], ResolutionPreset.max);
cameraInit();
}
void cameraInit() {
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
}).catchError((Object e) {
if (e is CameraException) {
switch (e.code) {
case 'CameraAccessDenied':
// Handle access errors here.
break;
default:
// Handle other errors here.
break;
}
}
});
}
#override
void dispose() {
controller.dispose();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
// _appLifecycleState = state;
});
if (state == AppLifecycleState.resumed) {
// App is in the foreground
print('App is in the foreground');
cameraInit();
} else if (state == AppLifecycleState.paused) {
// App is in the background
print('App is in the background');
}
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}