My login screen doesn't redirect me to the new screen after I successfully login in flutter - flutter

when I try to login it doesn't redirect me to my authenticated page(the state doesn't update) but it stays as it is, it redirects me only after I hot restart the app. I don't know what is wrong with my code.I control the user =null in landing page but landingPage cant return home page.
this is Landing Page
import '/material.dart';
import '/provider.dart';
import '/login-directory/home_page.dart';
import '/login-directory/sign_in_page.dart';
import '/model/user_model.dart' as usr;
import '/viewmodel/viewusermodel.dart';
class LandingPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final _userModel = Provider.of<UserModel>(context,listen: false);
if (_userModel.state == ViewState.Idle) {
if (_userModel.user == null) {
return SignInPage();//user==null
} else {
return HomePage(user: _userModel.user as usr.User);
}
}
else {
return Scaffold(
body: Center(child: CircularProgressIndicator(),),
);
}
}
}
this is User Repository:
import '/locator.dart';
import '/model/user_model.dart';
import '/services/auth_base.dart';
import '/services/fake_auth_service.dart';
import '/services/firebase_auth_service.dart';
enum AppMode{DEBUG,RELEASE}
class UserRepository implements AuthBase {
FirebaseAuthService _firebaseAuthService = locator<FirebaseAuthService>();
final FakeAuthService _fakeAuthService = locator<FakeAuthService>();
AppMode appMode = AppMode.RELEASE;
#override
Future<User?> currentUser() async {
if (appMode == AppMode.DEBUG) {
return await _fakeAuthService.currentUser();
}
else {
return await _firebaseAuthService.currentUser();
}
}
#override
Future<bool> logOut() async {
if (appMode == AppMode.DEBUG) {
return await _fakeAuthService.logOut();
}
else {
return await _firebaseAuthService.logOut();
}
}
#override
Future<User?> singInAnonymously() async {
if (appMode == AppMode.DEBUG) {
return await _fakeAuthService.singInAnonymously();
}
else {
return await _firebaseAuthService.singInAnonymously();
}
}
#override
Future<User?> signInWithGoogle() async {
if (appMode == AppMode.DEBUG) {
return await _fakeAuthService.singInAnonymously();
}
else {
return await _firebaseAuthService.signInWithGoogle();
}
}
}
Authbase :
abstract class AuthBase{
Future<User?> currentUser();
Future<User?> singInAnonymously();
Future<bool> logOut();
Future<User?> signInWithGoogle();
}
ViewUserModel:
import 'package:flutter/material.dart';
import 'package:/locator.dart';
import 'package:/model/user_model.dart' as usr;
import 'package:/repository/user_repository.dart';
import 'package:/services/auth_base.dart';
enum ViewState{Idle,Busy}
class UserModel with ChangeNotifier implements AuthBase {
ViewState _state = ViewState.Idle;
final UserRepository _userRepository = locator<UserRepository>();
usr.User? _user;
usr.User? get user =>_user;
ViewState get state => _state;
set state(ViewState value) {
_state = value;
notifyListeners(); //
}
UserModel(){
currentUser();
}
#override
Future<usr.User?> currentUser() async {
try {
state = ViewState
.Busy; //kullanıcı verisi cekilirken ekran verisini guncelliyorum
_user = (await _userRepository.currentUser())!;
return _user;
} catch (e) {
debugPrint("ViewModel currentUser is error $e" );
return null;
} finally {
state = ViewState.Idle;
}
}
#override
Future<bool> logOut() async {
try {
state = ViewState.Busy;
bool result =await _userRepository.logOut();
_user= null;
return result;
} catch (e) {
debugPrint("ViewModel currentUser is error $e" );
return false;
} finally {
state = ViewState.Idle;
}
}
#override
Future<usr.User?> singInAnonymously() async {
try {
state = ViewState
.Busy;
_user = (await _userRepository.singInAnonymously())!;
return _user;
} catch (e) {
debugPrint("ViewModel currentUser is error $e");
return null;
} finally {
state = ViewState.Idle;
}
}
#override
Future<usr.User?> signInWithGoogle() async {
try {
state = ViewState
.Busy;
_user = (await _userRepository.signInWithGoogle())!;
return _user;
} catch (e) {
debugPrint("ViewModel currentUser is error $e");
return null;
} finally {
state = ViewState.Idle;
}
}
}
GetIt locator:
GetIt locator=GetIt.instance;
void setupLocator(){
locator.registerLazySingleton(() => FirebaseAuthService());
locator.registerLazySingleton(() => UserRepository());
}
this is main.dart:
import '/viewmodel/viewusermodel.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();;
await Firebase.initializeApp();
setupLocator();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title:'Title',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch:Colors.purple,
),
home:ChangeNotifierProvider(
create:(context)=>UserModel(),
child: LandingPage()),
);
}
}

