1
I'm writing a code to login and Register with user email and password. And I'm trying to store that data into firestore and firebase storage.

I'm storing the registered person's image in to Firebase Storage. And other detailed information into firestore like name,email etc. Now the image is going to firebaseStorage but the other information that should be stored in firestore, is not going in firestore.

Error:

The registred user is being authenticated

Profile Images are getting uploaded successfully

But the FireStore Storage is Empty, the detailed info of the Registered User isn't approaching here.

But the FireStore Storage is Empty, the detailed info of the Registered User isn't approaching here.

Flutter Doctor

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.2.3, on Microsoft Windows [Version 10.0.19043.1200], locale en-PK)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] Connected device (2 available)

• No issues found!

pub.yaml

name: ecom_app
description: A new Flutter project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  cloud_firestore: ^2.5.0
  firebase_auth: ^3.0.2
  firebase_core: ^1.5.0
  shared_preferences: ^2.0.6
  fluttertoast: ^8.0.8
  image_picker: ^0.8.3+2
  firebase_storage: ^10.0.2
  flutter_staggered_grid_view: ^0.4.0
  provider: ^6.0.0
  path_provider: ^2.0.2
  image: ^3.0.2
  intl: ^0.17.0

  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter

# The following section is specific to Flutter.
flutter:
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - images/
  #   - images/a_dot_ham.jpeg

