Location Tracking in every 1 minute - xamarin.forms

I am creating a xamarin form app which require user location (user's longitude and latitude) after every 1 minute whether app is running in foreground or background.
I am able to get user location after every 1 minute if user stays at one position or moving slowly.
But Facing issue in getting location when user is in situation like riding bike or moving in speed,
I am not able to get user's location (user longitude and latitude) in such situatiion.
try
{
if (CrossGeolocator.Current.IsGeolocationAvailable)
{
if (CrossGeolocator.Current.IsGeolocationEnabled)
{
count += 1;
// var location = await GetLocationFromPhone().ConfigureAwait(false);
var location = await Geolocation.GetLocationAsync(new GeolocationRequest(GeolocationAccuracy.High, TimeSpan.FromSeconds(10)));
if (location != null)
{
var model = new lat_lon
{
lat = location.Latitude,
lon = location.Longitude,
dist = count
};
MessagingCenter.Send<lat_lon>(model, "LocationLngLet");
}
}
}
}
catch (TargetInvocationException srtiex)
{
}
catch (IllegalStateException ilsex)
{
}
catch (FeatureNotEnabledException fneex)
{
}
catch (NullReferenceException nrex)
{
}
catch (FeatureNotSupportedException fnsEx)
{
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (System.Exception ex)
{
// Unable to get location
}
Suggest any solution for this issue!!

This should run in a service (https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/services/ , https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-walkthroughs/location-walkthrough), because you need it to work no matter the phone's/app's state. Consider using LocationManagers for each project and set the properties you need for locationChanged.

Are you using GeolocatorPlugin, right?
And from the Geolocator Plugin documentation, especially Listing For Location Changes and Background Updates, we see:
Before subscribing to events you must start listening, which will start the managers to query for location changes.
To check to see if you are listning there is a nifty IsListening property on the CrossGeolocator.Current that you can use.
bool IsListening { get; }
Once you are ready to start listening for changes you can call the StartListeningAsync. After this, you can add event handlers to get the changes.
Task<bool> StartListeningAsync(TimeSpan minimumTime, double minimumDistance, bool includeHeading = false, ListenerSettings listenerSettings = null);
Note:
ListenerSettings are details more in the Background Updates documentation.
And background updates are handled a bit different on each platform. The Driving application is a great sample showing how to handle this on all mobile platforms.
For more details, you can check:
https://jamesmontemagno.github.io/GeolocatorPlugin/BackgroundUpdates.html

Related

Plugin BLE (v1.3.0) delay after characteristic.ReadAsync()

I’m developing an app and I want to read some characteristics one after one.
My issue is that after a read is done I must do a delay otherwise I get an error.
Why does it need a delay ? is there a way to write correctly read tasks one after other ?
I'm using Xamarin.forms and Ble v1.3.0 plugin.
I've tried "await Task.Delay(200)" between two consecutive ReadAsync() functions and it works fine but if I remove the delay, the second ReadAsync gets exception.
private async Task ReadChr(ICharacteristic LocalCharacteristic)
{
byte[] localData = { };
if (LocalCharacteristic.CanRead)
{
try
{
return localData = await LocalCharacteristic.ReadAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return null;
}
}
}
if (firstCharacteristic.CanRead)
{
var ccc = await ReadChr(firstCharacteristic);
}
await Task.Delay(200);
if (secondCharacteristic.CanRead)
{
var ddd = await ReadChr(secondCharacteristic);
}
I'm searching something like polling the read process status of the characteristic. Delay after ReadAsync does not seem a good practice coding.
Any idea ?

View event details in Firebase

I am sending app usage analytics events to Fabric and Firebase. Together with the event, I am also sending another value (an example event type is font_selection and the value I pass is which font the user selects - this is a number that tells me which font was used). I was using Fabric events and I could see which fonts were being used more or less when I selected the font_selection event (I could see numbers for each different font).
Since the Fabric functionality is being moved to Firebase, I started checking the Analytics section in Firebase. Unfortunately I cannot find the above information in Firebase > Analytics > Events. I can see the event, font_selection but when I click on it I do not get the additional information I used to get in Fabric. Is there something I am missing or has this additional information been removed from Firebase?
This is still an issue for me. Here is how I'm sending the event into Firebase:
protected void Report(string id, Severity severity, string message = null, Exception exception = null)
{
try
{
var processedId = id ?? severity.ToString().ToLowerInvariant();
var values = new Dictionary<string, string>();
values.Add("severity", severity.ToString().ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(message))
{
values.Add("message", message);
}
if (exception != null)
{
values.Add("exception", exception.Message);
values.Add("trace", exception.StackTrace);
}
SendEvent(values, processedId);
}
catch
{
// do nothing.
}
}
protected override void SendEvent(Dictionary<string, string> eventData, string id)
{
var firebaseAnalytics = FirebaseAnalytics.GetInstance(Android.App.Application.Context);
var bundle = new Android.OS.Bundle();
foreach(var pair in eventData)
{
bundle.PutString(pair.Key, pair.Value);
}
firebaseAnalytics.LogEvent(id, bundle);
}
During runtime, I call this successfully and I can see these event popping up in Firebase console:
But how do I display the rest of the properties that I have bundled with it? Here is what the console shows me in events:
I feel like I must be using it wrong or something. There is no UI to shows me a simple chronologically sorted table with events as they came in with properties they came with. I frankly don't understand what good is this tool to me.

Unable to remove Firebase node

I'm at a loss on this one. I'm unable to delete a node in Firebase either from the web app or through the Firebase console. When the /courses/{courseId}/members/{uid} node is removed, either through set(null) or remove(), the user's information is added immediately.
I do have two cloud functions updating the seats node so we can keep track of space, but neither of those point at the ../{uid} endpoint. I've also gone through my web app code to make sure there were no on_delete events writing to the tree. Any clues as to what's happening?
UPDATE
After going backward in my commit tree, I was able to confirm that it was the below cloud function disallowing deletes from the tree. So, my question now becomes, what in this function causing the behavior? I can't see anything that would re-write data. My database structure is below.
/courses ref
courses: {
someStringId1234: {
members: {
uid12345: {
code: 'someString',
email: 'some#email.com'
},
uid67890: { ... }
},
seats: 10
},
{ ... }
}
This cloud function watches for changes to the uid item. It grabs the parent node (members) and then updates the count in seats. For some reason, this is re-writing the previously deleted key and setting it to 0.
countRegistrations, firebase cloud function
exports.countRegistrations = functions.database.ref('/courses/{courseId}/members/{uid}').onWrite(
(change) => {
// get the `members` node for the item
const collectionRef = change.after.ref.parent;
console.log('collectionRef', collectionRef)
// get the `seats` key for updating
const countRef = collectionRef.parent.child('seats');
console.log('countRef', countRef)
let increment;
// If the ID is there after but not before, remove one seat
if (change.after.exists() && !change.before.exists()) {
increment = -1;
// if the ID is not there after, but there before, add one seat
} else if (!change.after.exists() && change.before.exists()) {
increment = 1;
} else {
// Nothing to change
return null;
}
// Return the promise from countRef.transaction() so the function
// waits for this async event to complete before it exits.
return countRef.transaction((current) => {
console.log('Line 38', current) // debugging, confirms the correct refs are grabbed by the function
return (current || 0) + increment;
}).then(() => {
return
});
});
Just for fun, here's what happens when I try to delete the node directly in the console. The database rules allow writing if you're logged in.
I had the same issue. Turns out that by deleting that node would cause too many firebase functions to execute. Try use the delete command in the CLI, it might give you more information on the error. firebase database:remove <//path to node>
I had same issue, and I just fixed it. The error occurred because of the node data it is using.
Please check where you use the node current, and break or sign out. Then, it is possible to delete the node.
Explanation: If the node is user info and current the user is logged in, it is impossible to delete the node. Continuously, re-created node as long as deleting node.
For this scenario, i am using handler to delay the refresh of my activity with 2-3 seconds, If anyone is getting this error then make sure:-
Do not make the refresh of an activity or display (reloading the database)
Use handler with 2-3 seconds delay, then the logged in user can't auto remake the node.
How i used to delete the node:-
myViewHolder.deleteicon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String childvalue = list.get(i).getPosition();
Log.d(TAG, "onClick: "+ childvalue);
FirebaseDatabase.getInstance().getReference()
.child("Submission/Rules").child(categorynametext).child(user.getUid()).child(childvalue).removeValue()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(context, "You have removed successfully", Toast.LENGTH_LONG).show();
try
{
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
///Here i am refreshing the activity
((Activity)context).finish();
((Activity)context).overridePendingTransition( 0, 0);
((Activity)context).startActivity(((Activity) context).getIntent());
((Activity)context).overridePendingTransition( 0, 0);
}
}, 3000);
}
catch (Exception e){
e.printStackTrace();
}
} else {
//enter msg or enter your code which you want to show in case of value is not remove properly or removed failed.
Toast.makeText(context, "There is an error while removing the rule, Please try again later", Toast.LENGTH_LONG).show();
}
}
});
}
});
UPDATE:
After working more in this, i found i was also getting the same error, because of using addValueEventListener< in this case it is auto adding the data while deleting or adding something in the database and if you use addListenerForSingleValueEvent, then there will not any problem while adding or deleting the data.
Final Conclusion:
addValueEventListener (If you want to refresh the page everytime any add or deletion occurs
addListenerForSingleValueEvent(If you don't want to refresh the page while adding or deleting something)

Detect if Firebase connection is lost/regained

Is there a strategy that would work within the current Firebase offering to detect if the server connection is lost and/or regained?
I'm considering some offline contingencies for mobile devices and I would like a reliable means to determine when the Firebase data layer is available.
This is a commonly requested feature, and we just released an API update to let you do this!
var firebaseRef = new Firebase('http://INSTANCE.firebaseio.com');
firebaseRef.child('.info/connected').on('value', function(connectedSnap) {
if (connectedSnap.val() === true) {
/* we're connected! */
} else {
/* we're disconnected! */
}
});
Full docs are available at https://firebase.google.com/docs/database/web/offline-capabilities.
Updated:
For many presence-related features, it is useful for a client to know when it is online or offline. Firebase Realtime Database clients provide a special location at /.info/connected which is updated every time the client's connection state changes. Here is an example:
DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("connected");
} else {
System.out.println("not connected");
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});
I guess this changed in the last couple of months. Currently the instructions are here:
https://firebase.google.com/docs/database/web/offline-capabilities
In summation:
var presenceRef = firebase.database().ref("disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnect().set("I disconnected!");
and:
var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
alert("connected");
} else {
alert("not connected");
}
});
I'll admit I don't know a lot about how references are set, or what that means (are you making them out of thin air or do you have to have already created them beforehand?) or which one of those would trigger something on the server as opposed to something on the front end, but if the link is still current when you read this, a little more reading might help.
For android you can make user offline by just a single function called onDisconnect()
I did this in one of my chat app where user needs to get offline automatically if network connection lost or user disconnected from Internet
DatabaseReference presenceRef = FirebaseDatabase.getInstance().getReference("USERS/24/online_status");
presenceRef.onDisconnect().setValue(0);
On disconnecting from network Here I am making online_status 0 of user whose Id is 24 in firebase.
getReference("USERS/24/online_status") is the path to the value you need to update on offline/online.
You can read about it in offline capabilities
Note that firebase takes time around 2-10 minutes to execute onDisconnect() function.
firebase for web
firebase.database().ref(".info/connected").on("value",(snap)=> {});
The suggested solution didn't work for me, so I decided to check the connection by writing and reading 'health/check' value. This is the code:
const config = {databaseURL: `https://${projectName.trim()}.firebaseio.com/`};
//if app was already initialised delete it
if (firebase.apps.length) {
await firebase.app().delete();
}
// initialise app
let cloud = firebase.initializeApp(config).database();
// checking connection with the app/database
let connectionRef = cloud.ref('health');
connectionRef.set('check')
.then(() => {
return connectionRef.once("value");
})
.then(async (snap) => {
if (snap.val() === 'check') {
// clear the check input
await connectionRef.remove();
// do smth here becasue it works
}
});

