I have install Firebase Performance monitoring on my React Native app
and integrate it successfully. After i want to track my network requests performance and go through as documentation.
const trackRequest = async (url,method) => {
// Define the network metric
const metric = await perf().newHttpMetric(url, method);
// Define meta details
metric.putAttribute('testAttr', 'testValue');
// Perform a HTTP request and provide response information
const response = await fetch(url);
metric.setHttpResponseCode(response.status);
metric.setResponseContentType(response.headers.get('Content-Type'));
metric.setResponsePayloadSize(response.headers.get('Content-Length'));
// Stop the trace
await metric.stop();
return response.json();
};
I use this function from documentation and call it every network requests time
fetch("www.example.com")
trackRequest("www.example.com","GET")
Can anyone explain me what i were doing wrong ?
It looks like you're not using the API correctly. There appears to be a good example in the documentation. You need to call start() on the metric before calling stop(). Also, the example shows that you should use await on each method call, but I don't really know if that's necessary.
const trackRequest = async (url,method) => {
const metric = await perf().newHttpMetric(url, method);
// !!! Don't forget to call start()
await metric.start();
await metric.putAttribute('testAttr', 'testValue');
const response = await fetch(url);
await metric.setHttpResponseCode(response.status);
await metric.setResponseContentType(response.headers.get('Content-Type'));
await metric.setResponsePayloadSize(response.headers.get('Content-Length'));
// Stop the trace only after you started it
await metric.stop();
return response.json();
};
Related
I am using App Check with my Flutter Android debug App to validate my app with my Cloud Run Node API. I followed the steps required to get and add the debug token to the Firebase Console Admin UI but it is rejecting my requests.
Here is my backend code:
const authenticate = async (req, res, next) => {
const appCheckToken = req.header('X-Firebase-AppCheck');
if (!appCheckToken) {
res.status(401);
return next('Unauthorized');
}
try {
const appCheckClaims = await firebaseAdmin.appCheck().verifyToken(appCheckToken);
// If verifyToken() succeeds, continue with the next middleware
// function in the stack.
return next();
} catch (err) {
res.status(401);
return next('Unauthorized');
}
}
And my main method in Flutter:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseAppCheck.instance.activate(
webRecaptchaSiteKey: 'recaptcha-v3-site-key',
// Default provider for Android is the Play Integrity provider. You can use the "AndroidProvider" enum to choose
// your preferred provider. Choose from:
// 1. debug provider
// 2. safety net provider
// 3. play integrity provider
androidProvider: AndroidProvider.debug,
);
runApp(const MyApp());
}
I make several requests from a React Native app to an API. Every request works fine both on iOS and Android except the DELETE method that does not work on Android. The call is correctly made, it goes through the API and the objects are deleted. But instead of getting the response, the call falls under the catch statement with [TypeError: Network request failed]. This does not happen in iOS.
Some people with the same problem were missing 'Content-Type': 'application/json' on the request headers which is not my case.
This is happening both locally, in testing and production stages (using an ip instead of localhost will do nothing).
The request is also successfully performed in Postman.
What can it be?
React Native 0.63.5
export const deleteApi = async (api: string, body?: any) => {
const userResponse = await getUserCredentials();
const authState = await getAuthState();
let response = await fetch(api, {
method: 'DELETE',
headers: await getHeaders(userResponse, authState),
body: JSON.stringify(body)
});
if (response.status === UNAUTHENTICATED_CODE)
response = await interceptor(response, userResponse, {
api: api,
method: 'DELETE',
body: body
});
return response;
};
leaveClass = async (
uuid: string,
onSuccess: () => void,
onFailure: (error: string) => void,
) => {
this.setLoading(true);
try {
const api = LEAVE_CLASS_API_PREFIX + uuid + LEAVE_CLASS_API_SUFFIX;
const response = await deleteApi(api);
if (response.status === SUCCESS_STATUS_CODE) {
onSuccess();
}
else {
const jsonResponse = await response.json();
if (jsonResponse.detail) onFailure(jsonResponse.detail);
else onFailure(translations.SOMETHING_WENT_WRONG);
}
} catch (error) {
console.log('leaveClass error: ', error);
}
this.setLoading(false);
};
You can use a network plugin for Flipper (https://fbflipper.com/docs/setup/plugins/network/), copy your request from it as a curl, and try to perform it from your terminal or postman. If it has the same error, the problem is not in React Native.
I am having an issue when work managers scheduler runs it gets stuck on reading data from database:
Future<List<TimesheetDays>> getTimesheetDays() async{
print('Getting DB');
Database db = await instance.database;
print('Getting DB stuff');
var timesheetday = await db.query('TimesheetDays',orderBy: 'TimesheetDayId');
// print(timesheetday);
List<TimesheetDays> timesheetDaysList = timesheetday.isNotEmpty ?
timesheetday.map((e) => TimesheetDays.fromMap(e)).toList() : [];
return timesheetDaysList;
}
It gets stuck on the
await instance.database
part of the code, now strange thing is that I have this project set on PC and Laptop. It only fails to work on PC whereas its fine on Laptop.
Work Manager code in case:
Callback Dispatcher
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
print('Executed scheduler!!');
try {
print('entered try catch!');
await CustomHttpRequests().synchronizeTimesheetDataLocally();
}
catch(_){
print('Error during execution');
}
print('Completed synchronization');
return Future.value(true);
});
}
Rest of the code:
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
print('creating task manager');
await Workmanager().initialize(
callbackDispatcher, // The top level function, aka callbackDispatcher
isInDebugMode: true, // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
);
Workmanager().registerPeriodicTask("1", fetchBackground, frequency: Duration(minutes: 15),initialDelay: Duration(minutes: 2)); //Android only (see below)
print('Task manager created');
runApp(
MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => CoreUser())
],
child: MyApp(),)
);
}
And just so the call in dispatcher makes sense it references straight to database in its first line so this is where it fails:
Future synchronizeTimesheetDataLocally() async{
//await synchronizeWasteGradings();
print("started reading");
var timesheetData = await DatabaseHelper.instance.getTimesheetDays();
Some things I tried to do to fix it:
"flutter clean"
Made sure MainActivity and GeneratedPluginRegistrant are the same on both devices
(sqflite & work manager are both being registered properly)
Basically went through this:
https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md
Any ideas how to fix this?
I am trying to store data received via FCM inside a class in order to navigate to a specific tab of my app after a user clicks on that notification.
My problem is that, as far as I could find on the web, the MainActivity is stopped when the app is not in the Foreground, and so, when I try and retrieve this data, I am not getting the updated variables. I have checked this using print statements throughout the app.
In order to store the information and use it when the app is brought back up, do I need to create a local database, or is there another way around this problem?
PS: I have a Stream that receives information that the user has clicked on the notification, and it updates the main page, but I cannot retrieve anything else from it, as it itself doesn't receive the json.
Thank you. Also, this was my first question posted here, be gentle if I didn't follow the protocol by the letter.
Sample code below.
Initialization:
FirebaseOption options = FirebaseOptions(
apiKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXx',
appId: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
messagingSenderId: 'XXXXXXXXXXXXXX',
projectId: 'XXXXXXXXXXXXx',
);
Future<void> backgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(
options: options,
);
var decoded = await NotificationModelPusherAG.fromJson(message.data);
var encodedMessage = await json.decode(decoded.message);
var decodedMessage = await PusherMessage.fromJson(encodedMessage);
notifications.type = message.data;
FirebaseNotifications.showNotification(decodedMessage.title, decodedMessage.description, message.data);
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final String INSTANCE_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
await PusherBeams.start(INSTANCE_ID);
await Firebase.initializeApp(
options: options,
);
/// Run this funk when a notification is received and app is in BG
FirebaseMessaging.onBackgroundMessage(backgroundHandler);
runApp(MyApp());
}
The class in which the data is stored:
class Notifications {
var tab = 0;
int get returnTab => return tab;
final _notificationUpdateController = BehaviorSubject();
Stream get update => _notificationUpdateController.stream;
shouldUpdate(add) {
_notificationUpdateController.sink.add(add);
}
void set type(messageData) {
if (messageData['type'] == 'xxxxxxx') {
this.tab = 1;
}
}
var notifications = Notifications();
The widget that should update:
StreamBuilder<Object>(
stream: notifications.update,
builder: (context, snapshot) {
if (updateMulti == true) {
print(notifications.returnTab); /// Here it is '0'
return multiScreen;
} else {
return multiScreen;
}
}
);
And the function that updates it:
flutterNotificationPlugin.initialize(
initSettings,
onSelectNotification: onSelectNotification
);
static Future onSelectNotification(String payload) {
print(payload); /// The payload is always null for some reason
print(notifications.returnTab); /// Here it shows '1' as it should
updateMulti = true;
notifications.shouldUpdate(true);
}
I kind of shortened the code a bit, if I missed something important do tell me, and I shall update accordingly.
Thank you again.
while trying to get the list of countries from my api, my code is sendig unlimited request to the server when i call the function one time. here is the flutter code
Future<dynamic> listePays() async{
http.Response response = await http.get(apiUrl+"api_pays", headers: {"Accept": "application/json"});
var resp = json.decode(response.body);
return resp;
}
i want to send just one request and work with the answers. ihave tried removing Future but i get the same issue
i call the function like this:
getPays() async {
Functions().listePays().then((data) async {
pays = data;
setState(() {});
});
}