Arquitectura de Aplicaciones

1

Pasos para aprender Flutter Avanzado

2

¿Qué es una Arquitectura de software?

3

Tipos de Arquitecturas para Flutter

4

Arquitectura BLoC en Flutter

5

BLoC + Clean Architecture en Flutter

6

Estructurando nuestro proyecto utilizando la Arquitectura BLoC

7

Haciendo BLoC Singleton en Flutter

8

Aplicando Providers al Proyecto

Firebase y Flutter

9

Integrando Firebase Authentication, Cloud Firestore y Firebase Storage al proyecto

10

Integrando Firebase a Flutter para Android

11

Integrando Firebase a Flutter para iOS

12

Creación de Pantalla de Login con Flutter

13

Creando botones reutilizables en Flutter

14

Autenticación de Firebase con Google

15

Implementando Firebase Authentication en BLoC Pattern

16

Streams en Flutter

17

Manejando una sesión con Firebase Authentication y Flutter

18

Implementando Google SignOut en BLoC

19

Implementando Google SignOut en View

20

Monitoreando y validando la conexión al Sign con Google

21

Mostrando los datos de usuario de Google en la interfaz en Flutter

Cloud Firestore de Firebase en Flutter

22

¿Qué es Cloud Firestore de Firebase?

23

Analizando un modelo de datos no relacional

24

Creando un Modelo de datos en Cloud Firestore

25

Enviando datos a Cloud Firestore

26

Creando un Widget gradiente personalizado

27

Manejo de Desbordamiendo de Texto de Widget Text

28

Botón de Back en un Appbar en Flutter

29

Navegación entre pantallas en Flutter

30

Widget Text Appbar personalizado en Flutter

31

Widget TextField personalizado en Flutter

32

Creando una Safe Area para una interfaz que tiene un AppBar

33

Widget TextField con iconos en Flutter

34

Retocando el CardView

35

Mostrando imágenes en un CardView

36

Creando un botón de Submit en Flutter

37

Envío de datos de un fórmulario en Flutter

38

Subiendo datos a Firestore de Firebase

39

Formularios en Flutter

Acceso al Hardware con Flutter

40

Acceso a la cámara en Flutter

41

Librerías de acceso a Hardware en Flutter

Firebase Storage en Flutter

42

Qué es y cómo funciona Firebase Storage en Flutter

43

Subiendo una imagen a Firebase Storage desde Flutter

Querys avanzados en Cloud Firestore de Firebase en Flutter

44

Manejo de imágenes en Cloud Firestore

45

Cloud Firestore insertando referencias y arrays en la base de datos

46

Descargar imágenes de Firebase Storage y mostrarlas en Flutter

47

Procesando datos con BLoC Pattern

48

Trayendo datos de Cloud Firestore

49

Persistiendo datos de un usuario logueado

50

Aplicando Filtros en Cloud Firestore

51

Construyendo los Places en la pantalla de Home

52

Mostrando los Places en la pantalla de Home

53

Actualizando datos en tiempo real

54

Manejando la lógica de likes, como botón toggle.

55

Insertando y obteniendo referencias en datos de Firestore.

56

Usando el caché para cargar imágenes más rápido

57

StreamController, sink, add y StreamBuilder

Conclusiones

58

Conclusiones

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Avanzado de Flutter

Curso Avanzado de Flutter

Anahí Salgado Díaz de la Vega

Anahí Salgado Díaz de la Vega

Manejando una sesión con Firebase Authentication y Flutter

17/58
Recursos

Aquí puedes ver el repositorio.

Aportes 48

Preguntas 12

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Hola, para seguir avanzando en el curso
en file bloc_user.dart

Stream<User> streamFirebase = FirebaseAuth.instance.authStateChanges();
  Stream<User> get authStatus => streamFirebase;

Si, al final pruebas y da error como este “[core/no-app] No Firebase App ‘[DEFAULT]’ has been created - call Firebase.initializeApp()” debes hacer lo siguiente:

en file pubspec.yaml agregar firebase_core

firebase_core: ^0.5.0

