I am developing a Tango Application with Unity and the Tango SDK, however, I need to be able to check the device's Wifi connectivity and connect to a Wifi Network accordingly.
With that in mind I started working on an Android Unity Network Plugin, but I am having troubles checking the device's connectivity; even though Wifi is on and the Device is indeed connected to a Wifi network, getActiveNetwork keeps returning null.
I spent a couple of days searching for a workaround, or an alternative implementation, but I couldn't find anything that works, below is the code I ended up using to perform the check after looking through the many Android Connectivity related questions I looked at, as well as all the permissions I am using in the Manifest.
(I would like to point out that I am currently returning an integer as a means to quickly debug the function when called via Unity C# Scripts, and right now the function always returns 0.)
public int IsConnectedToWifi(){
//SCCActivity activity = new SCCActivity();
ConnectivityManager cm = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm == null) return -2;
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { // connected to the internet
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
// connected to wifi
DebugToast(activeNetwork.getTypeName());
return 1;
//return activeNetwork.isConnected();
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
// connected to the mobile provider's data plan
DebugToast(activeNetwork.getTypeName());
return 2;
//return false;
}
}
else {
DebugToast("There is no active Network");
return 0;
//return false;
}
DebugToast("Failed to get a Connectivity Manager");
return -1;
//return false;
}
In AndroidManifest file:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
I would really appreciate any advice or guidance, thank you.
I is a bit old but maybe it helps someone. In my case when I changed the order of permissions in manifest in a way that ACCESS_NETWORK_STATE is before INTERNET then it worked
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
strange but works
Hey I don't know if you really want to check that is phone is connected to WIFI or MOBILE_INTERNET.
But if you just want to check that if mobile have connectivity
than below code works fine for me
public static final boolean isNetworkAvailable(Context context) {
boolean connected = false;
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo nf = connectivityManager.getActiveNetworkInfo();
if (nf != null && (nf.isConnected() || nf.isConnectedOrConnecting())) {
// we are connected to a network
connected = true;
} else
connected = false;
return connected;
}
I have been using this successfully in devices with kitkat and later:
public static boolean isConnectedWifi(Context context){
NetworkInfo info = Connectivity.getNetworkInfo(context);
return (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI);
}
I have also compared it to ConnectivityManager.TYPE_MOBILE in the past but can't remember how good or bad it worked.
Upon further debugging and looking through similar cases, I found and solved the issue.
I will leave my solution here in case someone else comes across a similar problem.
Basically, getActiveNetwork wasn't really returning null at all, it turns out that even though the permission was listed on the xml, "android.permission.ACCESS_NETWORK_STATE" was never granted and the function was throwing up an exception. The cause of the problem was the fact that, as I mentioned before, I am working on a Tango Application using the Tango SDK for Unity, and the xml provided by the Tango SDK was overwriting the xml from the Java plugin.
The solution was simple; I just added the permissions to the Tango SDK's xml instead.
Related
I have asked the following quoted question but found that all working gone in vain as android is now not allowing to register the broadcast for network changes.
You can not do it in Manifest where as you can still get calls when you register it in your Activity and that context is still alive .
Now I have implemented in my activity and I am getting my broadcast receivers call and all is working as expected. But when I do start my activity , I received the call automatically. Can not I just skipp that thing on activity start ?
here is my old question that I have asked in this thread:
I have an application where I have implemented the BroadcastReceiver for the Network changes.
It alerts me when there is any change in the network connection, Like
the network gets disconnected, the network gets connected, the network
gets changed etc
But I have observe that it does not alert me when the Wifi is
connected but the Internet goes off from that network.
Is there something to check such case and can we make broadcast for it
??
I have searched alot but did not get any answer of this. I hope I made
myself quiet clear about my requirements.
Have you check the documentation here?
https://developer.android.com/training/monitoring-device-state/connectivity-monitoring?hl=es-419
It explains you how to use ConnectivityManager to check the changes on connectivity
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
You can even check the type:
boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
Or even allow your app (via the Manifest) to consider the changes, by supporting this action:
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
We have an app we are making that needs to switch to cellular for some requests even when WiFi is connected.
According to the ConnectionManager documentation these following methods are now deprecated, but is not so clear on what to use instead.
public void useMobileNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
}
public void useDefaultNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE);
}
Do these methods still work in android 5/6? and if anyone has info or something to replace these methods with I would be very grateful!
Ok little bit more on the problem :)
I have managed to investigate ConnectivityManager and can see the networks using :
Network networkToUse = null;
Network[] networks;
networks = cm.getAllNetworks();
for (Network network : networks) {
NetworkInfo ni = cm.getNetworkInfo(network);
Log.e("NETWORKINFO", ni.getType() + " " + ni.getExtraInfo());
if (ni.getType()== ConnectivityManager.TYPE_WIFI) {
Log.e("NETWORKINFO", "isWifi");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
if (networkToUse == null) {
networkToUse = network;
}
}
}
if (ni.getType()== ConnectivityManager.TYPE_MOBILE) {
Log.e("NETWORKINFO", "HasMobile");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
networkToUse = network;
}
}
}
It is here I kind of get stuck because I can't logically see a way of telling the app to use one of these networks when performing a HttpsURLConnection from URL.openLink();.
UPDATE:
I have just noticed that the mobile one disappears shortly after WiFi connects. There is a moment where I get both but not for long.
I have also tried this:
final ConnectivityManager connection_manager =
(ConnectivityManager)httpsClient.getCheckoutController().getCheckout().getCurrentActivity().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A CELLULAR NETWORK " + connection_manager.getNetworkInfo(network));
}
});
request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A WIFI NETWORK "+connection_manager.getNetworkInfo(network));
}
});
but as with the "list" of networks" in previous try I only ever 1 callback, even if mobile data is on as well.
UPDATE;
Ok I seem to see mobile sometimes using above method. but it seems to create API level spaghetti hell. It sometimes also takes a very long time for the mobile callback to fire. I wonder if this is because it has to wake up the cellular modem and wait for it's handshake or something?
UPDATE;
I had another possible suggestion using Sockets (something I have little experience with..)
Does anyone know if it is possible to build a CELLULAR SSL connection socket to do https requests using HttpsURLConnection.getSocketFactory() and SSLSocket ?
Any info would be very welcome in this week long quest :D
UPDATE:
Found a good and categorical answer from someone at google:
How to stay connected through mobile network after WIFI is connected on Android?
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.
According to the Android documentation it is no longer working in Android version 5 and above.
This method was deprecated in API level 21.
Functionality has been removed as it no longer makes sense, with many more >than two networks - we'd need an array to express preference. Instead we >use dynamic network properties of the networks to describe their >precedence.
Found a good and categorical answer from someone at google: How to stay connected through mobile network after WIFI is connected on Android?
(Link is in edited info above)
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.
On GSM devices able to force on data network if wifi is on ,But on CDMA devcies it fails.
public boolean isMobileHighPriorityUP() {
ConnectivityManager connMgr = (ConnectivityManager) mCxt.getSystemService(Context.CONNECTIVITY_SERVICE);
State mobileHigh = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
Log.d(TAG, "--------- Network HIPRI State --------" + mobileHigh);
if(mobileHigh == State.CONNECTED){
return true;
}
return false;
}
Above always return false on CDMA but on GSM true..
Found enableHIPRI here on Phone Interface firmware code.
Assuming Phonebase is used for GSM, and CDMAPhonebase is used for CDMA which extends PhoneBase.
Could not find much info on the firmware codes above and code1 code2.Is CDMA firmware has some other design applied?Can you guys throw some light here.?
Thanks
NitZ
int resultInt = connMgr.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
Will return -1 if the device doesn't support HiPri; you have to fall back to forcing the 3g / 4g connection by turning off the wifi (and returning it to its previous state once you've finished).
Can't remember if all CDMA devices don't support HiPri, but it might be the device you're testing on?
I'm using HttpClient to post then retrieve something in Android, which works great, but when I dont have a internet connection it forces close, is their a way to catch UnknownHostException when making an HttpPost? I know I could make sure its connected to the internet before making the request, but what about if the phone just doesn't have service?
UnknownHostException is a Subclass of IOException, so you should be able to catch/manage it simply catching IOException or something more specific (NoRoute, ConnectTimeout, etc.)
Also consider adding connection check before doing network calls with ConnectivityManager
you can check for your intenet connection with
ConnectivityManager cm = (ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected() || cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
//connected
} else {
//not connected
}
And set the permissions in AndroidManifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
I am using this code to check if a WiFi or mobile network is connected.
private boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
}
return false;
}
This works fine. But what if my user is on a prepaid plan but doesn't have any credit for data? This method will still return true if data is enabled but my app will crash when it tries to download data from a server. How can I check for something like this?
I guess there are also other things that can halt my app accessing a server even when a wifi/mobile network is available.
You shouldn't crash anyway. Your download code should use try-catch to handle such problems. Communication problems during download are possible as well.
As a mobile platform, internet access on Android is inherently unreliable. As you are starting to realise, you should be writing your app so it is tolerant of intermittent data access.
You are catching some exceptions, but not handling them - that means that your app will continue past the exception as though it didn't happen, and then crashes because your httpClient object is in an invalid state and is likely throwing new exceptions, which you are not catching.