How to check first time app launch in Flutter - flutter

I am a beginner in a flutter, I have created my application but I want to check if the user opens the application for the first time after installing, I have seen this article but did not know how that?
This is the splash screen code, the code move the user directly to the Main screen after 3 sec, But I want to check if user first time opens the app and move the user to Welcome screen or if user not the first time and move the user to the Main screen.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:book_pen/main.dart';
import 'package:book_pen/Welcome.dart';
void main() {
runApp(new MaterialApp(
home: new SplashScreen(),
routes: <String, WidgetBuilder>{
'/HomePage': (BuildContext context) => new HomePage(),
'/WelcomePage': (BuildContext context) => new WelcomePage()
},
));
}
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
startTime() async {
var _duration = new Duration(seconds: 3);
return new Timer(_duration, navigationPageHome);
}
void navigationPageHome() {
Navigator.of(context).pushReplacementNamed('/HomePage');
}
void navigationPageWel() {
Navigator.of(context).pushReplacementNamed('/WelcomePage');
}
#override
void initState() {
super.initState();
startTime();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: new Image.asset(
'assets/images/SplashBack.jpg',
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
Center(
child: new Image.asset(
'assets/images/BigPurppleSecSh.png',
height: 150,
width: 300,
)),
],
),
);
}
}

#Abdullrahman, please use shared_preferences as suggested by others. Here is how you can do that,
Depend on shared_preferences package in pubspec.yaml and run Packages get:
dependencies:
flutter:
sdk: flutter
shared_preferences: ^0.5.4+6
Import the package:
import 'package:shared_preferences/shared_preferences.dart';
Implement it:
class _SplashScreenState extends State<SplashScreen> {
startTime() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool firstTime = prefs.getBool('first_time');
var _duration = new Duration(seconds: 3);
if (firstTime != null && !firstTime) {// Not first time
return new Timer(_duration, navigationPageHome);
} else {// First time
prefs.setBool('first_time', false);
return new Timer(_duration, navigationPageWel);
}
}
void navigationPageHome() {
Navigator.of(context).pushReplacementNamed('/HomePage');
}
void navigationPageWel() {
Navigator.of(context).pushReplacementNamed('/WelcomePage');
}
........
Note: SharedPreferences data will be removed if user clears the cache. SharePreferences is a local option. If you want to prevent that, you can use firestore to save bool value but firestore would probably be an overkill for a simple task like this.
Hope this helps.

You can use https://pub.dev/packages/shared_preferences add a value the first time a user enters

It is even simpler with is_first_run package. You simply do:
bool firstRun = await IsFirstRun.isFirstRun();
It returns true if the app is launched for the first time.

You may set up a boolean during first time app is launched or installed. Once the app is launched or installed first time, set it to true. The default value should be false.
After setting it to true, you must save this in the shared_preference in local storage.
After that each time on you relaunch the app, read the shared_preference value. The value should be always true unless you change it.
watch the video here

Related

Flutter - programmatically update TextField to show scrolling info

I'd like to show some debug info in my App (e. g. user pressed Button A) and was thinking of using the TextField widget for this.
Using below code, I can record ambient sound from my phone and I'd like to add a widget at the bottom that displays timestamps of when the recordings started and stopped, including length of the recording. The idea is to use a ring buffer (package:circular_buffer) that keeps track of a pre-defined number of text lines being displayed in the TextField. Whenever something happens, the new debug info is added as an element to the ring buffer and the TextField is updated. I am very new to flutter, so I'm completely unsure how to achieve this. I was trying to use setState() but I don't know how to call it from other widgets. Is there a way to register as listener to state changes of other widgets and update the text accordingly?
import 'dart:async';
import 'dart:io';
// locale, datetime formatting
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:record/record.dart';
import 'package:path_provider/path_provider.dart';
// local imports
import './display_timer.dart';
void main() {
runApp(myApp());
}
class myApp extends StatefulWidget {
#override
myAppState createState() => myAppState();
}
class myAppState extends State<myApp> {
final record = Record();
bool bPressed = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Record',
home: Scaffold(
appBar: AppBar(
title: const Text('Record'),
),
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
ElevatedButton(
child: bPressed ? const Text("Stop") : const Text("Record"),
onPressed: () {
setState(() {
bPressed = !bPressed;
});
action();
},
),
if (bPressed)
ElapsedTime(timestamp: DateTime.now().toString())
else
const Text("")
]),
),
));
}
String getTimestampSec() {
DateTime now = DateTime.now();
var dateString = DateFormat('yyyyMMdd_hhmmss').format(now);
return dateString;
}
Future<void> action() async {
// Get the state of the recorder
bool isRecording = await record.isRecording();
// Check and request permission
if (await record.hasPermission()) {
if (isRecording) {
// Stop recording
await record.stop();
} else {
// get write dir
// TODO: add fnc so dir only has to be initialize once
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
String outFile =
"$appDocPath/${getTimestampSec()}_ambient_test.m4a";
print("saving audio to: $outFile");
// Start recording
await record.start(
path: outFile,
encoder: AudioEncoder.aacLc, // by default
bitRate: 128000, // by default
samplingRate: 44100, // by default
);
}
}
print('Pressed');
}
}
To use setState() every time is not good practice rather than you can use ValueNotifier. Every time you update the string value it notify to your TextField and it will update TextField data.
ValueNotifier<String> logText = ValueNotifier<String>("Welcome");
ValueListenableBuilder(
valueListenable: logText,
builder: (context, logTextUpdate,child) {
return Text(
"${logText.value}",
style: TextStyle(fontSize: 25),
);
}),
when you want to update your text, assign value to logText
logText.value = "Happy to see you!"