y en file main.dart importar el package y modificar void main()

import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

así debería funcionar

En mi dispositivo cuando vuelvo a iniciar la aplicación aparece por un breve instante la pantalla de signIn.
Debuggeando el proyecto me di cuenta de que esto ocurre debido a que cuando el estado de la conexión esta en **waiting **la propiedad hasData del _snapshot _es false aunque el usuario se haya loggeado antes.
Por ello hice esta modificación para que mientras los datos cargan aparezca una pantalla de carga.

return StreamBuilder(
      stream: userBloc.getAuthStatus,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData) {
          return AppTrips();
        } else if (snapshot.hasError) {
          return Text("Ocurrio un error en la transmision de datos");
        } else if(snapshot.connectionState != ConnectionState.waiting) {
          return _signInScreen();
        }else{
          return Container(
            color: Colors.white,
            alignment: Alignment.center,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SizedBox(
                  height: 20,
                  width: 70,
                  child: CircularProgressIndicator(backgroundColor: Colors.cyan[400], )
                ),
                Container(
                  margin: EdgeInsets.only(top: 10),
                  child: Text("C a r g a n d o", style: TextStyle(color: Colors.blue[400], fontSize: 22, fontFamily: "Lato", decoration: TextDecoration.none)
                ),)
              ]
            ),
          );
        }
      },
    );```

Hola quisiera decirle a aquellas personas que si tienen un error, no se frustren o se desesperen llegando a abandonar el curso, recuerden que los errores son parte del proceso de aprendizaje y es bueno para uno mismo, ya que no soló aprendes a buscar y corregir el error; si no que aprendes a crecer como persona mejorando tu actitud, controlando tus emociones, etc… Por ejemplo les pongo mi caso, antes yo renegaba por que me salían errores y no encontraba como solucionarlo me frustraba y renegaba, pero entendí que es parte del proceso, ahora pienso, analizo y trato de solucionar mi código ya no me altero o reniego, en conclusión relájense, respiren, piensen y vuelvan a empezar o vayan a dormir un ratito y vuelvan a su proyecto. Saludos compañeros.

Hola! Espero que todos estén bien. A mi por lo menos me ha cosado llegar a esta parte y por loo que he visto a varios compañeros también, así que quería compartir mi código actualizado a la fecha (25/03/21)

Acá va el main.dart:

void main() async {
  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 BlocProvider(
      bloc: UserBloc(),
      child: MaterialApp(
        //Queremos exponer el bloc desde el widget más alto, que es este
        title: 'Hola mundo',
        theme: ThemeData(),
        home: SignInScreen(),
      ),
    );
  }
}

El bloc_user.dart:

class UserBloc implements Bloc {
  final authRepository = AuthRepository();
  //Flujo de datos -Streams
  //Stream - Firebase
  //StreamController

  Stream<User> streamFirebase = FirebaseAuth.instance.authStateChanges();
  //Quiero monitorear el estado de la sesion en la pantalla SignIn
  Stream<User> get authStatus => streamFirebase;

  //Casos de uso de la app
  //1. SignIn a la app con Google
  Future<User> signIn() => authRepository.signInFirebase();

  void dispose() {}
}

Y sign_in_screen.dart:

class SignInScreen extends StatefulWidget {
  @override
  _SignInScreenState createState() => _SignInScreenState();
}

class _SignInScreenState extends State<SignInScreen> {
  UserBloc userBloc;
  AsyncSnapshot snapshot;
  double screenWidth;

  @override
  Widget build(BuildContext context) {
    userBloc = BlocProvider.of(
        context); //Este bloc es de tipo singleton, lo instanciaremos a traves del provider. El context es el estado de la app

    return _handleCurrentSession();
  }

  //Aca creamos otro metodo que "maneje" el estado de la sesion
  Widget _handleCurrentSession() {
    return StreamBuilder(
        stream: userBloc.authStatus,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          //snapshot de aca contiene la data, el objeto user. Abajo se hace algo si no hay data de inicio de sesion
          if (!snapshot.hasData || snapshot.hasError) {
            return signInGoogleUi();
          } else {
            return PlatziTripsCupertino();
          }
        });
  }

  Widget signInGoogleUi() {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        //Porque tengo un fondo de pantalla y los botones sobre el
        children: [
          GradientBack(
            "",
            null, //Porque asi se llena la pantalla completa
          ),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                "Welcome\nThis is your Travel App",
                style: TextStyle(
                    fontSize: 37.0,
                    fontFamily: "Lato",
                    color: Colors.white,
                    fontWeight: FontWeight.bold),
              ),
              ButtonGreen(
                buttonText: "Login with Gmail",
                onPressed: () {
                  userBloc.signIn();
                },
                width: 300.0,
                height: 50.0,
              )
            ],
          )
        ],
      ),
    );
  }
}

Tuve que hacer algunos cambios en el pubspect.yaml, porque había que agregar la dependencia firebase_core para inicializar firebase como comentó algún compañero en su momento:

dependencies:
  flutter:
    sdk: flutter
  generic_bloc_provider: ^1.1.0
  firebase_auth: ^1.0.1
  google_sign_in: ^5.0.1
  firebase_storage: ^8.0.0
  cloud_firestore: ^1.0.2
  firebase_core: ^1.0.2

Y esos son todos los archivos que recuerdo haber cambiado. Ojala a alguien le sirva esto y nos funcione a todos el curso

No olviden agregar el SHA1 de Android debug.keystore porque a pesar de que dice que es opcional, si no lo hacen les traerá problemas como:

platformexception(sign_in failed com.google.android.gms.common.api.apiexception xxx, null)

bloc_user.dart al 7/nov/2021

import 'package:generic_bloc_provider/generic_bloc_provider.dart';
import 'package:trips/User/repository/auth_repository.dart';
import 'package:firebase_auth/firebase_auth.dart';

class UserBloc implements Bloc {

  final _auth_repository = AuthRepository();

  //Flujo de datos - Streams
  //Stream - Firebase
  //StreamController
  Stream<User?> streamFirebase = FirebaseAuth.instance.authStateChanges();
  Stream<User?> get authStatus => streamFirebase;



  //Casos uso
  //1. SignIn a la aplicación Google
  Future<UserCredential> signIn() {
    return _auth_repository.signInFirebase();
  }


  @override
  void dispose() {

  }
}

Hola comunidad
Deseo compartir mi experiencia con todos ustedes, en especial, con los futuros estudiantes; que como yo, van a lidiar con el código desactualizado de este curso.
Utilizando el código tal cual este era el error que encontraba al correr la aplicación:

E/flutter (10205): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found formethodinitonchannelplugins.flutter.io/google_sign_in)

Después de reinstalar incluso Android Studio 4.0.1 y descargar la versión más actualizada del SDK de Flutter (1.22.2) y mucho tiempo de investigación logré encontrar una forma de poder manejar la excepción al iniciar google_sign_in.

Básicamente en el archivo firebase_auth_api, debemos de validar si la variable googleSignInAccount es null o nó, seguidamente debemos obtener los credenciales mediante un tipo de variable AuthCredential y guardarlos en un tipo de variable AuthResult.

Con esto, finalmente podremos castear la variable tipo AuthResult en una nueva variable tipo FirebaseUser y así poder cumplir con el Future, cual está orientado para retornar una variable tipo FirebaseUser.

Dejo por acá el código de mi firebase_auth_api

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

class FirebaseAuthAPI {

  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn googleSignIn = GoogleSignIn();

  Future<FirebaseUser> signIn() async {
    GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();

    if(googleSignInAccount != null){
      GoogleSignInAuthentication googleSignInAuthentication =
      await googleSignInAccount.authentication;

      AuthCredential credential = GoogleAuthProvider.getCredential(
          idToken: googleSignInAuthentication.idToken,
          accessToken: googleSignInAuthentication.accessToken);

      AuthResult result = await _auth.signInWithCredential(credential);

      FirebaseUser user = (result) as FirebaseUser;
      return user;

    }
  }

}

Así, como las librerías que utilicé en mi pubspec.yaml

  generic_bloc_provider: ^1.0.9
  firebase_core: ^0.4.5
  firebase_auth: ^0.16.0
  google_sign_in: ^4.4.4
  cloud_firestore: ^0.13.7
  flutter_auth_buttons: ^0.10.0

Espero que este aporte pueda ayudar a orientar a futuros estudiantes, ya que en mi caso tuve que invertir una cantidad de tiempo absurda en entender el error y luego en encontrar una posible solución. Lamentablemente la documentación de google al respecto es muy escuálida y entiendo que para Platzi este tipo de detalles son difíciles de mantener ya que las actualizaciones son constantes.
Saludos

Hola, escribo por que al momento de hacer la prueba e iniciar sesión obtenía un una excepción un PlatformException(sign_in_failed… , específicamente, y la manera de solucionarlo fue que en la consola de firebase tuve que agregar el SHA1 y SHA256, si solo agregaba el SHA1 saltaba la excepción, espero que sirva este comentario y no tengan que perder tiempo buscando la solución 😉

Si han seguido todos los pasos tal cuál y no saben cuál es el error, prueben con autorizar las API:
https://console.developers.google.com/apis/credentials/consent
En iOS me salía el error pero en Android no, solo tenía que habilitar con el enlace de arriba.
Para que me deje guardar solo agregue cualquier url. Yo puse una de las que me salía en dominio autorizado y le agregué el http.

Es una pena que Platzi permita estas cosas. El curso en si es bueno. Pero hace dos años cuando lo sacaron. Ahora si lo intentas seguir no puedes porque esta desactualizado. Para el que se esta iniciando puede ser malo porque tiene que estar buscando solución por su cuenta, puede probar muchas posibles soluciones hasta que encuentre una que le sea útil. En este proceso el alumno puede aburrirse y pensar que le han timado.

Platzi presume de tener muchos cursos pero olvida que lo importante no es la cantidad sino la calidad. En Udemy puedes encontrar buenos cursos de Flutter. Puedes encontrar 1 curso de Dart y 2 de flutter de Fernando Herrera que es un gran profesional. Con lo que cuesta la suscripción de Platzi Expert puedes comprar muchos cursos en Udemy que también entregan certificados, tienen proyectos, tienen una comunidad de alumnos que comparten lo que saben y tienen algo muy importante. El profesor o algún colaborador de este responde a los mensajes y dudas de los alumnos. Los buenos cursos, como los del profesor que nombre antes, actualizan sus cursos, ya sea con videos o de manera escrita.

Solo es tener un control de calidad y añadir contenido actualizado aunque no sea en video. Al final estamos pagando para que otros alumnos nos resuelvan las dudas.

Hay contenido muy muy bueno pero otro no lo es tanto.

Yo estoy pagando Platzi especificamente para aprender Flutter, considero que Ann es super buena para ensenar por que aproveche al esperar a meterme a otros cursos de ella, pero en este especificamente creo que solo esta repasando lo que ella ya aprendio al hacer este proyecto, definitivamente aun no comprendo Bloc que es la Unica razon por la que estoy en Platzi.

Espero poder encontrar ayuda…

Hola la conexión fue exitosa y me muestra el nombre de usuario en consola, pero no me cambia de la pantalla de signIn. Me equivoqué en algo?

import 'package:flutter/material.dart';
import 'package:lavalo/gradient_back.dart';
import 'package:lavalo/widget/button_green.dart';
import 'package:lavalo/User/Bloc/bloc_user.dart';
import 'package:generic_bloc_provider/generic_bloc_provider.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:lavalo/platzi_trips.dart';

class SignIn extends StatefulWidget {
  @override
  _SignInState createState() => _SignInState();
}

class _SignInState extends State<SignIn> {

  UserBloc userBloc;

  @override
  Widget build(BuildContext context) {

    userBloc = BlocProvider.of(context);

    return _handleCurrentSession();
  }

  Widget _handleCurrentSession(){
    return StreamBuilder(
        stream: userBloc.authStatus,
        builder: (BuildContext context, AsyncSnapshot snapshot){
          if(snapshot.hasData || snapshot.hasError) {
            return signInGoogleUI();
          } else {
            return PlatziTrips();
          }
        },
    );
  }

  Widget signInGoogleUI() {


    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          GradientBack("", null),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text("Bienvenido \n Esta el la mejor app de lavanderia",
                style: TextStyle(
                    fontSize: 37.0,
                    fontFamily: "Lato",
                    color: Colors.white,
                    fontWeight: FontWeight.bold
                ),
              ),

              ButtonGreen(
                text: "Registrarme con Google",
                onPressed: (){

                  userBloc.signIn().then((FirebaseUser user) => print("El usuario es ${user.displayName}"));
                },
                width: 300.0,
                height: 50.0,
              )
            ],
          ),
        ],
      ),
    );
  }

}




Hola, en iOS no tuve problema, funcionó a la primera. Sin embargo, al momento de correr en Android, me pasó lo que a la mayoría (Exception SignIn de Google). Según algunos comentarios mencionaban que se debe tener instalado Google Play Services, pero al querer instalar no me cargaba, por lo que cambiando el dns de la siguiente manera me conecté a Internet (remplazar Pixel_2_API_28 por el nombre de tu avd):

emulator -avd Pixel_2_API_28 -dns-server 8.8.8.8

Una vez que la conexión estaba ok, instalé Google Play Services y funcionó correcto.

Es importante que esten el el projecto que firebase crea automáticamente en google cloud platform https://console.developers.google.com/apis/credentials/consent
y usar las urls de http://<id-project>.firebaseapp.com
y el id lo pueden obtener en las propiedades del proyecto

No se olviden de tener google play services instalado en el emulador o en el phone a la hora de utilizar el sigin con google.

Para solucionar el error 12500 en SignIn de Google hice lo siguiente:
en la consola de firebase ir a configuración -> usuarios y permisos -> configuración avanzada
Luego una vez en la consola cloud de google ir a Credenciales
y hacer lo siguiente:
completar los enlaces con el dominio: http://<id_project>.firebaseapp.com
ver ejemplo:
https://github.com/flutter/flutter/issues/33393

Hola, esta clase en particular es un punto muy critico dentro del programa, ya que a muchos de nosotros por un motivo X o Y nos genera una PlatformException(sign_in_failed, bla bla bla).

Sería muy bueno que entre todos compartieramos las experiencias para arreglar este error y ayudar a los demas a superar este bache

En mi caso particular, tenia el platformException(…12500), estoy intentando generar un nuevo keystore, actualizar el sha1 en Firebase, descargar el nuevo JSON y ahora tengo un platformException(…10).

Alguna idea que me puedan dar?

Les cuento!
esto aparecia al darle al boton de ingresar y la aplicacion paraba.
PlatformException (PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException:10: , null))

Buscando solucion. Resulta que hice mal el Sha-1 porque aunque me arrojo un codigo no es el codigo de java, agrego la imagen de como se debe hacer en windows por si alguien mas le ocurre

Al parecer si me hace el login porque me imprime en la consola el nombre del usuario, pero no cambia de pantallla, al hacer debug coloqué un punto de parada en el if que dirige a PlatziTripsCupertino y nunca pasa por allí, a alguien le pasó algo similar?

Hola, si algún compañero esta usando la librería. Flutter_signin_button, le recomiendo que deje de esta forma el código del botón.

class ButtonGreen extends StatefulWidget {
  final VoidCallback onPressed;

  ButtonGreen({Key key, @required this.onPressed});
  @override
  _ButtonGreenState createState() => _ButtonGreenState();
}

class _ButtonGreenState extends State<ButtonGreen> {
  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: SignInButton(
        Buttons.Google,
        text: "Ingresar con Google",
        onPressed: widget.onPressed,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
      ),
    );
  }
}

Comparto proyecto funicional a la fecha
https://github.com/norchili/places_app

A los que a la fecha aun les sigue dando error al hacer el “Run” lo que funciono para mi fue

main.dark

import 'package:firebase_core/firebase_core.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

y por ultimo:

GoogleService-Info.plist eliminé el archivo del proyecto y lo leí a través de XCode (clic derecho en Runnery luego Add Files…).

Y al fin compilo, espero sea de ayuda.

Hola, estoy bloqueado con un error al compilar el proyecto, alguien puede ayudarme a solucionarlo?

type '_BroadcastStream<User>' is not a subtype of type 'Stream<FirebaseUser>'

Para entender un poco mejor el tema de los Streams dejo el siguiente enlace
https://medium.com/comunidad-flutter/fundamentos-de-streams-en-dart-3a4030636516

Antes de correr la aplicación para iOS, les recomiendo hacer un borrado, antes de hacer esto me marcaba errores en la consola. En donde decía que no se podía abrir el emulador de iOS. Desde el root de la app correr “flutter clean”

Para aquellos que quieran entender un poco mejor el tema de async-await les dejo el siguiente video:
https://www.youtube.com/watch?v=u2axmPnxUoo

en esta parte del curso estoy un poco estresado no se si yo no veo los videos bien o definitivamente hay partes que se omtiten ( por ejemplo el metodo al boton de google sign in no se en que momento lo pusieron ) pero esta bien el problema que me encuentro actualmente es el que todos tienes ApiException 12500 …

ya elimine el .android volvi a generar otro nuevo , volvi a generar otro .json agregue el 256 y 1 ( sha) volvi a generar el json y nada que funciona . ya tengo registrado un correo . y tambien 2 claves al mismo tiempo alguna idea sugerencia o recomenacion ya que ya hice actualmente todo lo que se menciona en las preguntas

Buenas! Me pasa que el logueo se realiza correctamente (me devuelve el nombre por consola) pero siempre me muestra la pantalla de logueo y no puedo encontrar el error.

Gracias!

firebase_auth_api.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

class FirebaseAuthAPI {

  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn googleSignIn = GoogleSignIn();

  Future<FirebaseUser> signIn() async {
    GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
    GoogleSignInAuthentication gSA = await googleSignInAccount.authentication;

    FirebaseUser user = await _auth.signInWithCredential(
        GoogleAuthProvider.getCredential(idToken: gSA.idToken, accessToken: gSA.accessToken));

    return user;

  }

  signOut() async {
    await _auth.signOut().then((onValue) => print("Sesión cerrada"));
    googleSignIn.signOut();
    print("Sesiones cerradas");
  }

}```


