How to detect network change events asynchronously in UWP apps - c#

I am building a UWP app where I am trying to detect different type of network event changes asynchronously.
Where user can make network changes and see the effect of their changes promptly.
For example -
Airplane Mode ON/OFF detect asynchronously
Bluetooth ON/OFF detect asynchronously
Network connectivity ON/OFF detect asynchronously
I was able to detect Airplane Mode ON/OFF detect synchronously using following code
public bool isConnectedToNetwork()
{
return NetworkInformation.GetInternetConnectionProfile()?.NetworkAdapter != null;
}
private void checkAirplaneMode()
{
if(isConnectedToNetwork())
{
airplaneText.Text = "AirplaneMode: OFF";
}
else
{
airplaneText.Text = "AirplaneMode: ON";
}
}
But I wanna (I would like to) do it asynchronously as network event changes.
So, User don't have to run the app again and again to see the changes.

UWP provides specific events to notify these changes, such as NetworkInformation.NetworkStatusChanged Event ,BluetoothDevice.ConnectionStatusChanged Event.
If you want to detect network change events, you could register for notifications of connection state change events.
// register for network status change notifications
networkStatusCallback = new NetworkStatusChangedEventHandler(OnNetworkStatusChange);
if (!registeredNetworkStatusNotif)
{
NetworkInformation.NetworkStatusChanged += networkStatusCallback;
registeredNetworkStatusNotif = true;
}
Then you could retrieve the connection state change information and add your trigger code.
async void OnNetworkStatusChange(object sender)
{
// get the ConnectionProfile that is currently used to connect to the Internet
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (InternetConnectionProfile == null)
{
//add code about not connected
}
else
{
//add code about connected
}
}

Related

BLE advertisement UWP application

Im trying to make a program that can scan for BLE advertisements. I have been looking at the Windows-universal-samples, more precisely the sample called BluetoothAdvertisement. I want to make a simple UWP application that can scan for BLE advertisements and show them in a listbox. But my application can't find anything at all and I'm totally lost.
namespace BleDiscAdv2
{
public sealed partial class MainPage : Page
{
// The Bluetooth LE advertisement watcher class is used to control and customize Bluetooth LE scanning.
private BluetoothLEAdvertisementWatcher watcher;
public MainPage()
{
this.InitializeComponent();
// Create and initialize a new watcher instance.
watcher = new BluetoothLEAdvertisementWatcher();
//Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm
//will start to be considered "in-range"
watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
// Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction with OutOfRangeTimeout
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;
// Set the out-of-range timeout to be 2 seconds. Used in conjunction with OutOfRangeThresholdInDBm
// to determine when an advertisement is no longer considered "in-range"
watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Attach a handler to process the received advertisement.
// The watcher cannot be started without a Received handler attached
watcher.Received += OnAdvertisementReceived;
}
private void btStart_Click(object sender, RoutedEventArgs e)
{
watcher.Start();
}
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
DateTimeOffset timestamp = eventArgs.Timestamp;
string localName = eventArgs.Advertisement.LocalName;
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lbModtaget.Items.Add("Name of device: " + localName + "\t" + "Time for advertisement: " + timestamp.ToString("hh\\:mm\\:ss\\.fff"));
});
}
}
}
Can someone tell me what is wrong?
I'm new to BLE and I haven't been coding for a while.
Best regards
Christian
But my application can't find anything at all and I'm totally lost.
Please ensure that your app has enable Bluetooth capability in the Package.appxmanifest. See Basic Setup for details.
Please ensure the Bluetooth radio of running device was turn on and available.
There're devices are advertising and meet the filter. You can run the Scenario 2 of the Bluetooth advertisement official sample on another device to ensure that.
By testing on my side, your code snippet can scan the BLE advertisements well. In your code snippet, you didn't listen to the Stopped event handle of the watcher which is for notification to the app that the Bluetooth LE scanning for advertisements has been cancelled or aborted either by the app or due to an error. If the watcher is force stopped it will not get any advertisements.
You can add the Stopped event handle to check if there is a BluetoothError.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Attach a handler to process the received advertisement.
// The watcher cannot be started without a Received handler attached
watcher.Received += OnAdvertisementReceived;
watcher.Stopped += OnAdvertisementWatcherStopped;
}
private async void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
txtresult.Text = string.Format("Watcher stopped or aborted: {0}", args.Error.ToString());
});
}
For example, RadioNotAvailable may be caused by the running device is not enable the Bluetooth, OtherError may be caused by Bluetooth capability doesn't enabled. If the watcher is not stopped and there're advertisements, your app should work.

