Run code after closed Flutter app (detached) - android

I want to run some tasks when I closed application using flutter, This tasks are some functions to delete data from firebase when the app is closing (detached)
I used WorkManager and didChangeAppLifecycleState, it is work when state == AppLifecycleState.pused but not work if the state == AppLifecycleState.detached.
what I can to do that, thank you
const task = 'test';
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
await Firebase.initializeApp();
currentFirebaseUser = fAuth.currentUser;
FirebaseFirestore.instance.collection('locations').doc(currentFirebaseUser!.uid).delete();
print(currentFirebaseUser!.uid+"++++++++++++++++++");
return Future.value(true);
});
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Workmanager().initialize(
callbackDispatcher,
isInDebugMode: true,
);
AwesomeNotifications().initialize(null, [
NotificationChannel(
channelKey: 'test_channel',
channelName: 'Test Notification',
channelDescription: 'Notifications for basic testing',
)
]);
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(
MyApp(
child: ChangeNotifierProvider(
create: (context) => AppInfo(),
child: GetMaterialApp(
initialBinding: ControllerBindings(),
title: 'Drivers App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const AuthGate(),
debugShowCheckedModeBanner: false,
),
),
),
);
}
class MyApp extends StatefulWidget {
final Widget? child;
const MyApp({this.child});
static void restartApp(BuildContext context) {
context.findAncestorStateOfType<_MyAppState>()!.restartApp();
}
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver{
Key key = UniqueKey();
void restartApp() {
setState(() {
key = UniqueKey();
});
}
#override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
// TODO: implement dispose
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) async {
if (state == AppLifecycleState.detached) {
var uniqueName = DateTime.now().second.toString();
await Workmanager().registerOneOffTask(uniqueName, task);
print("------------------------");
}
}
#override
Widget build(BuildContext context) {
return KeyedSubtree(
key: key,
child: widget.child!,
);
}
}

Related

Cannot resolve symbol '#android:color/white'

I'm having this issue while creating a splash screen in flutter. I looked for an answer but no one solve the matter or answer perfectly.
Cannot resolve symbol '#android:color/black'
Create StateFulWidget
Add one Future.delayed() to initstate.
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SecondScreen(),
),
);
});
}
Duration(seconds:3) will wait for 3 seconds on the splash screen then it will redirect to SecondScreen.
the code should be like this
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
#override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SecondScreen(),
),
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
child: const Center(child: Text("Splash Screen")),
),
);
}
}
the whole code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const SplashScreen(),
);
}
}
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
#override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SecondScreen(),
),
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
child: const Center(child: Text("Splash Screen")),
),
);
}
}
class SecondScreen extends StatefulWidget {
const SecondScreen({super.key});
#override
State<SecondScreen> createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.green,
child: const Center(
child: Text("Home Screen"),
),
),
);
}
}
If it was useful, you can choose it as an approved answer and give points. Good coding.
Try using this,
<item android:background="#android:color/white" />
When it comes to drawable you should assign XMLs or images in your drawable or mipmap resource

showing black screen on backpress Flutter

I am using Webview with WillPopScope, webview internal back button is working fine but on the first page back press is not working.
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SafeArea(child: MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
InAppWebViewController _controller;
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => canGoBack(context),
child: Scaffold(
body: InAppWebView(
initialUrlRequest:
URLRequest(url: Uri.parse("https://www.google.com/")),
onWebViewCreated: onWebviewCreated,
),
),
);
}
void onWebviewCreated(InAppWebViewController controller) {
_controller = controller;
}
canGoBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
return Future.value(true);
}
}
}
tried with
canGoBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
Navigator.pop(context, true);
return Future.value(false);
}
}
the issue is showing the black if there is no webview history.
You don't have any previous root and you're using
Navigator.pop(context, true); // in canGoBack function
That's cause to issue. Remove that line and it will work.

Flutter build apk release crashing when opening the app only in first time

