FromBluetoothAddressAsync throws 'System.IO.FileNotFoundException' in mscorlib.ni.dll - bluetooth

I'm developing an app that connects ta a BLE beacon, for this I use the BluetoothLEAdvertisementWatcher API. When I receive an advertisement I want to connect to the device to read the GATT characteristics.
So I start a BLEwatcher
BluetoothLEAdvertisementWatcher watcher;
watcher.Received += OnAdvertisementReceived;
watcher.Stopped += OnAdvertisementWatcherStopped;
watcher.Start();
Then I try to access the device
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
var address = eventArgs.BluetoothAddress;
BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
Debug.WriteLine(device.Name + " - " + device.DeviceId);
....
This fails with (at FromBluetoothAddressAsync line)
An exception of type 'System.IO.FileNotFoundException' occurred in
mscorlib.ni.dll but was not handled in user code
Additional information: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
The funny thing is: if I open the system's bluetooth devices window it works fine!
So when I open the bluetooth devices window and run the app the error is not thrown, when I close the bluetooth devices window it throws the error.
Note that it always throws this error in a background task.
Apparently it does work on build 10.0.10586.218.
I found this online from someone with the same issue:
LUMIA 950, Windows 10, 1511, 10.0.14332.1001
Exception thrown on FromIdAsync(): 'System.IO.FileNotFoundException'
in mscorlib.ni.dll
LUMIA 730, Windows 10, 1511, 10.0.10586.218
Exception thrown on FindAllAsync(): 'System.ArgumentException'
LUMIA 920, Windows 10, 1511, 10.0.10586.218
No Error!
Screenshots:

The Problem
This error is caused by calling FromBluetoothAddressAsync in a non-UI thread. Windows 10 requires user consent when an app tries to access a Bluetooth peripheral. When FromBluetoothAddressAsync is called, Windows tries to create a consent dialogue. Because this is not a UI thread, the consent dialogue cannot appear and an exception is thrown.
Solution
First, you should make the BluetoothLEAdvertisementWatcher more specific to the peripheral that you're searching for. If you don't, then your app will see every single Bluetooth LE device and prompt for user consent on every one- a terrible user experience.
There are multiple ways to filter advertisements. You can do it manually in your OnAdvertisementReceived method using properties from eventArgs or you can set filters in the BluetoothLEAdvertisementWatcher itself. For example, to find Bluetooth LE devices that have a heart rate monitor, do:
watcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(GattServiceUuids.HeartRate);
To make a call on a UI thread, you need to use a dispatcher. You can set up a dispatcher using the following code:
// Variable in your class
CoreDispatcher dispatcher;
// Init for your class
public MainPage() {
...
// Init the dispatcher, this must be done on the main thread
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
...
}
Then, when you receive an advertisement, you can do your own filtering then tell the dispatcher to connect to the Bluetooth LE device on the main thread.
private async void ConnectToBTDevice(BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
// This will cause a consent prompt if the user hasn't already consented
var btDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
}
private bool Filter(BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
// Return true if the advertisement has the name we're looking for
return eventArgs.Advertisement.LocalName != null && eventArgs.Advertisement.LocalName.Equals("Peripheral Name");
}
private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
// Do our own filtering (for example)
if(!this.Filter(eventArgs)) return;
// Connect to the Bluetooth device in the UI (main) thread
this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.ConnectToBTDevice(eventArgs));
}

Aren't the BLE Windows APIs lovely and the nice (un)documented exceptions they give you?
You shouldn't use AdvertisementWatcher if you have the intent to pair to a device I guess. Instead use a DeviceInformation watcher with a specific selector for BLE-devices that contain both paired and non-paired devices. That will give a ready-to-use DeviceInformation object you can pair with.
The sample code for that can be seen at https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing, scenario number 8.

Related

Android Bluetooth connection parameter

