Login Page code Flutter Android Studio with Firebase

Jyotishgher Astrology
By -
40 minute read
0

 Login Page code Flutter Android Studio with Firebase

This tutorial will guide you through the process of enabling Google Sign In authentication to flutter application using firebase authentication with step-by-step and show’s the user’s data.I am just writing the login code I think you know how to setup if not then ping me in the comments

Login Page code Flutter Android Studio with Firebase

Firebase setup

Before Firebase app setup, enable the Google sign-in method in the authentication section. Build> Authentication> Sign-in method.

Just make a Simple main.dart file:

import 'package:flutter/material.dart';
import 'package:petlove/utils/LoginPage.dart';

import 'mainkk.dart';
import 'models/User_model.dart';
import 'package:firebase_core/firebase_core.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); // Make sure this is called
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
// Dummy user for testing
final dummyUser = UserModel(
uid: 'abc123',
email: 'test@example.com',
displayName: 'Test User',
ngo_uid: 'ngo_001',
photoURL: 'https://example.com/photo.jpg',
);

return MaterialApp(
title: 'PetLove',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: LoginPage(),
);
}
}


Now make a LoginPage():

import 'package:flutter/material.dart';
import 'package:petlove/utils/auth_service.dart';
import 'package:petlove/models/User_model.dart';
import '../mainkk.dart';

class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
final AuthService authService = AuthService();
bool isLoading = false;

void _signIn() async {
setState(() {
isLoading = true;
});

final user = await authService.signInWithGoogle();

setState(() {
isLoading = false;
});

if (user != null) {
final userModel = UserModel(
uid: user.uid,
email: user.email ?? '',
displayName: user.displayName ?? '',
photoURL: user.photoURL ?? '',
ngo_uid: 'example_ngo',
);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => MyCustomForm(user: userModel)),
);
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.deepPurple[50], // Light purple background
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"A care for Your",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.deepPurple,
),
),
const SizedBox(height: 40),
Image.asset(
'assets/petcare_image.PNG', // You can add a cute image here
height: 180,
),
const SizedBox(height: 40),
isLoading
? const CircularProgressIndicator(
color: Colors.deepPurple,
)
: ElevatedButton.icon(
icon: const Icon(Icons.login, color: Colors.white),
label: const Text(
"Sign in with Google",
style: TextStyle(fontSize: 18),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.deepPurple,
minimumSize: Size(double.infinity, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: _signIn,
),
],
),
),
),
);
}
}

 

Check this line in above code-

MaterialPageRoute(builder: (context) => MyCustomForm(user: userModel)),

CAlling MyCustomForm (in my case this is Mainkk.dart file)

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:petlove/models/User_model.dart';
import 'package:petlove/screens/home_page.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geoflutterfire2/geoflutterfire2.dart';

class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key, required UserModel user})
: _user = user,
super(key: key);

final UserModel _user;

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

class MyCustomFormState extends State<MyCustomForm> {
GeoFlutterFire geo = GeoFlutterFire();
final _formKey = GlobalKey<FormState>();
late UserModel _user;
File? image;
String? imageURL;
int uploadStatus = 0;
late LatLng location;
late GeoFirePoint geopoint;

FirebaseStorage storage = FirebaseStorage.instance;
final descriptionController = TextEditingController();
final animalController = TextEditingController();
final locationController = TextEditingController();

@override
void initState() {
super.initState();
_user = widget._user;
// Initialize with default location to avoid null issues
location = const LatLng(37.7749, -122.4194); // Default: San Francisco
geopoint = geo.point(latitude: location.latitude, longitude: location.longitude);
}

@override
void dispose() {
descriptionController.dispose();
animalController.dispose();
locationController.dispose();
super.dispose();
}

Future<void> uploadImage() async {
if (image == null) return;

setState(() {
uploadStatus = 1;
});

try {
// Enforce 30-second timeout for the entire upload process
String response = await uploadFile().timeout(
const Duration(seconds: 30),
onTimeout: () {
throw TimeoutException('Image upload timed out after 30 seconds');
},
);

setState(() {
imageURL = response;
uploadStatus = 2;
});
} catch (e) {
print('Upload error: $e');
// Show feedback to user
ScaffoldMessenger.of(context as BuildContext).showSnackBar(
SnackBar(content: Text('Upload failed: $e')),
);
// Redirect to HomePage after a brief delay to show SnackBar
await Future.delayed(const Duration(seconds: 1));
if (mounted) {
Navigator.of(context as BuildContext).pushReplacement(
MaterialPageRoute(builder: (context) => HomePage(user: _user)),
);
}
setState(() {
uploadStatus = 0;
});
}
}

Future<String> uploadFile() async {
final fileName = basename(image!.path);
final destination = 'files/$fileName';
final ref = FirebaseStorage.instance.ref(destination).child('file/');
// Wrap the upload task in a Future to ensure timeout applies
final uploadTask = ref.putFile(image!);
final snapshot = await uploadTask;
final imgUrl = await snapshot.ref.getDownloadURL();
return imgUrl;
}

Future<void> pickImage() async {
try {
final pickedImage = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedImage == null) return;
setState(() {
image = File(pickedImage.path);
});
} catch (e) {
print('Failed to pick image: $e');
}
}

