GetNetworkType in Android 11 - telephonymanager

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.

Related

Setting request timeout with Netflix Feign and Hystrix

I'm creating a REST client using Feign. I've got my calls working, but I want to add some timeout support, and I'm having a heck of a time figuring out how to do that.
Feign's documentation says "to use Hystrix with Feign, add the Hystrix module to your classpath. Then use the HystrixFeign builder." Ok, so now I've got this:
service = HystrixFeign.builder()
.decoder(new GsonDecoder())
.target(ProjectService.class, URL_TO_BE_MOVED_TO_PROPS);
Now all of my methods are returning HystrixCommands, which I can execute or queue, but I still can't see how to configure them.
The Hystrix wiki (https://github.com/Netflix/Hystrix/wiki/Configuration) says that configuration should be added into the HystrixCommand constructor like this:
public HystrixCommandInstance(int id) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(500)));
this.id = id;
But my commands are being built/return by Feign, so I don't have access to the constructors.
One more thing worth noting is that the Feign-Hystrix readme (https://github.com/Netflix/feign/tree/master/hystrix) says "To use Hystrix with Feign, add the Hystrix module to your classpath. Then, configure Feign to use the HystrixInvocationHandler," but a Google search for HystrixInvocationHandler points me toward a non-Netflix repo. Even if I used that, I don't see how to configure Feign to use it.
Please tell me I'm being dumb and that this is super simple, which will make me feel gladness that I'm past this issue, and shame for not being able to figure it out on my own.
TL;DR: I want to set timeouts on requests made by my Feign client. How do?
Turns out you can set Hystrix properties using an instance of com.netflix.config.ConfigurationManager (from com.netflix.archaius:archaius-core).
Feign uses method names as HystrixCommandKeys, so you can access their properties using those names:
ConfigurationManager.getConfigInstance().setProperty("hystrix.command." + methodName + ".execution.isolation.thread.timeoutInMilliseconds", 1500);
This is assuming you've used HystrixFeign to construct your client, which wraps each call in HystrixCommand objects.
To simplify, I created a loop of my methods so I could apply the timeout service-wide:
private void configureHystrix() {
Method[] methods = ProjectService.class.getMethods();
String methodName;
for(int i = 0; i < methods.length; i++) {
methodName = methods[i].getName();
ConfigurationManager.getConfigInstance().setProperty(String.format("hystrix.command.%s.execution.isolation.thread.timeoutInMilliseconds", methodName), config.getTimeoutInMillis());
}
}
After some debugging I managed to set Hystrix timeout as follows:
HystrixFeign.builder()
.setterFactory(getSetterFactory())
.target(...);
// copy-paste feign.hystrix.SetterFactory.Default, just add andCommandPropertiesDefaults
private SetterFactory getSetterFactory() {
return (target, method) -> {
String groupKey = target.name();
String commandKey = Feign.configKey(target.type(), method);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(15000));
};
}

Authenticate user in WinForms (Nothing to do with ASP.Net)

