I have Windows 10 Pro, build 10586.494 on HP ZBook G2. When I go to Settings -> Devices -> Bluetooth and switch on Bluetooth, I can see nearby BLE devices (they are custom made BLE devices manufactured by my company).
I want to interact with my BLE devices in Universal Windows application (in Visual Studio 2015). I use this code (it is just a snippet of code)
BluetoothLEAdvertisementWatcher watcher;
//....
watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
watcher.Received += WatcherOnReceived;
watcher.Start();
//....
private void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs btAdv)
{
}
When I run this application, WatcherOnReceived is never executed (although watcher.Start was executed). Why and how to fix it?
If found a better workaround for this. (I'm using Win 10 1803.)
First, to recap the problem since the original question is not entirely clear about it:
BluetoothLEAdvertisementWatcher works if BLE device is advertising before watcher.Start()
BluetoothLEAdvertisementWatcher does not work if BLE device starts advertising after watcher.Start()
If BluetoothLEAdvertisementWatcher is not working after watcher.Start(), it will begin working when Windows 10 Bluetooth Settings is opened or closed (i.e. the opening or closing of the settings window triggers BluetoothLEAdvertisementWatcher to start working)
So, the workaround I came up with is to keep starting and stopping a second BluetoothLEAdvertisementWatcher in the background to create the same sort of trigger that the Windows Bluetooth Settings window provides.
For example, using a WinForms timer:
...
var timer = new Timer { Interval = 1000 };
timer.Tick += Timer_Tick;
timer.Start();
...
private void Timer_Tick(object sender, EventArgs e)
{
var watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (s, a) => { };
watcher.Start();
Task.Delay(500).ContinueWith(_ => watcher.Stop());
}
I have to keep Bluetooth switched on in Settings -> Devices -> Bluetooth in order to receive advertisements in my app.
Related
I have a Windows Universal UWP app that I want to launch as a replacement shell on Windows 10 Home.
Typically for Win32 apps this is to set HKCU\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell to the appropriate EXE.
I have configured the UWP app with an execution alias in the Package.appxmanifest
<Extensions>
<uap5:Extension
Category="windows.appExecutionAlias"
Executable="App1.exe"
EntryPoint="App1.App">
<uap5:AppExecutionAlias>
<uap5:ExecutionAlias Alias="App1.exe" />
</uap5:AppExecutionAlias>
</uap5:Extension>
</Extensions>
I have also overridden App.OnActivated() to launch the application with this:
protected override void OnActivated(IActivatedEventArgs args)
{
switch (args.Kind)
{
case ActivationKind.CommandLineLaunch:
{
CommandLineActivatedEventArgs cmdLineArgs =
args as CommandLineActivatedEventArgs;
CommandLineActivationOperation operation = cmdLineArgs.Operation;
string cmdLineString = operation.Arguments;
string activationPath = operation.CurrentDirectoryPath;
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage),
string.Format("CurrentDirectory={0}, Arguments={1}", activationPath, cmdLineString));
Window.Current.Activate();
}
}
break;
default:
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage),
string.Format("CurrentDirectory={0}, Arguments={1}", Environment.CurrentDirectory, string.Empty));
Window.Current.Activate();
}
}
break;
}
}
Running App1.exe from command line works properly.
However placing the App1.exe registry: Shell='App1.exe'
does not launch the app (screen stays black on login.
I assume this is possible, because if I set Shell='Skype.exe'
Which is the execution alias for the Skype UWP app, skype launches properly on login.
I am searching for the missing piece of the puzzle.
** EDIT 2/14/21 **
So, I think the issue is that UWP apps are hosted in the explorer.exe application and if that is not running it, the app will never be able to run. Either that or it primes the UWP framework somehow.
I think Skype is likely a Hosted UWP app: Created Hosted apps
So what I have done is make a standard Win32 application that launches explorer.exe and quickly cripples it before it can display anything by implementing a keyboard hook to prevent Windows Key and other potential shortcuts, and also hiding the taskbar. Then starting the UWP app.
Its a little bit hackish, so I have not posted it as the solution, hoping that a cleaner one still is posted
I have an interesting problem that appears to be related to multicast being switched off (at the kernal) on newer andriod devices, please note This is NOT an issue with setting up UDP on multi adapters or LTE/WIFI, I understand that.
A lot of googling and trying loads things out have offered up a multitude of answers, e.g. acquire multi cast locks and some git hub issues where people say its impossible as devices have multicast disabled in the kernel. I have also just found this on SO
My code works fine on:-
Nexus 5 Andriod 8.1 - API 27
Lenovo Tablet Andriod 8.1 - API 27
That is it can send and receive UDP packets that is not directly targeted to the IP address of the phone.
It does NOT receive UDP packets on:-
Pixel 3a Andriod 10/11 APIS 29/30
The Xamarin forms code to replicate this is:
public TestCameraPage()
{
InitializeComponent();
sendClient = new UdpClient
{
EnableBroadcast = true,
ExclusiveAddressUse = false,
MulticastLoopback = true
};
sendClient.Client.Bind(new IPEndPoint(IPAddress.Any, CameraPort));
Lab1.Text = "Started to listen for UDP packets";
sendClient.BeginReceive(DiscoverCallback, sendClient);
}
private void DiscoverCallback(IAsyncResult result)
{
try
{
var ep = new IPEndPoint(IPAddress.Any, CameraPort);
var data = sendClient.EndReceive(result, ref ep);
var msg = $"Received: {Encoding.UTF8.GetString(data)}";
//Sniff out camera IP
var ip = $"{data[15]}.{data[14]}.{data[13]}.{data[12]}";
Device.BeginInvokeOnMainThread(() =>
{
Lab1.Text = $"CAMERA IP: {ip} FULL MESSAGE: {msg}";
});
}
finally
{
sendClient.BeginReceive(DiscoverCallback, sendClient);
}
}
private void Button_OnClicked(object sender, EventArgs e)
{
var data = PollMessageToCamera();
sendClient.Send(data, data.Length, "255.255.255.255", ListeningPort);
}
So my questions are two fold
Is it possible to receive UDP packets that are NOT broadcasted directly to the device on a newer Andriod phone?
If it is possible what do I need to do to fix it?
Example output on nexus and tablets
I should also point out I have a console app that can send UDP messages and if I use this (ip address of pixel 3a), it works
sendClient.Send(data, data.Length, "192.168.1.248", CameraPort);
If I use 255.255.255.255 (multi cast) in console app only the nexus and tablet works the pixel 3a doesn't
sendClient.Send(data, data.Length, "255.255.255.255", CameraPort);
I am not getting all devices when I am trying to scan Bluetooth devices with my application. It does not show android and windows device list. I have attached screenshots to understand my problem.
Here is my code.
_centralManager = new CBCentralManager(DispatchQueue.CurrentQueue);
_centralManager.DiscoveredPeripheral += _centralManager_DiscoveredPeripheral;
_centralManager.UpdatedState += (object sender, EventArgs e) =>
{
var manager = sender as CBCentralManager;
if (manager.State == CBCentralManagerState.PoweredOn)
_centralManager.ScanForPeripherals(new CBUUID[0]);
};
Scan event:
public void _centralManager_DiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs e)
{
var device = e.Peripheral;
var rssi = e.RSSI;
var ads = e.AdvertisementData;
}
Note: In my app, I was show device which name is not equal to null or blank.
I had implemented GATTA server on an Android device and it worked.
First, run the app on an Android device, start the server and done.
https://github.com/androidthings/sample-bluetooth-le-gattserver/blob/master/java/app/src/main/java/com/example/androidthings/gattserver/GattServerActivity.java
In my case, I wanted to do this for android things. So I implemented the code in android things.
I am developing an app for windows phone 7. There is a media element which plays video from a url. When i lock the phone, the audio and video stops playing. I have tried disabling ApplicationIdleDetetction and i have handled Rootframe Obscured and Unobscured. I just couldn't figure out how to continue playing the audio when the phone is locked.
Any help on this is greatly appreciated !!
thanks
graham
Use the AudioPlayerAgent to keep the music playing even when the phone gets locked!
Check the "Background Audio Player Sample" on the Windows Phone Code Samples.
Video will automatically stop playing when the screen is locked - that is a built-in system feature. Think of it as a fail-safe for applications that will drain the device battery by playing video in the background, which is an unnecessary task anyway - who watches the content? ApplicationIdleDetection won't help with this task at all.
If you have a separate audio stream, you could use AudioPlayerAgent, that can be used to play both local and remote audio streams.
Read this:
Background Audio Overview for Windows Phone
How to: Play Background Audio for Windows Phone
Streaming Audio in Windows Phone
You can do this with a dispatcher timer. Here is an example of how I do it in my app Searchler (This feature not yet in marketplace, update coming very soon!) using the MMP Player Framework available # http://smf.codeplex.com/
namespace Searchler.Views
{
public partial class PlayerView : PhoneApplicationPage
{
bool appUnderLock = false;
DispatcherTimer dispatcherTimer = new DispatcherTimer();
}
public PlayerView()
{
InitializeComponent();
//Hack to enable play under lock screen
UIThread.Invoke(() => VideoPlayer.PlayStateChanged += VideoPlayer_PlayStateChanged);
UIThread.Invoke(() => (Application.Current as App).RootFrame.Obscured += RootFrame_Obscured);
UIThread.Invoke(() => (Application.Current as App).RootFrame.Unobscured += RootFrame_Unobscured);
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, 0, 3);
}
void dispatcherTimer_Tick(object sender, EventArgs e)
{
if( VideoPlayer.PlaybackPosition == VideoPlayer.EndPosition)
((PlayerViewModel)DataContext).Next(); //Custom GetNext Video Method
}
void RootFrame_Unobscured(object sender, EventArgs e)
{
dispatcherTimer.Stop();
appUnderLock = false;
}
void RootFrame_Obscured(object sender, ObscuredEventArgs e)
{
dispatcherTimer.Start();
appUnderLock = true;
}
}
is it possible to check whether the location services are active?
I mean Settings > Location > Location services
There is probably no direct API for calling, but could it work with the GeoCoordinateWatcher?
GeoCoordinateWatcher g = new GeoCoordinateWatcher();
g.Start();
if (g.Permission.Equals(GeoPositionPermission.Granted))
{
//Your location services is enabled. Go ahead.
//Your codes goes here.
}
else if (g.Permission.Equals(GeoPositionPermission.Denied) || g.Permission.Equals(GeoPositionPermission.Unknown))
{
MessageBox.Show("Location services are disabled. To enable them, Goto Settings - Location - Enable Location Services.", "Location services", MessageBoxButton.OK);
}
You can use the following code to determine the status of the Location service:
var watcher = new GeoCoordinateWatcher();
if (GeoPositionStatus.Disabled == watcher.Status)
{
// Watcher is disabled.
}
More realistically, you'll want to pay more attention to change to the status (just because the service isn't disabled doesn't mean you've got location data), so you shoudl take a look at the MSDN Documentation for working with the Location service.
There's also a good post on filtering and emulating location data using the Reactive extensions, which is perfect for that pre-device testing, though to save you time on that front the Widnows Phone Team have released the Windows Phone GPS Emulator.
Even with the started GeoCoordinateWatcher you will get NoData if the sensor is disabled. What you should try using instead is TryStart:
GeoCoordinateWatcher g = new GeoCoordinateWatcher();
MessageBox.Show(g.TryStart(false,TimeSpan.FromSeconds(30)).ToString());
If it returns False, it means that the sensor is disabled. If it returns True, it is enabled. Set an appropriate timeout period (in the snippet above I am using 30 seconds) and delegate this process to a secondary thread, so it won't hang the UI.
You can add a StatusChanged event to your GeoCoordinateWatcher and test for GeoPositionPermission.Denied in the permissions when it fires.
watcher = new GeoCoordinateWatcher();
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
watcher.Start();
void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
if (watcher.Permission == GeoPositionPermission.Denied)
{
// Location services were disabled
}
}
Hope that helps.
Made this one based on TeJ's answer.
public override void OnNavigatedTo()
{
using (var watcher = new GeoCoordinateWatcher())
{
try
{
watcher.Start();
}
finally
{
IsAllowedInSystem = watcher.Permission.Equals(GeoPositionPermission.Granted);
watcher.Stop();
}
}
}
And my apps' ToggleSwitch.IsEnabled is binded to IsAllowedInSystem.
When i'm switching to Location Service, disable it and return back to app, my ToggleSwitch is disabled (also a string "Please, enable Location Service in System settings" in visible). When i'm switching to Location Service, enable it and return back to my app, my ToggleSwitch is enabled and user can set it up.