Flutter - programmatically update TextField to show scrolling info - flutter

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!"

Related

How to update the values of varaible when background service changes its value?

We are working in a flutter group project. In which we are doing some tasks with background service. Basically we are fetching the usage time of all the third party applications for every 1 minute. Basically, we use app_usage package for getting the usage time of all the apps. This package returns the list of apps with usage_time, appName, packageName, etc.. whenever we are calling app_usage package with starting time and ending time it will return the list of apps with usage time for the given duration.
i.e.,
List<AppUsageInfo> apps = await AppUsage.getAppUsage(starting, ending);
This line will return the list of apps at the particular instance. But for background task we call the same line in the Timer.periodic function with the duration of 1 minute. So, we thought this will return the usage time of apps for every 1 minute. But when we printing the apps usage time...its not updating but if there some refresh is done to the app the updated values are displaying. for eg. If the refreshing action is made after the 5th minute the value exactly changes to 5th minute by skipping the previous values. So, is there any way to update the values at real time in background.
This is sample code.
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
// ignore: depend_on_referenced_packages
import 'package:flutter_background_service_android/flutter_background_service_android.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:device_apps/device_apps.dart';
import 'package:app_usage/app_usage.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeService();
runApp(const MyApp());
}
var item = AppModel(name: 'untitled', usage: 2000);
Future<void> initializeService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
// this will be executed when app is in foreground or background in separated isolate
onStart: onStart,
// auto start service
autoStart: true,
isForegroundMode: true,
),
iosConfiguration: IosConfiguration(
// auto start service
autoStart: true,
// this will be executed when app is in foreground in separated isolate
onForeground: onStart,
// you have to enable background fetch capability on xcode project
onBackground: onIosBackground,
),
);
service.startService();
}
// to ensure this is executed
// run app from xcode, then from xcode menu, select Simulate Background Fetch
bool onIosBackground(ServiceInstance service) {
WidgetsFlutterBinding.ensureInitialized();
print('FLUTTER BACKGROUND FETCH');
return true;
}
void getUsageStats() async {
try {
DateTime ending = DateTime.now();
int daySubtracter = ending.hour;
int minSubtracter = ending.minute;
int secSubtracter = ending.second;
DateTime starting = ending.subtract(
Duration(
hours: daySubtracter,
minutes: minSubtracter,
seconds: secSubtracter,
),
);
print(starting);
print(ending);
List<AppUsageInfo> apps = await AppUsage.getAppUsage(starting, ending);
for (var app in apps) {
if (app.appName == item.name) {
if ((item.usage - app.usage.inSeconds) < 10) {
print("Time is equal");
} else {
print("Remaining seconds: ${item.usage - app.usage.inSeconds}");
}
}
}
} on AppUsageException catch (exception) {
print(exception);
}
}
void onStart(ServiceInstance service) async {
// Only available for flutter 3.0.0 and later
DartPluginRegistrant.ensureInitialized();
// For flutter prior to version 3.0.0
// We have to register the plugin manually
if (service is AndroidServiceInstance) {
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
// bring to background
Timer.periodic(
const Duration(seconds: 20),
(timer) async {
if (service is AndroidServiceInstance) {
service.setForegroundNotificationInfo(
title: "REMIT application is running",
content: "Timer running",
);
}
//external plugin for background
if (Platform.isAndroid) {
getUsageStats();
}
},
);
}
class AppModel {
late String name;
late int usage;
AppModel({required this.name, required this.usage});
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String text = "Stop Service";
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Service App'),
),
body: Center(
child: Column(
children: [
ElevatedButton(
child: const Text("Background Mode"),
onPressed: () {
FlutterBackgroundService().invoke("setAsBackground");
},
),
],
),
),
),
);
}
}
We are calling the getUsageStats method for every 20 seconds for updated usage time. To cross check the code we are printing it on the terminal but the usage time not updating untill any refresh happens to the code.

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()
],
),
),
),
);
}
}

Download, save as, and change background image of the phone with Flutter

I need help regarding the images in my app. I would like to add 3 buttons for:
Download
Save as
Change phone wallpaper
I'm not using urls. I already have my images in an assets repository.
Do you have any idea how I can do that? Thank you.
You can copy paste run full code below
You can use package https://pub.dev/packages/wallpaper_manager
You can directly set wallpaper with image in assets
Example code's assets image path is "assets/tmp1.jpg"
code snippet
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:wallpaper_manager/wallpaper_manager.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _wallpaperFile = 'Unknown';
String _wallpaperAsset = 'Unknown';
#override
void initState() {
super.initState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await WallpaperManager.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// 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(() {
_platformVersion = platformVersion;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromFile() async {
setState(() {
_wallpaperFile = "Loading";
});
String result;
var file = await DefaultCacheManager().getSingleFile(
'https://images.unsplash.com/photo-1542435503-956c469947f6');
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromFile(
file.path, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// 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(() {
_wallpaperFile = result;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromAsset() async {
setState(() {
_wallpaperAsset = "Loading";
});
String result;
String assetPath = "assets/tmp1.jpg";
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// 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(() {
_wallpaperAsset = result;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("Platform Version"),
onPressed: initPlatformState,
),
Center(
child: Text('Running on: $_platformVersion\n'),
),
RaisedButton(
child: Text("Set wallpaper from file"),
onPressed: setWallpaperFromFile,
),
Center(
child: Text('Wallpaper status: $_wallpaperFile\n'),
),
RaisedButton(
child: Text("Set wallpaper from asset"),
onPressed: setWallpaperFromAsset,
),
Center(
child: Text('Wallpaper status: $_wallpaperAsset\n'),
),
],
)),
);
}
}

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;
});
}

How to check first time app launch in 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