Fetching data from firebase error happen flutter - android

while building whatsapp clone status uploading to database perfectly done , no issues in that case . But while displaying from DB to screen error found :- I/flutter (11808): RangeError (index): Invalid value: Valid value range is empty: 0
code of getstatus function
Future<List> getStatus(BuildContext context) async {
List statusData = [];
try {
List<Contact> contacts = [];
if (await FlutterContacts.requestPermission()) {
contacts = await FlutterContacts.getContacts(withProperties: true);
}
for (int i = 0; i < contacts.length; i++) {
var statusesSnapshot = await firestore
.collection('status')
.where(
'phoneNumber',
isEqualTo: contacts[i].phones[0].number.replaceAll(
' ',
'',
),
)
.where(
'createdAt',
isGreaterThan: DateTime.now()
.subtract(const Duration(hours: 24))
.microsecondsSinceEpoch,
)
.get();
for (var tempData in statusesSnapshot.docs) {
Status tempStatus = Status.fromMap(tempData.data());
if (tempStatus.whoCanSee.contains(auth.currentUser!.uid)) {
statusData.add(tempStatus);
}
}
}
} catch (e) {
if (kDebugMode) print(e);
showSnackBar(context: context, content: e.toString());
}
return statusData;
}

Related

"NoSuchMethodError: The method '[]' was called on null." Erro in my Stream

I am getting the Error "NoSuchMethodError: The method '[]' was called on null." from my stream. I tried to change my code several times and added print statements, which get printed correctly, but my Stream ends up returning an error, which is the one from the subject line. Any idea why? How can I Fix the error?
This is the result of the print data statement:
data:
{
userId1: 59jTMEbvqFd8C8UhInksauAVNk63,
userId2: 2ssfDEPhPhcIwInUWdlm0ReH5RZ2,
latestMessageTime: Timestamp(seconds=1667140814, nanoseconds=334000000),
lastMessageSenderId: 59jTMEbvqFd8C8UhInksauAVNk63,
created_at: 2022-10-26 19:44:13.793275,
latestMessage: TEST 3,
roomId: Qv30s8kATJbFJIWRdBEo
}
.
Stream<RoomsListModel> roomsStream() async* {
try {
// get all active chats
var rooms = await FirebaseFirestore.instance
.collection("rooms")
.where("users", arrayContains: userId)
.orderBy("latestMessageTime", descending: true)
.snapshots();
print("rooms: $rooms");
// get Other user details
await for (var room in rooms) {
for (var doc in room.docs) {
var data = doc.data() as Map<String, dynamic>;
print("data: $data");
var otherUser = await getOtherUser(
data["users"][0] == userId ? data["users"][1] : data["users"][0]);
print("otherUser: $otherUser");
yield RoomsListModel(
roomId: doc.id,
userId: otherUser["user id"],
avatar: otherUser["photoUrl"],
name: otherUser["name"],
lastMessage: data["latestMessage"],
lastMessageTime: data["latestMessageTime"]);
}
}
} catch (e) {
print("Error: $e");
}
}
.
Future getOtherUser(String id) async {
// get other user profile
var user = await FirebaseFirestore.instance
.collection("users")
.doc(id)
.get()
.then((value) => value.data()) as Map<String, dynamic>;
// return other user profile
return user;
}
change this:
var otherUser = await getOtherUser(
data["users"][0] == userId ? data["users"][1] : data["users"][0]);
to this:
var otherUser = await getOtherUser(
data["userId1"] == userId ? data["userId2"] : data["userId1"]);

Flutter String is in Future null

I want to use a string in this function that has the phone number of the device.
I get the phone number with this:
Future<void> initMobilNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
String mobileNumber = '';
try {
mobileNumber = await MobileNumber.mobileNumber;
_simCard = await MobileNumber.getSimCards;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
if (!mounted) return;
setState(() {
var re = RegExp(r'\+[^]*');
_mobileNumber = mobileNumber.replaceRange(0, 3, ''.replaceAll(re, '+'));
});
}
My problem is that if I want to print _mobileNumber or use it in http.get I get null or a error with "Invalid Arguments"
Future<http.Response> _fetchSampleData() async {
String s = _mobileNumber;
print(s);
return http.get('http://test.php?TestPhone=' + _mobileNumber);
}
Future<void> getDataFromServer() async {
final response = await _fetchSampleData();
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
_list = data.values.toList();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
showAlertNoInternet(context);
print('Failed to load data from server');
}
}
Where is my mistake?
The problem is that I want to call the phone number before it has even been fetched. So this always resulted in null. I fixed this by fetching the number when I start the app with all the other data I need.

How to return Future<object> and assign it to just object , flutter

