.Net Maui app completion handlers and iOS HealthKit not working with HttpClient - dotnet-httpclient

This works perfectly in Android.
public async Task<double> UploadData()
{
double steps = 0.0;
await _healthData.GetSteps((totalSteps) =>
{
SentrySdk.CaptureMessage("totalSteps = " + totalSteps);
MainThread.BeginInvokeOnMainThread(() =>
{
steps = totalSteps;
//Task.Delay(1000);
});
});
SentrySdk.CaptureMessage("UploadData steps = " + steps);
var fitness = new Fitness();
fitness.Steps = steps;
await _restService.SaveItemAsync(fitness, true);
return steps;
}
In iOS, totalSteps is correct, but steps is still 0 when fitness.Steps = steps runs. Bottom line, I can't get the totalSteps value from inside the _healthData.GetSteps((totalSteps) operation. The Android Google Fit and iOS HealthKit API calls run with completion handlers.
At this stage, I'm just trying to figure out how to upload data (steps, calories, active minutes, distance) to my server.
Does anyone know how to make this work? I can display all the data (steps, calories, active minutes, distance) in a View using an ObservableCollection.

I got this to work by embedding the calls like so.
_healthData.GetHealthPermissionAsync((result) =>
{
if (result)
{
_healthData.FetchSteps((totalSteps) =>
{
_healthData.FetchMetersWalked((metersWalked) =>
{
_healthData.FetchActiveMinutes((activeMinutes) =>
{
_healthData.FetchActiveEnergyBurned((caloriesBurned) =>
{
var fitness = new Fitness();
fitness.Steps = totalSteps;
fitness.Calories = caloriesBurned;
fitness.Distance = metersWalked;
fitness.Minutes = activeMinutes;
_restService.SaveItemAsync(fitness, true);
});
});
});
});
}
});

Related

Aurelia, Electron: Possible EventEmitter memory leak detected