C# UWP, reusing geofences in geofencemonitor

I'm developing UWP app which will assist people with public transportation in my city. It uses geofencing to notify when the device is near some station. All is working fine, but slow. On my lumia 830 it took 4-5 seconds to prepare data for all 250 geofences and create them. Since, geofencemonitor runs under system and can store my geofences even when my app is terminated, I thought it would be smart to not recreate all geofences again and again on every app startup, but create them once and then just reuse them.
But I cant figure out how. When I start my app, Geofencemonitor.Current.Count is 250 and GeofenceMonitor.Current.Status is Ready, but it never fires Geoface state changed event.
My problem:
I m trying to reuse geofences in geofencemonitor. When I run my app and during startup I dont call Geofencemonitor.Current.Geofences.Clear(); and then create and add all my geofences -> geofence state change event is never fired.
Edit: It seems, that geofence status change fires only once after I add geofence to geofencemonitor, independently on if the app was restarted or not. But "used" geofence still remains in geofence monitor. Does geofence have some supended state? Am I missing some geofence property?
Here is how I create geofence:
var geofence = new Geofence(id, geocircle, mask, false, dwellTime);
GeofenceMonitor.Current.Geofences.Add(geofence);
My questions:
"Since, geofencemonitor runs under system and can store my geofences even when my app is terminated" - Is this really true?
If my first questions is true, and it is possible to reuse geofences, what am I doing wrong or do you know some place where I can go deeper into Geofencing in UWP?
Thanks for advice.
Here is how I listen geofences state change event:
ItsValueIs250 = Geofencemonitor.Current.Geofences.Count;
ItsValueIsReady = Geofencemonitor.Current.Status;
public async void OnGeofenceStateChanged(GeofenceMonitor sender, object e)
{
var reports = sender.ReadReports();
await Dispatcher.DispatchAsync( () =>
{
foreach (GeofenceStateChangeReport report in reports)
{
GeofenceState state = report.NewState;
Geofence geofence = report.Geofence;
if (state == GeofenceState.Entered)
{
stationInRange.Add(geofence.Id);
StationInRangeCount = stationInRange.Count().ToString();
}
else if (state == GeofenceState.Exited)
{
stationInRange.Remove(geofence.Id);
}
}
});
}
And maybe this method which I call during startup.
async public Task<string> GeomonitorInitialize()
{
string message = string.Empty;
var accessStatus = await Geolocator.RequestAccessAsync();
switch (accessStatus)
{
case GeolocationAccessStatus.Allowed:
int i = 0;
i = GeofenceMonitor.Current.Geofences.Count;
return message;
case GeolocationAccessStatus.Denied:
message = "GeoDenied";
return message;
case GeolocationAccessStatus.Unspecified:
message = "GeoError";
return message;
default:
message = "Default";
return message;
}
}
I will add any piece of code I use as you will wish. Thank you.

What events are triggered when a user clicks on a notification in notification center in ios/xamarin