how to get mobile number in flutter

I am using "mobile_number(version - 1.0.3)" plugin to get mobile number in flutter app, am running in original device but i couldn't get mobile number.instead of errors i can get mobile number as null along with other sim details as shown in screen shot.
help me to resolve this problem, i had just copy pasted the example given by plugin that is the code
plugin link
It says:
Note: If the mobile number is not pre-exist on sim card it will not return te phone number.
I think mobile number does not pre-exist on the SIM if the SIM is not original (i.e. replaced)
If the phone number isn't stored on the sim (aka null), then you can't get it from anywhere else, in that case you probably want to forward the user to a different page where they can type the phone number using TextField and then store it somewhere
Use Mobile_number package to get mobile number and other details. For example
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobile_number/mobile_number.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _mobileNumber = '';
List<SimCard> _simCard = <SimCard>[];
#override
void initState() {
super.initState();
MobileNumber.listenPhonePermission((isPermissionGranted) {
if (isPermissionGranted) {
initMobileNumberState();
} else {}
});
initMobileNumberState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initMobileNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
String mobileNumber = '';
// Platform messages may fail, so we use a try/catch PlatformException.
try {
mobileNumber = (await MobileNumber.mobileNumber)!;
_simCard = (await MobileNumber.getSimCards)!;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_mobileNumber = mobileNumber;
});
}
Widget fillCards() {
List<Widget> widgets = _simCard
.map((SimCard sim) => Text(
'Sim Card Number: (${sim.countryPhonePrefix}) - ${sim.number}\nCarrier Name: ${sim.carrierName}\nCountry Iso: ${sim.countryIso}\nDisplay Name: ${sim.displayName}\nSim Slot Index: ${sim.slotIndex}\n\n'))
.toList();
return Column(children: widgets);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_mobileNumber\n'),
fillCards()
],
),
),
),
);
}
}

How to detect mock location in flutter for ios and android

I am using package of location and google maps flutter in my screen and I want to detect wether user using fake gps or not.. Is there a package that can detect mock location in flutter that available in android and ios? I have tried using TrustFall package but my app always close unexpectedly.. is there another way to detect mock location in flutter?
Use Geolocator and check the Position object's isMocked property.
you can use TrustLocation
permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
usage :
import 'package:trust_location/trust_location.dart';
/* Assuming in an async function */
/// query the current location.
LatLongPosition position = await TrustLocation.getLatLong;
/// check mock location on Android device.
bool isMockLocation = await TrustLocation.isMockLocation;
using steam:
// input seconds into parameter for getting location with repeating by timer.
// this example set to 5 seconds.
TrustLocation.start(5);
/// the stream getter where others can listen to.
TrustLocation.onChange.listen((values) =>
print('${values.latitude} ${values.longitude} ${values.isMockLocation}')
);
/// stop repeating by timer
TrustLocation.stop();
Example:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:trust_location/trust_location.dart';
import 'package:location_permissions/location_permissions.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _latitude;
String _longitude;
bool _isMockLocation;
/// initialize state.
#override
void initState() {
super.initState();
requestLocationPermission();
// input seconds into parameter for getting location with repeating by timer.
// this example set to 5 seconds.
TrustLocation.start(5);
getLocation();
}
/// get location method, use a try/catch PlatformException.
Future<void> getLocation() async {
try {
TrustLocation.onChange.listen((values) => setState(() {
_latitude = values.latitude;
_longitude = values.longitude;
_isMockLocation = values.isMockLocation;
}));
} on PlatformException catch (e) {
print('PlatformException $e');
}
}
/// request location permission at runtime.
void requestLocationPermission() async {
PermissionStatus permission =
await LocationPermissions().requestPermissions();
print('permissions: $permission');
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Trust Location Plugin'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Column(
children: <Widget>[
Text('Mock Location: $_isMockLocation'),
Text('Latitude: $_latitude, Longitude: $_longitude'),
],
)),
),
),
);
}
}
for more information you can see https://pub.dev/packages/trust_location
github link : https://github.com/wongpiwat/trust-location
I think better to use safe_device. It's working on both Android and IOS