I very long Looking for but not found a answer, hot to change bluetooth connection parameter (Connection Interval, Slave Latency, Supervision Timeout) on Android (master) device. Must importent for me is Supervision Timeout becouse on android by defaut is 20 seconds and i need lessen, i find CONNECTION_PRIORITY_BALANCED, CONNECTION_PRIORITY_HIGH and CONNECTION_PRIORITY_LOW_POWER but they dont change Supervision Timeout time,
or impossible to change connection parameter from Android (master)?
Please help me.
Thanks in advence.
Unfortunately, you are only allowed to do whatever API allows you. In most cases, mobile OS APIs do not allow you to do low level settings for the purpose of user friendly experience. Imagine you developed an app which uses connection parameters that drains battery... Then the user of your application would most probably complain about the OS provider or the OEM. This is not wanted and should be prevented. However, if you want to do low level changes for experimental reasons (research etc.), I would recommend you to download the Android API source code, do the changes and insert the custom ANdroid API to your phone (you need to root your phone).
Here is the related part from the source code in BluetoothGatt.class related to your request:
public boolean requestConnectionPriority(int connectionPriority) {
if (connectionPriority < CONNECTION_PRIORITY_BALANCED ||
connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
throw new IllegalArgumentException("connectionPriority not within valid range");
}
if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
if (mService == null || mClientIf == 0) return false;
try {
mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
}
return true;
}
I would look for the implementation of BluetoothGattService#connectionParameterUpdate.

How to prevent the screen from locking on UWP 10

I want to prevent the phone to lock if the user didnt interact with the phone for some time.
In win8 phone development i used the PhoneApplicationService.UserIdleDetectionMode Property. Unfortunately i cannot find anything alike for win 10 universal app.
Any suggestions?
Simple Answer
DisplayRequest class
var displayRequest = new DisplayRequest();
displayRequest.RequestActive(); //to request keep display on
displayRequest.RequestRelease(); //to release request of keep display on
Detailed Answer
Using display requests to keep the display on consumes a lot of power. Use these guidelines for best app behavior when using display requests.
Use display requests only when required, that is, times when no user input is expected but the display should remain on. For example, during full screen presentations or when the user is reading an e-book.
Release each display request as soon as it is no longer required.
Release all display requests when the app is suspended. If the display is still required to remain on, the app can create a new display request when it is reactivated.
To Request keep display on
private void Activate_Click(object sender, RoutedEventArgs e)
{
if (g_DisplayRequest == null)
{
g_DisplayRequest = new DisplayRequest();
}
if (g_DisplayRequest != null)
{
// This call activates a display-required request. If successful,
// the screen is guaranteed not to turn off automatically due to user inactivity.
g_DisplayRequest.RequestActive();
drCount += 1;
}
}
To release request of keep display on
private void Release_Click(object sender, RoutedEventArgs e)
{
// This call de-activates the display-required request. If successful, the screen
// might be turned off automatically due to a user inactivity, depending on the
// power policy settings of the system. The requestRelease method throws an exception
// if it is called before a successful requestActive call on this object.
if (g_DisplayRequest != null)
{
g_DisplayRequest.RequestRelease();
drCount -= 1;
}
}
References - Prevent the screen from locking on Universal Windows Platform
Hope it help someone!!
You want the DisplayRequest class in Windows 10.

Resume music after exit app on windows phone

