The logic in the program I wrote is that it is like Twitter. There will be photo sharing and text sharing. However, there is an error in my codes and when I do not share photos, I get the error 'Null check-operator used on null value'. How can I change this?
When I do not share photos, I get the error below.
These are my codes. I would appreciate it if you could tell me the changes I need to make.
add_post_screenn
class AddPostScreen extends StatefulWidget {
const AddPostScreen({Key? key}) : super(key: key);
#override
State<AddPostScreen> createState() => _AddPostScreenState();
}
class _AddPostScreenState extends State<AddPostScreen> {
Uint8List? _file;
final TextEditingController _descriptionController = TextEditingController();
bool _isLoading = false;
void postImage(
String uid,
String username,
String profImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file!, uid, username, profImage);
if (res == 'succes') {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
showSnackBar(e.toString(), context);
}
}
_selectImage(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text('Create a Post'),
children: [
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Take a photo'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(
ImageSource.camera,
);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Chose from gallery'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(
ImageSource.gallery,
);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
],
);
});
}
void clearImage() {
_file = null;
}
#override
void dispose() {
super.dispose();
_descriptionController.dispose();
}
#override
Widget build(BuildContext context) {
final User user = Provider.of<UserProvider>(context).getUser;
//yorum satırı olacak
return _file == null
? Center(
child: IconButton(
icon: const Icon(Icons.upload),
onPressed: () => _selectImage(context),
),
)
// //buraya kadar
: Scaffold(
appBar: AppBar(
backgroundColor: mobileBackgroundColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: clearImage,
),
title: const Text('Paylaşım'),
centerTitle: false,
actions: [
TextButton(
onPressed: () => postImage(
user.uid,
user.username,
user.photoUrl,
),
child: const Text(
'Paylaş',
style: TextStyle(
color: Colors.blueAccent,
fontWeight: FontWeight.bold,
fontSize: 16,
),
))
],
),
body: Column(
children: [
_isLoading
? const LinearProgressIndicator()
: const Padding(
padding: EdgeInsets.only(
top: 0,
),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundImage: NetworkImage(user.photoUrl),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.45,
child: TextField(
controller: _descriptionController,
decoration: const InputDecoration(
hintText: 'Hayallerini Yaz!',
border: InputBorder.none,
),
maxLines: 8,
),
),
SizedBox(
height: 45,
width: 45,
child: AspectRatio(
aspectRatio: 487 / 451,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(_file!),
fit: BoxFit.fill,
alignment: FractionalOffset.topCenter,
)),
),
),
),
const Divider(),
],
),
],
),
);
}
}
firestore_methods
class FirestoreMethods {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
//upload post
Future<String> uploadPost(
String description,
Uint8List file,
String uid,
String username,
String profImage,
) async {
String res = 'Some error occurred';
try {
String photoUrl =
await StorageMethods().uploadImageToStorage('posts', file, true);
String postId = const Uuid().v1();
Post post = Post(
description: description,
uid: uid,
username: username,
postId: postId,
datePublished: DateTime.now(),
postUrl: photoUrl,
porfImage: profImage,
likes: [],
);
_firestore.collection('posts').doc(postId).set(
post.toJson(),
);
res = 'succes';
} catch (err) {
res = err.toString();
}
return res;
}
Future<void> LikePost(String postId, String uid, List likes) async {
try {
if (likes.contains(uid)) {
await _firestore.collection('posts').doc(postId).update({
'likes': FieldValue.arrayRemove([uid]),
});
} else {
await _firestore.collection('posts').doc(postId).update({
'likes': FieldValue.arrayUnion([uid]),
});
}
} catch (e) {
print(
e.toString(),
);
}
}
Future<void> postComment(String postId, String text, String uid, String name,
String profilePic) async {
try {
if (text.isNotEmpty) {
String commentId = const Uuid().v1();
await _firestore
.collection('posts')
.doc(postId)
.collection('comments')
.doc(commentId)
.set({
'profilePic': profilePic,
'name': name,
'uid': uid,
'text': text,
'commentId': commentId,
'datePublished': DateTime.now(),
});
} else {
print('Text is empty');
}
} catch (e) {
print(
e.toString(),
);
}
}
storage.methods
class StorageMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
// firebase deposuna resim ekleme firebase deposuna resim ekleme
Future<String> uploadImageToStorage(
String childName, Uint8List file, bool isPost) async {
// firebase depolama alanımıza konum oluşturma
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser!.uid);
if (isPost) {
String id = const Uuid().v1();
ref = ref.child(id);
}
// putting in uint8list format -> Upload task like a future but not future
UploadTask uploadTask = ref.putData(file);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
}
The error cause comes from the _file!. When posting only text there is going to be no _file as it's going to be null.
To fix this change the references from _file! to just _file and the FirestoreMethods.uploadPost should be the following:
FirestoreMethods.uploadPost - Change file to be nullable and check for null.
Future<String> uploadPost(
String description,
Uint8List? file, // <- Here
String uid,
String username,
String profImage,
) async {
String res = 'Some error occurred';
try {
String photoUrl = file != null // <- Here
? await StorageMethods().uploadImageToStorage('posts', file, true)
: '';
String postId = const Uuid().v1();
Post post = Post(
description: description,
uid: uid,
username: username,
postId: postId,
datePublished: DateTime.now(),
postUrl: photoUrl,
porfImage: profImage,
likes: [],
);
_firestore.collection('posts').doc(postId).set(
post.toJson(),
);
res = 'succes';
} catch (err) {
res = err.toString();
}
return res;
}
_AddPostScreenState.postImage - Change _file! to just _file
void postImage(
String uid,
String username,
String profImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file, uid, username, profImage);
if (res == 'succes') {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
showSnackBar(e.toString(), context);
}
}
I think you are getting error in this line
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser!.uid);
Here the current user maybe null. To fix this error for now you can use
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser?.uid);
//Note instead of using ! I have used ? which means currentUser can be null. ! means you are marking that its not null and value is unknown
but please note that you are receiving _auth.currentUser as null. Please check those codes
Related
I'm trying to store data that fetched from API using sqflite
Now I'm getting an error saying...
A value of type 'List' can't be returned from the method 'getAllEmployees' because it has a return type of 'Future<List>'.
Here's my employee_provider.dart file
class EmployeeApiProvider {
Future<List<Employee>> getAllEmployees() async {
var url = "http://demo8161595.mockable.io/employee";
var response = await Dio().get(url);
return employeeFromJson(response.data).map((employee) {
DBProvider.db.createEmployee(employee);
}).toList();
}
}
How to fix this?
And other files relevant to this are...
db_provider.dart
class DBProvider {
static Database? _database;
static final DBProvider db = DBProvider._();
DBProvider._();
Future<Database?> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'employee_manager.db');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE Employee('
'id INTEGER PRIMARY KEY,'
'email TEXT,'
'firstName TEXT,'
'lastName TEXT,'
'avatar TEXT'
')');
});
}
createEmployee(Employee newEmployee) async {
await deleteAllEmployees();
final db = await database;
final res = await db!.insert('Employee', newEmployee.toJson());
return res;
}
Future<int> deleteAllEmployees() async {
final db = await database;
final res = await db!.rawDelete('DELETE FROM Employee');
return res;
}
Future<List<Employee>> getAllEmployees() async {
final db = await database;
final res = await db!.rawQuery("SELECT * FROM EMPLOYEE");
List<Employee> list =
res.isNotEmpty ? res.map((c) => Employee.fromJson(c)).toList() : [];
return list;
}
}
employee_model.dart
List<Employee> employeeFromJson(String str) =>
List<Employee>.from(json.decode(str).map((x) => Employee.fromJson(x)));
String employeeToJson(List<Employee> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Employee {
int id;
String email;
String firstName;
String lastName;
String avatar;
Employee({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.avatar,
});
factory Employee.fromJson(Map<String, dynamic> json) => Employee(
id: json["id"],
email: json["email"],
firstName: json["firstName"],
lastName: json["lastName"],
avatar: json["avatar"],
);
Map<String, dynamic> toJson() => {
"id": id,
"email": email,
"firstName": firstName,
"lastName": lastName,
"avatar": avatar,
};
}
home.dart
class _HomeState extends State<AbcView> {
var isLoading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Api to sqlite'),
centerTitle: true,
actions: <Widget>[
Container(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon: const Icon(Icons.settings_input_antenna),
onPressed: () async {
await _loadFromApi();
},
),
),
Container(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteData();
},
),
),
],
),
body: isLoading
? const Center(
child: CircularProgressIndicator(),
)
: _buildEmployeeListView(),
);
}
_loadFromApi() async {
setState(() {
isLoading = true;
});
var apiProvider = EmployeeApiProvider();
await apiProvider.getAllEmployees();
await Future.delayed(const Duration(seconds: 2));
setState(() {
isLoading = false;
});
}
_deleteData() async {
setState(() {
isLoading = true;
});
await DBProvider.db.deleteAllEmployees();
await Future.delayed(const Duration(seconds: 1));
setState(() {
isLoading = false;
});
}
_buildEmployeeListView() {
return FutureBuilder(
future: DBProvider.db.getAllEmployees(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.separated(
separatorBuilder: (context, index) => const Divider(
color: Colors.black12,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Text(
"${index + 1}",
style: const TextStyle(fontSize: 20.0),
),
title: Text(
"Name: ${snapshot.data[index].firstName} ${snapshot.data[index].lastName} "),
subtitle: Text('EMAIL: ${snapshot.data[index].email}'),
);
},
);
}
},
);
}
}
Maybe you could try to add await in front of the DBProvider.db.createEmployee?
class EmployeeApiProvider {
Future<List<Employee>> getAllEmployees() async {
var url = "http://demo8161595.mockable.io/employee";
var response = await Dio().get(url);
return employeeFromJson(response.data).map((employee) async {
await DBProvider.db.createEmployee(employee);
}).toList();
}
}
here is the error message from the console
user.dart
import 'package:cloud_firestore/cloud_firestore.dart';
class User {
final String email;
final String uid;
final String photoUrl;
final String username;
final String bio;
final List<String> followers;
final List<String> following;
const User({
required this.email,
required this.uid,
required this.photoUrl,
required this.username,
required this.bio,
required this.followers,
required this.following,
});
static User fromSnap(DocumentSnapshot snap) {
var snapshot = snap.data() as Map<String, dynamic>;
return User(
username: snapshot["username"],
uid: snapshot["uid"],
email: snapshot["email"],
photoUrl: snapshot["photoUrl"],
bio: snapshot["bio"],
followers: snapshot["followers"],
following: snapshot["following"],
);
}
Map<String, dynamic> toJson() => {
"username": username,
"uid": uid,
"email": email,
"photoUrl": photoUrl,
"bio": bio,
"followers": followers,
"following": following,
};
}
user_provider
import 'package:flutter/material.dart';
import 'package:social_network/models/user.dart';
import 'package:social_network/resources/auth_method.dart';
class UserProvider with ChangeNotifier {
User? _user;
final AuthMethods _authMethods = AuthMethods();
User get getUser => _user!;
Future<void> refreshUser() async {
User? user = await _authMethods.getUserDetails();
_user = user;
notifyListeners();
}
}
add_post_screen
import 'dart:typed_data';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:social_network/providers/user_provider.dart';
import 'package:social_network/resources/firestore_methods.dart';
import 'package:social_network/utils/colors.dart';
import 'package:social_network/utils/utils.dart';
class AddPostScreen extends StatefulWidget {
const AddPostScreen({Key? key}) : super(key: key);
#override
_AddPostScreenState createState() => _AddPostScreenState();
}
class _AddPostScreenState extends State<AddPostScreen> {
Uint8List? _file;
bool _isLoading = false;
final TextEditingController _descriptionController = TextEditingController();
_selectImage(BuildContext parentContext) async {
return showDialog(
context: parentContext,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Create a post'),
children: <Widget>[
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Take a photo'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(ImageSource.camera);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Choose from gallery'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(ImageSource.gallery);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
void postImage(
String uid,
String username,
String profileImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file!, uid, username, profileImage);
if (res == "Succes") {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
setState(() {
_isLoading = false;
});
showSnackBar(e.toString(), context);
}
}
void clearImage() {
setState(() {
_file = null;
});
}
#override
void dispose() {
super.dispose();
_descriptionController.dispose();
}
#override
Widget build(BuildContext context) {
final UserProvider userProvider = Provider.of<UserProvider>(context);
return _file == null
? Center(
child: IconButton(
icon: const Icon(Icons.upload),
onPressed: () => _selectImage(context),
),
)
: Scaffold(
appBar: AppBar(
backgroundColor: mobileBackgroundColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: clearImage,
),
title: const Text('Post to'),
centerTitle: false,
actions: <Widget>[
TextButton(
onPressed: () => postImage(
userProvider.getUser.uid,
userProvider.getUser.username,
userProvider.getUser.photoUrl,
),
child: const Text(
'Post',
style: TextStyle(
color: Colors.redAccent,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
],
),
body: Column(
children: [
_isLoading
? const LinearProgressIndicator()
: const Padding(
padding: EdgeInsets.only(top: 0),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundImage: NetworkImage(
'https://images.unsplash.com/photo-1522441815192-d9f04eb0615c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=654&q=80',
// userProvider.getUser.photoUrl,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: TextField(
controller: _descriptionController,
decoration: const InputDecoration(
hintText: 'Write a caption...',
border: InputBorder.none,
),
maxLines: 8,
),
),
SizedBox(
height: 45,
width: 45,
child: AspectRatio(
aspectRatio: 487 / 451,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(_file!),
fit: BoxFit.fill,
alignment: FractionalOffset.topCenter,
),
),
),
),
),
const Divider(),
],
)
],
));
}
}
auth_methods.dart
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:social_network/models/user.dart' as model;
import 'package:social_network/resources/storage_methods.dart';
class AuthMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<model.User?> getUserDetails() async {
User currentUser = _auth.currentUser!;
DocumentSnapshot documentSnapshot =
await _firestore.collection('user').doc(currentUser.uid).get();
return model.User.fromSnap(documentSnapshot);
}
//sign up the user
Future<String> signUpUser({
required String email,
required String password,
required String username,
required String bio,
required Uint8List? file,
}) async {
String res = "Some error occurred";
try {
if (email.isNotEmpty ||
password.isNotEmpty ||
username.isNotEmpty ||
bio.isNotEmpty ||
file != null) {
//register the user
UserCredential cred = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
String photoUrl = await StorageMethods()
.uploadImageToStorage('profilePictures', file!, false);
//adding user to our database
model.User _user = model.User(
bio: bio,
username: username,
uid: cred.user!.uid,
email: email,
photoUrl: photoUrl,
following: [],
followers: [],
);
await _firestore.collection("users").doc(cred.user!.uid).set(
_user.toJson(),
);
res = "Succes";
} else {
res = "Please enter all the fields";
}
} catch (err) {
res = err.toString();
}
return res;
}
// logging the user
Future<String> loginUser(
{required String email, required String password}) async {
String res = "Some error occured";
try {
if (email.isNotEmpty || password.isNotEmpty) {
await _auth.signInWithEmailAndPassword(
email: email, password: password);
res = "Succes";
} else {
res = "Please enter all the fields required";
}
} catch (err) {
res = err.toString();
}
return res;
}
}
Hello. I'll try to make a post button and when I try to upload a photo and press the post button I receive this error.
Do you have any solution for this error? Thanks a lot!
Error message:
Restarted application in 474ms.
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
════════ Exception caught by gesture ═══════════════════════════════════════════
Null check operator used on a null value
════════════════════════════════════════════════════════════════════════════════
[VERBOSE-2:profiler_metrics_ios.mm(203)] Error retrieving thread information: (os/kern) object terminated
I believe that your issue in
onPressed: () => postImage(
userProvider.getUser.uid,
userProvider.getUser.username,
userProvider.getUser.photoUrl,
),
Make sure that the user is not null before calling the method,
It would be more helpful to post more code _authMethods.getUserDetails(); what’s inside this method?
UPDATE:
Future<model.User?> getUserDetails() async {
User currentUser = _auth.currentUser!;
DocumentSnapshot documentSnapshot =
await _firestore.collection('user').doc(currentUser.uid).get();
//add the following lines
print('documentSnapshot: $documentSnapshot');
if(documentSnapshot == null) return null;
return model.User.fromSnap(documentSnapshot);
}
I am tring to pas data to user profile screen from firebase
i have got error Unhandled Exception: 'package:cloud_firestore/src/collection_reference.dart': Failed assertion: line 116 pos 14: 'path.isNotEmpty': a document path must be a non-empty string
what do i need fix?
user prfile controller
lass ProfileController extends GetxController {
final Rx<Map<String, dynamic>> _user = Rx<Map<String, dynamic>>({});
Map<String, dynamic> get user => _user.value;
Rx<String> _uid = ''.obs;
updateUserID(String uid) {
_uid.value = uid;
getUserData();
}
void getUserData() async {
print("HELLO");
List<String> thumbnails = [];
// var myVideos = await firestore
// .collection('videos')
// .where('uid', isEqualTo: "9GFyxV41rkd0Iu0oy1tctobVNk92")
// .get();
//
// for (int i = 0; i < myVideos.docs.length; i++) {
// thumbnails.add((myVideos.docs[i].data() as dynamic)['thumbnail']);
// }
DocumentSnapshot userDoc =
await firestore.collection('users').doc(_uid.value).get();
final userData = userDoc.data()! as dynamic;
print(userData);
String name = userData['name'];
String profilePhoto = userData['profilePhoto'];
int likes = 0;
int followers = 0;
int following = 0;
bool isFollowing = false;
// for (var item in myVideos.docs) {
// likes += (item.data()['likes'] as List).length;
// }
// var followerDoc = await firestore
// .collection('users')
// .doc(_uid.value)
// .collection('followers')
// .get();
// var followingDoc = await firestore
// .collection('users')
// .doc(_uid.value)
// .collection('following')
// .get();
// followers = followerDoc.docs.length;
// following = followingDoc.docs.length;
// firestore
// .collection('users')
// .doc(_uid.value)
// .collection('followers')
// .doc(authController.user.uid)
// .get()
// .then(
// (value) {
// if (value.exists) {
// isFollowing = true;
// } else {
// isFollowing = false;
// }
// },
// );
_user.value = {
'followers': followers.toString(),
'following': following.toString(),
'isFollowing': isFollowing,
'likes': likes.toString(),
'profilePhoto': profilePhoto,
'name': name,
'thumbnails': thumbnails,
};
update();
}
followUser() async {
var doc = await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.get();
if (!doc.exists) {
await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.set({});
await firestore
.collection('users')
.doc(authController.user.uid)
.collection('following')
.doc(_uid.value)
.set({});
_user.value
.update('followers', (value) => (int.parse(value) + 1).toString());
} else {
await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.delete();
await firestore
.collection('users')
.doc(authController.user.uid)
.collection('following')
.doc(_uid.value)
.delete();
_user.value
.update('followers', (value) => (int.parse(value) - 1).toString());
}
_user.value.update('isFollowing', (value) => !value);
update();
}
}
auth Controller
class AuthController extends GetxController {
static AuthController instance = Get.find(); //TODO 2
var displayName = '';
var displayPhoto = '';
String myId = '';
late Rx<User?> _user; //TODO 1
User get user => _user.value!; //TODO 3
Rx<File?>? pickedImageVal;
File? get profilePhoto => pickedImageVal!.value;
FirebaseAuth auth = FirebaseAuth.instance;
User? get userProfile => auth.currentUser;
var isSignedIn = false.obs;
var _googleSignIn = GoogleSignIn();
var googleAccount = Rx<GoogleSignInAccount?>(null);
var firebaseStorage = FirebaseStorage.instance;
var firestore = FirebaseFirestore.instance;
// var authController = AuthController.instance;
#override
void onReady() {
super.onReady();
_user = Rx<User?>(firebaseAuth.currentUser);
_user.bindStream(firebaseAuth.authStateChanges());
ever(_user, _setInitialScreen);
}
_setInitialScreen(User? user) {
if (user == null) {
Get.offAll(OnboardingPage());
} else {
Get.offAll(const Home());
}
}
#override
void onInit() {
displayName = userProfile != null ? userProfile!.displayName! : '';
super.onInit();
}
void pickImage() async {
final pickedImage =
await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
Get.snackbar(
'プロファイル写真', 'You have successfully selected your profile picture!');
}
pickedImageVal = Rx<File?>(File(pickedImage!.path));
}
Future<String> _uploadToStorage(File image) async {
Reference ref =
firebaseStorage.ref().child('profilePics').child(auth.currentUser!.uid);
UploadTask uploadTask = ref.putFile(image);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
void signUp(String name, String email, String password, File? image) async {
try {
await auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) {
displayName = name;
auth.currentUser!.updateDisplayName(name);
});
isSignedIn = true.obs;
String downloadUrl = await _uploadToStorage(profilePhoto!);
model.UserM user = model.UserM(
name: name,
email: email,
uid: auth.currentUser!.uid,
profilePhoto: downloadUrl,
);
await firestore
.collection('users')
.doc(auth.currentUser!.uid)
.set(user.toJson());
update();
Get.offAll(() => Root());
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'weak-password') {
message = 'The password provided is too weak.';
} else if (e.code == 'email-already-in-use') {
message = ('The account already exists for that email.');
} else {
message = e.message.toString();
}
Get.snackbar(title, message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signIn(String email, String password) async {
try {
await auth
.signInWithEmailAndPassword(email: email, password: password)
.then((value) => displayName = userProfile!.displayName!);
isSignedIn = true.obs;
myId = userProfile!.uid; //TODO 4
update();
Get.offAll(() => Root());
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'wrong-password') {
message = 'Invalid Password. Please try again!';
} else if (e.code == 'user-not-found') {
message =
('The account does not exists for $email. Create your account by signing up.');
} else {
message = e.message.toString();
}
Get.snackbar('ユーザー名が存在しません。', 'アカウントを作成してください。',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
//TODO; what is Get.snackbar.e.tostring(), means?
Get.snackbar(
'Error occured!',
e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white,
);
}
}
void resetPassword(String email) async {
try {
await auth.sendPasswordResetEmail(email: email);
Get.back();
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'user-not-found') {
message =
('The account does not exists for $email. Create your account by signing up.');
} else {
message = e.message.toString();
}
Get.snackbar(title, message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signInWithGoogle() async {
try {
googleAccount.value = await _googleSignIn.signIn();
print(googleAccount.value);
displayName = googleAccount.value!.displayName!;
displayPhoto = googleAccount.value!.photoUrl!;
isSignedIn.value = true;
update(); // <-- without this the isSignedin value is not updated.
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signout() async {
try {
await auth.signOut();
await _googleSignIn.signOut();
displayName = '';
isSignedIn.value = false;
update();
Get.offAll(() => Root());
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
}
//
// extension StringExtention on String{
// String capitalizedString(){
// return'${this[0].toUpperCase()}${this.substring(1)}';
// }
// }
user profile screen
class ProfileScreen extends StatefulWidget {
final String uid;
ProfileScreen({Key? key, required this.uid}) : super(key: key);
#override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
final ProfileController profileController = Get.put(ProfileController());
#override
void initState() {
super.initState();
profileController.updateUserID(widget.uid);
}
#override
Widget build(BuildContext context) {
return GetBuilder<ProfileController>(
init: ProfileController(),
builder: (controller) {
// if (controller.user.isEmpty) {
// return Center(
// child: CircularProgressIndicator(),
// );
// }
print(controller.user);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black12,
leading: Icon(Icons.person_add_alt_1_outlined),
actions: [
Icon(Icons.more_horiz),
],
title: Text(controller.user['name'].toString()),
),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipOval(
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: controller.user['profilePhoto']
.toString(),
height: 100,
width: 100,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error)),
)
],
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Text(controller.user['following'].toString()),
SizedBox(
height: 5,
),
Text('following'),
],
),
Container(
color: Colors.black54,
width: 1,
height: 15,
margin: EdgeInsets.symmetric(horizontal: 15),
),
Column(
children: [
Text(controller.user['followers'].toString()),
SizedBox(
height: 5,
),
Text('follower'),
],
),
Container(
color: Colors.black54,
width: 1,
height: 15,
margin: EdgeInsets.symmetric(horizontal: 15),
),
Column(
children: [
Text(controller.user['likes'].toString()),
SizedBox(
height: 5,
),
Text('likes'),
],
)
],
),
SizedBox(
height: 15,
),
Container(
width: 140,
height: 47,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black12,
),
),
child: Center(
child: InkWell(
onTap: () {
// if (widget.uid == authController.user.uid) {
// authController.signOut();
// } else {
// controller.followUser();
},
// },
child: const Text(
"",
// widget.uid == authController.user.uid
// ? 'sign out'
// controller.user['isFollowing']
// ? 'unfollow'
// : 'follow',
),
),
),
),
I'm working on a code that asks for an OTP verification code to register the phone in firebase. It works fine manually but I want to make the code or app read the code sent in SMS from firebase and check it automatically.
For example, most applications when the verification code is requested and after the phone receives the verification code, the code is automatically written in the verification code registration boxes.
I searched for a long time, but it didn't work with me.
full code:
class _OtpScreenState extends State<OtpScreen> {
String phoneNo;
String smsOTP;
String verificationId;
String errorMessage = '';
final FirebaseAuth _auth = FirebaseAuth.instance;
bool showLoading = false;
void signInWithPhoneAuthCredential(PhoneAuthCredential phoneAuthCredential) async {
setState(() {
showLoading = true;
});
try {
final authCredential = await _auth.signInWithCredential(phoneAuthCredential);
setState(() {
showLoading = false;
});
if (authCredential?.user != null) {
}
} on FirebaseAuthException catch (e) {
setState(() {
showLoading = false;
});
print(e.message);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: SingleChildScrollView(
child: Container(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: PinEntryTextField(
fields: 6,
onSubmit: (text) {
smsOTP = text as String;
},
),
),
],
),
GestureDetector(
onTap: () {
verifyOtp();
},
child: Container(
margin: const EdgeInsets.all(8),
height: 45,
width: double.infinity,
decoration: BoxDecoration(
color: CustomColors.Background,
borderRadius: BorderRadius.circular(0),
),
alignment: Alignment.center,
child: Text('Check'),
),
),
],
),
)
],
),
),
),
),
),
);
}
Future<void> generateOtp(String contact) async {
final PhoneCodeSent smsOTPSent = (String verId, [int forceCodeResend]) {
verificationId = verId;
};
try {
await _auth.verifyPhoneNumber(
phoneNumber: contact,
codeAutoRetrievalTimeout: (String verId) {
verificationId = verId;
},
codeSent: smsOTPSent,
timeout: const Duration(seconds: 60),
verificationCompleted: (AuthCredential phoneAuthCredential) {},
verificationFailed: (exception) {
print(exception);
});
} catch (e) {
handleError(e as PlatformException);
}
}
//Method for verify otp entered by user
Future<void> verifyOtp() async {
if (smsOTP == null || smsOTP == '') {
print('please enter 6 digit otp');
return;
}
try {
final AuthCredential credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsOTP,
);
signInWithPhoneAuthCredential(credential);
} catch (e) {
handleError(e as PlatformException);
} }
void handleError(PlatformException error) {
switch (error.code) {
case 'ERROR_INVALID_VERIFICATION_CODE':
FocusScope.of(context).requestFocus(FocusNode());
setState(() {
errorMessage = 'Invalid Code';
});
print('error');
break;
default:
print('error');
break;
}
}
}
For IOS, SMS autofill is provided by default.
For android you can use this package.
Use this in your code:
String otpValue = credential.smsCode.toString();
Example from my code:
I am trying to access the fullName from the list created in my Future function, but unable to do. I tried it through indexing and this method I have tried snapshot.data.fullName, but still unable to retrieve the data, even after returning from future function I was facing problems.
Below is code for User model
class User {
final String fullname;
final String contactno;
final String address;
final String city;
final String gender;
final String email;
User(this.fullname, this.contactno, this.address, this.city, this.gender, this.email);
factory User.fromMap(Map<String, dynamic> json) {
return User(
json['fullname'],
json['contactno'],
json['address'],
json['city'],
json['gender'],
json['email']
);
}
}
Stateful Class Code
class EditProfile extends StatefulWidget {
// final String user_fullname;
// //const EditProfile(this.user_fullname);
// const EditProfile ({ Key key, this.user_fullname}): super(key: key);
#override
_EditProfileState createState() => _EditProfileState();
}
Future<List<User>> getData() async {
var id = "26";
var url = baseurl + patientData + id;
var data;
var rest;
print('Calling uri: $url');
// 4
http.Response response = await http.get(url);
// 5
if (response.statusCode == 200) {
data = response.body;
print(data);
} else {
print(response.statusCode);
}
//Map<String, dynamic> user = jsonDecode(data);
var jsonData = jsonDecode(data.body);
List<User> users = [];
for (var u in jsonData) {
User user = User(u['fullname'], u['contactno'], u['address'], u['city'], u['gender'], u['email']);
users.add(user);
}
// print(users.length.toString);
}
I want to access the fullName from my above list in future function in Text widget where I have used snapshot.data.fullName below
class _EditProfileState extends State<EditProfile> {
#override
void initState() {
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
getData().then((value) {
print(value);
});
return FutureBuilder(
future: getData(),
// ignore: missing_return
builder: (context, snapshot) {
if (snapshot.hasData) {
return WillPopScope(
onWillPop: () {},
child: Scaffold(
appBar: AppBar(title: Text("Your Profile"), automaticallyImplyLeading: false, actions: <Widget>[
IconButton(
icon: Icon(
Icons.logout,
color: Colors.white,
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => PatientDashboard()));
},
)
]),
body: SingleChildScrollView(
child: Container(
// color: Colors.pink,
child: Column(
children: [
Center(
child: Padding(
padding: const EdgeInsets.only(top: 18.0),
child: Container(
// color: kPrimaryLightColor,
child: Stack(
children: [
//Image
CircleAvatar(
radius: 100,
backgroundColor: Colors.red[900],
child: CircleAvatar(
radius: 95,
backgroundImage: _pic == null ? AssetImage("assets/images/doctor2.jpg") : FileImage(_pic),
),
),
Positioned(
bottom: 5,
right: 15,
child: CircleAvatar(
backgroundColor: Colors.cyanAccent,
child: GestureDetector(
onTap: () {
setState(() {
//firstname = widget.user_fullname;
getImage();
state = 19;
});
},
child: Icon(Icons.camera_alt)),
radius: 20,
),
)
],
),
),
),
),
//Name
Container(
width: double.infinity,
//color: Colors.grey[400],
child: Stack(
children: [
Center(
child: Padding(
padding: const EdgeInsets.only(left: 18.0, top: 20),
child: Container(
//color: Colors.cyan[50],
width: MediaQuery.of(context).size.width * 0.78,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Name"),
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: state == 1
? TextField(
decoration: InputDecoration(border: InputBorder.none, hintText: "${snapshot.data}", hintStyle: TextStyle(fontSize: 17, fontWeight: FontWeight.bold)), //style: TextStyle(under),
onChanged: (text) {
firstname = text;
},
)
: Text(
snapshot.data.fullName,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
)],
else {
return Center(child: CircularProgressIndicator());
}
},
);
}
}
but I am getting this error
Error: NoSuchMethodError: 'body'
method not found
```
Arguments: []
at Object.throw_ [as throw] (http://localhost:59886/dart_sdk.js:5333:11)
at Object.defaultNoSuchMethod (http://localhost:59886/dart_sdk.js:5778:15)
at String.noSuchMethod (http://localhost:59886/dart_sdk.js:6878:19)
at Object.noSuchMethod (http://localhost:59886/dart_sdk.js:5774:30)
at Object.dload (http://localhost:59886/dart_sdk.js:5395:17)
at getData (http://localhost:59886/packages/newfypapproach/patient/screens/patientForgotPassword.dart.lib.js:12720:64)
at getData.next (<anonymous>)
at http://localhost:59886/dart_sdk.js:39031:33
at _RootZone.runUnary (http://localhost:59886/dart_sdk.js:38888:58)
at _FutureListener.thenAwait.handleValue (http://localhost:59886/dart_sdk.js:33874:29)
at handleValueCallback (http://localhost:59886/dart_sdk.js:34434:49)
at Function._propagateToListeners (http://localhost:59886/dart_sdk.js:34472:17)
at _Future.new.[_completeWithValue] (http://localhost:59886/dart_sdk.js:34314:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:59886/dart_sdk.js:34337:35)
at Object._microtaskLoop (http://localhost:59886/dart_sdk.js:39175:13)
at _startMicrotaskLoop (http://localhost:59886/dart_sdk.js:39181:13)
at http://localhost:59886/dart_sdk.js:34688:9
```
I had used this different approach for creating a future function returning list of strings and the list was working perfectly having all values.
```
Future<List<String>> getData() async {
var id = "26";
var url = baseurl + patientData + id;
var data;
var rest;
print('Calling uri: $url');
// 4
http.Response response = await http.get(url);
// 5
if (response.statusCode == 200) {
data = response.body;
print(data);
// rest = data['result'] as List;
// print(rest);
//print(data);
} else {
print(response.statusCode);
}
Map<String, dynamic> user = jsonDecode(data);
// var name = user['result']['name'];
String fullName = user['result'][0][0];
String contactNo = user['result'][0][1];
String address = user['result'][0][2];
String city = user['result'][0][3];
String gender = user['result'][0][4];
String email = user['result'][0][5];
return <String>[fullName, contactNo, address, city, gender, email];
}
Change your getData as follows
Future<List<User>> getData() async {
var id = "26";
var url = baseurl + patientData + id;
Map<String, dynamic> data ={};
var rest;
// 4
http.Response response = await http.get(url);
// 5
if (response.statusCode == 200) {
data = response.body;
print(data);
} else {
print(response.statusCode);
}
//Map<String, dynamic> user = jsonDecode(data);
var jsonData = jsonDecode(data);
List<User> users = [];
for (var u in jsonData) {
User user = User(u['fullname'], u['contactno'], u['address'], u['city'], u['gender'], u['email']);
users.add(user);
}
return users; }