I have created a small Flutter app, which includes firebase auth and database. I want to deploy it with firebase hosting and did all the necessary steps, but it is still not working. The webside is just empty or MAYBE waiting for something (not sure about that).
firebase login
firebase init
added "site": "xxxxxxxxxxx-d1d99" to my firebase.json file
added js sdks to index.html:
<script src="/__/firebase/8.3.2/firebase-auth.js"></script>
<script src="/__/firebase/8.3.2/firebase-database.js"></script>
firebase deploy
Also I have chosen the 'web' directory instead of 'build/web' as my public directory, because my flutter project creates the flutter create web there.
My main.dart looks like the following. Except from the MaterialApp(), it is completely the same as suggested by flutter/firebase on how to do it.
main.dart
import 'package:faschingsplaner/views/auth/authentication.dart';
import 'package:faschingsplaner/views/auth/root_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'views/add_carnival_view/add_carnival_view.dart';
import 'views/home_view/home_view.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// Set default `_initialized` and `_error` state to false
bool _initialized = false;
bool _error = false;
// final Future<FirebaseApp> _fbApp = Firebase.initializeApp();
// Define an async function to initialize FlutterFire
void initializeFlutterFire() async {
try {
await Firebase.initializeApp();
setState(() {
_initialized = true;
});
} catch(e) {
setState(() {
_error = true;
});
}
}
#override
void initState() {
initializeFlutterFire();
super.initState();
}
#override
Widget build(BuildContext context) {
if (_error) {
return Center(
child: Text('Error occured: $_error'),
);
}
if (!_initialized) {
return Center(
child: CircularProgressIndicator(),
);
}
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: [GlobalMaterialLocalizations.delegate],
supportedLocales: [
const Locale('de'),
],
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Color.fromRGBO(58, 66, 86, 1.0),
accentColor: Colors.blue),
initialRoute: '/authentication',
routes: {
RootPage.routeName: (context) => RootPage(auth: new Auth()),
HomeView.routeName: (context) => HomeView(),
AddView.routeName: (context) => AddView(),
});
}
}
At this point, I have totally no clue what could be wrong. Please consider that I am pretty new to flutter.
Related
I'm new to flutter and Dart currently, I'm using flutter 2.03 and trying to build a multi-language app using the easy_localization package (3.0.0). At first, everything was alright when I try to change the app language from the setting page or the first page which is shown one time, the app translates the content and stays on the same page but yesterday the app started reloading when I change the app locale :
onChanged: (newValue) async {
if (newValue == 'English') {
await context.setLocale(Locale('en'));
} else if (newValue == 'Français') {
await context.setLocale(Locale('fr'));
} else if (newValue == 'العربية') {
await context.setLocale(Locale('ar'));
}
},
All I want is to make the app make hot reload and translate the page and stay on the same screen without reloading the whole app and back to Home Screen.
Main.dart
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:sg_user_dash/screens/homescreen.dart';
import 'package:sg_user_dash/screens/language.dart';
import 'package:shared_preferences/shared_preferences.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(EasyLocalization(
supportedLocales: [Locale('en'), Locale('fr'), Locale('ar')],
path: 'assets/translations',
fallbackLocale: Locale('en'),
child: MyApp()));
}
Future<String> nextdisplay() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool _seen = (prefs.getBool('seen') ?? false);
if (_seen) {
return "Homepage";
} else {
await prefs.setBool('seen', true);
return "walkthrough";
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Smart Government',
theme: ThemeData(),
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
home: FutureBuilder(
future: nextdisplay(),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
if (snapshot.data == "walkthrough") {
return Language();
} else if (snapshot.data == "Homepage") {
return HomeScreen();
} else {
return Language();
}
}
return Center(
child: CupertinoActivityIndicator(),
);
}));
}
}
Thank you <3
I have a solution if someone needs to change locale on Android or IOs automatically from device settings.
Since changing the language usually requires changing the app with focus, your app will pause and resume when you return to it.
For this reason I have used the app life cycle as a listener to change the language, giving me good results.
(Check the docs for more info about App Lifecycle: Android | IOs).
Next I will show a simple example that could be useful to you.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
supportedLocales: const [
Locale('es'),
Locale('en'),
Locale('fr'),
Locale('pt'),
Locale('it'),
Locale('de'),
],
fallbackLocale: const Locale('en'),
path: 'res/assets/langs',
useOnlyLangCode: true,
child: const MyApp(),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(
LifecycleEventHandler(
resumeCallBack: () {
final locale = context.locale.toString();
// Get lang code only if not using country code.
final platformLocale = Platform.localeName.split("_")[0];
if(platformLocale != locale) {
// Select device lang or English if not supported.
final supportedLocale = getSuppLangOrEn(platformLocale);
context.setLocale(Locale(supportedLocale));
}
},
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
title: 'Localized App',
theme: theme,
home: const HomeScreen(),
initialRoute: HomeScreen.routeName,
routes: routes,
),
);
}
}
And the LifecycleEventHandler would look like this:
class LifecycleEventHandler extends WidgetsBindingObserver {
final VoidCallback? resumeCallBack;
final VoidCallback? suspendingCallBack;
LifecycleEventHandler({
this.resumeCallBack,
this.suspendingCallBack,
});
#override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
if (resumeCallBack != null) {
resumeCallBack!();
}
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
if (suspendingCallBack != null) {
suspendingCallBack!();
}
break;
}
}
}
Credits: LifecycleEventHandler code was taken from here.
easy_localization save the language when its change on runtime you don't need to save it again.
I have a video on how to use easy_localization I think it can be a help
https://www.youtube.com/watch?v=LS8KFYsR244
so sample add setState((){});
thats work for me, But I dont know why :)
onChanged: (newValue) async {
if (newValue == 'English') {
await context.setLocale(Locale('en'));
} else if (newValue == 'Français') {
await context.setLocale(Locale('fr'));
} else if (newValue == 'العربية') {
await context.setLocale(Locale('ar'));
}
setState((){});
},
I have a MultiProvider in the main with the following code:
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => ReadPreferences(),
),
ChangeNotifierProvider(
create: (context) => ItemsCrud(),
),
],
child: MaterialApp(...
I am using shared preferences to save and updated the last opened list, so the following in my ReadPreferences file:
import 'package:flutter/foundation.dart'; //To use the "ChangeNotifier"
import 'package:shared_preferences/shared_preferences.dart'; //local store
class ReadPreferences extends ChangeNotifier {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
String openedList = '';
//Constructor method
ReadPreferences() {
getPreferences();
}
void getPreferences() async {
final SharedPreferences prefs = await _prefs;
openedList = prefs.getString('openedList');
}
Future<bool> updateOpenedList({String listTitle}) async {
final SharedPreferences prefs = await _prefs;
bool result = await prefs.setString('openedList', listTitle);
if (result == true) {
openedList = listTitle;
}
notifyListeners();
return result;
}
}
When I'm trying to update the opened list it updates in the shared Preferences file normally but it never listen to the new "openedList" value in my homepage screen.
The code I use in the homepage screen like the following:
child: Text(Provider.of<ReadPreferences>(context).openedList),
I checked many times by printing the new value inside the "ReadPreferences" files, but outside it, it keeps give me the old value not the updated one at all.
I tested with a modified Flutter Counter (default app), everything seams to be working fine. Note that I'm not calling setState() anywhere, so the only refresh is coming from the ReadPreferences class.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ReadPreferences extends ChangeNotifier {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
String openedList = '';
//Constructor method
ReadPreferences() {
getPreferences();
}
void getPreferences() async {
final SharedPreferences prefs = await _prefs;
openedList = prefs.getString('openedList');
}
Future<bool> updateOpenedList({String listTitle}) async {
final SharedPreferences prefs = await _prefs;
bool result = await prefs.setString('openedList', listTitle);
if (result == true) {
openedList = listTitle;
}
notifyListeners();
return true;
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => ReadPreferences(),
)
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(Provider.of<ReadPreferences>(context).openedList)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_counter++;
Provider.of<ReadPreferences>(context, listen: false).updateOpenedList(listTitle: (_counter).toString());
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
I finally found the answer, many thanks for #Andrija explanation. What I was doing wrong is to create a new instance from ReadPreferences() then using it for the update method, but the correct approach is to use Provider.of<ReadPreferences>(context, listen: false).updateOpenedList(listTitle: list.title); to use the update method.
For more explanation I'll add #Andrija comment hereafter:-
You are right, you should be using Provider.of. When you add Provider using ChangeNotifierProvider(create: (context) => ReadPreferences(), ) - new instance of ReadPreferences() is created, and it is kept in WidgetTree. This is the instance you want, and you get it by using Provider.of. In your code above, you created a new instance of ReadPreferences - and this is where you added a new value. This new instance has nothing to do with the one that Provider manages, and this new instance has nothing to do with your Widget.
I'm trying to understand RiverPod by migrating my simple FireStore auth Provider example to RiverPod.
This is my AuthenticationService:
import 'package:firebase_auth/firebase_auth.dart';
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
// with StreamProvider we listen to these changes
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return 'Signed in';
} on FirebaseAuthException catch (e) {
return e.message;
}
}
Future<String> signUp({String email, String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return 'Signed up ';
} on FirebaseAuthException catch (e) {
return e.message;
}
}
Future<void> signOut() async {
await _firebaseAuth.signOut();
}
}
In main.dart I made 2 providers so I can use the service and listen to the property inside of the AuthenticationService
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:meditatie_app/authentication_service.dart';
import 'package:meditatie_app/home_page.dart';
import 'package:meditatie_app/signin_page.dart';
import 'package:provider/provider.dart';
Future<void> main() async {
// initalize Firebase and before that we need to initialize the widgets.
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
// Normal provider to serve the AuthenticationService in the widgettree
// so the login form can use this provider to use .singIn()
Provider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
// also a StreamProvider that serves the AuthenticationSerivce authStateChanges
// this stream is updated by the FirebaseAuth package when users signin or out
// this provider use context.read<AuthenticationService> to find the
// provider dived here above
StreamProvider(
create: (context) =>
context.read<AuthenticationService>().authStateChanges,
)
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AuthenticationWrapper(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}
Here the SingIn page:
import 'package:flutter/material.dart';
import 'package:meditatie_app/authentication_service.dart';
import 'package:provider/provider.dart';
class SignInPage extends StatelessWidget {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
...
RaisedButton(
onPressed: () {
// Sign in code
context.read<AuthenticationService>().signIn(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
},
...
This works fine with normal Provider, but I can't get it to work with RiverPod
What I did was:
These providers I made global in providers.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/all.dart';
import 'authentication_service.dart';
final authenticationSeriviceProvider =
Provider((ref) => AuthenticationService(FirebaseAuth.instance));
final authStateChangeProvider = StreamProvider.autoDispose<User>((ref) {
return ref
.watch(authenticationSeriviceProvider)
.authStateChanges;
});
Is this correct? The authStateChangeProvider is using the authenticationSeriviceProvider
When is use it like:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:meditatie_app/home_page.dart';
import 'package:meditatie_app/signin_page.dart';
import 'package:flutter_riverpod/all.dart';
import 'providers.dart';
Future<void> main() async {
// initialize Firebase and before that we need to initialize the widgets.
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
// riverpod needs at toplevel a Provider container
// for storing state of different providers.
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AuthenticationWrapper(),
);
}
}
// Riverpods ConsumerWidget
// which can consume a provider
// rebuild if the value of the provider changes
class AuthenticationWrapper extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final firebaseUser = watch(authStateChangeProvider);
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}
My 'firebaseUser' is not a User anymore, but an AsyncValue
When I change it to:
class AuthenticationWrapper extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final User firebaseUser = watch(authStateChangeProvider).data?.value;
if (firebaseUser != null) {
return HomePage();
}
return SignInPage();
}
}
It is working, but what am I doing wrong that I now work with AsyncValue
Expanding the previous answer AsyncValue<T> is a sealed class, think of it as StreamBuilder in Flutter having AsyncSnapshot<T> which wraps the value returned from the stream and gives you options to check if its connecting, waiting, withError or withData. In your case
class AuthenticationWrapper extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
return watch(authStateChangeProvider).when(
data: (user) => user == null ? SignInPage() : HomePage(),
loading: () => CircularProgressIndicator(),
error: (err, stack) => SignInPage(),
);
}
}
should handle all the options, now when loading it will show a progress indicator, if there is an error (connection, bad result, etc) it will display the SignInPage, and finally when there is a value you still will need to check if the value returned from the Stream is null (As far as I understand Firebase returns null when there is no user signed in, it doesn't mean the stream is empty) and display the right widget if its null or not.
Just like Provider, after retrieving the user you still have to do the logic with that
See the documentation.
You should use AsyncValue's exposed states to decide what to render. Your code could look something like the following:
class AuthenticationWrapper extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
return watch(authStateChangeProvider).when(
data: (user) => user == null ? SignInPage() : HomePage(),
loading: () => CircularProgressIndicator(),
error: (err, stack) => SignInPage(),
);
}
}
So adjust your return logic to what you'd like for the data, loading, and error states, but this should give you a general idea on how to use AsyncValue.
Another way I found was to use it the way this tutorial did, but with the new riverpod changes:
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_shopping_list/repositories/auth_repository.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final authControllerProvider = StateNotifierProvider<AuthController, User?>(
(ref) => AuthController(ref.read)..appStarted(),
);
class AuthController extends StateNotifier<User?> {
final Reader _read;
StreamSubscription<User?>? _authStateChangesSubscription;
AuthController(this._read) : super(null) {
_authStateChangesSubscription?.cancel();
_authStateChangesSubscription = _read(authRepositoryProvider)
.authStateChanges
.listen((user) => state = user);
}
#override
void dispose() {
_authStateChangesSubscription?.cancel();
super.dispose();
}
void appStarted() async {
final user = _read(authRepositoryProvider).getCurrentUser();
if (user == null) {
await _read(authRepositoryProvider).signInAnonymously();
}
}
}
And then I used it like this:
#override
Widget build(BuildContext context, WidgetRef ref) {
User? user = ref.watch<User?>(authControllerProvider);
return user != null
? MaterialApp(
title: 'My App',
builder: (context, child) => _Unfocus(child: child!),
home: MainNavigation(),
debugShowCheckedModeBanner: false,
)
: const MaterialApp(
title: 'My App,
home: LoginPage(),
debugShowCheckedModeBanner: false,
);
}
*this is my main.dart my problem is when I switch the language of the app I want the (Copy, Paste, etc.,) to be only English. for example, when I change it to the Arabic language I want the clipboard text (Copy, Paste, etc.,) to remain in the English language. i triend alot but not found any solution *
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:pir_zakat/screens/AboutUsScreen.dart';
import 'package:pir_zakat/screens/SettingScreen.dart';
import 'package:pir_zakat/screens/loading_screen.dart';
import 'localization/zakat_localization.dart';
import 'screens/first_part_screen.dart';
import 'screens/loading_screen.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:pir_zakat/Utilites/constants.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
static void setLocal(BuildContext context, Locale locale) {
_MyAppState state = context.findAncestorStateOfType<_MyAppState>();
state.setLocal(locale);
}
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = Locale('fa', 'IR');
void setLocal(Locale newLocal) {
setState(() {
_locale = newLocal;
print('new local is ${newLocal.languageCode}');
});
}
#override
void didChangeDependencies() {
getLocale().then((local) {
setState(() {
this._locale = local;
});
});
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
if (_locale == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return MaterialApp(
theme: ThemeData.dark().copyWith(
primaryColor: Color(0xFF0A0E21),
scaffoldBackgroundColor: Color(0xFF0A0E21),
),
debugShowCheckedModeBanner: false,
locale: Locale('de'),
localizationsDelegates: [
// ... app-specific localization delegate[s] here
ZakatLocalization.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('fa', 'IR'), // Hebrew
Locale('en', 'US'), // English
Locale('ar', 'SA'), // Hebrew
// ... other locales the app supports
],
localeResolutionCallback: (deviceLocale, supportedLocales) {
for (var local in supportedLocales) {
if (local.languageCode == deviceLocale.languageCode &&
local.countryCode == deviceLocale.countryCode) {
return deviceLocale;
}
}
return supportedLocales.first;
},
initialRoute: LoadingScreen.id,
routes: {
LoadingScreen.id: (context) => LoadingScreen(),
FirstPartScreen.id: (context) => FirstPartScreen(),
SettingString.id: (context) => SettingString(),
AboutUsScreen.id: (context) => AboutUsScreen(),
},
);
}
}
}
I prefer resting from all this effort and use ready made plugin like localize_and_translate
anyway, what you need is to use key for the main widget class and request a new one or something so you restart you app for everything to take effect in place and you need to add iOS delegates also
take a look at how the plugin source code manage things, and you should get it, it creates LocalizedApp class which includes restart method for requesting new key for main widget class within LocalizedApp and that gets the magic done
I'm trying to send a message via the IsolateNameServer in flutter.
However, I am unable to receive messages. I've tried checking if the receiver port is listening by calling port.listen() twice, and it says that it is already listening.
Where am I going wrong? [ I am closely following this documentation ]
Here is my main.dart, based on the above doc:
import 'dart:isolate';
import 'dart:math';
import 'dart:ui';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
final ReceivePort port = ReceivePort();
const String isolateName = 'isolate';
main() async {
WidgetsFlutterBinding.ensureInitialized();
IsolateNameServer.registerPortWithName(
port.sendPort,
isolateName,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
accentColor: Colors.pink,
floatingActionButtonTheme:
FloatingActionButtonThemeData(backgroundColor: Colors.pink)),
home: AlarmManagerExample());
}
}
class AlarmManagerExample extends StatefulWidget {
#override
_AlarmManagerExampleState createState() => _AlarmManagerExampleState();
}
class _AlarmManagerExampleState extends State<AlarmManagerExample> {
#override
void initState() {
super.initState();
AndroidAlarmManager.initialize();
port.listen((_) async => await workForMe());
}
workForMe() async {
print("Secondary Function Triggered!");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: RaisedButton(
onPressed: () async {
await AndroidAlarmManager.oneShot(const Duration(seconds: 5),
Random().nextInt(pow(2, 21)), callback);
},
child: Text(
"Alarm Manager",
),
),
),
);
}
static SendPort uiSendPort;
static callback() {
print("Callbacks Triggered!");
// This will be null if we're running in the background.
uiSendPort ??= IsolateNameServer.lookupPortByName(isolateName);
uiSendPort?.send(null);
}
}
The output I am getting is :
Callbacks Triggered!
However, the expected output is:
Callbacks Triggered!
Secondary Function Triggered!
I do believe that error is caused because the workForMe() function isn't static. Moreover, I don't know if callBacks support Future or async.
With that said, try this, as there is no need to make it async.
static void workForMe() {
print("Secondary Function Triggered!");
}