Note: Cross-posted to ServerFault, based on comments.
Intro
I need to password protect some actions in my application, such as loading/saving files, clicking check-boxes, etc. This is a standard C# .Net 4.0, WinForms application which will run on Windows 7 in a corporate network.
I was about to roll my own very basic system (read obfuscation with wide open backdoors) with a text file of users/passwords/permissions (hashed and salted) until after some searching I found what looks like a
tantalizingly simple approach , but I'm having trouble finding a good tutorial on Roles that isn't about ASP.NET.
Question
So does anyone know of one or more tutorials that show me how to:
Create a Windows User/Group and give that User/Group a Role or Permission.
Note that I'm testing this from my company's networked laptop, but will deploy it on the customer's corporate network (Not sure if this is an issue, or how tricky this will get).
Create winforms/console app sample with even just a single method that prints "Hello World" if I'm authenticated or throws an exception if I'm not?
I've never done Network Admin or anything related and I keep reading about Active Directory and Local Users Vs Networked Users... I was hoping for an approach where I could build to an Interface and just ask Windows if the current user has permission ABC and not care too much about how Windows figured that out. Then I can make a concrete implementation for each Local/Network/ActiveDirectory/etc. use case as required (or if required... as I don't even know that right now).
Background
- read if interested, but not required to answer question
Just to make sure I'm going in the right direction here, basically I need/want to test this on my development PC to make sure it's going to have a good end-user experience for my customer. The problem is that currently they run an Auto-login script for each computer that runs my application and there are several different operators that use my application throughout the day. The customer wants password protection on certain features of my app and only provide that to certain operators. I have no problem fitting this in, as I've expected the request for a while, I just haven't ever programmed authentication before.
I think it's worthwhile to convince my customer to give each operator their own network account and assign whatever permissions they want to that operator or group, in case they need to fire somebody, change permissions, etc. It also means I just open several options for them and they can group those permissions however they see fit based on internal corporate policies, which I really shouldn't have to be worried about (but will be if I have to roll my own, as they're IT department knows almost nothing of my application).
From what I can tell it also makes my life a lot easier by not having to deal with hashing passwords and encryption, etc. and just handle which Role is required to click this or that button.
First of all, you'd have to determine, if you really want a simple role-based-authentication (you may want to read: http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/)
If you're sure it's absolutely sufficient, you're already on the right way with the SO link you provided in your question. It's kind of confusing that there is no support of 'roles' by default in Windows, but there are groups. Groups can be local or remote (e.g. ActiveDirectory), so an admin could assign users to certain groups, that are specific for your application (for an example look here: http://msdn.microsoft.com/en-us/library/ms731200(v=vs.110).aspx)
One key is: You have to prepare your application's central principal, hence fill it with roles, supported for the current user.
Therefore, On the very startup of your application you then check the current active user and set your application wide principal and role(s). This may look like this (just a very simple example):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace WindowsPrincipalTrial
{
public class Program
{
// you could also move these definitions to a config file
private static IDictionary<string, string> _groupRoleMappings = new Dictionary<string, string>()
{
{"MYAPPUSERGRP", MyRoles.Standard},
{"MYAPPSUPPORTGRP", MyRoles.Extended},
{"MYAPPADMINGRP", MyRoles.Admin},
};
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var allRoleNames = getGroupCorrespondingRoles(windowsId);
var newPrincipal = new GenericPrincipal(windowsId, allRoleNames);
Thread.CurrentPrincipal = newPrincipal;
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
private static string[] getGroupCorrespondingRoles(WindowsIdentity id)
{
// you also could do this more elegant with LINQ
var allMappedRoleNames = new List<string>();
string roleName;
foreach (var grp in id.Groups)
{
var groupName = grp.Translate(typeof(NTAccount)).Value.ToUpper();
if (_groupRoleMappings.TryGetValue(groupName, out roleName))
{
allMappedRoleNames.Add(roleName);
}
}
return allMappedRoleNames.ToArray();
}
}
public static class MyRoles
{
public const string Standard = "standard_role";
public const string Extended = "extended_role";
public const string Admin = "admin_role";
}
}
Then your Application-Principal is set up.
Now you could check access in your code like this:
public void DoSomethingSpecial()
{
if (Thread.CurrentPrincipal.IsInRole(MyRoles.Extended))
{
// do your stuff
}
else
{
// maybe display an error
}
}
Or more drastically:
public void DoSomethingCritical()
{
var adminPermission = new PrincipalPermission(null, MyRoles.Admin);
adminPermission.Demand();
// do stuff
}
what is possible even declarative, as known from ASP.NET:
[PrincipalPermission(SecurityAction.Demand, Role=MyRoles.Admin)]
public void DoSomethingMoreCritical()
{
// do stuff
}
The ugly thing with the latter two examples is, that they throw exceptions, when the right role isn't hit.
So the mapping between roles and groups you have to do quite at the start of your app, according to the systems you want to use (local groups, AD groups, LDAP groups etc.).
If you, however, prefer authentication with actions and roles, after all, have a look at Windows Identity Foundation and Claims Based Authorization! There are already some ready-to-use frameworks out there (e.g. https://github.com/thinktecture/Thinktecture.IdentityModel).
UPDATE:
When it comes to activity based and thereby claims based authorization, I will try in short, how you could achieve it, by using Thinktecture's IdentityModel.
Generally that approach still uses roles internally, but has a kind of translation layer in between. Thinktecture already encapsulates many things needed. Authorization checks in code are then done via claim permissions. They are technically kind of request for an access to a certain resource. For the sake of simplicity I limit my example for actions only, by using one single default resource (since ClaimPermission doesn't accept an empty resource).
If you want to use action#resource pairs, you'd have to modify the code respectively.
At first you need a ClaimsAuthorizationManager
public class MyClaimsAuthorizationManager : ClaimsAuthorizationManager
{
private IActivityRoleMapper _actionToRolesMapper;
public MyClaimsAuthorizationManager(IActivityRoleMapper mapper)
{
_actionToRolesMapper = mapper;
}
public override bool CheckAccess(AuthorizationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
try
{
var action = getActionNameFromAuthorizationContext(context);
var sufficientRoles = _actionToRolesMapper.GetRolesForAction(action)
.Select(roleName => roleName.ToUpper());
var principal = context.Principal;
return CheckAccessInternal(sufficientRoles, principal);
}
catch (Exception ex)
{
return false;
}
}
protected virtual bool CheckAccessInternal(IEnumerable<string> roleNamesInUpperCase, IClaimsPrincipal principal)
{
var result = principal.Identities.Any(identity =>
identity.Claims
.Where(claim => claim.ClaimType.Equals(identity.RoleClaimType))
.Select(roleClaim => roleClaim.Value.ToUpper())
.Any(roleName => roleNamesInUpperCase.Contains(roleName)));
return result;
}
// I'm ignoring resources here, modify this, if you need'em
private string getActionNameFromAuthorizationContext(AuthorizationContext context)
{
return context.Action
.Where(claim => claim.ClaimType.Equals(ClaimPermission.ActionType))
.Select(claim => claim.Value)
.FirstOrDefault();
}
}
As you may have guessed, IActivityRoleMapper is an interface for a class, that returns the names of all roles, that include permission for a given action.
This class is very individual and I guess you'll find your way implementing it, because it's not the point here. You could do it by hardcoding, loading from xml or from a database. Also you would have to change/extend it, if you wanted to you action#resource pairs for permission requests.
Then you'd have to change the code in main() method to:
using Thinktecture.IdentityModel;
using Thinktecture.IdentityModel.Claims;
using Microsoft.IdentityModel.Web;
private static void Main(string[] args)
{
var windowsId = WindowsIdentity.GetCurrent();
if (windowsId != null)
{
var rolesAsClaims = getGroupCorrespondingRoles(windowsId)
.Select(role => new Claim(ClaimTypes.Role, role))
.ToList();
// just if you want, remember the username
rolesAsClaims.Add(new Claim(ClaimTypes.Name, windowsId.Name));
var newId = new ClaimsIdentity(rolesAsClaims, null, ClaimTypes.Name, ClaimTypes.Role);
var newPrincipal = new ClaimsPrincipal(new ClaimsIdentity[] { newId });
AppDomain.CurrentDomain.SetThreadPrincipal(newPrincipal);
var roleMapper = new ActivityRoleMapper(); // you have to implement
// register your own authorization manager, so IdentityModel will use it per default
FederatedAuthentication.ServiceConfiguration.ClaimsAuthorizationManager = new MyClaimsAuthorizationManager(roleMapper);
}
else
{
throw new NotSupportedException("There must be a logged on Windows User.");
}
}
Finally you can check access this way:
public const string EmptyResource = "myapplication";
public void DoSomethingRestricted()
{
if (!ClaimPermission.CheckAccess("something_restricted", EmptyResource))
{
// error here
}
else
{
// do your really phat stuff here
}
}
Or again, with exceptions:
private static ClaimPermission RestrictedActionPermission = new ClaimPermission(EmptyResource, "something_restricted");
public void DoSomethingRestrictedDemand()
{
RestrictedActionPermission.Demand();
// play up, from here!
}
Declarative:
[ClaimPermission(SecurityAction.Demand, Operation = "something_restricted", Resource = EmptyResource)]
public void DoSomethingRestrictedDemand2()
{
// dostuff
}
Hope this helps.

Silverlight CaptureDeviceConfiguration.RequestDeviceAccess() - how does it know?

CaptureDeviceConfiguration.RequestDeviceAccess() method must be invoked by user interaction, otherwise it fails. My question is how does Silverlight know the invocation came from user (i.e. via Button.Click())?
Have a look at this: http://liviutrifoi.wordpress.com/2011/05/18/silverlight-isolatedstoragefile-increasequotato/
Quote:
I was curios though how exactly does silverlight know what a user
initiated event is, but after digging through .net framework source
code I’ve got to a dead end:
if ((browserService == null) || !browserService.InPrivateMode())
{
//..
}
return false; //means that IncreaseQuota will fail
where browser.IsInPrivateMode is:
[SecuritySafeCritical]
public bool InPrivateMode()
{
bool privateMode = false;
return (NativeMethods.SUCCEEDED(UnsafeNativeMethods.DOM_InPrivateMode(this._browserServiceHandle, out privateMode)) && privateMode);
}
where DOM_InPrivateMode is in a DllImport["agcore"], which according
to microsoft is confidential :( So it looks like I won’t find out soon
how they’re detecting user initiated events, although I’m guessing
they have some centralized private method that detects clicks for
example, and then probably sets a flag that this was indeed “a user
initiated event”, and since you can’t forge clicks or keypresses using
javascript and since you can’t call those private methods using
reflection, it’s “safe”.

WCF/Silverlight: How can I foul a Channel?

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.

WP7 check if internet is available

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.

Resources