How Can I PAUSE or RESUME a async task using a button in flutter?

I'm Building An Flutter Application which requires image changes after a period of time. I thought using while loop with a sleep method inside may solve the problem. But It didn't, Image is only getting change after the loop ends. Application UI also gets froze.
So, I used the async Task which I can't control with a Button.
Desired Output: Image should be changed after every 10 seconds and the user can pause or resume method execution.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Test(
),
),
)
);
}}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
int imgnumber=1;
int varToCheckButtonPress = 0;
String BtnTxt = "START";
void inc(){
while(imgnumber<10)
{
print(imgnumber);
await Future.delayed(const Duration(seconds: 10));
setState(() {
imgnumber++;
});
}
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(flex: 1,
child: Container(
child: Image.asset('images/'+imgnumber.toString()+'.png'),
height: 500,
width:500,
color: Colors.green,
),
),
FlatButton(
child: Text(BtnTxt),
onPressed: (){
if (varToCheckButtonPress == 0) {
setState(() {
inc();
BtnTxt = 'PAUSE';
varToCheckButtonPress = 1;
});
} else if (varToCheckButtonPress == 1) {
setState(() {
BtnTxt = 'RESUME';
varToCheckButtonPress = 0;
});
}
},
)
],
);
}
}
I want the user to control the UI with a single button behave as START, PAUSE and RESUME.
Can we Use normal function To implement this functionality?
You should make use of Bloc pattern to manage your states, e.g: StreamBuilder, Providers, and make a timer to push new imageUrl to the sink and let the streamBuilder receive the latest imageUrl.
As for your button, all it controls is the timer. When u hit the play button, new imageUrl will keep pushing to the sink, while you press paused, simply stop the timer, and new image Url will not be pushing new imageUrl to the sink, and of course, reset the timer when you hit the stop button.
Here is a very detail Bloc pattern tutorial you can follow: Medium
The shortcut to achieve this is :
You can probably hold a function in async loop and call setState method on tap to change it's state.
For example :
call this function in desired location
while (_isPaused) {
await Future.delayed(Duration(milliseconds: 500));
}
and then call set state method from onTap, just like this
onTap:(){
setState((){
_isPaused? _isPaused=false: _isPaused=true;
});
}

Where do I run initialisation code when starting a flutter app?

Where do I run initialisation code when starting a flutter app?
void main() {
return runApp(MaterialApp(
title: "My Flutter App",
theme: new ThemeData(
primaryColor: globals.AFI_COLOUR_PINK,
backgroundColor: Colors.white),
home: RouteSplash(),
));
}
If I want to run some initialisation code to, say fetch shared preferences, or (in my case) initialise a package (and I need to pass in the the BuildContext of the MaterialApp widget), what is the correct way to do this?
Should I wrap the MaterialApp in a FutureBuilder? Or is there a more 'correct' way?
------- EDIT ---------------------------------------------------
I have now placed the initialisation code in RouteSplash() widget. But since I required the BuildContext of the app root for the initialisation, I called the initialisation in the Widget build override and passed in context.ancestorInheritedElementForWidgetOfExactType(MaterialApp). As I don't need to wait for initialisation to complete before showing the splash screen, I haven't used a Future
One simple way of doing this will be calling the RouteSplash as your splash screen and inside it perform the initialization code as shown.
class RouteSplash extends StatefulWidget {
#override
_RouteSplashState createState() => _RouteSplashState();
}
class _RouteSplashState extends State<RouteSplash> {
bool shouldProceed = false;
_fetchPrefs() async {
await Future.delayed(Duration(seconds: 1));// dummy code showing the wait period while getting the preferences
setState(() {
shouldProceed = true;//got the prefs; set to some value if needed
});
}
#override
void initState() {
super.initState();
_fetchPrefs();//running initialisation code; getting prefs etc.
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: shouldProceed
? RaisedButton(
onPressed: () {
//move to next screen and pass the prefs if you want
},
child: Text("Continue"),
)
: CircularProgressIndicator(),//show splash screen here instead of progress indicator
),
);
}
}
and inside the main()
void main() {
runApp(MaterialApp(
home: RouteSplash(),
));
}
Note: It is just one way of doing it. You could use a FutureBuilder if you want.
To run code at startup, put it in your main.dart. Personally, that's the way I do it, to initialise lists etc.