I hope you all are doing well today. I have another flutter issue that I have been stuck on for the past few days now. I'm attempting to upload this data to my firestore instance, but my post button never seems to be triggering. I have attempted to print a statement from the method that it evokes, but I can't seem to get that to work either. I'm attempting to create a social media app, and any and all help would be appreciated.
My main goal is to get the post button to execute in upload.dart.
I have also included home.dart since the two classes are connected in terms of performance.
upload.dart
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttermedia/models/user.dart';
import 'package:fluttermedia/pages/home.dart';
import 'package:fluttermedia/widgets/progress.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:image/image.dart' as Im;
import 'package:uuid/uuid.dart';
class Upload extends StatefulWidget {
final User currentUser;
Upload({this.currentUser});
#override
_UploadState createState() => _UploadState();
}
class _UploadState extends State<Upload> {
TextEditingController locationController = TextEditingController();
TextEditingController captionController = TextEditingController();
File file;
bool isUploading = false;
String postId = Uuid().v4();
handleChooseFromGallery() async{
Navigator.pop(context);
File file = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
this.file = file;
});
}
handleTakePhoto() async {
Navigator.pop(context);
File file = await ImagePicker.pickImage(source: ImageSource.camera,maxHeight: 675,maxWidth: 960);
setState(() {
this.file = file;
});
}
selectImage(parentContext){
return showDialog(
context: parentContext,
builder: (context) {
return SimpleDialog(
title: Text("Create Post"),
children: <Widget>[
SimpleDialogOption(
child: Text("Photo With Camera"),
onPressed: handleTakePhoto,
),
SimpleDialogOption(
child: Text("Image from Gallery"),
onPressed: handleChooseFromGallery,
),
SimpleDialogOption(
child: Text("Cancel"),
onPressed: () => Navigator.pop(context),
),
],
);
}
);
}
Container buildSplashScreen(){
return Container(
color: Theme.of(context).accentColor.withOpacity(0.6),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset('assets/images/upload.svg',height: 260.0,),
Padding(
padding: EdgeInsets.only(top:20.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Text(
"Upload Image",
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
),
),
color: Colors.deepOrange,
onPressed: () => selectImage(context),
),
)
],
),
);
}
clearImage(){
setState(() {
file = null;
});
}
//This compresses images for firebase
compressImage() async{
final tempDir = await getTemporaryDirectory();
final path = tempDir.path;
Im.Image imageFile = Im.decodeImage(file.readAsBytesSync());
final compressedImageFile = File('$path/img_$postId.jpg')..writeAsBytesSync(Im.encodeJpg(imageFile,quality: 85));
setState(() {
file = compressedImageFile;
});
}
Future<String> uploadImage(imageFile) async{
StorageUploadTask uploadTask = storageRef.child("post_$postId.jpg").putFile(imageFile);
StorageTaskSnapshot storageSnap = await uploadTask.onComplete;
String downloadUrl = await storageSnap.ref.getDownloadURL();
return downloadUrl;
}
//upload new info to firestore that creates a new collection
createPostInFirestore({String mediaUrl, String location, String description}){
postsRef.document(widget.currentUser.id)
.collection("userPosts")
.document(postId)
.setData({
"postId": postId,
"ownerId": widget.currentUser.id,
"username": widget.currentUser.username,
"mediaUrl": mediaUrl,
"description": description,
"location": location,
"timestamp": timeStamp,
"likes":{}
});
}
//Getting the info from the caption, location and pic
handleSubmit() async{
setState(() {
isUploading = true;
});
await compressImage();
String mediaUrl = await uploadImage(file);
createPostInFirestore(
mediaUrl: mediaUrl,
location: locationController.text,
description: captionController.text,
);
captionController.clear();
locationController.clear();
setState(() {
file = null;
isUploading = false;
});
}
Scaffold buildUploadForm(){
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white70,
leading: IconButton(
icon: Icon(Icons.arrow_back,color: Colors.black,),
onPressed: clearImage,
),
title: Text(
"Caption Post",
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
FlatButton(
onPressed: () => isUploading ? null : () => handleSubmit(),
child: Text(
"Post",
style: TextStyle(
color: Colors.blueAccent,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
)
],
),
body: ListView(
children: <Widget>[
isUploading ? linearProgress(context):Text(""),
Container(
height: 220.0,
width: MediaQuery.of(context).size.width*0.8,
child: Center(
child: AspectRatio(
aspectRatio: 16/9,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: FileImage(file),
)
),
),
),
),
),
Padding(
padding: EdgeInsets.only(top:10),
),
ListTile(
leading: CircleAvatar(
backgroundImage: CachedNetworkImageProvider(widget.currentUser.photoUrl),
),
title: Container(
width: 250.0,
child: TextField(
controller: captionController,
decoration: InputDecoration(
hintText: "Write a Caption...",
border: InputBorder.none,
),
),
),
),
Divider(),
ListTile(
leading: Icon(Icons.pin_drop,color: Colors.orange,size: 35.0),
title: Container(
width: 250.0,
child: TextField(
controller: locationController,
decoration: InputDecoration(
hintText: "Where was this photo taken",
border: InputBorder.none,
),
),
),
),
Container(
width: 200.0,
height: 100.0,
alignment: Alignment.center,
child: RaisedButton.icon(
label: Text(
"Use Current Location",
style: TextStyle(color: Colors.white),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Colors.blue,
onPressed: () => print("Get user location"),
icon: Icon(
Icons.my_location,
color: Colors.white,
),
),
)
],
),
);
}
#override
Widget build(BuildContext context) {
return file == null ? buildSplashScreen() : buildUploadForm();
}
}
home.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttermedia/models/user.dart';
import 'package:fluttermedia/pages/activity_feed.dart';
import 'package:fluttermedia/pages/create_account.dart';
import 'package:fluttermedia/pages/profile.dart';
import 'package:fluttermedia/pages/search.dart';
import 'package:fluttermedia/pages/upload.dart';
import 'package:google_sign_in/google_sign_in.dart';
final GoogleSignIn googleSignIn = GoogleSignIn();
final StorageReference storageRef = FirebaseStorage.instance.ref();
final usersRef = Firestore.instance.collection('users');
final postsRef = Firestore.instance.collection('posts');
final DateTime timeStamp = DateTime.now();
User currentUser;
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool isAuth = false;
PageController pageController;
int pageIndex = 0;
#override
void initState() {
super.initState();
pageController = PageController();
// Detects if user signs in
googleSignIn.onCurrentUserChanged.listen((account) {
handleSignIn(account);
}, onError: (err){
print('Error sigining in: $err');
});
//Reauthenticate user when app is opened
googleSignIn.signInSilently(suppressErrors: false)
.then((account) =>
handleSignIn(account)).catchError((err){
print('Error signing in on retry: $err');
});
}
#override
Widget build(BuildContext context) {
return isAuth ? buildAuthScreen() : buildUnAuthScreen();
}
#override
void dispose(){
pageController.dispose();
super.dispose();
}
//Helper Functions
//The sign in section of the code
handleSignIn(GoogleSignInAccount account){
if(account != null){
createUserInFirestore();
setState(() {
isAuth = true;
});
}else{
setState(() {
isAuth = false;
});
}
}
login(){
googleSignIn.signIn();
}
logout(){
googleSignIn.signOut();
}
onPageChanged(int pageIndex){
setState(() {
this.pageIndex = pageIndex;
});
}
createUserInFirestore() async{
// 1) Check if user exists in users collection in database (According to id)
final GoogleSignInAccount user = googleSignIn.currentUser;
DocumentSnapshot doc = await usersRef.document(user.id).get();
if(!doc.exists){
// 2) If the user doesn't exist, take them to create account page
final username = await Navigator.push(context, MaterialPageRoute(builder: (context) => CreateAccount()));
// 3) get username from create account, use it to make new user document in users collection
usersRef.document(user.id).setData({
"id":user.id,
"username":username,
"photoUrl": user.photoUrl,
"email":user.email,
"displayName": user.displayName,
"bio":"",
"timeStamp": timeStamp,
});
doc = await usersRef.document(user.id).get();
}
currentUser = User.fromDocument(doc);
//print(currentUser);
//print(currentUser.username);
}
onTap(int pageIndex){
//This what you would use to animate in between the different screens
pageController.animateToPage(
pageIndex,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut
);
}
//UI Code
Widget buildAuthScreen() {
return Scaffold(
body: PageView(
children: <Widget>[
//Timeline(),
RaisedButton(
child: Text('Logout'),
onPressed: logout,
),
ActivityFeed(),
Upload(currentUser: currentUser),
Search(),
Profile(),
],
controller: pageController,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: CupertinoTabBar(
currentIndex: pageIndex,
onTap: onTap,
activeColor: Theme.of(context).primaryColor,
items: [
BottomNavigationBarItem(icon: Icon(Icons.whatshot),),
BottomNavigationBarItem(icon: Icon(Icons.notifications_active),),
BottomNavigationBarItem(icon: Icon(Icons.photo_camera, size: 34.0,),),
BottomNavigationBarItem(icon: Icon(Icons.search),),
BottomNavigationBarItem(icon: Icon(Icons.account_circle),),
],
),
);
/*return RaisedButton(
child: Text('Logout'),
onPressed: logout,
);*/
}
Scaffold buildUnAuthScreen() {
return Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Theme.of(context).primaryColor,
Theme.of(context).accentColor,
]
)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text('FlutterMedia',
style: TextStyle(
fontFamily: "Signatra",
fontSize: 90.0,
color: Colors.white
),
),
GestureDetector(
onTap:() => login(),
child: Container(
width: 260,
height: 60,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/google_signin_button.png'),
fit: BoxFit.cover,
),
),
),
)
],
),
),
);
}
}
onPressed: () => isUploading ? null : () => handleSubmit(),
Well, there's your problem. You meant to have a tertiary condition that makes onPressed call handleSubmit when isUploading is false. Instead, you have made onPressed into a function that returns a function.
To hopefully make that more clear, let's blow this function up into proper non-lambda functions and if/else blocks:
onPressed: () {
if (isUploading) {
return null;
} else {
return () {
handleUpload();
}
}
}
So consider what happens when the button is pressed. It calls the outer function, which checks isUploading. If true, the function returns null, and if false, it returns another function that, if called, calls handleUpload. So how this plays out is that onPressed will never be null (it just returns null sometimes) and handleUpload never gets called (since the inner function that is returned is never then called itself).
Remove the outer lambda and it will work:
onPressed: isUploading ? null : () => handleSubmit(),
Related
So I made a CRUD app with Firebase Firestore in Flutter. I have this error where it says
Exception caught by gesture
═══════════════════════
a document path must be a non-empty string
'package:cloud_firestore/src/collection_reference.dart':
package:cloud_firestore/src/collection_reference.dart:1
Failed assertion: line 116 pos 14: 'path.isNotEmpty'
I build this app with various tutorial videos in Youtube. I can make the Create, Read, and Delete features but I face this problem with Update features. Here's the code ...or check this Github https://github.com/rayhanyovi/Dapurku
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:dapurkuu/warna.dart';
import 'package:dapurkuu/widget.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
//=====================================
const Color Red = Color(0xFFDA4040);
const Color Blue = Color(0xFF5F52EE);
const Color Black = Color(0xFF3A3A3A);
const Color Grey = Color(0xFF717171);
const Color BGColor = Color(0xFFEEEFF5);
final controllerName = TextEditingController();
final controllerAge = TextEditingController();
final controllerBirthday = TextEditingController();
final updateName = TextEditingController();
final updateAge = TextEditingController();
final updateBirthday = TextEditingController();
//=====================================
class User {
String id;
final String name;
final int age;
final DateTime birthday;
User({
this.id = '',
required this.name,
required this.age,
required this.birthday,
});
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'age': age,
'birthday': birthday,
};
static User fromJson(Map<String, dynamic> json) => User(
id: json['id'],
name: json['name'],
age: json['age'],
birthday: (json['birthday'] as Timestamp).toDate(),
);
}
//=====================================
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(statusBarColor: Colors.transparent));
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Test",
home: Home(),
);
}
}
//=====================================
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final CollectionReference _users =
FirebaseFirestore.instance.collection('users');
#override
Widget build(BuildContext context) {
Future createUser(User user) async {
final docUser = FirebaseFirestore.instance.collection('users').doc();
user.id = docUser.id;
final json = user.toJson();
await docUser.set(json);
Future updateUser(User user) async {
final docUser = FirebaseFirestore.instance.collection('users').doc();
user.id = docUser.id;
final json = user.toJson();
await docUser.update(json);
}
}
Widget buildUser(User user) {
return Container(
margin: EdgeInsets.only(
right: 20,
left: 20,
bottom: 15,
),
child: Material(
child: ListTile(
onTap: () {
print("card");
},
contentPadding:
EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 15),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
tileColor: Colors.white,
title: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(
user.name,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jumlah: ${user.age}',
),
Text(
'Kadaluarsa: ${DateFormat('dd MMMM yyyy').format(user.birthday)}')
],
),
trailing: Wrap(spacing: 0, children: [
IconButton(
icon: Icon(Icons.edit),
iconSize: 24,
color: Colors.black,
onPressed: () async {
await Edit(context, createUser);
},
),
IconButton(
icon: Icon(Icons.delete),
iconSize: 24,
color: Colors.red,
onPressed: () {
final docUser = FirebaseFirestore.instance
.collection('users')
.doc(user.id);
docUser.delete();
},
),
]),
),
),
);
}
return Scaffold(
backgroundColor: BGColor,
appBar: _AppBar(),
body: Column(
children: [
/* JUDUL */
Column(
children: [
Container(
margin: EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
child: SearchBox()),
Container(
margin: EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
child: Text(
'Bahan Dapurmu',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Black,
),
),
)
],
),
/* STREAM BUILDER */
StreamBuilder(
stream: readUsers(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final users = snapshot.data!;
return Expanded(
child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: users.map(buildUser).toList(),
),
);
} else if (snapshot.hasError) {
return Container(
child: Text("data kosong"),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Create(context, createUser);
},
child: Icon(Icons.add),
),
);
}
Edit(BuildContext context, Future<dynamic> updateUser(User user)) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Tambahkan bahan"),
content: Column(
children: [
TextField(
decoration: const InputDecoration(
labelText: 'Nama',
),
controller: updateName,
),
TextField(
decoration: const InputDecoration(
labelText: 'Umur',
),
controller: updateAge,
keyboardType: TextInputType.number,
),
TextField(
controller: updateBirthday,
//editing controller of this TextField
decoration: InputDecoration(
labelText: "Enter Date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1950),
//DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2100));
if (pickedDate != null) {
print(
pickedDate);
//pickedDate output format => 2021-03-10 00:00:00.000
//formatted date output using intl package => 2021-03-16
setState(() {
updateBirthday.text = pickedDate
.toString(); //set output date to TextField value.
});
} else {}
},
),
],
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("Ubah Data"),
onPressed: () {
final user = User(
name: updateName.text,
age: int.parse(updateAge.text),
birthday: DateTime.parse(updateBirthday.text),
);
final docUser = FirebaseFirestore.instance
.collection('users')
.doc(user.id);
updateUser(user);
}),
],
);
});
}
Create(BuildContext context, Future<dynamic> createUser(User user)) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Tambahkan bahan"),
content: Column(
children: [
TextField(
decoration: const InputDecoration(
labelText: 'Nama',
),
controller: controllerName,
),
TextField(
decoration: const InputDecoration(
labelText: 'Umur',
),
controller: controllerAge,
keyboardType: TextInputType.number,
),
TextField(
controller: controllerBirthday,
//editing controller of this TextField
decoration: InputDecoration(
labelText: "Enter Date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1950),
//DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2100));
if (pickedDate != null) {
print(
pickedDate);
//pickedDate output format => 2021-03-10 00:00:00.000
//formatted date output using intl package => 2021-03-16
setState(() {
controllerBirthday.text = pickedDate
.toString(); //set output date to TextField value.
});
} else {}
},
),
],
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("Tambahkan"),
onPressed: () {
final user = User(
name: controllerName.text,
age: int.parse(controllerAge.text),
birthday: DateTime.parse(controllerBirthday.text),
);
createUser(user);
}),
],
);
});
}
Stream<List<User>> readUsers() => FirebaseFirestore.instance
.collection('users')
.snapshots()
.map((snapshot) =>
snapshot.docs.map((doc) => User.fromJson(doc.data())).toList());
}
//=====================================
AppBar _AppBar() {
return AppBar(
elevation: 0,
backgroundColor: BGColor,
title: Center(
child: Text(
"Dapurku",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Black,
),
),
),
);
}
//=====================================
class UpdateButton extends StatelessWidget {
const UpdateButton({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: IconButton(
icon: Icon(Icons.edit),
iconSize: 24,
color: Colors.black,
onPressed: () {},
),
);
}
}
//=====================================
class SearchBox extends StatelessWidget {
const SearchBox({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 10),
child: const TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0),
prefixIcon: Icon(
Icons.search,
color: Black,
size: 20,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 20,
minWidth: 25,
),
border: InputBorder.none,
hintText: "Cari Bahan...",
hintStyle: TextStyle(
color: Grey,
)),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
);
}
}
Can you tell me what I did wrong or help me solve the problem? I've been looking for it anywhere and solving this problem for days. It is for my school assignment :/
The auth.dart page looks like this, when I click on login it gives this error.
Exception has occurred.
FirebaseAuthException ([firebase_auth/unknown] Given String is empty or null)
import 'package:cloud_firestore/cloud_firestore.dart';
import "package:firebase_auth/firebase_auth.dart";
import 'package:firebase_core/firebase_core.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
//giriş yap fonksiyonu
Future<User?> signIn(String email, String password) async {
var user = await _auth.signInWithEmailAndPassword(
email: email, password: password);
return user.user;
}
//çıkış yap fonksiyonu
signOut() async {
return await _auth.signOut();
}
//kayıt ol fonksiyonu
Future<User?> createPerson(String name, String email, String password) async {
var user = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
await _firestore
.collection("Person")
.doc(user.user!.uid)
.set({'userName': name, 'email': email});
return user.user;
}
}
It also redirects to errors_patch.dart page. I don't understand that.
#patch
class Error {
#patch
static String _objectToString(Object object) {
return Object._toString(object);
}
#patch
static String _stringToSafeString(String string) {
return json.encode(string);
}
#patch
StackTrace? get stackTrace => _stackTrace;
#pragma("vm:entry-point")
StackTrace? _stackTrace;
#patch
#pragma("vm:external-name", "Error_throwWithStackTrace")
external static Never _throw(Object error, StackTrace stackTrace);
Okay, so apparently, the solution is to add the text editing controller you declared to their respective textfield.
import 'package:flutter/material.dart';
import 'package:meetime_app/constant/picture.dart';
import 'package:meetime_app/home.dart';
import 'package:meetime_app/service/auth.dart';
import '../constant/colors.dart';
import '../constant/text_style.dart';
//Değişkenler tanımlandı.
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
//AuthService Değişkeni eklendi
AuthService _authService = AuthService();
class LoginPage extends StatefulWidget {
LoginPage({Key? key}) : super(key: key);
#override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: SingleChildScrollView(
child: Container(
margin: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 75),
_inputImage(context),
_inputField(context),
_inputTextButton(context),
_inputButton(context),
_inputGoogleLogin(context),
],
),
)),
));
}
_inputImage(context) {
return Image.asset(meetimeLogo, height: 250, width: 500);
}
_inputField(context) {
return Column(children: [
TextField(
controller: _emailController,
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.mail,
),
label: Text("E-mail-Username",
style: TextStyleMeetime.headline16subtitle),
hintText: "E-mail-Username",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
),
),
const SizedBox(
height: 20,
),
TextField(
controller: _passwordController,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.check),
label: Text("Password", style: TextStyleMeetime.headline16subtitle),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
),
obscureText: true,
),
]);
}
_inputTextButton(context) {
return Container(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
child: Text("Şifremi Unuttum", style: TextStyleMeetime.blacktext14)),
);
}
_inputButton(context) {
return Container(
color: ColorsPalette.pinkOpacityPalette80,
height: 39,
width: 129,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: ColorsPalette.pinkOpacityPalette80,
),
onPressed: () {
//Firebase Giriş İşlemleri
_authService.signIn(
_emailController.text, _passwordController.text);
// Bitiş
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return HomeNavigatePage();
},
));
},
child: Text(
"Giriş Yap",
style: TextStyleMeetime.whitetext16,
)),
);
}
_inputGoogleLogin(context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
iconPictureGoogle,
height: 24,
width: 24,
),
TextButton(
onPressed: () {},
child: Text(
"Google ile Giriş Yap",
style: TextStyleMeetime.headline16subtitle,
))
],
);
}
}
Note
I added the controller to the form field, so this should solve your problem.
I'm trying to consume an API for the login screen but keep getting this error.
I want to be able to login via an API to my flutter app.
the first part is what is being posted to the API and the second part is the server response as seen on the code below
I/flutter ( 892): {email: rashid.david12#gmail.com, password: 123456789}
I/flutter ( 892): {errors: [The email field is required., The password field is required.]}
This is my code, what should I do, or any workaround for the error above?
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class Signin extends StatefulWidget {
#override
_SigninState createState() => _SigninState();
}
class _SigninState extends State<Signin> {
// For CircularProgressIndicator.
bool visible = false ;
// Getting value from TextField widget.
final emailController = TextEditingController();
final passwordController = TextEditingController();
Future userLogin() async{
// Showing CircularProgressIndicator.
setState(() {
visible = true ;
});
// Getting value from Controller
String email = emailController.text;
String password = passwordController.text;
// SERVER LOGIN API URL
var url = 'http://192.236.160.238/api/login';
// Store all data with Param Name.
var data = {'email': email, 'password' : password};
// Starting Web API Call.
var response = await http.post(url, body: json.encode(data[email]));
print(data);
// Getting Server response into variable.
var message = jsonDecode(response.body);
print(message);
// If the Response Message is Matched.
if(message == 'success')
{
// Hiding the CircularProgressIndicator.
setState(() {
visible = false;
});
// Navigate to Home & Sending Email to Next Screen.
Navigator.pushNamed(context, '/home');
}else{
// If Email or Password did not Matched.
// Hiding the CircularProgressIndicator.
setState(() {
visible = false;
});
// Showing Alert Dialog with Response JSON Message.
// showDialog(
// context: context,
// builder: (BuildContext context) {
// return AlertDialog(
// title: new Text(message),
// actions: <Widget>[
// FlatButton(
// child: new Text("OK"),
// onPressed: () {
// Navigator.of(context).pop();
// },
// ),
// ],
// );
// },
// );
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
title: const Text('Bdm Self Service App'),
centerTitle: true,
actions: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.search),
),
],
backgroundColor: Colors.blue,
elevation: 0.0,
),
body: Padding(
padding: EdgeInsets.fromLTRB(30.0, 40.0, 30.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: CircleAvatar(
backgroundImage: AssetImage('assets/rcmsbg.png'),
radius: 60.0,
),
),
SizedBox(height: 10.0),
TextFormField(
controller: emailController,
decoration: InputDecoration(labelText: 'Enter Username or Email'),
),
SizedBox(height: 10.0),
TextFormField(
controller: passwordController,
decoration: InputDecoration(labelText: 'Enter Password'),
autofocus: false,
obscureText: true,
),
SizedBox(height: 20.0),
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.green)),
onPressed: userLogin,
child: Text('login'),
color: Colors.green,
minWidth: 300.0,
),
SizedBox(height: 20.0),
Text('Forgot Password?'),
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.green)),
onPressed: () {
Navigator.pushNamed(context, '/resetpassword');
},
child: Text('Reset Password'),
color: Colors.green,
minWidth: 200.0,
),
SizedBox(height: 20.0),
Text('Do not have an account yet?'),
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.green)),
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: Text('Sign Up'),
color: Colors.green,
minWidth: 200.0,
),
],
),
// ],
),
// ),
);
}
}
If I am reading your code correctly, on the login function you are only
sending email and
// Store all data with Param Name.
var data = {'email': email, 'password' : password};
// Starting Web API Call.
var response = await http.post(url, body: json.encode(data)); // REMOVED [email]
print(data);
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
class SignUpScreen extends StatefulWidget {
const SignUpScreen({Key? key}) : super(key: key);
#override
_SignUpScreenState createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
void login(String email , password) async {
try{
Response response = await post(
Uri.parse('https://reqres.in/api/login'),
body: {
'email' : 'eve.holt#reqres.in',
'password' : 'cityslicka'
}
);
if(response.statusCode == 200){
var data = jsonDecode(response.body.toString());
print(data['token']);
print('Login successfully');
}else {
print('failed');
}
}catch(e){
print(e.toString());
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sign Up Api'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: emailController,
decoration: InputDecoration(
hintText: 'Email'
),
),
SizedBox(height: 20,),
TextFormField(
controller: passwordController,
decoration: InputDecoration(
hintText: 'Password'
),
),
SizedBox(height: 40,),
GestureDetector(
onTap: (){
login(emailController.text.toString(), passwordController.text.toString());
},
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(10)
),
child: Center(child: Text('Login'),),
),
)
],
),
),
);
}
}
I am working on an application to set wallpapers, which comes to the application through the link "imgUrl", but when I want to set a specific image as wallpaper it gives me this error,
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)
I hope you will give me an easy way to set an image as a wallpaper and also a way to save the image inside the device,
Note: I am using flutter for Android only
import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:get/get.dart';
import 'package:image_downloader/image_downloader.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'dart:io';
import 'dart:async';
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:wallpaper/wallpaper.dart';
class ImgDetails extends StatefulWidget {
#override
_ImgDetailsState createState() => _ImgDetailsState();
}
class _ImgDetailsState extends State<ImgDetails> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
var imgPath ;
String home = "Home Screen",
lock = "Lock Screen",
both = "Both Screen",
system = "System";
String _title = Get.arguments['title'];
String _imgUrl = Get.arguments['url'];
#override
Widget build(BuildContext context) {
final snackBar = SnackBar(
content: Text(_title),
duration: const Duration(seconds:3),
);
return Scaffold(
appBar: AppBar(
title: Text(_title),
centerTitle: true,
),
key: _scaffoldKey,
body: Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
height: double.infinity,
child: InteractiveViewer(
maxScale: 6,
child: FadeInImage(
image: NetworkImage(_imgUrl),
placeholder: AssetImage('assets/img/img_ot_found.jpg'),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: MediaQuery.of(context).size.width*0.8,
height: MediaQuery.of(context).size.height*0.08,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.purple , Colors.purpleAccent]
)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(icon: Icon(Icons.save_alt_rounded , color: Colors.white,size: 32), onPressed: (){
}),
IconButton(icon: Icon(Icons.imagesearch_roller, color: Colors.white,size: 32), onPressed: (){
_modal();
}),
IconButton(icon: Icon(Icons.info_outline, color: Colors.white,size: 32,), onPressed: (){
_scaffoldKey.currentState.showSnackBar(snackBar);
}),
],
),
),
),
],
),
);
}
_askPermission() async {
if (Platform.isAndroid) {
await PermissionHandler().requestPermissions([
PermissionGroup.storage,
PermissionGroup.camera,
PermissionGroup.location,
]);
} else {
await PermissionHandler()
.checkPermissionStatus(PermissionGroup.storage);
}
}
_modal() {
showModalBottomSheet(
backgroundColor: Colors.white.withOpacity(0.2),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30,)),
context: context,
builder: (BuildContext context) {
return Container(
height: 130,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.8),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
)
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_createTile(context, 'Home Screen', Icons.home, _action1),
SizedBox(height: 10,),
_createTile(context, 'Lock Screen', Icons.lock, _action2),
],
),
);
}
);
}
ListTile _createTile(BuildContext context, String name, IconData icon,
Function action) {
return ListTile(
leading: Icon(icon,
color: Colors.blueAccent,),
title: Text(name,
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.w500, fontSize: 20),),
onTap: () {
Navigator.pop(context);
action();
},
);
}
_action1() async {
if (Platform.isAndroid) {
await _askPermission();
}
var response = await Dio()
.get(_imgUrl, options: Options(responseType: ResponseType.bytes));
//await ImageGallerySaver.saveImage(Uint8List.fromList(response.data));
home = await Wallpaper.homeScreen(_imgUrl);
final result = home = home;
print(result);
}
_action2() async {
if (Platform.isAndroid) {
await _askPermission();
}
var response = await Dio()
.get(_imgUrl, options: Options(responseType: ResponseType.bytes));
//await ImageGallerySaver.saveImage(Uint8List.fromList(response.data));
home = await Wallpaper.lockScreen(_imgUrl);
final result = home = lock;
print(result);
}
}
You are having a problem with the permission. You need to add a permission code to the AndroidManifest file. Can you send me all the error logs so I can figure out what privilege is missing?
I my project I am using google sign in and i want to maintain persistent sign in how to do it for the below code. The problem is once i sign in and if i close the app then when I reopen the app i have to sign in again.
Once I open the app i get an option to Sign in with google once i sign in with google I got to the first screen where details about me the signed in user are available and then if i close the app without signing in then when I restart the application i have to sign in again how should i sign in once and be signed in until i press the sign out button
main.dart
import 'package:flutter/material.dart';
import 'login_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Login',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(),
);
}
}
login_page.dart
import 'package:chat/sign_in.dart';
import 'package:flutter/material.dart';
import 'first_screen.dart';
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(size: 150),
SizedBox(height: 50),
_signInButton(),
],
),
),
),
);
}
Widget _signInButton() {
return OutlineButton(
splashColor: Colors.grey,
onPressed: () {
signInWithGoogle().whenComplete(
() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
},
);
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("assets/google_logo.png"), height: 35.0),
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
)
],
),
),
);
}
}
sign_in.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
String name;
String email;
String imageUrl;
Future<String> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
// Checking if email and name is null
assert(user.email != null);
assert(user.displayName != null);
assert(user.photoUrl != null);
name = user.displayName;
email = user.email;
imageUrl = user.photoUrl;
// Only taking the first part of the name, i.e., First Name
if (name.contains(" ")) {
name = name.substring(0, name.indexOf(" "),);
}
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
void signOutGoogle() async {
await googleSignIn.signOut();
print("User Sign Out");
}
first_screen.dart
import 'package:chat/login_page.dart';
import 'package:chat/sign_in.dart';
import 'package:flutter/material.dart';
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Colors.blue[100], Colors.blue[400]],
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
imageUrl,
),
radius: 60,
backgroundColor: Colors.transparent,
),
SizedBox(height: 40),
Text(
'NAME',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
name,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Text(
'EMAIL',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
email,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
RaisedButton(
onPressed: () {
signInWithGoogle();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) {
return LoginPage();
},
),
ModalRoute.withName('/'),
);
},
color: Colors.deepPurple,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Sign Out',
style: TextStyle(fontSize: 25, color: Colors.white),
),
),
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40)),
)
],
),
),
),
);
}
}
The main() method is the first method called and it seems that you always go to the LoginPage widget. You can change to a StatefulWidget and check if the user is logged in or not, by using the initState():
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((res) {
print(res);
if (res != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home()),
);
}
else
{
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
);
}
});
}
For example, here you check if the user is not equal to null, then go to the details page or home page if not then go to the LoginPage.