I'm building a system resource monitor as a project using electron and aurelia.
Main.js
var ramInfo = {};
var result = await si.mem()
ramInfo.total = parseInt(result.total / 1024 / 1024);
ramInfo.used = parseInt(result.used / 1024 / 1024);
ramInfo.percentUsed = parseInt((ramInfo.used / ramInfo.total) * 100);
ramInfo.percentAvailable = parseInt((ramInfo.percentUsed - 100) * -1);
event.sender.send('ram-reply', ramInfo);
})
Overview.js:
async attached () {
await this.getRamInfo();
this.startDataRefresh();
}
async getRamInfo () {
window.ipc.send('ram');
await window.ipc.on('ram-reply', (event, result) => {
this.system.ram = result;
//This line gets logged an additional time each time the setInterval function runs
console.log(this.system.ram);
this.ramData.series = [this.system.ram.percentAvailable, this.system.ram.percentUsed];
new Chartist.Pie('.ram-chart', this.ramData , this.options);
});
console.log("Break");
}
startDataRefresh() {
let scope = this;
setInterval(function() {
scope.getRamInfo();
}, 3000);
}
I am receiving the folowing error in my electron console:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 ram-reply listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
I would only think that the getRamInfo() function would run once every three seconds, however, the console.log portion of the function is getting logged an additional time each time the function runs. I'm fairly certain this is where the issue lies, I'm just not sure why it is running multiple times per interval.
EDIT:
I've reached a partial solution in moving the setInterval function into main.js:
ipcMain.on('ram', async (event) => {
setInterval(async function() {
var ramInfo = {};
var result = await si.mem()
ramInfo.total = parseInt(result.total / 1024 / 1024);
ramInfo.used = parseInt(result.used / 1024 / 1024);
ramInfo.percentUsed = parseInt((ramInfo.used / ramInfo.total) * 100);
ramInfo.percentAvailable = parseInt((ramInfo.percentUsed - 100) * -1);
event.sender.send('ram-reply', ramInfo)
}, 3000);
})
It seems like each time the original setInterval called to ipcMain this created a new listener and each time every listener returned the results. I would like it to be dependant on the view that is open so controlling this via the view would be preferable.
Try this:
async getRamInfo () {
window.ipc.send('ram');
return new Promise(resolve => window.ipc.once('ram-reply', (event, result) => resolve(result));
}
async refresh() {
const ramInfo = await this.getRamInfo();
this.ramData.series = [this.system.ram.percentAvailable, this.system.ram.percentUsed];
new Chartist.Pie('.ram-chart', this.ramData , this.options);
// ...
}
startDataRefresh() {
if(!this.interval) {
this.interval = setInterval(() => this.refresh(), 3000);
}
}
stopDataRefresh() {
if(this.interval) {
clearInterval(this.interval);
delete this.interval;
}
}
main part - window.ipc.once('ram-reply' - use once for one-time event subscription

BackgroundGeolocation not working in background but in foreground fire why?

Team i have implemented the tracking functionality in our app and using BackgroundGeolocation but its not working in the background below we have mentioned scenario:
Case 1:
BackgroundGeolocation is fire only 1 time if i am foreground not in background below links we have used for BackgroundGeolocation :
https://www.joshmorony.com/adding-background-geolocation-to-an-ionic-2-application/
https://www.freakyjolly.com/ionic-3-get-background-device-location-using-cordova-and-ionic-native-geolocation-plugins/
i have tried above links but i got same result for me.i really stuck location issues in ionic3 as well ionic community is not supported for any query.
loadLocation(){
// foreground Tracking
var self = this;
//get user currentLocation and update user location after move move
self.watch = this.geolocation.watchPosition(options).filter((p: any) => p.code === undefined).subscribe((position: Geoposition) => {
//self.subscription = self.watch.subscribe((position) => {
var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
console.log('lat fire1.....', +position.coords.latitude);
console.log('long fire.....', +position.coords.longitude);
//set center to map and set zoom....
self.map.setCenter(latLng);
self.map.setZoom(16);
//updateDriverLocation for get driver updated location...
self.updateDriverLocation(position.coords.latitude, position.coords.longitude);
//moveMarker for ,move marker......
self.moveMarker(position);
}, (err) => {
console.log(err);
});
// Background Tracking
let config = {
desiredAccuracy: 0,
stationaryRadius: 20,
distanceFilter: 10,
debug: true,
interval: 2000
};
this.backgroundGeolocation.configure(config).subscribe((location) => {
alert('dddddd');
console.log('BackgroundGeolocation: ' + location.latitude + ',' + location.longitude);
//updateDriverLocation for get driver updated location...
self.updateDriverLocation(location.latitude,location.longitude);
self.moveMarker(location);
}, (err) => {
console.log(err);
});
// Turn ON the background-geolocation system.
this.backgroundGeolocation.start();
}
I tried each and everything but nothing worked please team help me.

FirebaseDatabase web iOS / OSX

I'm working on a website for a school project containing a button which you need to press. When pressed, the button takes a value from the database, child 'aantal' and adds 1. When that is done, it re-uploads it back to the database. One page further, you can see the live number of that child. The problem is, this is not working on iOS 9 or lower and on OSX Yosemite or lower. On android and windows it works fine.
Reusable code;
This is just a button. If you press the button it adds 1 on the int. This is very strange because it doesn't doesn't work on the OS mentioned above.
<script src="https://www.gstatic.com/firebasejs/3.6.9/firebase.js"></script>
<script language="JavaScript">
// Initialize Firebase
var config = {
apiKey: //API KEY,
authDomain: //FIRBASE DOMAIN,
databaseURL: //DATABASE URL,
storageBucket: //STORAGE BUCKET,
messagingSenderId: //MESGSENDID
};
firebase.initializeApp(config);
var number;
var database = firebase.database().ref().child('aantal');
function buy() {
database.on('value', snap => number = snap.val());
var count = parseInt(number, 10) + 1;
database.set(count);
}
</script>
This code will not work, initialise own Firebase project for testing.
For security reasons I removed my details.
Edit
Turns out Safari (9.1/iOS 9.3 and below) doesn't support arrow functions.
Changing database.on('value', snap => number = snap.val()); to database.on('value', function(snap) { number = snap.val()}); fixed the issue.
Well I mean, that code shouldn't work anywhere.
function buy() {
database.on('value', snap => number = snap.val());
var count = parseInt(number, 10) + 1;
database.set(count);
}
Firebase is asynchronous, and you're not waiting for it to actually load number from the database.
This should work.
function buy() {
database.on('value', snap => {
number = snap.val();
var count = parseInt(number, 10) + 1;
database.set(count);
});
}
I don't know whether this is actually the issue you're having or if you just wrote this in your example. Also, when incrementing values you should be using Transactions.
function buy() {
database.transaction(function(value) {
if (value) {
value++;
}
return value;
});
}

Xamarin.Forms ZXing.Net.Mobile loosing current page after scan result on iOS 10

I'm using Xamarin.Forms and I have implemented ZXing.Net.Mobile for scanning bar codes.
On Android it's working fine, on iOS 10 after reading a barcode the function "OnScanResult" is fired and executes the command Navigation.PopAsync() which closes the scanning page but after a second it closes also the current page where I have displayed the result !
MyTapScan.Tapped += async (sender, e) =>
{
await MyBtScan.ScaleTo(1.20, 100, Easing.Linear);
await MyBtScan.ScaleTo(1, 100, Easing.Linear);
await Task.Delay(50);
//--------------------------------------------
MyAppLib.MyAppUtilitiesBarCodeReader MyBarCodeReader = new MyAppLib.MyAppUtilitiesBarCodeReader();
var MyScannerPage = MyBarCodeReader.GetBarCodeReaderPage();
//--------------------------------------------
MyScannerPage.OnScanResult += (result) => {
//Stop scanning
MyScannerPage.IsScanning = false;
//Pop the page and show the result
Device.BeginInvokeOnMainThread(() => {
Navigation.PopAsync();
MyMachSerialNumber.Text = result.Text;
});
};
//--------------------------------------------
//Display scanner
await Navigation.PushAsync(MyScannerPage);
};
Please please help..!! :)
Every time MyTapScan.Tapped is called you are subscribing to MyScannerPage.OnScanResult so if you tap button 5 times your OnScanResult will be called 5 times. I hope now you know how to solve that.
One of possible solutions:
Take your OnScanResult delegate and make it separate function, let say ScanFinished. Then instead of
MyScannerPage.OnScanResult += (result)
do
MyScannerPage.OnScanResult -= ScanFinished;
MyScannerPage.OnScanResult += ScanFinished;
Then you can be sure the event unsubscribed before you subscribe to it again
I have introduced a new variable to check if the scanning was already fired and now it's working fine and as expected.
This is the code:
MyTapScan.Tapped += async (sender, e) =>
{
await MyBtScan.ScaleTo(1.20, 100, Easing.Linear);
await MyBtScan.ScaleTo(1, 100, Easing.Linear);
await Task.Delay(50);
bool MyIsScanning = true;
//--------------------------------------------
MyAppLib.MyAppUtilitiesBarCodeReader MyBarCodeReader = new MyAppLib.MyAppUtilitiesBarCodeReader();
var MyScannerPage = MyBarCodeReader.GetBarCodeReaderPage();
//--------------------------------------------
MyScannerPage.OnScanResult += (result) => {
//Stop scanning
MyScannerPage.IsScanning = false;
//Pop the page and show the result
Device.BeginInvokeOnMainThread(() => {
if (MyIsScanning == true)
{
MyIsScanning = false;
MyMachSerialNumber.Text = result.Text;
Navigation.PopAsync();
}
});
};
//--------------------------------------------
//Display scanner
await Navigation.PushAsync(MyScannerPage);
};

Creating chat "rooms" using Node, Express, Heroku, and Socket.io

So I've been building an app for quite some time and I'm running into problems in terms of scalability. I'm new to Node, and Heroku for that matter. Please bear with me.
I originally followed this tutorial to get my node service up and running. Essentially, it creates a real-time chat service. However, my question now comes with creating 'rooms'. It doesn't make sense to me that I might have 15+ chats going on, yet they all are calling the same functions on the same clientSocket, and I have to determine what UI updates go to which clients on the front end. As of now, I have upwards of 15 clients all trying to interact on different chats, but I'm pushing updates to everyone at once (for example, when a message is posted), then determining who's UI to update based on which room ID I'm cacheing on each device. Seems like a terrible waste of computing power to me.
I'm thinking that the solution involves modifying how each client connects (which is the code snippet below). Is there a way to create location based 'rooms', for example, where the clients connected are the only ones getting those updates? Any idea how to go about this solution? If anyone is also willing to just explain what I'm not understanding about Node, Express, Heroku, Socket.io or others, please do let me know.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var pg = require('pg');
var userList = [];
var typingUsers = {};
var ActiveQueue = [];
app.get('/', function(req, res){
res.send('<h1>Active RT Queue</h1>');
});
var conString = "postgres://url";
pg.defaults.ssl = true;
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
return console.error('could not connect to postgres', err);
}
});
http.listen(process.env.PORT || 5000, function(){
console.log('Listening on *:5000');
});
io.on('connection', function(clientSocket){
console.log('a user connected');
clientSocket.on('disconnect', function(){
console.log('user disconnected');
var clientNickname;
for (var i=0; i<userList.length; i++) {
if (userList[i]["id"] == clientSocket.id) {
userList[i]["isConnected"] = false;
clientNickname = userList[i]["nickname"];
break;
}
}
delete typingUsers[clientNickname];
io.emit("userList", userList);
//io.emit("userExitUpdate", clientNickname);
//io.emit("userTypingUpdate", typingUsers);
});
clientSocket.on("exitUser", function(clientNickname){
for (var i=0; i<userList.length; i++) {
if (userList[i]["id"] == clientSocket.id) {
userList.splice(i, 1);
break;
}
}
io.emit("userExitUpdate", clientNickname);
});
clientSocket.on("connectUser", function(clientNickname) {
var message = "User " + clientNickname + " was connected.";
console.log(message);
var userInfo = {};
var foundUser = false;
for (var i=0; i<userList.length; i++) {
if (userList[i]["nickname"] == clientNickname) {
userList[i]["isConnected"] = true
userList[i]["id"] = clientSocket.id;
userInfo = userList[i];
foundUser = true;
break;
}
}
if (!foundUser) {
userInfo["id"] = clientSocket.id;
userInfo["nickname"] = clientNickname;
userInfo["isConnected"] = true
userList.push(userInfo);
}
io.emit("userList", userList);
io.emit("userConnectUpdate", userInfo)
});
///functions pertaining to transfer of messages and updating the UI follow
I would try something like this:
io.on('connection', function(clientSocket) {
clientSocket.on('room:general', function(data) {
var user = data.user;
var message = data.message;
console.log('%s sent new message: %s',user,message);
io.emit('room:general:newMessage', data);
});
//and so for each room
.........
});
and from front end you need to send JSONObject:
{
user:your_username,
message:user_message
}
,
socket.emit("room:general", json_object);
socket.on("room:general:newMessage", onYourDefinedEmiterListener);
..........
..........
//and so for each room
I never made Chat Application, hope it helps.

Resources