i`m using mediaElement to play background music in my app. And that works just fine.
Problem is when the user minimize the application. When the application resume there is no sound... I can play other sounds in my application but cant play that background music any more.
First i have this code to stop all background music at first time app open:
if (Microsoft.Xna.Framework.Media.MediaPlayer.State == MediaState.Playing)
{
Microsoft.Xna.Framework.Media.MediaPlayer.Pause();
FrameworkDispatcher.Update();
}
xaml code of that mediaElement
<MediaElement AutoPlay="True" Source="/Dodaci/pozadina.mp3" x:Name="muzika_pozadina" MediaEnded="pustiPonovo" Loaded="pustiPonovo" />
and the cs code
private void pustiPonovo(object sender, RoutedEventArgs e)
{
muzika_pozadina.Play();
}
sound is about 300kb size.
So, how can i resume that sound playing after the user resume the application?
When your App is put into Dormant State (when you hit Start buton for example), the MediaElement is stopped. Then after you return to your App (and it wasn't Tombstoned), the Page is not Initialized once again, which means that your MediaElement is not loaded once again, so your Music doesn't start once again.
It depends on your purpose and code how it can be returned. In very simple example when you don't need to remember music last position you can just set source of your MediaElement once again in OnNavigatedTo() event:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
muzika_pozadina.Source = new Uri("/Dodaci/pozadina.mp3", UriKind.RelativeOrAbsolute);
}
As you have set your MediaElement.AutoPlay to true - it should start automatically (because of that you probably also don't need your Loaded event pustiPonovo).
In more complicated cases you can take an advantage of Activation and Deactivation events of your App - returning to MediaElement from Dormant/Tombstoned case is well explained here in the article.
You should also read about Fast App Resume in case User decides to return to your App by Tile instead of Launchers-Choosers.
I haven't tried above code, but hopefully it will do the job.

Websphere Server threads getting hung

We have an application where we use an H2 embedded database to store the data. We have a synchronized write method which does DB inserts. Since the H2 DB is a small Java embedded DB, we use "synchronized" on the write method to handle the transaction management in embedded DB rather than in DB.
But during heavy load, we could see that the write thread is getting hung. We are not sure for which resource, this thread is getting hung.
Please look at this snippet of code:
public synchronized int write(IEvent event) {
String methodName = "write";
Connection conn = null;
PreparedStatement updtStmt = null;
Statement stmt = null;
ResultSet rSet = null;
int status = 0;
try {
dbConnect.checkDBSizeExceed();
conn = dbConnect.getConnection();
updtStmt = conn.prepareStatement(insertQuery);
updtStmt.setString(1, (String) event.getAttributeValue());
......
updtStmt.setString(30, (String) event.getAttributeValue());
updtStmt.setBoolean(31, false);
status = updtStmt.executeUpdate();
}catch(SQLException ex){
logger.log(methodName,logger.print(ex),Logger.ERROR);
} catch(Exception ex){
logger.log(methodName,logger.print(ex),Logger.ERROR);
} finally {
try {
if (updtStmt != null)
updtStmt.close();
if (conn != null)
conn.close();
}catch(SQLException ex) {
logger.log(methodName,logger.print(ex),Logger.ERROR);
return status;
}
return status;
}
}
We have multiple write methods which can access this DB. From the code we could see that the code is straightforward. But we are not sure where the resource is locked.
Another problem is in the thread dump in the (Websphere) system.out, we could see the thread stacktrace as below.
[6/15/12 3:13:38:225 EDT] 00000032 ThreadMonitor W WSVR0605W: Thread "WebContainer : 3" (00000066) has been active for 632062 milliseconds and may be hung. There is/are 2
thread(s) in total in the server that may be hung.
at com.xxxx.eaws.di.agent.handlers.AuditEmbeddedDBHandler.store(Unknown Source)
at com.xxxx.eaws.di.agent.eventlogger.2LoggerImpl.logEvent(Unknown Source)
at com.xxxx.eecs.eventlogger.EventLoggerAdapter.logAuditEvent(EventLoggerAdapter.java:682)
at com.xxxx.eecs.eventlogger.EventLoggerAdapter.logEvent(EventLoggerAdapter.java:320)
at com.xxxx.eecs.eventlogger.EventLogger.logEventInternal(EventLogger.java:330)
at com.xxxx.eecs.eventlogger.EventLogger.logEvent(EventLogger.java:283)
at com.ibm.wps.auth.impl.ImplicitLoginFilterChainImpl.login(ImplicitLoginFilterChainImpl.java:55)
at com.ibm.wps.auth.impl.AuthenticationFilterChainHandlerImpl.invokeImplicitLoginFilterChain(AuthenticationFilterChainHandlerImpl.java:393)
at com.ibm.wps.auth.impl.InitialAuthenticationHandlerImpl.checkAuthentication(InitialAuthenticationHandlerImpl.java:204)
at com.ibm.wps.state.phases.PhaseManagerImpl.callInitialAuthenticationHandler(PhaseManagerImpl.java:240)
In the above stacktrace, I need to know the reason why I am getting "Unknown Source" in the stack trace. Those jars are available in the class path and we also have the H2.jar in the classpath. We are not sure why, if the thread gets in hung in H2, we are not able to get the thread stacktrace.
If not, I also need to know why the thread stack trace is showing "Unknown Source".
Appreciate your help.
Thanks in advance.
Are you using ejbs? How do you get the connection? Is it injected by the aop server? Do you retrieve it from jndi? You should Not synchronize the method.
Even if it is an embedded db you should rely on the app server facilities.
You need to configure the connection as a datasource, even if your db is in memory. If you want a serialized write on the db you need to configure the connection pool to the serialized ansi isolation level (there are 4 ansi isolation levels). In this way you should obtain the same effect in a managed environment (the app server) without the synchronized, that should be avoided inside an app server.
Unknown Source typically implies that the line numbers are available.
When you compile, the compiler can add in debug information like line numbers. If they are not present in the JAR or .class files, the JVM can't provide you that information.
HTH
It looks like the conn = dbConnect.getConnection(); is waiting for more than 60000ms.
The error thrown by WAS is because resource adapter has one mechanism poll period. It is considered the rate (in milliseconds) at which to poll the enterprise information system (EIS) event store for new inbound events. The poll cycle is established at a fixed rate, meaning that if execution of the poll cycle is delayed for any reason, the next cycle will occur immediately to “catch up”. During the poll period, the polling thread will be sleeping.
Once the time is calculated to 60000 milliseconds, the WebSphere Application Server thread monitor regards this polling thread as hung and throws the exception.

Notification sound not playing in J2ME

I am working on a J2ME application.
I am using Nokia 6131 NFC phone. I am using NetBeans IDE.
I have 4 forms and I am playing some notification sounds for the user while filling the form.
The problem is sound goes off suddenly after 3 to 4 min and the only solution is to exit the application and again open it.
My Code
public void playSoundOK()
{
try
{
InputStream is = getClass().getResourceAsStream("/OK.wav");
Player player = Manager.createPlayer(is,"audio/X-wav");
player.realize();
player.prefetch();
player.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
Exception
at com.nokia.mid.impl.isa.mmedia.audio.AudioOutImpl.openSession(AudioOutImpl.java:206)
at com.nokia.mid.impl.isa.mmedia.MediaOut.openDataSession(MediaOut.java:282)
at com.nokia.mid.impl.isa.mmedia.MediaPlayer.doPrefetch(MediaPlayer.java:155)
at com.nokia.mid.impl.isa.amms.audio.AdvancedSampledPlayer.doPrefetch(+4)
at com.nokia.mid.impl.isa.mmedia.BasicPlayer.prefetch(BasicPlayer.java:409)
at org.ird.epi.ui.UtilityClass.playSoundOK(UtilityClass.java:139)
at org.ird.epi.ui.EnrollmentForm.targetDetected(+695)
at javax.microedition.contactless.DiscoveryManager.notifyTargetListeners(DiscoveryManager.java : 700)
at javax.microedition.contactless.DiscoveryManager.access$1200(DiscoveryManager.java:103)
at javax.microedition.contactless.DiscoveryManager$Discoverer.notifyIndication(DiscoveryManager.java:882)
at com.nokia.mid.impl.isa.io.protocol.external.nfc.isi.NFCConnectionHandler$IndicationNotifier.run(+67) javax.microedition.media.MediaException: AUD
I would advise you to split NFC and audio playback into 2 different threads.
It is typically a bad idea to call a method that should take some time to complete (like prefetch) from inside an API callback (like targetDetected) because it makes you rely on a particularly robust kind of internal threading model that may not actually exist in your phone's implementation of MIDP.
You should have one thread whose sole purpose is to play the sounds that your application can emit. Use the NFC callback to send a non-blocking command to play a sound (typically using synchronized access to a queue of commands). The audio playback thread can decide to ignore commands if they were issued at a time when it was busy playing a sound (no point in notifying the users of multiple simultaneous NFC contacts)
You should close your player. Add the following code to your method:
PlayerListener listener = new PlayerListener() {
public void playerUpdate(Player player, String event, Object eventData) {
if (PlayerListener.END_OF_MEDIA.equals(event)) {
player.close();
}
}
};
player.addPlayerListener(listener);

Resources