Config.dart (here I've declared all the requierd values in a class EcommerceApp

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';
class EcommerceApp{
  static const String appName='E-shop';
  static SharedPreferences sharedPreferences=SharedPreferences.getInstance() as SharedPreferences;
  static FirebaseAuth auth=FirebaseAuth.instance;
  static User user=FirebaseAuth.instance as User;
  static FirebaseFirestore firestore=FirebaseFirestore.instance;

  static String collectionUser='users';
  static String  collectionOrder='orders';
  static String  userCartList='usercart';
  static String  subCollectionAddress='userAddress';

  static final String userName='name';
  static final String userEmail ='email';
  static final String userPhotoUrl='photoUrl';
  static final String userId ='userid';
  static final String userAvatarUrl='avatarUrl';
  static final String addressId='addressId';
  static final String totalAmount='totalAmount';
  static final String productId='productId';
  static final String paymentDetails='paymentDetails';
  static final String orderTime='orderTime';
  static final String isSucces='isSucces';

}

Registerpage.dart(registering new a user, no error in code but Informaton isn't storing in firestore)

import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:ecom_app/Config/config.dart';
import 'package:ecom_app/DialogBox/errordialog.dart';
import 'package:ecom_app/DialogBox/loadingDialog.dart';
import 'package:ecom_app/Store/StoreHomePage.dart';
import 'package:ecom_app/Widgets/CustomTextField.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class Registration extends StatefulWidget {
  const Registration({Key? key}) : super(key: key);

  @override
  _RegistrationState createState() => _RegistrationState();
}

class _RegistrationState extends State<Registration> {
  final TextEditingController _nameController =TextEditingController();
  final TextEditingController _emailController =TextEditingController();
  final TextEditingController _passwordController =TextEditingController();
  final TextEditingController _cpasswordController =TextEditingController();
  final GlobalKey<FormState> _formKey=GlobalKey<FormState>();
  String userImageUrl='';
  File? _imagefile;
  @override
  Widget build(BuildContext context) {
    double _screenwidth=MediaQuery.of(context).size.width,_screenHeight=MediaQuery.of(context).size.height;
    return SingleChildScrollView(
      child: Container(
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: [
            SizedBox(
              height: 10.0,
            ),
            Container(
             height: _screenHeight*0.25,
              width: _screenwidth*0.25,
              child:Column(
                children: [
                  Spacer(),
                  _imagefile !=null ? Image.file(_imagefile!):

                  CircleAvatar(
                    radius: _screenwidth * 0.15,
                    child: Icon(Icons.add_photo_alternate,size: _screenHeight*0.15
                        ,color: Colors.grey),
                  ),
                ],
              )

            ),
            /*InkWell(
              onTap: ()=>_PickImage(),

              ),*/

            SizedBox(
              height: 8.0,
            ),
            ElevatedButton(
                onPressed: ()=>_PickImage(),
                child:Icon(Icons.camera)
            ),
            SizedBox(
              height: 8.0,
            ),
            Form(
              key: _formKey,
                child: Column(
                  children: [
                    customtextfield(
                      controller: _nameController,
                      data: Icons.person,
                      hinttext: 'Name',
                      isObsecure:false
                    ),
                    customtextfield(
                        controller: _emailController,
                        data: Icons.email,
                        hinttext: 'Email',
                        isObsecure:false,
                    ),
                    customtextfield(
                        controller: _passwordController,
                        data: Icons.lock,
                        hinttext: 'Password',
                        isObsecure:true,
                    ),
                    customtextfield(
                        controller: _cpasswordController,
                        data: Icons.security,
                        hinttext: 'Confirm Password',
                        isObsecure: true,
                    ),
                  ],
                )
            ),
            ElevatedButton(
                onPressed: ()=>_uploadandSaveImage(),
                style: ElevatedButton.styleFrom(primary: Colors.pink,onPrimary: Colors.deepPurple),
                child:Text("Sign up"),
            ),
            SizedBox(
              height: 30.0,
            ),
            Container(
              height: 4.0,
              width: _screenwidth*0.8,
              color: Colors.pink,
            ),
            SizedBox(
              height: 15.0,
            )
          ],
        ),
      ),
    );
  }
  Future<void> _PickImage() async{
    final _imagefile =await ImagePicker().pickImage(source: ImageSource.camera);
    final _imageselected=File(_imagefile!.path);
    setState(() {
      this._imagefile=_imageselected;
    });


  }
  Future<void>_uploadandSaveImage() async{
  if(_imagefile == null)
      {
        showDialog(
            context: context,
            builder: (c)
            {
              return ErrorDialog(message: 'Please Select an Image');
            }
        );
      }
    else
      {
        _passwordController.text==_cpasswordController.text
            ? _nameController.text.isNotEmpty &&
    _emailController.text.isNotEmpty&&
    _passwordController.text.isNotEmpty&&
    _cpasswordController.text.isNotEmpty

            ? uploadToFirebaseStorage()

            : displayDialog('Field Can Not Be Empty!...')
            : displayDialog('Password Does Not Match');
      }

  }
  displayDialog(String msg) async{
    showDialog(
        context: context,
        builder: (c)
        {
          return ErrorDialog(message: msg);
        }
    );
  }
  uploadToFirebaseStorage()
  async {
    showDialog(
        context: context, builder: (c){
         return LoadingAlertDialog(message: 'Authentication Pleas wait...' );
    }
    );

    String imageFileName =DateTime.now().microsecondsSinceEpoch.toString();
    Reference storageReference=FirebaseStorage.instance.ref().child(imageFileName);
    UploadTask storageUploadTask=storageReference.putFile(_imagefile!);
    TaskSnapshot taskSnapshot=await storageUploadTask.whenComplete(() => null);
    await taskSnapshot.ref.getDownloadURL().then((urlImage){
      userImageUrl=urlImage;
      _registerUser();
    });

  }
  FirebaseAuth _auth=FirebaseAuth.instance;
   void _registerUser() async{
    User? firebaseuser;
    await _auth.createUserWithEmailAndPassword(
        email: _emailController.text.trim(),
        password: _passwordController.text.trim(),
    ).then((auth)
        {
          firebaseuser=auth.user!;
        }).catchError((error){
         Navigator.pop(context);
         showDialog(context: context, builder: (c)
         {
           return ErrorDialog(message: error.message.toString());
         });

    });

    if(firebaseuser != null)
      {
        savetoFirestore(firebaseuser!).then((value){
          Navigator.pop(context);
          Route route=MaterialPageRoute(builder: (c)=> StoreHome());
          Navigator.pushReplacement(context, route);
        });
      }
  }

  savetoFirestore(User fuser) async{
     FirebaseFirestore.instance.collection('users').doc(fuser.uid).set(
       {
        'uid':fuser.uid,
        'email': fuser.email,
         'name':_nameController.text.trim(),
         'url':userImageUrl,
         EcommerceApp.userCartList:['garbageValue'],
       }
     );
     await EcommerceApp.sharedPreferences.setString('uid', fuser.uid);
     await EcommerceApp.sharedPreferences.setString(EcommerceApp.userEmail, fuser.email!);
     await EcommerceApp.sharedPreferences.setString(EcommerceApp.userName, _nameController.text.trim());
     await EcommerceApp.sharedPreferences.setString(EcommerceApp.userAvatarUrl, userImageUrl);
     await EcommerceApp.sharedPreferences.setStringList(EcommerceApp.userCartList,['garbageValue']);
  }
}

UPDATE in Error:

enter image description here

M Nouman
  • 437
  • 1
  • 5
  • 22
  • It looks like your save to firestore function is not being called, try putting print functions in it, before, during and after the .then command. Also try going up the tree in the code to see the last executed command – Siddharth Agrawal Aug 23 '21 at 16:04
  • I understood your point , but can you please show it by making changes into my code that I provided. If you'll show me where exactly I have to put those print functions that would be much helpful for me. – M Nouman Aug 24 '21 at 14:29

2 Answers2

0

You have a condition that checks if the firebaseuser variable is not not null before storing the user information to Firestore.

But the firebaseuser variable is null because it is outside of the .then block added after you created the user.

Solution:

You should move the condition inside the .then block so the firebaseuser variable is not null when the condition is checked.