I have a custom class that fetches data from the database, that returns Future<List<Line>>, which lies in line_list.dart files :
Future<List<Line>> fetchingLinesData() async {
List<Line> lineList = [];
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'main.db');
Database database = await openDatabase(path, version: 1);
database.transaction((tnx) async {
dbRef.child('line').once().then((DataSnapshot dataSnapshot) async {
dataSnapshot.value.forEach((key, value) async {
List<Station> inLineStations = [];
for (var i = 0; i < 100; i++) {
if (value["station_$i"] != null) {
List<Map> stations = await tnx.rawQuery("SELECT * FROM Station");
stations.forEach((s) {
if (s['stationName'] == value["station_$i"]) {
Station stationInstance = Station(
key: s['key'],
cityName: s['cityName'],
stationName: s['stationName'],
stationLongitude: s['stationLongitude'],
stationLatitude: s['stationLatitude']);
inLineStations.add(stationInstance);
}
});
}
}
Line lineInstance = Line(
startStation: value['start_station'],
endStation: value['end_station'],
inLineStations: inLineStations,
notes: value['notes'],
price: value['price'],
transportationType: value['transportation_type']);
lineList.add(lineInstance);
});
});
});
return lineList;
}
}
and then in my main.dart widget, I have this :
List<Line> allLines = [];
I want to do something like this :
allLines = LinesList().fetchingLinesData();
But of course, it gives me an error as am trying to assign Future<List<Line>> to List<Line>
how to do it?
You have to await for future to complete.
allLines = await LinesList().fetchingLinesData();
You would just put the code below in a async function make main async and make your code
allLines = await LinesList().fetchingLinesData();

need some processing to do before cloud function returns a promise. But promise is return before the processing

i have a cloud function where i pass an array of numbers and compare those numbers with collection in the firestore . And if the numbers are present than return an array with those numbers. But before comparing those numbers the function return empty value in the promise.
I've tried using async await but the execution sequence remained same.
//sort contact list
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col=admin.firestore().collection("joshua");
var match:[]
match=data.list
var perm1=new Array()
res11.push("454675556")
console.log("above resolve")
for(let val in match){
var inter=await Promise.all([getValues(col,val)])
console.log("inside resolve"+inter)
}
perm1.push("23432")
console.log("just before resolve")
return new Promise((res,rej)=>{
res(perm1)
})
});
//the async function which is suppose to process on every iteration
function getValues(col1:any,val1:any)
{
return new Promise(async(res,rej)=>{
var query= await col1.where('Listed','array-contains',val1)
var value=await query.get()
res(value)
})
.catch(err=>{
console.log(err)
})
}
i want the sequence to be asynchronous where the return value from getValues is waited upon and inside getValues result of query.get is waited upon.
so that at last return only be sent when all process is finished.
I think this is what you are looking for
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col = admin.firestore().collection("joshua");
var match:[]
match = data.list
var perm1 = []
// res11.push("454675556") // ? undefined
for(let val in match){
var inter = await getValues(col,val)
console.log("inside resolve" + inter)
}
perm1.push("23432") // ??
// console.log("just before resolve")
return Promise.resolve(perm1)
});
const getValues = async (col1:any, val1:any) => {
const query = col1.where('Listed','array-contains', val1)
var value = await query.get().then(getAllDocs)
return value
}
const getAllDocs = function(data: any) {
const temp: Array<any> = []
data.forEach(function (doc: any) {
temp.push(doc.data())
})
return temp
}

Firebase Functions response return null

Firebase Function Code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const db = admin.firestore();
const gameRef = db.collection('Game');
function newRoom(uid) {
gameRef.add({
users: [
uid
],
playing: false,
moves: [],
win: ""
}).then(ref => {
return {
"game": ref.id
}
}).catch(err => {
console.log(err.message)
})
}
function joinRoom(uid, id, data) {
data.users.push(uid);
data.playing = true;
gameRef.doc(id).update(data)
.then(ref => {
return {
"game": id
}
}).catch(err => {
console.log(err.message);
})
;
}
exports.helloWorlds = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
const query = gameRef.where('playing', '==', false).get()
.then(snapshot => {
if (snapshot.docs.length === 0) {
return newRoom(uid)
} else {
return joinRoom(uid, snapshot.docs[0].id, snapshot.docs[0].data())
}
}).catch(err => {
console.log(err.message)
});
});
Android Code
fun requestGame(text:String): Task<HashMap<*, *>> {
// Create the arguments to the callable function.
val data = hashMapOf("text" to text, "push" to true)
return mFunctions
.getHttpsCallable("helloWorlds")
.call(data)
.continueWith {
val result = it.result.data as HashMap<*, *>
result
}
function code works fine. When I make a request on the android device, it returns null. İt write the datas to the database smoothly. Another problem is that sometimes the function does not work when it is not running for a certain period of time. I think the problem is JavaScript, but I did not solve the problem
Right now you're not returning anything from helloWorlds itself, which means that Cloud Functions can't know when it's done. You'll want to return query at the end of helloWorlds:
exports.helloWorlds = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
const query = gameRef.where('playing', '==', false).get()
.then(snapshot => {
if (snapshot.docs.length === 0) {
return newRoom(uid)
} else {
return joinRoom(uid, snapshot.docs[0].id, snapshot.docs[0].data())
}
}).catch(err => {
console.log(err.message)
});
return query;
});
return gameRef.where(...
exports.helloWorlds = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
return gameRef.where('playing', '==', false).get()
.then(snapshot => {
if (snapshot.docs.length === 0) {
return newRoom(uid)
} else {
return joinRoom(uid, snapshot.docs[0].id, snapshot.docs[0].data())
}
}).catch(err => {
console.log(err.message)
});
});

Categories

Resources