Future<void> pickImageC() async {
try {
final pickedImage = await ImagePicker().pickImage(
source: ImageSource.camera,
imageQuality: 50,
);
if (pickedImage == null) return;
setState(() {
image = File(pickedImage.path);
});
} catch (e) {
print('Failed to pick image: $e');
}
}

void _awaitReturnValueFromSecondScreen(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SetCurrentLocation(user: _user),
),
);

if (result != null) {
setState(() {
location = result;
geopoint = geo.point(latitude: location.latitude, longitude: location.longitude);
});
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
elevation: 0,
backgroundColor: const Color.fromARGB(255, 4, 50, 88),
title: const Text(
'New Request',
style: TextStyle(color: Colors.white),
),
centerTitle: true,
),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: TextFormField(
controller: animalController,
decoration: const InputDecoration(
icon: Icon(Icons.pets),
hintText: 'Enter Species of Animal',
labelText: 'Animal',
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: TextFormField(
controller: descriptionController,
decoration: const InputDecoration(
icon: Icon(Icons.report_sharp),
hintText: 'Give description of the Animal',
labelText: 'Description',
),
),
),
const SizedBox(height: 10),
Center(
child: MaterialButton(
color: const Color.fromARGB(255, 4, 50, 88),
child: const Text(
"Choose current location",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
onPressed: () => _awaitReturnValueFromSecondScreen(context),
),
),
const SizedBox(height: 10),
Center(
child: Column(
children: [
MaterialButton(
color: const Color.fromARGB(255, 4, 50, 88),
child: const Text(
"Pick Image from Camera",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
onPressed: pickImageC,
),
MaterialButton(
color: const Color.fromARGB(255, 4, 50, 88),
child: const Text(
"Pick Image from Gallery",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
onPressed: pickImage,
),
const SizedBox(height: 20),
if (image != null)
SizedBox(
height: 300,
width: 300,
child: Image.file(image!, fit: BoxFit.contain),
),
const SizedBox(height: 10),
if (uploadStatus == 0)
MaterialButton(
color: const Color.fromARGB(255, 4, 50, 88),
child: const Text('Submit Image', style: TextStyle(color: Colors.white)),
onPressed: uploadImage,
)
else if (uploadStatus == 1)
const CircularProgressIndicator()
else if (uploadStatus == 2)
ElevatedButton(
onPressed: () async {
try {
// Firestore insertion with 30-second timeout
await FirebaseFirestore.instance
.collection('Request')
.add({
'Description': descriptionController.text,
'UserID': _user.uid,
'Location': geopoint.data,
'ImageURL': imageURL,
'Animal': animalController.text,
'IsCompleted': false,
'HelperUID': '',
})
.timeout(
const Duration(seconds: 30),
onTimeout: () {
throw TimeoutException(
'Firestore insertion timed out after 30 seconds');
},
);

// Navigate to success screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RequestFormSubmitted(user: _user),
),
);
} catch (e) {
print('Firestore insertion error: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Submission failed: $e')),
);
// Redirect to HomePage
await Future.delayed(const Duration(seconds: 1));
if (mounted) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => HomePage(user: _user),
),
);
}
}
},
child: const Text('Submit'),
),
],
),
),
],
),
),
),
);
}
}