auth_repository.dart

import ‘package:firebase_auth/firebase_auth.dart’;
import ‘package:platzi_trips_app/User/repository/firebase_auth_api.dart’;

class AuthRepository {

final _firebaseAuthAPI = FirebaseAuthAPI();

Future<FirebaseUser> signInFirebase() => _firebaseAuthAPI.signIn();

signOut() => _firebaseAuthAPI.signOut();

}```

bloc_user.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:generic_bloc_provider/generic_bloc_provider.dart';
import 'package:platzi_trips_app/User/repository/auth_repository.dart';
import 'package:firebase_auth/firebase_auth.dart';

class UserBloc implements Bloc{
  
  final _auth_repository = AuthRepository();

  Stream<FirebaseUser> streamFirebase = FirebaseAuth.instance.onAuthStateChanged;
  Stream<FirebaseUser> get authStatus => streamFirebase;



  Future<FirebaseUser> signIn(){
    return _auth_repository.signInFirebase();
  }

  @override
  void dispose() {
    
  }

}```



sign_in_screen.dart

import ‘package:firebase_auth/firebase_auth.dart’;
import ‘package:flutter/material.dart’;
import ‘package:generic_bloc_provider/generic_bloc_provider.dart’;
import ‘package:platzi_trips_app/User/bloc/bloc_user.dart’;
import ‘package:platzi_trips_app/platzi_trips_cupertino.dart’;
import ‘package:platzi_trips_app/widgets/gradient_back.dart’;
import ‘package:platzi_trips_app/widgets/button_green.dart’;
import ‘package:platzi_trips_app/User/bloc/bloc_user.dart’;
import ‘package:generic_bloc_provider/generic_bloc_provider.dart’;
import ‘package:firebase_auth/firebase_auth.dart’;
import ‘package:platzi_trips_app/platzi_trips_cupertino.dart’;

