My app WP7 was not accepted because it fails to load if the internet is not available. I looked for a way to check it and found this command
NetworkInterface.GetIsNetworkAvailable()
But it isn't working on the emulator and I do not have any device to test it.
Could someone tell me if it returns false if the device is in Airplane mode? If not, how can I check for it?
Thanks,
Oscar
Edit: I also tried with this code:
try
{
wsClient.CurrenciesCompleted += new EventHandler<CurrencyConversion.CurrenciesCompletedEventArgs>(wsClient_CurrenciesCompleted);
wsClient.CurrenciesAsync(null);
}
catch
{
NetworkNotAvailable();
}
But I am not able to catch the exception, I also tried in the wsClient_CurrenciesCompleted method, but also no good.
Where could I test it?
Don't test for "the internet in general" - test for the service you'll actually be connecting to. Test for it by trying to connect to it - make some simple, non-destructive request on start-up. Yes, that will take a tiny bit of the user's data allowance, but:
You will be warming up the networking stack and making a connection which should end up being kept alive automatically, so future latency will be reduced.
You could warn the user that they may have limited functionality if the connection fails.
An Alternative to Jon's suggestion is to check which network interface is available. This is very handy in cases were you need to adjust which service you call based on network speed. For example the switch statement below could be modified to return an Enum to represent the quality of the network.
public class NetworkMonitorClass
{
private Timer timer;
private NetworkInterfaceType _currNetType = null;
private volatile bool _valueRetrieved = false;
public NetworkMonitorClass()
{
//using a timer to poll the network type.
timer = new Timer(new TimerCallBack((o)=>
{
//Copied comment from Microsoft Example:
// Checking the network type is not instantaneous
// so it is advised to always do it on a background thread.
_currNetType = Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType;
_valueRetrieved = true;
}), null, 200, 3000); // update the network type every 3 seconds.
}
public NetworkInterfaceType CurrentNetworkType
{
get
{
if(false == _valueRetrieved ) return NetworkInterfaceType.Unknown;
return _currNetType;
}
private set { ;}
}
public bool isNetworkReady()
{
if(false == _valueRetrieved ) return false;
switch (_currentNetworkType)
{
//Low speed networks
case NetworkInterfaceType.MobileBroadbandCdma:
case NetworkInterfaceType.MobileBroadbandGsm:
return true;
//High speed networks
case NetworkInterfaceType.Wireless80211:
case NetworkInterfaceType.Ethernet:
return true;
//No Network
case NetworkInterfaceType.None:
default:
return false;
}
}
}
See http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation.networkinterface.networkinterfacetype(VS.92).aspx
GetIsNetworkAvailable() will always return true in the emulator. For testing in the emulator you'll need to work round this in code.
This can be a useful quick check but you also (as Jon pointed out) need to handle the scenario of not being able to connect to your specific server.
Handling this can be done by catching the WebException when you try and get the response in the callback.
private static void DownloadInfoCallback(IAsyncResult asynchronousResult)
{
try
{
var webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// This will cause an error if the request failed
var webResponse = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
.....
}
catch (WebException exc)
{
// Handle error here
}
}
GetIsNetworkAvailable() works properly on device.
You can mock your handling of this for testing in the emulator using Microsoft.Devices.Environment.DeviceType.
I would be inclined to test both for avaiability of the internet and availability of your site through exception handling and provide feedback to the user of the app that indicates what the true reason is for features being unavailable.
Related
Following the changes posted here, the getNetworkType method is deprecated from Android R and onwards.
When trying to use this method in a R compiled application, results in the following exception being thrown:
java.lang.SecurityException: getDataNetworkTypeForSubscriber: uid 10225 does not have android.permission.READ_PHONE_STATE.
at android.os.Parcel.createExceptionOrNull(Parcel.java:2285)
at android.os.Parcel.createException(Parcel.java:2269)
at android.os.Parcel.readException(Parcel.java:2252)
at android.os.Parcel.readException(Parcel.java:2194)
at com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:7565)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2964)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2928)
at com.ironsource.environment.ConnectivityService.getCellularNetworkType(ConnectivityService.java:197)
at com.ironsource.sdk.service.DeviceData.updateWithConnectionInfo(DeviceData.java:98)
at com.ironsource.sdk.service.DeviceData.fetchMutableData(DeviceData.java:54)
at com.ironsource.sdk.service.TokenService.collectDataFromDevice(TokenService.java:120)
at com.ironsource.sdk.service.TokenService.getRawToken(TokenService.java:177)
at com.ironsource.sdk.service.TokenService.getToken(TokenService.java:166)
at com.ironsource.sdk.IronSourceNetwork.getToken(IronSourceNetwork.java:183)
This is fine and is expected according to the documentation. If I compile the application to any version before Android R, the exception doesn't show.
This exception indicates that I need to request the android.permission.READ_PHONE_STATE permission.
I wanted to know if there is a way to get the network type with any other API that does NOT require this permission (as this permission's level is dangerous and I would rather not ask the user for it).
Take runtime permission for READ_PHONE_STATE to ignore crash of getDataNetworkTypeForSubscriber
#Override
protected void onStart() {
super.onStart();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
int res = checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE);
if (res != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.READ_PHONE_STATE}, 123);
}
}
}
private final static int REQUEST_CODE_ASK_PERMISSIONS = 1002;
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "READ_PHONE_STATE Denied", Toast.LENGTH_SHORT)
.show();
} else {
}
stepAfterSplash();
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
You can still use getDataNetworkType(); This method does not necessarily need READ_PHONE_STATE, as stated in his Doc, but that it's sufficient "that the calling app has carrier privileges".
https://developer.android.com/reference/android/telephony/TelephonyManager#getDataNetworkType()
For what I know about getting those privigileges, it could be tricky/really hard, you may look into getting carrier privileges and using this method, which is also the suggested substitution for getNetworkType().
This method necessarily need READ_PHONE_STATE by this way in your activity not just manifest >>>
// Check if the READ_PHONE_STATE permission is already available.
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
//here >> use getNetworkType() method
// like this example
mStationInfo.set_networkType(mTelephonyManager.getNetworkType());
}
else {}
We can use ConnectivityManager#getNetworkCapabilities and NetworkCapablities#hasTransport like this
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActivityNetwork());
boolean isMobile = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
boolean isWifi = caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
Reference:
android.net.NetworkInfo
This class was deprecated in API level 29. Callers should instead use the ConnectivityManager.NetworkCallback API
to learn about connectivity changes, or switch to use
ConnectivityManager#getNetworkCapabilities or
ConnectivityManager#getLinkProperties to get information
synchronously. Keep in mind that while callbacks are guaranteed to be
called for every event in order, synchronous calls have no such
constraints, and as such it is unadvisable to use the synchronous
methods inside the callbacks as they will often not offer a view of
networking that is consistent (that is: they may return a past or a
future state with respect to the event being processed by the
callback). Instead, callers are advised to only use the arguments of
the callbacks, possibly memorizing the specific bits of information
they need to keep from one callback to another.
So my friend I have the same trouble as you but so far I came with a temporary fix I use the compileSdkVersion 29 not 30 as well as the targetSdkVersion 29 and my buildToolsVersion 28.0.3 and my app is loading fine.
Since this problem by me its coming due a third party library so till the fix the error I can not fix it alone, but I think with this temporary solution for now is quite well.
Looking at the source code for Dappers QueryAsync method
SqlMapper.Async.cs
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
{
using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
{
DbDataReader reader = null;
try
{
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
var func = tuple.Func;
if (command.Buffered)
{
var buffer = new List<T>();
var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
object val = func(reader);
if (val == null || val is T)
{
buffer.Add((T)val);
}
else
{
buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
}
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
}
finally
{
using (reader) { /* dispose if non-null */ }
if (wasClosed) cnn.Close();
}
}
}
Note this line (413):
using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
My question is, will my connection be disposed of correctly without me having to wrap my code calling in to this in a using block?
Note following line in the code you post:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....
That shows QueryAsync is an extension method of IDbConnection. That means, instance of connection is created in your code somewhere.
As mentioned here, there are two ways to manage connection with Dapper:
Fully manage yourself:
Here, you are fully responsible for opening and closing connection. This is just like how you treat connection while working with ADO.NET.
Allow Dapper to manage it:
Dapper automatically opens the connection (if it was not opened) and closes it (if it was opened by Dapper) for you.
Considering this, only choice remain here is to open/close connection in your code or allow Dapper to do this for you. If you are doing this yourself then Dapper does not interfere at all.
If you want to allow Dapper to handle the open/close connection for you and are worried that whether it will close it properly, then yes, it closes it properly.
Find following code in your post:
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
....
if (wasClosed) cnn.Close();
Dapper maintains the state/flag in wasClosed variable if connection was opened by Dapper. You can see in your code that the connection is also properly closed at the end. Further, you can further check the Dapper source code to see how the this is handled in multiple methods. Specially check SqlMapper.Async.cs and SqlMapper.cs files.
Now, this is all about open/close. What about Dispose? Following is what Marc Gravell says in one of the comment for this answer: https://stackoverflow.com/a/12629170/5779732
well, technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls, you might as well let dapper do it. If you are opening/closing at a wider granularity (per request, for example), it would be better for your code to do it and pass an open connection to dapper.
So, if you really want to Dispose the connection instead of just open/close, better you wrap it in using block in your code and pass open connection to Dapper. As mentioned in the comment, this post discusses difference between Dispose and Close.
I'm working with a fingerprint sensor on Arduino, but sometimes, on runtime, my WPF app throws an exception on sp.Open() saying "COM3" Access denied"
Here's the code on c#:
public string ConfigPort()
{
SerialPort sp = new SerialPort();
sp.BaudRate = 9600;
sp.PortName = AutodetectArduinoPort();
sp.Open();
string s = "";
while (true)
{
s = sp.ReadLine();
Console.WriteLine(s);
return s;
}
}
Here's the AutodetectArduinoPort method:
public string AutodetectArduinoPort()
{
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
if (desc.Contains("Arduino"))
{
return deviceId;
}
}
}
catch (ManagementException e)
{
/* Do Nothing */
}
return null;
}
Any solution??
This happens quite a lot with Arduino, personally I think there's a problem with the FTDI driver....certainly wouldn't be the first issue with them. What I do when this happens is physically unplug the device from the USB port, wait for the notification sound from Windows and then plug it back in again. This seems to "reset" the port and force whatever is holding it open to release it, and you're good to go again. You may need to do this quite a bit over time, so the only other tip I have is to use a cheap USB hub so that you wind up wearing out the port pins on that rather than your expensive laptop/desktop.
The error you're getting means that the port is already open. Make sure that you only call ConfigPort() once, and after you're done processing data from the Arduino, close the port with sp.Close(). I would suggest converting sp into a global variable, and subscribing to the OnClosing event of your WPF window, so you can close the port when the user closes the application.
I guess most of us agree, that NIO2 is a fine thing to make use of. Presumed you want to monitor some part of the file system for incoming xml - files it is an easy task now. But what if I want to integrate the things into an existing Java EE application so I don't have to start another service (app-server AND the one which monitors the file system)?
So I have the heavy weight app-server with all the EJB 3.1 stuff and some kind of service monitoring the file system and take appropriate action once a file shows up. Interestingly the appropriate action is to create a Message and send it by JMS and it might be nice to integrate both into the app server.
I tried #Startup but deployment freezes (and I know that I shouldn't make use of I/O in there, was just a try). Anyhow ... any suggestions?
You could create a singleton that loads at startup and delegates the monitoring to an Asynchronous bean
#Singleton
#Startup
public class Initialiser {
#EJB
private FileSystemMonitor fileSystemMonitor;
#PostConstruct
public void init() {
String fileSystemPath = ....;
fileSystemMonitor.poll(fileSystemPath);
}
}
Then the Asynchronous bean looks something like this
#Stateless
public class FileSystemMonitor {
#Asynchronous
public void poll(String fileSystemPath) {
WatchService watcher = ....;
for (;;) {
WatchKey key = null;
try {
key = watcher.take();
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue; // If events are lost or discarded
}
WatchEvent<Path> watchEvent = (WatchEvent<Path>)event;
//Process files....
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
} finally {
if (key != null) {
boolean valid = key.reset();
if (!valid) break; // If the key is no longer valid, the directory is inaccessible so exit the loop.
}
}
}
}
}
Might help if you specified what server you're using, but have you considered implementing a JMX based service ? It's a bit more "neutral" than EJB, is more appropriate for a background service and has fewer restrictions.
I was told that I shouldn't cache channels in Silverlight/WCF because they may become faulted and unsuable. Can somone show me some sample code that would prove it can happen.
Call a service to prove the connection can work (i.e. no bogus URL)
Make a second call that fouls the channel by causing it to go into a faulted condition
Repeat the first call, which would fail.
In my own testing, the key is whether the binding you're using is session-oriented or not. If you're using a stateless binding like BasicHttpBinding, you can muck up the channel all you want and you're good. For instance, I've got a WCF service using the BasicHttpBinding that looks like this -- note specifically the Channel.Abort() call in SayGoodbye():
public class HelloWorldService : IHelloWorldService
{
public string SayHello()
{
return "Hello.";
}
public string SayGoodbye()
{
OperationContext.Current.Channel.Abort();
return "Goodbye.";
}
}
And the Silverlight client code looks like this (ugly as hell, sorry).
public partial class ServiceTestPage : Page
{
HelloWorldServiceClient client;
public ServiceTestPage()
{
InitializeComponent();
client = new HelloWorldServiceClient();
client.SayHelloCompleted += new EventHandler<SayHelloCompletedEventArgs>(client_SayHelloCompleted);
client.SayGoodbyeCompleted += new EventHandler<SayGoodbyeCompletedEventArgs>(client_SayGoodbyeCompleted);
client.SayHelloAsync();
}
void client_SayHelloCompleted(object sender, SayHelloCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayHello() with result: {0}.", e.Result);
client.SayGoodbyeAsync();
}
else
{
Debug.WriteLine("Called SayHello() with the error: {0}", e.Error.ToString());
}
}
void client_SayGoodbyeCompleted(object sender, SayGoodbyeCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayGoodbye() with result: {0}.");
}
else
{
Debug.WriteLine("Called SayGoodbye() with the error: {0}", e.Error.ToString());
}
client.SayHelloAsync(); // start over
}
}
And it'll loop around infinitely as long as you want.
But if you're using a session-oriented binding like Net.TCP or HttpPollingDuplex, you've got to be much more careful about your channel handling. If that's the case, then of course you're caching your proxy client, right? What you have to do in that instance is to catch the Channel_Faulted event, abort the client, and then recreate it, and of course, re-establish all your event-handlers. Kind of a pain.
On a side note, when it comes to using a duplex binding, the best approach that I've found (I'm open to others) is to create a wrapper around my proxy client that does three things:
(1) Transforms the obnoxious event-raising code generated by the "Add Service Reference" dialog box into a far-more-useful continuation-passing pattern.
(2) Wraps each of the events raised from the server-side, so that the client can subscribe to the event on my wrapper, not the event on the proxy client itself, since the proxy client itself may have to be deleted and recreated.
(3) Handles the ChannelFaulted event, and (several times, with a timeout) attempts to recreate the proxy client. If it succeeds, it automatically resubscribes all of its event wrappers, and if it fails, it throws a real ClientFaulted event which in effect means, "You're screwed, try again later."
It's a pain, since it seems like this is the sort of thing that should have been included with the MS-generated code in the first place. But it sure fixes a whole lot of problems. One of these days I'll see if I can get this wrapper working with T4 templates.