I am building a Xamarin.Formscross platform mobile app, which uses Monkey.Robotics for its Bluetoth Low Energy functionality. I am connecting to an mbed based implimentation of a custom GATT service.
In the Xamarin C#, What triggers the Characteristic ValueUpdated event in Monkey.Robotics?
This is a standard example my C# is based on:
if (characteristic.CanUpdate) {
characteristic.ValueUpdated += (s, e) => {
Debug.WriteLine("characteristic.ValueUpdated");
Device.BeginInvokeOnMainThread( () => {
UpdateDisplay(characteristic);
});
IsBusy = false; // only spin until the first result is received
};
IsBusy = true;
characteristic.StartUpdates();
}
This has been working, but since I changed to my own custom GATT service which I am connecting to, the ValueUpdated event is never triggered. What is this event and how is it triggered? Is this a property read from the Characteristic, as set up by the mbed device, or is it something which the mobile end works out?
Thanks
this is from the Android implementation
this._gattCallback.CharacteristicValueUpdated += (object sender, CharacteristicReadEventArgs e) => {
// it may be other characteristics, so we need to test
if(e.Characteristic.ID == this.ID) {
// update our underlying characteristic (this one will have a value)
//TODO: is this necessary? probably the underlying reference is the same.
//this._nativeCharacteristic = e.Characteristic;
this.ValueUpdated (this, e);
}
};
Related
I'm using push notification with FCM in a Xamarin Forms application, so everything looks to be working fine except for one specific case.
Used package: Plugin.FirebasePushNotification
The event CrossFirebasePushNotification.Current.OnNotificationReceived += is being called only once when the application is open and when the app starts.
if I send 2 or more notifications from the server it's only called for the first notification, after that stop working. However the notification popup is always shown no matter what, even when the is in foreground, background, killed.
I want this to be called when the app is open because I need to perform an action depending on the notification data.
I'm testing in iOS 15.3.1
Intructions: https://github.com/CrossGeeks/FirebasePushNotificationPlugin/blob/master/docs/GettingStarted.md
Versions:
"Plugin.FirebasePushNotification" Version="3.4.1"
"Xamarin.Forms" Version="5.0.0.2337"
Thanks in advance.
My entire AppDelegate.cs Code:
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
NSObject _onKeyboardShowObserver;
NSObject _onKeyboardHideObserver;
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Rg.Plugins.Popup.Popup.Init();
Xamarin.FormsMaps.Init();
Firebase.Core.App.Configure();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
RegisterKeyBoardObserver();
FirebasePushNotificationManager.Initialize(options, true);
return base.FinishedLaunching(app, options);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
FirebasePushNotificationManager.RemoteNotificationRegistrationFailed(error);
}
// To receive notifications in foreground on iOS 9 and below.
// To receive notifications in background in any iOS version
//[Export("application:didReceiveRemoteNotification")]
[Export("messaging:didReceiveRemoteNotification:withCompletionHandler:")]
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired 'till the user taps on the notification launching the application.
// If you disable method swizzling, you'll need to call this method.
// This lets FCM track message delivery and analytics, which is performed
// automatically with method swizzling enabled.
FirebasePushNotificationManager.DidReceiveMessage(userInfo);
// Do your magic to handle the notification data
System.Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
void RegisterKeyBoardObserver()
{
if (_onKeyboardShowObserver == null)
_onKeyboardShowObserver = UIKeyboard.Notifications.ObserveWillShow((object sender, UIKeyboardEventArgs args) =>
{
NSValue result = (NSValue)args.Notification.UserInfo.ObjectForKey(new NSString(UIKeyboard.FrameEndUserInfoKey));
CGSize keyboardSize = result.RectangleFValue.Size;
MessagingCenter.Send<object, KeyboardAppearEventArgs>(this, Constants.iOSKeyboardAppears, new KeyboardAppearEventArgs { KeyboardSize = (float)keyboardSize.Height });
});
if (_onKeyboardHideObserver == null)
_onKeyboardHideObserver = UIKeyboard.Notifications.ObserveWillHide((object sender, UIKeyboardEventArgs args) =>
MessagingCenter.Send<object, string>(this, Constants.iOSKeyboardDisappears, Constants.iOSKeyboardDisappears));
}
public override void WillTerminate(UIApplication application)
{
if (_onKeyboardShowObserver == null)
{
_onKeyboardShowObserver.Dispose();
_onKeyboardShowObserver = null;
}
if (_onKeyboardHideObserver == null)
{
_onKeyboardHideObserver.Dispose();
_onKeyboardHideObserver = null;
}
}
}
Some suggestions for troubleshooting .
As Almis mentioned , place the code into OnStart of App.cs.
Make sure that initialization is correct, check iOS Initialization .
If problem persists , consider raising issue on github .
After different tests I could find what is causing the issue, but I don’t know why.
One of the things I do in the OnNotificationReceived event is show a local Push Notification by calling the NotificationCenter.Current.Show method, and that is what is causing the problem. When I comment the line of code that calls await NotificationCenter.Current.Show(notification) start working fine.
Once the NotificationCenter.Current.Show is executed, then the CrossFirebasePushNotification plugging starts working like if my App is in background or foreground.
I use the Lync SDK 2013 and try to check if a new conversation is incoming or outgoing. I don't want to check for audio/video calls only, I want to check in on each modality type.
private void Conversation_Added(object sender, ConversationManagerEventArgs e)
{
Conversation conversation = e.Conversation;
IDictionary<ModalityTypes, Modality> modalities = conversation.Modalities;
bool conversationIsIncoming = modalities.Any(modality => modality.Value.State == ModalityState.Notified);
}
When the event gets triggered and it comes to the Any method I get this error
NullReferenceException object reference not set to an instance of an object.
System.Collections.Generic.KeyValuePair.Value.get
returned null.
So obviously I have to use a null check here but maybe the whole code may be wrong? How can I check if the conversation is incoming or outgoing?
Your idea is basically correct but when you check for the notified state is incorrect.
You need to hook the ModalityStateChanged event, and if you only want to know about audio/video "Calls" then you also only need to hook for conversations that have AudioVideo modality type.
e.g.
private void ConversationManager_ConversationAdded(object sender, ConversationManagerEventArgs e)
{
if (e.Conversation.Modalities.TryGetValue(ModalityTypes.AudioVideo, out var avModality))
{
avModality.ModalityStateChanged += AvModalityOnStateChanged;
}
}
private void AvModalityOnStateChanged(object sender, ModalityStateChangedEventArgs e)
{
if (e.NewState == ModalityState.Notified)
{
bool conversationIsIncoming = true;
}
}
Don't forget to unhook from the ModalityStateChanged when you don't need to know the state change any longer.
I need to detect when wifi is turned on/off. For that purpose I'm using Connectivity by James Montemagno, but the problem is that I don't get an ConnectivityChanged event if the Phone have access to mobile network and I turn on/off the wifi.
Here is the mapping of the event:
CrossConnectivity.Current.ConnectivityChanged += (sender, args) =>
{
WiFiConnected = CrossConnectivity.Current.ConnectionTypes.Contains(ConnectionType.WiFi);
};
So can I detect Connectivity Changed on Wifi? I would like to do it in Xamarin Forms code so I won't have to implement a solution for each platform.
Here What Your Looking For
CrossConnectivity.Current.ConnectivityChanged += (sender, args) =>
{
if (args.IsConnected.ToString().Equals("False"))
{
if (CrossConnectivity.Current.ConnectionTypes.Contains(ConnectionType.WiFi))
{
// WE LOST AN CONNECTION BUT WIFI IS STILL ON
}
}
else
{
if (CrossConnectivity.Current.ConnectionTypes.Contains(ConnectionType.WiFi))
{
// WIFI WAS TURN ON AND WE HAVE A CONNECTION
}
else
{
// WE HAVE A CONNECTION BUT NOT WIFI
}
}
};
I dont know if there is a xamarin forms solution but you can do it plateform specific. In android with BroadcastReceiver.. for other plateforms i have no idea..
I'm coding an MVVM Silverlight application with MVVMLight. I was asking myself what is the best way to communicate between the Model and the ViewModel. My Model has asynchronous calls from a web service and I don't know what is the best way to get the return value.
I've tried this:
public static void ModifySomething(Something s)
{
var c = MyServiceFactory.GetService();
c.ModifySomethingCompleted += (sender, e) =>
{
if (e.Error != null)
{
Messenger.Default.Send(new XyzException(e.Error, "ModifyError"));
return;
}
Messenger.Default.Send(e.Result, "ModifyOk");
};
c.ModifySomethingAsync(s);
}
and this:
public static void ModifySomething(Something s, Action<Something, Exception> callback)
{
var c = ServiceFactory.RecupererService();
c.ModifySomethingCompleted += (sender, e) =>
{
if (callback != null) callback(e.Result, e.Error);
};
c.ModifySomethingAsync(s);
}
Both works, in the first example I'm using the MvvmLight Messenger, so I have to register a list of string messages for every methods of my model, and then any ViewModel can hook to this action.
In the second example, I use the classic approach to send a callback which is fired on the Completed event. Only one callback is fired, but the code is much more readable.
What is the best approach ?
I would say: Depends on! Seriously! It depends on
what you would like to accomplish (good design, expandability etc)
what you are used to do
what your desired target environment wants
how many people are working on the project
estd. 1.000 items more
I like the first approach because it gives me a service-bus-like behaviour and I can use configuration if I want to. The second one is more specific in terms of type-safety because you could make errors posting the messages.
I am writing a C# .NET 3.5 Windows Service that needs to perform some actions whenever a user logon or unlock event occurs. I have tried registering the service by adding my event handler to Microsoft.Win32.SystemEvents.SessionSwitch:
using Microsoft.Win32;
SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLogon)
{
// Do Task
}
else if (e.Reason == SessionSwitchReason.SessionUnlock)
{
// Do Task
}
}
Also I have tried to override the OnSessionChange(SessionChangeDescription changeDescription) {...} method inherited by the ServiceBase class:
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
if (changeDescription.Reason == SessionChangeReason.SessionLogon)
{
// Do Task
}
else if (changeDescription.Reason == SessionChangeReason.SessionUnlock)
{
// Do Task
}
base.OnSessionChange(changeDescription);
}
Many session events are handled by either of the methods described, unfortunately neither of these methods handle the event of a session unlock when fast user switching and terminal services are stopped and disabled. However the event is handled when both services are enabled and running. The work environment this will be deployed on will not have the services enabled.
Is there another way to accomplish this within the C# .NET managed code environment? Many questions I have seen answer the question with the methods described above, they do work correctly but not when both fast user switching and terminal services is disabled.
The CanHandleSessionChangeEvent property is set to False by default.
Insert the following code when initializing the components
public Service1()
{
InitializeComponent();
this.CanHandleSessionChangeEvent = true;
this.CanHandlePowerEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;
this.AutoLog = true;
}
If you're having difficulty with SessionSwitchReason you can enable 'Other Logon/Logoff Events' in windows eventlog and monitor for these events yourself. It's a bit messy because you have to poll the logs in someway, but it does the trick.
See - https://stackoverflow.com/a/40675839/6715034