Here's the code with the change:

void _registerUser() async {
    User? firebaseuser;
    await _auth
        .createUserWithEmailAndPassword(
      email: _emailController.text.trim(),
      password: _passwordController.text.trim(),
    )
        .then((auth) {
      firebaseuser = auth.user!;

      if (firebaseuser != null) {
        savetoFirestore(firebaseuser!).then((value) {
          Navigator.pop(context);
          Route route = MaterialPageRoute(builder: (c) => StoreHome());
          Navigator.pushReplacement(context, route);
        });
      }
    }).catchError((error) {
      Navigator.pop(context);
      showDialog(
          context: context,
          builder: (c) {
            return ErrorDialog(message: error.message.toString());
          });
    });
}

Update:

SharedPreferences.getInstance() returns Future<SharedPreferences> and not SharedPreferences.

You should fix the shared preferences errors by making the following code updates:

  • Declare the sharedPreferences variables as of type Future.

    class EcommerceApp{
      static Future<SharedPreferences> sharedPreferences=SharedPreferences.getInstance();
      ...
    }
    
  • Await the EcommerceApp.sharedPreferences variable before making any operations with it. Make the change below to your savetoFirestore method:

    savetoFirestore(User fuser) async{
     SharedPreferences sharedPreferences = await EcommerceApp.sharedPreferences;
    
     await sharedPreferences.setString('uid', fuser.uid);
     await sharedPreferences.setString(EcommerceApp.userEmail, fuser.email!);
     await sharedPreferences.setString(EcommerceApp.userName, _nameController.text.trim());
     await sharedPreferences.setString(EcommerceApp.userAvatarUrl, userImageUrl);
     await sharedPreferences.setStringList(EcommerceApp.userCartList,['garbageValue']);
    }
    
Victor Eronmosele
  • 7,040
  • 2
  • 10
  • 33
  • I tried with the function you made, but the result is same. No data in firestore. – M Nouman Aug 24 '21 at 14:22
  • Is there an error message on the console? – Victor Eronmosele Aug 24 '21 at 14:28
  • Not in the red lines but in white lines it shows " [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type 'Future' is not a subtype of type 'SharedPreferences' in type cast " 'W/GooglePlayServicesUtil(10080): Google Play Store is missing.' 'E/GooglePlayServicesUtil(10080): GooglePlayServices not available due to error 9' , "java.lang.AssertionError: Method getAlpnSelectedProtocol not supported for object SSL socket over Socket[address=firestore.googleapis.com/172.217.19.10,port=443,localPort=37638]" There are multiple lines like these... – M Nouman Aug 24 '21 at 14:33
  • What line does the SharedPreferences error refer to? – Victor Eronmosele Aug 25 '21 at 09:09
  • According to stack first it is in the Config.dart file, where I've declared the sharedpreference first time in the class EcommerceApp. Then in Register.dart file, 'savetofirestore' function where I've used sharedprefrences 5 times for uid,email etc. And then in _registeruser function because the savetofirestore function is being called their. – M Nouman Aug 25 '21 at 13:09
  • `SharedPreferences.getInstance()` returns `Future` and not `SharedPreference`. Checkout https://pub.dev/documentation/shared_preferences/latest/shared_preferences/SharedPreferences/getInstance.html – Victor Eronmosele Aug 25 '21 at 13:12
  • Ok I got that, but then how should I declare sharedprefrences? because without .getInstance(), it gives me error and doesn't declare it. Should I use 'final Future sharedPrefsFuture = completer.future;' – M Nouman Aug 25 '21 at 13:17
  • Sorry for the inconvenience but would you please check on my question Error update as well, once. – M Nouman Aug 25 '21 at 13:33
  • You will have to put it in something like initstate or something. https://stackoverflow.com/questions/57559489/flutter-provider-in-initstate Try some answers from here to see which one works the best for you – Siddharth Agrawal Aug 25 '21 at 17:17
  • First thing first, I commented that part just to see if the data is going in firestore or not. But still no data in firestore, even after the updated sharedprefrences functions. It says Google Play Store is missing due to error 9. And also I'm getting this "error getting token java.util.concurrent.ExecutionException: com.google.firebase.internal.api.FirebaseNoSignedInUserException: Please sign in before trying to get a token." – M Nouman Aug 25 '21 at 18:12
  • Thanks a lot for the help and time @Victor and ,Siddharth. – M Nouman Aug 25 '21 at 19:55
0

Finally I've found the answer, I tried multiple ways but it has to be the permission rules of Cloud Firestore. I don't know if it work for everyone, but worked for me. And I would suggest that use all the above solutions that were answered, as well. But this didn't work on emulator. When I used my actual android phone, then it worked. These are the rules that I found here Failed to update ssl context.

service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}}}
M Nouman
  • 437
  • 1
  • 5
  • 22