class SignInScreen extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _SignInScreen();
}

}

class _SignInScreen extends State<SignInScreen>{

UserBloc userBloc;

@override
Widget build(BuildContext context) {
userBloc = BlocProvider.of(context);
return singInGoogleUI();
}

Widget _handleCurrentSession(){
return StreamBuilder(
stream: userBloc.authStatus,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasData || snapshot.hasError){
return singInGoogleUI();
} else{
return PlatziTripsCupertino();
}
},
);
}

Widget singInGoogleUI(){
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: <Widget>[
GradientBack("", null),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(“Welcome \n This is yout Travel App”,
style: TextStyle(
fontSize: 37.0,
fontFamily: “Lato”,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
ButtonGreen(
text: “Login with Gmail”,
onPressed: (){
userBloc.signIn().then((FirebaseUser user) => print(“El usuario es ${user.displayName}”));
},
width: 300.0,
height: 50.0,

        )
          ],
        )
    ],
  ),
);

}

}```

Entonces si es necesario indicar el tipo de bloc 😃

    final appBloc = BlocProvider.of<BlocUser>(context);

Los que tienen errores revisen que tengan registrado el SHA-1 y sigan la sugerencia de Brayan Sanjuan

Es importante que esten el el projecto que firebase crea automáticamente en google cloud platform https://console.developers.google.com/apis/credentials/consent
y usar las urls de http://<id-project>.firebaseapp.com
y el id lo pueden obtener en las propiedades del proyecto

Después de eso me funcionó sin más problemas. Aunque no lo crean es un error común según veo por todo StackOverflow

Algunos inconvenientes con gradle.
Solucionado en Win10/Android Studio 3.5.2

Tools --> Flutter --> Flutter Clean

Volviendo a compilar el proyecto.

También habilitando la conexión del proyecto en la consola de Firebase

<Proyecto> --> Authentication -->todo de Acceso --> Google : Habilitado

Saludos 😉

Como raro, funciono a la primera, genial

Tener en cuenta lo mencionado por algunos compañeros:

@marceloandresacosta:
Para solucionar el error 12500 SignIn de Google se debe hacer lo siguiente:
en la consola de firebase ir a configuración -> usuarios y permisos -> configuración avanzada
Luego una vez en la consola cloud de google ir a Credenciales
y hacer lo siguiente:
completar los enlaces con el dominio: http://<id_project>.firebaseapp.com
ver ejemplo:
https://github.com/flutter/flutter/issues/33393

Donde se cambia las urls ya llegue a credenciales ayuda por favor

¿Cómo puedo manejar un error en el inicio de sesión?
Este sucede cuando en iOS o en Android cancelo el proceso de iniciar sesión.

Buenos dias,
Yo tengo este error

<D/skia ( 5677): Shader compilation error
D/skia ( 5677): ------------------------
D/skia ( 5677): Errors:>

No he podido quitarlo, pero si pulsas el boton (Flutter Hot Restart) te permite cargar usuario y registrarte.
Un saludo

wtFF Creí que no funcionaria a la primera!!!

Alguien mepuede ayudar con ese erro 157 por favor se lo agradeceria mucho

Un feedback de cual login esta mejor o ninguno?

Hola una pregunta, estoy teniendo un error que no me deja iniciar la app. El error dice “Unable to find BLoC of type _BlocProvider<UserBloc>.”

A continuación dejo el código para que me comenten que está mal o como puedo solucionarlo, desde ya muchas gracias.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:generic_bloc_provider/generic_bloc_provider.dart';
import 'package:initium/User/bloc/bloc_user.dart';
import 'package:initium/User/ui/screens/home_screen.dart';
import 'package:initium/button.dart';

import '../../../gradient_back.dart';

class SignInScreen extends StatefulWidget {
  @override
  _SignInScreenState createState() => _SignInScreenState();
}

class _SignInScreenState extends State<SignInScreen> {
  @override
  UserBloc userBloc;

  Widget build(BuildContext context) {
    final userBloc = BlocProvider.of<UserBloc>(context);
    return _handleCurrentSession();
  }

  Widget _handleCurrentSession() {
    return StreamBuilder(
      stream: userBloc.authStatus,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (!snapshot.hasData || snapshot.hasError) {
          return signInGoogleUI();
        } else {
          return HomeScreen();
        }
      },
    );
  }

  Widget signInGoogleUI() {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          GradientBack("Autenticación", null),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                "Bienvenido.\nA tu aplicacion de pedidos",
                style: TextStyle(
                  fontSize: 28.0,
                  fontFamily: "Montserrat",
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
                textAlign: TextAlign.start,
              ),
              Button(
                text: "Inicia con Google",
                onPressed: () {
                  userBloc.signIn().then((FirebaseUser user) =>
                      print("El usuario es ${user.displayName}"));
                },
                heigth: 50.0,
                width: 300.0,
              )
            ],
          )
        ],
      ),
    );
  }
}

Funciona perfecto! (en android me regresó a login, pero en cuanto presioné la pantalla, se mostró la página principal. Wierd!

Hasta este punto los acompaño, voy a presentar el examen y tomar algunos cursos de solo flutter por aparte. Siento que de un punto en adelante el curso está muy desactualizado por lo que se vuelve frustrante, agotador y aburrido sin poder encontrar las respuestas. Este problema de conexiones con firebase lo he encontrado en otros cursos (Angular por ejemplo) y siempre hay que buscar por otra parte las respuestas. Espero que se cambie esa metodología y que se comience a integrar otro tipo de base de datos o que se actualice la información, en fin saludos a todos, gracias a la profesora y nunca paren de aprender.

Cuando intento correr la aplicación en iphone me da el siguiente mensaje. Espero alguien me pueda apoyar.

The following assertion was thrown building FutureBuilder<FirebaseApp>(state: _FutureBuilderState<FirebaseApp>#bb31d):
MediaQuery.of() called with a context that does not contain a MediaQuery.```