I'm using ios/xamarin to build mobile app and I want to determine which events will be triggered when a user clicks on a notification in notification center in ios/xamarin when the application is running in the background or not active.
I checked that the ReceivedRemoteNotification event is triggered when I click on the notification in the notification center either if the app is active or not.
When application is active:
If your application is active then following method will be called by default to receive notification:
DidReceiveRemoteNotification
If you want to call ReceivedRemoteNotification by default then you will have to add key UIBackgroundModes with value remote-notification in info.plist file
When application is in background
iOS will display received notification by it self. Currently there is no way to call any method in this case. So, when user will tap on received notification at that time again DidReceiveRemoteNotification method will be called, where you will have your notification regarding details.
When application is InActive:
iOS will dislay received notification by it self, once again there is no way to call any method in this case. Now, when user will tap on received notification at that time FinishedLaunching method will be called and using following code you can have your data for both local and remote notification:
if (options != null)
{
// check for a local notification
if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
{
UILocalNotification localNotification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;
if (localNotification != null)
{
//--your code
}
}
// check for a remote notification
if (options.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
{
NSDictionary remoteNotification = options[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
if (remoteNotification != null)
{
//--your code
}
}
}
Check the Xamarin documentation. Another event is ReceivedLocalNotification based on usage. For Remote notification the registration workflow is also described there.
Old question however if you or someone else still search an answer..
There is no event called for this action, but you can determinate if your app was started by clicking on a local and/or remote notification using the "options" variable coming with the FinishedLaunching method.
If null, your app was started normally, if not null then it was probably started by clicking on a notification in the notification center.
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
/*
// Your init code, for ex.
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(string.Empty));
*/
if (options != null)
if (options.Keys != null)
if (options.Keys.Count() != 0)
{
UILocalNotification localnotif = null;
if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
localnotif = options.ObjectForKey(UIApplication.LaunchOptionsLocalNotificationKey) as UILocalNotification;
if (localnotif != null)
{
UIAlertView alert = new UIAlertView()
{
Title = "LocalNotification",
Message = string.Format("Content: {0}, {1}", localnotif.AlertTitle, localnotif.AlertBody)
};
alert.AddButton("OK");
alert.Show();
}
}
return base.FinishedLaunching(app, options);
}

NetworkChange.NetworkAddressChanged event does not fire

I am developing a windows phone 7 app which is required to work with network.
I wanted my application to connect when NetworkAddress is changed that it becomes available. So I used NetworkChange.Networkaddresschanged. I was testing my app on emulator. It fires up first time but as there is no network I do nothing. This NetworkAddresschanged does not fire up the second time when network is available.
My code is
public void OnNetworkDownEvent()
{
lock (_networkChange)
{
var handler =_OnNetworkDown;
if (handler != null)
{
_OnNetworkDown();
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
NetworkChange.NetworkAddressChanged -= OnNetworkChange;
NetworkChange.NetworkAddressChanged += OnNetworkChange;
});
_connectionDown = true;
Monitor.Wait(_networkChange);
OnNetworkUpEvent();
}
}
public void OnNetworkUpEvent()
{
var handler = _OnNetworkUp;
if (handler != null)
{
_OnNetworkUp();
}
}
private void OnNetworkChange(object sender, EventArgs e)
{
lock(_networkChange)
{
if(NetworkInterface.GetIsNetworkAvailable())
{
if (_connectionDown)
{
_connectionDown = false;
Monitor.Pulse(_networkChange);
//OnNetworkUpEvent();
}
}
}
}
I call Networkdownevent() when network is down.And at that time I attach a delegate to NetworkAddressChange.
I do not know why this is happening.
The phone will see the USB connection to the host PC as it's primary connection so changes to the network connection of the attached PC will not have an impact on the phone.
This is one scenario where you can't test with the debugger attached. You'll have to store/display your debug output on the device with it not attached.
For testing I recommend having the phone connect to WiFi only and then controlling the connection state by turning the access point on or off. (This is the simplest technique I'm aware of for such a situation.)

dotRAS Disconnected State not triggered

Can someone give me a heads up... I'm trying to use the dotRAS .NET control, and this code to change the value of internetConnected (boolean) using an event handler...
But it seems that the state RasConnectionState.Disconnected is not triggered by dotRAS hangup()..
Any ideas? Am I doing it totally wrong... or have I managed to find a bug?
public class USBModem
{
// private vars
private RasDialer dialer = new RasDialer();
private bool internetConnected = false;
/// <summary>
/// Default constructor for USBModem
/// </summary>
public USBModem()
{
// Add Events for dialer
dialer.StateChanged += new EventHandler<StateChangedEventArgs>(dialer_StateChanged);
}
void dialer_StateChanged(object sender, StateChangedEventArgs e)
{
// Handle state changes here
switch (e.State)
{
case RasConnectionState.Connected:
internetConnected = true;
Console.WriteLine(e.State.ToString());
break;
case RasConnectionState.Disconnected:
internetConnected = false;
Console.WriteLine(e.State.ToString());
break;
default:
Console.WriteLine("INFO -> Unhandled state: " + e.State.ToString());
break;
}
}
public void ConnectInternet(string connectionName)
{
// Dial
dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);
dialer.EntryName = connectionName;
dialer.DialAsync();
}
public void DisconnectInternet()
{
foreach (RasConnection connection in dialer.GetActiveConnections())
{
connection.HangUp();
}
}
}
I've made some changes to the documentation for RasDialer in the 1.2 release to hopefully address this problem.
Apparently, a very simple (but widespread) mistake.
Basically the RasDialer component only handles events while a dialing operation is in progress.
The disconnected event would be raised if perhaps the modem line became unplugged during the connection attempt.
If you want to monitor client connections on the machine for connection/disconnection or a couple other events, use a RasConnectionWatcher. This will receive notifications from Windows when connection changes are made outside of a dialing operation.
Documentation on dotRAS is particularly sparse on Google... Head to http://dotras.codeplex.com for further information. The Help files included with the SDK are also very useful.

Categories