Related

how to mock firebase_messaging in flutter?

Hello im trying to mock firebase messaging to get token but when i try to test i get some error,can someone help me to solve this error. This error occur only in testing and not in my emulator or mobile phone. Here is my setupFirebaseAuthMocks. Thank you
my test
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
void main() {
setupFirebaseAuthMocks();
late ProviderContainer container;
group('AuthenticationControllerTest -', () {
setUpAll(() async {
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
registerThirdPartyServices();
});
tearDown(() {
unregisterThirdPartyServices();
//container.dispose();
});
});
Error
MissingPluginException(No implementation found for method Messaging#getToken on channel plugins.flutter.io/firebase_messaging)
here is the method im trying to call
Future<Result<Failure, bool>> registerUserFirebaseToken() async {
try {
log.i('Registering Firebase');
final fireBaseMessaging = FirebaseMessaging.instance;
final token = await fireBaseMessaging.getToken();
log.v('Firebase token: $token');
await api.post(
link: '${env.getValue(kAuthUrl)}users/auth/firebase',
body: {'token': token},
hasHeader: true,
);
return const Success(true);
} catch (e) {
return Error(Failure(message: 'Firebase registration went wrong, Please try again!', content: e.toString()));
}
}
For those having the same issue, there is an example of a Mock on the official firebase messaging Github
Depending on your Mockito's version, you may have to update this code a little bit.
Here is the Mock file I'm using with Mockito v5.3.2
// ignore_for_file: require_trailing_commas
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
import 'package:firebase_messaging_platform_interface/firebase_messaging_platform_interface.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
typedef Callback = Function(MethodCall call);
final MockFirebaseMessaging kMockMessagingPlatform = MockFirebaseMessaging();
Future<T> neverEndingFuture<T>() async {
// ignore: literal_only_boolean_expressions
while (true) {
await Future.delayed(const Duration(minutes: 5));
}
}
void setupFirebaseMessagingMocks() {
TestWidgetsFlutterBinding.ensureInitialized();
setupFirebaseCoreMocks();
// Mock Platform Interface Methods
// ignore: invalid_use_of_protected_member
when(kMockMessagingPlatform.delegateFor(app: anyNamed('app')))
.thenReturn(kMockMessagingPlatform);
// ignore: invalid_use_of_protected_member
when(kMockMessagingPlatform.setInitialValues(
isAutoInitEnabled: anyNamed('isAutoInitEnabled'),
)).thenReturn(kMockMessagingPlatform);
}
// Platform Interface Mock Classes
// FirebaseMessagingPlatform Mock
class MockFirebaseMessaging extends Mock
with MockPlatformInterfaceMixin
implements FirebaseMessagingPlatform {
MockFirebaseMessaging() {
TestFirebaseMessagingPlatform();
}
#override
bool get isAutoInitEnabled {
return super.noSuchMethod(Invocation.getter(#isAutoInitEnabled),
returnValue: true, returnValueForMissingStub: true) as bool;
}
#override
FirebaseMessagingPlatform delegateFor({FirebaseApp? app}) {
return super.noSuchMethod(
Invocation.method(#delegateFor, [], {#app: app}),
returnValue: TestFirebaseMessagingPlatform(),
returnValueForMissingStub: TestFirebaseMessagingPlatform(),
) as FirebaseMessagingPlatform;
}
#override
FirebaseMessagingPlatform setInitialValues({bool? isAutoInitEnabled}) {
return super.noSuchMethod(
Invocation.method(
#setInitialValues, [], {#isAutoInitEnabled: isAutoInitEnabled}),
returnValue: TestFirebaseMessagingPlatform(),
returnValueForMissingStub: TestFirebaseMessagingPlatform(),
) as FirebaseMessagingPlatform;
}
#override
Future<RemoteMessage?> getInitialMessage() {
return super.noSuchMethod(Invocation.method(#getInitialMessage, []),
returnValue: neverEndingFuture<RemoteMessage>(),
returnValueForMissingStub: neverEndingFuture<RemoteMessage>())
as Future<RemoteMessage?>;
}
#override
Future<void> deleteToken() {
return super.noSuchMethod(Invocation.method(#deleteToken, []),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as Future<void>;
}
#override
Future<String?> getAPNSToken() {
return super.noSuchMethod(Invocation.method(#getAPNSToken, []),
returnValue: Future<String>.value(''),
returnValueForMissingStub: Future<String>.value('')) as Future<String?>;
}
#override
Future<String> getToken({String? vapidKey}) {
return super.noSuchMethod(
Invocation.method(#getToken, [], {#vapidKey: vapidKey}),
returnValue: Future<String>.value(''),
returnValueForMissingStub: Future<String>.value('')) as Future<String>;
}
#override
Future<void> setAutoInitEnabled(bool? enabled) {
return super.noSuchMethod(Invocation.method(#setAutoInitEnabled, [enabled]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as Future<void>;
}
#override
Stream<String> get onTokenRefresh {
return super.noSuchMethod(
Invocation.getter(#onTokenRefresh),
returnValue: const Stream<String>.empty(),
returnValueForMissingStub: const Stream<String>.empty(),
) as Stream<String>;
}
#override
Future<NotificationSettings> requestPermission(
{bool? alert = true,
bool? announcement = false,
bool? badge = true,
bool? carPlay = false,
bool? criticalAlert = false,
bool? provisional = false,
bool? sound = true}) {
return super.noSuchMethod(
Invocation.method(#requestPermission, [], {
#alert: alert,
#announcement: announcement,
#badge: badge,
#carPlay: carPlay,
#criticalAlert: criticalAlert,
#provisional: provisional,
#sound: sound
}),
returnValue: neverEndingFuture<NotificationSettings>(),
returnValueForMissingStub:
neverEndingFuture<NotificationSettings>())
as Future<NotificationSettings>;
}
#override
Future<void> subscribeToTopic(String? topic) {
return super.noSuchMethod(Invocation.method(#subscribeToTopic, [topic]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as Future<void>;
}
#override
Future<void> unsubscribeFromTopic(String? topic) {
return super.noSuchMethod(Invocation.method(#unsubscribeFromTopic, [topic]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as Future<void>;
}
}
class TestFirebaseMessagingPlatform extends FirebaseMessagingPlatform {
TestFirebaseMessagingPlatform() : super();
}
and here is the unit test itself
void main() {
setupFirebaseMessagingMocks();
setUpAll(() async {
await Firebase.initializeApp();
FirebaseMessagingPlatform.instance = kMockMessagingPlatform;
});
test('An example of test', () {
//...
when(kMockMessagingPlatform.getToken(vapidKey: anyNamed('vapidKey')))
.thenAnswer(
(_) => Future.value('DEVICE_ID'),
);
//...
});
}

Succeeding Bloc are not working after latest Bloc migration

I am using a MultiBlocProvider which is working for all Bloc before I migrate it to v8.0.1. Now, only the first Bloc (SignInBloc) is working.
This is on my main.dart
return MultiBlocProvider(
providers: [
BlocProvider<SignInBloc>(
create: (context) => SignInBloc(
authenticationRepository: authenticationRepository,
userDataRepository: userDataRepository,
),
),
BlocProvider<SignUpBloc>(
create: (context) => SignUpBloc(
authenticationRepository: authenticationRepository,
userDataRepository: userDataRepository,
),
),
Edit: here is my SignInBloc
SignInBloc(
{required this.authenticationRepository,
required this.userDataRepository})
: super(SignInInitialState()) {
on<CheckIfSignedInEvent>(mapCheckIfSignedInEventToState);
}
Future<void> mapCheckIfSignedInEventToState(
CheckIfSignedInEvent event,
Emitter<SignInState> emit,
) async {
try {
bool isSignedIn = await authenticationRepository.checkIfSignedIn();
if (isSignedIn) {
emit(CheckIfSignedInEventCompletedState(true));
} else {
emit(CheckIfSignedInEventCompletedState(false));
}
} catch (e) {
print(e);
emit(CheckIfSignedInEventFailedState());
}
}
I am not sure what to show but here is my SignUpBloc which is similar to my SignInBloc
SignUpBloc(
{required this.authenticationRepository,
required this.userDataRepository})
: super(SignUpInitialState()) {
on<SignUpWithGoogle>(mapSignUpWithGoogleEventToState);
}
Stream<SignUpState> mapSignUpWithGoogleEventToState(
SignUpWithGoogle event,
Emitter<SignUpState> emit,
) async* {
emit(SignUpInProgressState());
try {
User? checkUser = await authenticationRepository.checkIfUserExists();
if (checkUser != null) {
emit(SignUpWithGoogleInitialExistState());
} else {
bool checkDup =
await authenticationRepository.checkIfUserDup(event.name);
if (checkDup == true) {
emit(SignUpWithNameExistState());
} else {
User firebaseUser = await authenticationRepository.signUpWithGoogle();
emit(SignUpWithGoogleInitialCompletedState(firebaseUser));
}
}
} catch (e) {
print(e);
emit(SignUpWithGoogleInitialFailedState());
}
}
My main.dart will call the splash screen which has the declaration of the bloc
late SignInBloc signInBloc;
late SignUpBloc signupBloc;
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
signInBloc = BlocProvider.of<SignInBloc>(context);
signupBloc = BlocProvider.of<SignUpBloc>(context);
What I tried to do it to put alot of Print statement in order to check which part is getting called but I don't get why the SignUpBloc is not getting called anymore. Please help. Thanks!
Edit: I tried to debug.
This will trigger my SignInBloc. I'm able to listen to my SignInBloc.
signInBloc.add(CheckIfSignedInEvent());
This should trigger my SignUpBloc. But it doesn't do anything similar to my SignInBloc.
signupBloc.add(SignUpWithGoogle(name: selectedName));
Here's both of my events for comparison:
class CheckIfSignedInEvent extends SignInEvent {
#override
String toString() => 'CheckIfSignedInEvent';
}
class SignUpWithGoogle extends SignUpEvent {
final String name;
SignUpWithGoogle({required this.name});
#override
String toString() => 'SignUpWithGoogleEvent';
}
This is the part where I listen to the states which is both in my splash screen. Only signInBloc is able to listen.
signupBloc.stream.listen((state) {
print('BLOC: signupBloc splash screen init : $state');
});
signInBloc.stream.listen((state) {
print('BLOC: signinBloc splash screen init : $state');
});
It turns out that changing the Stream to Future will fix my issue. async* should also be changed to async
Future<void> mapSignUpWithGoogleEventToState(
SignUpWithGoogle event,
Emitter<SignUpState> emit,
) async {
emit(SignUpInProgressState());
try {
User? checkUser = await authenticationRepository.checkIfUserExists();
if (checkUser != null) {
emit(SignUpWithGoogleInitialExistState());
} else {
bool checkDup =
await authenticationRepository.checkIfUserDup(event.name);
if (checkDup == true) {
emit(SignUpWithNameExistState());
} else {
User firebaseUser = await authenticationRepository.signUpWithGoogle();
emit(SignUpWithGoogleInitialCompletedState(firebaseUser));
}
}
} catch (e) {
print(e);
emit(SignUpWithGoogleInitialFailedState());
}
}

Flutter Pusher Websocket package not working

I have a backend Laravel application that uses Pusher for notifications. I would like to show notifications in my Flutter app (both iOS and Android). I found that https://pub.dev/packages/pusher_websocket_flutter/ package has the best score, but I can't get it to work. I've followed this tutorial, and I get no errors (whatever I put for my APP_KEY, which must be wrong), but I never get anything shown.
Has anyone managed to get this working, or should I switch to firebase?
This is my pusher_service.dart:
import 'package:flutter/services.dart';
import 'package:pusher_websocket_flutter/pusher.dart';
import 'dart:async';
class PusherService {
Event lastEvent;
String lastConnectionState;
Channel channel;
StreamController<String> _eventData = StreamController<String>();
Sink get _inEventData => _eventData.sink;
Stream get eventStream => _eventData.stream;
Future<void> initPusher() async {
try {
await Pusher.init('XXX', PusherOptions(cluster: 'XX'), enableLogging: true);
print("Pusher initialized");
}
on PlatformException catch (e) {
print(e.message);
}
}
void connectPusher() {
Pusher.connect(
onConnectionStateChange: (ConnectionStateChange connectionState) async {
lastConnectionState = connectionState.currentState;
print("Pusher connected");
}, onError: (ConnectionError e) {
print("Error: ${e.message}");
});
}
Future<void> subscribePusher(String channelName) async {
channel = await Pusher.subscribe(channelName);
print("Pusher subscribed to channel");
}
void unSubscribePusher(String channelName) {
Pusher.unsubscribe(channelName);
}
void bindEvent(String eventName) {
channel.bind(eventName, (last) {
final String data = last.data;
_inEventData.add(data);
});
print("Pusher data binded");
}
void unbindEvent(String eventName) {
channel.unbind(eventName);
_eventData.close();
}
Future<void> firePusher(String channelName, String eventName) async {
await initPusher();
connectPusher();
await subscribePusher(channelName);
bindEvent(eventName);
}
}
My pusher_test.dart:
import 'package:flutter/material.dart';
import 'package:chalet/services/pusher_service.dart';
import 'package:pusher/pusher.dart';
import 'dart:async';
class PusherTest extends StatefulWidget {
#override
_PusherTestState createState() => _PusherTestState();
}
class _PusherTestState extends State<PusherTest> {
PusherService pusherService = PusherService();
#override
void initState() {
pusherService = PusherService();
pusherService.firePusher('public', 'create');
testPusher();
super.initState();
}
#override
void dispose() {
pusherService.unbindEvent('create');
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: StreamBuilder(
stream: pusherService.eventStream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return Container(
child: Text(snapshot.data),
);
},
),
),
);
}
}
I've checked and my snapshot.connectionState is always waiting.
Try this:
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:pusher_client/pusher_client.dart';
//instantiate Pusher Class
class PusherController {
static final PusherController _pusherController =
PusherController._internal();
factory PusherController() {
return _pusherController;
}
PusherController._internal();
PusherClient pusher;
Channel channel;
StreamController<String> _eventData = StreamController<String>.broadcast();
Sink get _inEventData => _eventData.sink;
Stream get eventStream => _eventData.stream;
String channelName = "";
String prevChannelName = "";
String eventName = "";
void initPusher() {
PusherOptions options = PusherOptions(
cluster: "eu",
);
pusher = new PusherClient("key", options,
autoConnect: true, enableLogging: true);
}
void setChannelName(String name) {
channelName = name;
print("channelName: ${channelName}");
}
void setEventName(String name) {
eventName = name;
print("eventName: ${eventName}");
}
void subscribePusher() {
channel = pusher.subscribe(channelName);
pusher.onConnectionStateChange((state) {
log("previousState: ${state.previousState}, currentState: ${state.currentState}");
});
pusher.onConnectionError((error) {
log("error: ${error.message}");
});
//Bind to listen for events called and sent to channel
channel.bind(eventName, (PusherEvent event) {
print("xxxxxxxxx From pusher xxxxxxxxx");
print('xxxxx This is Event name - $eventName xxxx');
print('xxxxx This is Event gotten - ${event.data} xxx');
_inEventData.add(event.data);
prevChannelName = eventName;
});
}
void connectPusher() {
pusher.connect();
}
void disconnectPusher() async {
await channel.unbind(eventName);
await pusher.disconnect();
}
}
Then use streamBuilder and stream from evenStream.

How to correctly save the value in sharedPreferences? - Flutter

Where am I going wrong?
I have login with google to get the token and send it to graphgl, this token is saved (it was meant to be) in sharedpreferences, but it is not saving, I have the following action (mobx).
#action
Future loginWithGoogle() async {
user = await _authRepository.getGoogleLogin();
final idToken = await user.getIdToken();
print('Bearer ${idToken.token}');
sharedPreferenceService.setToken('Bearer ${idToken.token}');
}
Services shared.
class SharedPreferenceService {
SharedPreferences _prefs;
Future<bool> getSharedPreferencesInstance() async {
_prefs = await SharedPreferences.getInstance().catchError((e) {
print("shared prefrences error : $e");
return false;
});
return true;
}
Future setToken(String token) async {
await _prefs.setString('token', token);
}
Future clearToken() async {
await _prefs.clear();
}
Future<String> get token async => _prefs.getString('token');
}
SharedPreferenceService sharedPreferenceService = SharedPreferenceService();
Action login in view.
#action
Future loginWithGoogle() async {
try {
loading = true;
await auth.loginWithGoogle();
Modular.to.pushReplacementNamed('/index');
} catch (e) {
loading = false;
}
}
The login happens normal but it accuses error when it goes to index, informing that it received null the getString("token").
I/flutter ( 3198): ClientException: Unhandled Failure NoSuchMethodError: The method 'getString' was called on null.
I/flutter ( 3198): Receiver: null
I/flutter ( 3198): Tried calling: getString("token")
This token string is not being saved.
Sorry for bad english
Just copied your code and made some changes just check:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
SharedPreferenceService sharedPreferenceService = SharedPreferenceService();
#override
void initState() {
super.initState();
loginWithGoogle();
getSharedValues();
}
getSharedValues() async{
bool value = await sharedPreferenceService.getSharedPreferencesInstance();
if(value)
print(await sharedPreferenceService.token);
}
loginWithGoogle() async {
// this is the where you get your bearer, but time being I have taken sample bearer
String token =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJZb3VuaXNaYXJnYXIiLCJlbWFpbCI6InlvdW5pc0BiYXh0dXJlLmNvbSIsImp0aSI6IjlhNjc2OTVlLTBiZmEtNDdmMy04ZTVlLWVhYWMzY2VmNmRlOSIsIklkIjoiMSIsIkVtYWlsIjoieW91bmlzQGJheHR1cmUuY29tIiwiZXhwIjoxNTgzODQ2ODU0LCJpc3MiOiJQYWNpZmljIFByaW50aW5nIiwiYXVkIjoiUGFjaWZpYyBQcmludGluZyJ9.CKxBwAB7YeOKJRmoCg4_JAhJKHP2qXb7KJXPysqmbAs';
bool value = await sharedPreferenceService.getSharedPreferencesInstance();
if (value == true) {
sharedPreferenceService.setToken('Bearer $token');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(body: Center(child: Text('sample'))));
}
}
class SharedPreferenceService {
SharedPreferences _prefs;
Future<bool> getSharedPreferencesInstance() async {
_prefs = await SharedPreferences.getInstance().catchError((e) {
print("shared prefrences error : $e");
return false;
});
return true;
}
Future setToken(String token) async {
await _prefs.setString('token', token);
}
Future clearToken() async {
await _prefs.clear();
}
Future<String> get token async => _prefs.getString('token');
}
Thank you very much, I made the correction in the action.
#action
Future loginWithGoogle() async {
user = await _authRepository.getGoogleLogin();
final idToken = await user.getIdToken();
print('Bearer ${idToken.token}');
bool value = await sharedPreferenceService.getSharedPreferencesInstance();
if (value == true) {
sharedPreferenceService.setToken('Bearer ${idToken.token}');
}
}

Signing out of flutter app with sqflite database

I am trying to write the code for signing out of a flutter app logging in (The database of the map is made with sqflite).
However I am getting the following error message:
flutter: NoSuchMethodError: The method 'notify' was called on null.
Receiver: null
Tried calling: notify(Instance of 'AuthState')
Have provided code of required files below.
I am trying to incorporate a sign out function in the home_screen.dart file but I feel I am missing a link between the auth.dart, auth_provider.dart, login_screen.dart and home_screen.dart files. The codes of the required files for the issue are as follows:
File: database_helper.dart
import 'dart:async';
import 'dart:io' as io;
import 'package:path/path.dart';
import 'package:better_login/user.dart';
import 'package:sqflite/sqflite.dart' ;
import 'package:path_provider/path_provider.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = new
DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
static Database _db;
Future<Database> get db async {
if(_db != null)
return _db;
_db = await initDb();
return _db;
}
DatabaseHelper.internal();
initDb() async {
io.Directory documentsDirectory = await
getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "main.db");
var theDb = await openDatabase(path, version: 1, onCreate:
_onCreate);
return theDb;
}
void _onCreate(Database db, int version) async {
// When creating the db, create the table
await db.execute(
"CREATE TABLE User(username TEXT,password TEXT)");
print("Created tables");
}
Future<int> saveUser(User user) async {
var dbClient = await db;
int res = await dbClient.insert("User", user.toMap());
return res;
}
Future<int> deleteUsers() async {
var dbClient = await db;
int res = await dbClient.delete("User");
return res;
}
Future<bool> isLoggedIn() async {
var dbClient = await db;
var res = await dbClient.query("User");
return res.length > 0? true: false;
}
}
File:auth.dart
import 'package:better_login/database_helper.dart';
enum AuthState{ LOGGED_IN, LOGGED_OUT }
abstract class AuthStateListener {
void onAuthStateChanged(AuthState state);
}
class AuthStateProvider {
static final AuthStateProvider _instance = new
AuthStateProvider.internal();
List<AuthStateListener> _subscribers;
factory AuthStateProvider() => _instance;
AuthStateProvider.internal() {
_subscribers = new List<AuthStateListener>();
initState();
}
void initState() async {
var db = new DatabaseHelper();
var isLoggedIn = await db.isLoggedIn();
if(isLoggedIn)
notify(AuthState.LOGGED_IN);
else
notify(AuthState.LOGGED_OUT);
}
void subscribe(AuthStateListener listener) {
_subscribers.add(listener);
}
void dispose(AuthStateListener listener) {
for(var l in _subscribers) {
if(l == listener)
_subscribers.remove(l);
}
}
void notify(AuthState state) {
_subscribers.forEach((AuthStateListener s) =>
s.onAuthStateChanged(state));
}
}
File: auth_provider.dart
import 'package:flutter/material.dart';
import 'package:better_login/auth.dart';
class AuthProvider extends InheritedWidget {
const AuthProvider({Key key, Widget child, this.auth}) : super(key: key, child: child);
final AuthStateListener auth;
#override
bool updateShouldNotify(InheritedWidget oldWidget) => true;
static AuthProvider of(BuildContext context) {
return context.inheritFromWidgetOfExactType(AuthProvider);
}
}
File: home_screen.dart
import 'package:flutter/material.dart';
import 'package:better_login/auth.dart';
import 'package:better_login/login_screen.dart';
import 'package:better_login/login_screen_presenter.dart';
import 'package:better_login/auth_provider.dart';
class HomeScreen extends StatelessWidget {
HomeScreen({this.authStateListener, this.authStateProvider});
final AuthStateListener authStateListener;
final AuthStateProvider authStateProvider;
void _signOut() async {
try{
authStateProvider.notify(AuthState.LOGGED_OUT);
authStateListener.onAuthStateChanged(AuthState.LOGGED_OUT);
}catch(e){
print(e);
}
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: new AppBar(
title: new Text("Home"),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.exit_to_app), onPressed: (){_signOut();}),
],
),
body: new Center(
child: new Text("Welcome home!"),
),
);
}
}