Remote Shared Object comes undefined - Red5

Cant find any solution for this. Im trying to store some data on remote shared object and retrieve it. At the moment im working locally. Anyway, i read probably all posts on internet about that and still cant understand where is my problem. I managed to store arguments on rso, but when i tried to receive those values, im only getting undefined.
Here is my code for the version when im only working with client side and on server side just watching when client connects to shared objects or changes the value.
protected function application1_creationCompleteHandler(event:FlexEvent):void {
var room_id:Number = vars("room");
connection = new NetConnection();
connection.connect("rtmp://127.0.0.1/video/" + room_id);
connection.addEventListener(NetStatusEvent.NET_STATUS, onConnected);
connection.client = this;
}
private function onConnected(event:NetStatusEvent) : void {
if(event.info.code == "NetConnection.Connect.Success") {
so = SharedObject.getRemote("video", connection.uri, true);
so.addEventListener(SyncEvent.SYNC, onSync);
so.connect(connection);
// if i try to trace so in there it will be undefined
} else {
Alert.show("Unsuccessful Connection", "Information");
}
And finally:
private function onSync(event:SyncEvent):void {
for(var i:Object in event.changeList) {
var changeObj:Object = event.changeList[i];
switch(changeObj.code) {
case "success":
if(so.data.cameras) {
Alert.show(this.so.data.cameras.toString(), "I changed it");
} else {
Alert.show("I changed", "Information");
}
break;
case "change":
if(so.data.cameras)
Alert.show(so.data.cameras.toString(), "First");
else if (this.so.data.cameras) {
Alert.show(this.so.data.cameras.toString(), "Second");
} else {
Alert.show("Can't found changed value", "Error");
}
break;
}
}
}
And here we go, i always get the undefined value of cameras, unless im the client who is changing the value, but everybody else gets undefined value. So i cant understand, all listeners a noticed about changes, on the server side code i see that i have changes, and i even opened persistent red5 shared object file and i see there is value, but i just cant retrieve it. Anybody has a solution? I would be very grateful.
Updated:
Answer is here: rso between flex and red5. I can create but cant read

Resources