Estaba presentando errores con la autenticación que me estaba devolviendo nulo, entonces me puse a revisar todo el flujo y me di cuenta que estaba generando de forma incorrecta la promesa (Future) y así lo solucione, previamente Ann lo había explicado .

Future<FirebaseUser> signIn() {
    return _auth_repository.signInFirebase();
  }```

El curso en algunos aspectos esta un desactualizado así que nos tocara realizar varias búsquedas para solucionar algunos problemas. Todas las versiones de Firebase se han actualizado y ahora debe llamar Firebase.initializeApp() antes de usar cualquier producto de Firebase. Y para poder llamar este metodo debemos poner en el archivo pubspec.yaml firebase_coreversión (0.5.0+). La informacion en stackoverflow la pueden encontrar aqui

Paso 1: Colocar en pubspec.ymal en la parte de dependencias

dependencies:
  flutter:
    sdk: flutter
  firebase_core : ^0.5.0

Paso 2: Colocar lo siguiente en el main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

Con esto el código debería correr bien, considerando que ya hallan resuelto los problemas las ultimas clases por lo desactualizadas que están, pero este aporte es para esta clase en especifico.

Tengo el mismo error para el sign in

Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 16: , null)

Tengo ya rato investigando pero no doy con los que pueda ser pero nada, tampoco pude solucionando agregando el SHA256 y actualizando el google-services.json.

PlatformException (PlatformException(ERROR_INVALID_CREDENTIAL, The supplied auth credential is malformed or has expired. [ Unable to parse Google id_token: ya29.a0Ae4lvC3nFj7cvfERsMWMq70SDe57mMNH0jfLfl0ukSrcCvaCWBf99p8SiCto1SMKW9_ejaXd9EK_ydz3rDRjUX067QQ85Ik2t5SMm6kUSGT3pg-61jKWnCJq65EhPI6o50IskL40uZ4FEnLIe6QbmmsCNW9xX1RZUUM ], null))

tengo ese error al momento de autenticarme con google aluguna idea