Apparently the error is actually in the main.dart -- crashing when opening the app only in first time
I am developing a flutter application with a welcome screen that appears only the first time the app is opened, after that the main screen is a webview
This is my main.dart
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
color: Colors.amber,
home: new Splash(),
);
}
}
class Splash extends StatefulWidget {
#override
SplashState createState() => new SplashState();
}
class SplashState extends State<Splash> with AfterLayoutMixin<Splash> {
Future checkFirstSeen() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool _seen = (prefs.getBool('seen') ?? false);
if (_seen) {
Navigator.of(context).pushReplacement(
new MaterialPageRoute(builder: (context) => new Home()));
} else {
await prefs.setBool('seen', true);
Navigator.of(context).pushReplacement(
new MaterialPageRoute(builder: (context) => new IntroScreen()));
}
}
#override
void afterFirstLayout(BuildContext context) => checkFirstSeen();
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Text('Carregando...'),
),
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Entrega na Obra',
home: HomePage(),
);
}
}
class IntroScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Entrega na Obra',
home: WelcomeScreen(),
);
}
}

Camera renders slowly when using websockets in CameraImage stream

Flutter camera app renders very slowly when using websockets in image streams. How can I improve my app performance? what is the best way to overcome this? On emulator it works just fine but on real device there is lot of delay and stuttering. Can we use async for camera app? If yes, how can I use it with this code?
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:web_socket_channel/io.dart';
import 'dart:convert';
import 'package:archive/archive.dart';
List<CameraDescription> cameras;
Future<void> main() async {
cameras = await availableCameras();
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: CameraApp(),
);
}
}
class CameraApp extends StatefulWidget {
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController controller;
IOWebSocketChannel channel = IOWebSocketChannel.connect('ws://192.168.0.6:8000/');
#override
void initState() {
super.initState();
controller = CameraController(cameras[1], ResolutionPreset.low);
controller.initialize().then((_) async{
await controller.startImageStream((onAvailable) {
sd(onAvailable);
});
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
void sd(onAvailable) {
var framesY = onAvailable.planes[0].bytes;
List<int> gzipBytes = new GZipEncoder().encode(framesY);
String compressedString = base64Encode(gzipBytes);
channel.sink.add(compressedString);
}
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return new Scaffold(
body: new Container(
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
),
),
);
}
}

Show running clock on flutter

I wanted to know if there is any way to show a real time clock in dart?
Date and time (e.g 11/14/2018 19:34) and the time will continue to run.
Time can be taken from the device itself.
The below uses the intl plugin to format the time into MM/dd/yyyy hh:mm:ss. Make sure to update your pubspec.yaml.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Time Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Time Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _timeString;
#override
void initState() {
_timeString = _formatDateTime(DateTime.now());
Timer.periodic(Duration(seconds: 1), (Timer t) => _getTime());
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text(_timeString),
),
);
}
void _getTime() {
final DateTime now = DateTime.now();
final String formattedDateTime = _formatDateTime(now);
setState(() {
_timeString = formattedDateTime;
});
}
String _formatDateTime(DateTime dateTime) {
return DateFormat('MM/dd/yyyy hh:mm:ss').format(dateTime);
}
}
Simplest solution:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class ClockWidget extends StatelessWidget {
const ClockWidget({super.key});
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: Stream.periodic(const Duration(seconds: 1)),
builder: (context, snapshot) {
return Text(DateFormat('MM/dd/yyyy hh:mm:ss').format(DateTime.now()));
},
);
}
}
Put it anywhere you like.
This is the same code which Albert had given, but in case you don't want to use the intl package, you can make these changes to this code:
import 'package:flutter/material.dart';
import 'dart:async';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.red),
home: FlutterTimeDemo(),
);
}
}
class FlutterTimeDemo extends StatefulWidget{
#override
_FlutterTimeDemoState createState()=> _FlutterTimeDemoState();
}
class _FlutterTimeDemoState extends State<FlutterTimeDemo>
{
String _timeString;
#override
void initState(){
_timeString = "${DateTime.now().hour} : ${DateTime.now().minute} :${DateTime.now().second}";
Timer.periodic(Duration(seconds:1), (Timer t)=>_getCurrentTime());
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Fluter Test'),),
body:Center(
child: Text(_timeString, style: TextStyle(fontSize: 30),),
),
);
}
void _getCurrentTime() {
setState(() {
_timeString = "${DateTime.now().hour} : ${DateTime.now().minute} :${DateTime.now().second}";
});
}
}

Categories

Resources