class RequestFormSubmitted extends StatefulWidget {
const RequestFormSubmitted({Key? key, required UserModel user})
: _user = user,
super(key: key);

final UserModel _user;

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

class _RequestFormSubmittedState extends State<RequestFormSubmitted> {
late UserModel _user;

@override
void initState() {
super.initState();
_user = widget._user;
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Request Submitted Successfully!",
style: TextStyle(fontSize: 20, color: Colors.white),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color.fromARGB(255, 4, 50, 88),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => HomePage(user: _user)),
);
},
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: Text(
'Go Home',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 2,
),
),
),
),
],
),
),
);
}
}

class SetCurrentLocation extends StatefulWidget {
const SetCurrentLocation({Key? key, required UserModel user})
: _user = user,
super(key: key);

final UserModel _user;

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

class _SetCurrentLocationState extends State<SetCurrentLocation> {
late UserModel _user;
late GoogleMapController _googleMapController;
late Position currentPosition;
bool locationSetFlag = false;
double newLatitude = 0.0;
double newLongitude = 0.0;

// Default coordinates (San Francisco)
static const LatLng defaultLocation = LatLng(37.7749, -122.4194);

@override
void initState() {
super.initState();
_user = widget._user;
}

@override
void dispose() {
_googleMapController.dispose();
super.dispose();
}

Future<Position> _determinePosition() async {
try {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
throw 'Location services are disabled.';
}

LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
throw 'Location permissions are denied';
}
}

if (permission == LocationPermission.deniedForever) {
throw 'Location permissions are permanently denied.';
}

currentPosition = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
);
return currentPosition;
} catch (e) {
print('Error fetching location: $e');
return Position(
latitude: defaultLocation.latitude,
longitude: defaultLocation.longitude,
timestamp: DateTime.now(),
accuracy: 0.0,
altitude: 0.0,
heading: 0.0,
speed: 0.0,
speedAccuracy: 0.0,
altitudeAccuracy: 0.0,
headingAccuracy: 0.0,
);
}
}

void _sendDataBack(BuildContext context) {
if (!locationSetFlag) {
newLatitude = currentPosition.latitude;
newLongitude = currentPosition.longitude;
}
LatLng latLngToSendBack = LatLng(newLatitude, newLongitude);
Navigator.pop(context, latLngToSendBack);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
elevation: 0,
backgroundColor: const Color.fromARGB(255, 4, 50, 88),
title: const Text(
'Set Current Location',
style: TextStyle(color: Colors.white),
),
centerTitle: true,
),
body: FutureBuilder<Position>(
future: _determinePosition(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Stack(
alignment: Alignment.center,
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(snapshot.data!.latitude, snapshot.data!.longitude),
zoom: 15,
),
onMapCreated: (controller) => _googleMapController = controller,
markers: {
Marker(
markerId: const MarkerId('currentLocation'),
position: locationSetFlag
? LatLng(newLatitude, newLongitude)
: LatLng(snapshot.data!.latitude, snapshot.data!.longitude),
infoWindow: const InfoWindow(title: 'Your Current Location'),
),
},
onTap: (LatLng position) {
setState(() {
locationSetFlag = true;
newLatitude = position.latitude;
newLongitude = position.longitude;
});
},
),
Positioned(
bottom: 15,
child: MaterialButton(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
elevation: 10,
color: const Color.fromARGB(255, 4, 50, 88),
child: const Text(
"Submit current location",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => _sendDataBack(context),
),
),
],
);
} else if (snapshot.hasError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Error: ${snapshot.error}'),
const SizedBox(height: 10),
const Text('Using default location.'),
ElevatedButton(
onPressed: () {
setState(() {
newLatitude = defaultLocation.latitude;
newLongitude = defaultLocation.longitude;
locationSetFlag = true;
});
_sendDataBack(context);
},
child: const Text('Use Default Location'),
),
],
),
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
Tags:

Post a Comment

0Comments

Post a Comment (0)