Connect to wifi without internet programmatically - android

I'm using the following code to connect to a WiFi network without internet connection, because it hosts its own web-server where I want to connect even if there is no internet connection available.
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = String.format("\"%s\"", scanResult.SSID);
wifiConfiguration.preSharedKey = String.format("\"%s\"", "secret");
int netId = wifiManager.addNetwork(wifiConfiguration)
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
This works fine on every device below Android Marshmallow (I'm using CM13, so is it maybe related to CyanogenMod?): When I use this code to connect, Android still uses the mobile connection and mark the WiFi symbol with an exclamation mark. Seconds later it shows a notification with the question if I want to stay connected, because the network has no internet connection.
Problem: My app tries to connect automatically to my web-server which fail, because there is obviously no internet connection. Of course it would be possible to wait until I can reach my web-server, but it should work without user interaction.
How does ChromeCast or any other IoT device solve this? I never saw a notification like this when I was setting up my ChromeCast device.

I solved this by binding (connectivityManager.bindProcessToNetwork(network);) the current process to the connected network. This prevents the "keep using this network" Dialog and allows you to communicate with the device over wifi.
NetworkRequest.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
if (!Settings.System.canWrite(mActivity)) {
Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + mActivity.getPackageName()));
mActivity.startActivity(goToSettings);
}
}
connectivityManager.bindProcessToNetwork(null);
if (mSsid.contains("my_iot_device-xxxxxxxxx")) {
connectivityManager.bindProcessToNetwork(network);
} else {
}
} else {
//This method was deprecated in API level 23
ConnectivityManager.setProcessDefaultNetwork(null);
if (mSsid.contains("my_iot_device-xxxxxxxxx")) {
ConnectivityManager.setProcessDefaultNetwork(network);
} else {
}
}
try {
//do a callback or something else to alert your code that it's ok to send the message through socket now
} catch (Exception e) {
Crashlytics.logException(e);
e.printStackTrace();
}
connectivityManager.unregisterNetworkCallback(this);
}
});
}

Related

Connect to Wifi in Android Q programmatically

I had this function to connect in Wifi network, below Android 10 it works fine, but when I tried on Android 10, I had a successful connection but WITHOUT internet, I knew it's a bug in Android 10 but I found this application which can connect to wifi from Android 10 with no problem.
I'm blocked for days.
My function :
private void connectToWifi(String ssid, String password)
{
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
try {
Log.e(TAG,"connection wifi pre Q");
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "\"" + ssid + "\"";
wifiConfig.preSharedKey = "\"" + password + "\"";
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
} catch ( Exception e) {
e.printStackTrace();
}
} else {
Log.e(TAG,"connection wifi Q");
WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid( ssid )
.setWpa2Passphrase(password)
.build();
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build();
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
super.onAvailable(network);
connectivityManager.bindProcessToNetwork(network);
Log.e(TAG,"onAvailable");
}
#Override
public void onLosing(#NonNull Network network, int maxMsToLive) {
super.onLosing(network, maxMsToLive);
Log.e(TAG,"onLosing");
}
#Override
public void onLost(Network network) {
super.onLost(network);
Log.e(TAG, "losing active connection");
}
#Override
public void onUnavailable() {
super.onUnavailable();
Log.e(TAG,"onUnavailable");
}
};
connectivityManager.requestNetwork(networkRequest,networkCallback);
}
}
So far what is working for me on the majority of devices I have tested with, with a fallback option to at least stop the dreaded 'looping request' and to allow a successful manual connection
The below code is written in Kotlin, please google how to covert to Java if needed.
Create a NetworkCallback which is required for API >= 29 (prior it was not required but could be used)
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// To make sure that requests don't go over mobile data
connectivityManager.bindProcessToNetwork(network)
} else {
connectivityManager.setProcessDefaultNetwork(network)
}
}
override fun onLost(network: Network) {
super.onLost(network)
// This is to stop the looping request for OnePlus & Xiaomi models
connectivityManager.bindProcessToNetwork(null)
connectivityManager.unregisterNetworkCallback(networkCallback)
// Here you can have a fallback option to show a 'Please connect manually' page with an Intent to the Wifi settings
}
}
Connect to a network as follows:
val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(pass)
.build()
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
// Add the below 2 lines if the network should have internet capabilities.
// Adding/removing other capabilities has made no known difference so far
// .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
// .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build()
connectivityManager.requestNetwork(networkRequest, networkCallback)
As stated here by Google, some OEM Roms are not 'holding on to the request' and therefore the connection is dropping instantly. OnePlus have fixed this problem in some of their later models but not all. This bug will continuously exist for certain phone models on certain Android builds, therefore a successful fallback (i.e. a manual connection with no network disruption) is required. No known workaround is available, but if found I will update it here as an option.
To remove the network, do the following:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//This is required for Xiaomi models for disconnecting
connectivityManager.bindProcessToNetwork(null)
} else {
connectivityManager.setProcessDefaultNetwork(null)
}
connectivityManager.unregisterNetworkCallback(it)
Please keep in mind, an automatic connection allows for an automatic & manual disconnection. A manual connection (such as the suggested fallback for OnePlus devices) does not allow an automatic disconnection. This will also need to be handled within the app for a better UX design when it comes to IoT devices.
Some extra small tips & info:
now that a system dialog opens, the app calls onPause and onResume respectively. This affected my logic regarding automatic connection to IoT devices. In some case, onResume is called before the network callback is finished.
In regards to tests, I have yet to be able to get around the dialog by just using espresso and it may block some tests that were working before API 29. It may be possible using other frameworks such as uiautomator. In my case I adjusted the tests to work up until the dialog shows, and run further tests thereafter.
Using Intents.init() does not work.
onUnavailable is called when the the network has been found, but the user cancels. It is not called when the network was not found or if the user cancels the dialog before the network has been found, in this case no other methods are called, use onResume to catch it.
when it fails on the OnePlus it called onAvailable() -> onCapabilitiesChanged() -> onBlockedStatusChanged (blocked: false) -> onCapabilitiesChanged() -> onLost() respectively
removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) wont help keep the connection on a OnePlus as stated here
setting the Bssid wont help keep the connection on a OnePlus as stated here
google cannot help, they have stated it is out of their hands here
OnePlus forum posts confirming it working for some models (but not all) after an update, see here, here & here
when GPS is switched off, the SSID names of networks are not available
if the dialog comes several times, check your own activity lifecycle, in my case some models were calling onResume before the network callback was received.
manually connecting to a network without internet capabilities needs user confirmation to keep the connection (sometimes in the form of a dialog or as a notification), if ignored, the system will disconnect from the network shortly afterwards
List of devices tested:
Google Pixel 2 - No issues found
Samsung S10 SM-G970F - No issues found
Samsung S9 SM-G960F - No issues found
One Plus A5000 (OxegenOS 10.0.1) - Major Issue with automatic connection
HTC One M8 (LineageOS 17.1) - No issues found
Xiaomi Mi Note 10 - Issue with disconnecting (Fixed, see code example)
Samsung A50 - Dialog repetitively appears after successful connection (sometimes)
Huawei Mate Pro 20 - Dialog repetitively appears after successful connection (sometimes)
Huawei P40 Lite - Doesn't call onLost()
CAT S62 Pro - No issues found
Sony Xperia SZ2 - No issues found
Samsung Note10 - No issues found
In case if you want to connect to WiFi with INTERNET, you should use this kind of NetworkRequest:
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build();
Also, you need specify default route for your process to make requests to connected WiFi AP permanently. Just add call of next method to your NetworkCallback under onAvaliable like this:
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
createNetworkRoute(network, connectivityManager);
}
};
if (connectivityManager!= null) connectivityManager.requestNetwork(request, networkCallback);
.
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private static void createNetworkRoute(Network network, ConnectivityManager connectivityManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.bindProcessToNetwork(network);
} else {
ConnectivityManager.setProcessDefaultNetwork(network);
}
}
Don't forget disconnect from the bound network:
connectivityManager.unregisterNetworkCallback(networkCallback);
Finally, you can find best practice in different libraries like WifiUtils.
You can try wifisuggestion api, I'm able to connect using them.
final WifiNetworkSuggestion suggestion1 =
new WifiNetworkSuggestion.Builder()
.setSsid("YOUR_SSID")
.setWpa2Passphrase("YOUR_PRE_SHARED_KEY")
.build();
final List<WifiNetworkSuggestion> suggestionsList =
new ArrayList<WifiNetworkSuggestion>();
suggestionsList.add(suggestion1);
WifiManager wifiManager =
(WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status == 0 ){
Toast.makeText(this,"PSK network added",Toast.LENGTH_LONG).show();
Log.i(TAG, "PSK network added: "+status);
}else {
Toast.makeText(this,"PSK network not added",Toast.LENGTH_LONG).show();
Log.i(TAG, "PSK network not added: "+status);
}
Since Android 10, I've have to use the following code to connect to a specific wifi network.
private ConnectivityManager mConnectivityManager;
#Override
public void onCreate(#Nullable Bundle savedInstanceState){
// instantiate the connectivity manager
mConnectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
}
public void connect(String ssid, String password) {
NetworkSpecifier networkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.setIsHiddenSsid(true) //specify if the network does not broadcast itself and OS must perform a forced scan in order to connect
.build();
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(networkSpecifier)
.build();
mConnectivityManager.requestNetwork(networkRequest, mNetworkCallback);
}
public void disconnectFromNetwork(){
//Unregistering network callback instance supplied to requestNetwork call disconnects phone from the connected network
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
private ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback(){
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
//phone is connected to wifi network
}
#Override
public void onLosing(#NonNull Network network, int maxMsToLive) {
super.onLosing(network, maxMsToLive);
//phone is about to lose connection to network
}
#Override
public void onLost(#NonNull Network network) {
super.onLost(network);
//phone lost connection to network
}
#Override
public void onUnavailable() {
super.onUnavailable();
//user cancelled wifi connection
}
};
References:
https://anutoshdatta.medium.com/new-wifi-apis-on-android-10-481c525108b7
https://developer.android.com/guide/topics/connectivity/wifi-suggest
I was also facing the same issue, even after 3 months I was unable to solve this. But I have found one awesome and cool solution.
startActivity(new Intent("android.settings.panel.action.INTERNET_CONNECTIVITY"))
Just add these lines instead of connecting to the wifi from the app, this will prompt user to select a wifi and connect and as soon as user do it, it will connect to the wifi and also it will have internet also.
Just connecting to the wifi from the app will not access the internet. Do this, this is the best solution.
So, the solution for me is compile your app with targetSdkVersion 28.
and for connection to wifi use this function
connectToWifi(String ssid, String key)
it's just a workaround for the moment, waiting Google to publish a fix for this bug, for more information the issue reported to Google : issuetracker.google.com/issues/138335744
public void connectToWifi(String ssid, String key) {
Log.e(TAG, "connection wifi pre Q");
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "\"" + ssid + "\"";
wifiConfig.preSharedKey = "\"" + key + "\"";
int netId = wifiManager.addNetwork(wifiConfig);
if (netId == -1) netId = getExistingNetworkId(wifiConfig.SSID);
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
}
If you have root access (adb root):
Manually connect to the Wifi Network of your choosing.
Pull these ADB files:
adb pull /data/misc/wifi/WifiConfigStore.xml
adb pull /data/misc/wifi/WifiConfigStore.xml.encrypted-checksum
Save in a folder that would designate the Wifi Network:
Ex: GarageWifi
Ex: BusinessWifi
Copy to location of your choosing. Don't change the names of the files you pulled.
Whenever you want to connect to a desired wifi network:
adb push <location>\WifiConfigStore.xml /data/misc/wifi/
adb push <location>\WifiConfigStore.xml.encrypted-checksum /data/misc/wifi/
adb reboot

Android Q - Wifi connectionproblem with WifiNetworkSpecifier

On Android 10 (Q) I try to connect to a wifi without internet access with WifiNetworkSpecifier.
The first connection work without any problem. After that first connection I can't connect anymore.
Then I have to switch Off/On the wifi network again and than it works one time again.
This problem I have with a Xiaomi Mi 9 SE, with a Samsung Galaxy S10e the error does not exist.
How can I solve this problem, because I can't switch off/on the wifi programmatically on Android Q.
Has anyone a workaround for this problem?
My workaround is to inform the user to do a switch off/on by him self and start a panelIntent. But this is not a fine solution for me.
Here is my code:
On the init():
if (Build.VERSION.SDK_INT >= LOLLIPOP)
{
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
if (SDK_INT >= Q)
{
WifiNetworkSpecifier.Builder wifiNetworkSpecifierBuilder = new WifiNetworkSpecifier.Builder();
wifiNetworkSpecifierBuilder.setSsid(ssid);
wifiNetworkSpecifierBuilder.setWpa2Passphrase(password);
WifiNetworkSpecifier wifiNetworkSpecifier = wifiNetworkSpecifierBuilder.build();
networkRequestBuilder.setNetworkSpecifier(wifiNetworkSpecifier);
}
networkRequest = networkRequestBuilder.build();
networkCallback = new NetworkCallback()
{
#Override
public void onAvailable(Network network)
...
};
}
if (SDK_INT < Q)
{...}
... when the thread is running:
#Override
public void run()
{
NetworkBinding();
while (runSendThread)
{...}
NetworkUnbinding();
}
... and the bindingMethodes:
public void NetworkBinding()
{
try
{
if (SDK_INT >= VERSION_CODES.LOLLIPOP)
{
mConManager.requestNetwork(networkRequest, networkCallback);
}
}
catch (Exception e)
{
HandleException(e);
}
}
public void NetworkUnbinding()
{
try
{
if (Build.VERSION.SDK_INT >= VERSION_CODES.M)
{
mConManager.bindProcessToNetwork(null);
}
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
{
mConManager.unregisterNetworkCallback(networkCallback);
android.net.ConnectivityManager.setProcessDefaultNetwork(null);
}
}
catch (Exception e)
{
HandleException(e);
}
}
For others who have similar situations:
I have found out, that the problem was on the router which needed a firmware-update.
I think some newer phones try to find out if the network is ok and if they do not get the right response they mark the network as corrupt.
After the firmware-update, the connections work with every phone.

android on connect to network listener background

What is the best way to do this after version (7.0)
I was doing this using "BroadcastReceiver" but after version (7.0) Problems began to appear
I try to use "GcmTaskService" and "JobScheduler"
But I did not find the way right.
can any one help me?
RxAndroid (https://github.com/ReactiveX/RxAndroid) offers really helpful tools for reacting to asynchronous processes.
Specifically pertaining to network connectivity you can begin the connection using the built in android NetworkManager and WifiConfiguration and observe connectivity using the RxAndroid ReactiveNetwork static methods.
WifiConfiguration wifiConfig = new WifiConfiguration();
conf.ssid = "\"SecureNetwork\"" //Note that quote characters are required in the SSID
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiManager wifiManger = (WifiManager) appContext.getSystemService(Context.WIFI_SERVICE);
if (wifiManager == null) {
//error handling - make sure you have permissions etc
}
int connectionId = wifiManager.addNetwork(conf);
if (connectionId == -1) {
//Network is already configured - find configuration using wifiManger.getConfiguredNetworks();
}
wifiManager.enableNetwork(connectionId, true); //Attempt to connect to network
//Now use RxAndroid ReactiveNetwork to observe connectivity
ReactiveNetwork.observeNetworkConnectivity(context)
.filter(ConnectivityPredicate.hasState(NetworkInfo.State.CONNECTED))
.filter(ConnectivityPredicate.hasType(ConnectivityManager.TYPE_WIFI))
.flatMap(connectivity -> {
int currentNetId = wifiManager.getConnectionInfo().getNetworkId();
if (currentNetId == connectionNetId) {
return Observable.just(true);
} else {
return Observable.error("Not connected to new network")
}
.doOnNext(mBoolean -> //Do whatever you want to now that you are connect)
.doOnError(mError ->> //Handle error)
.suscribe();

Connect to WiFi Which Doesn't Have Internet

I'm trying to connect to a WiFi hotspot (open network) which doesn't have Internet access when the app starts.
However, there's another saved Wifi which has Internet. When I turn on Wifi, it always connects automatically to the one with Internet access.
I have been trying to fix this issue for like a week now! But nothing is working. In fact, my code disconnects from the network with internet but doesn't connect to the network I want. It doesn't make sense.
On the WiFi settings activity, it says "No Internet detected. Won't reconnect automatically."
private boolean tryConnect(WifiManager wifiManager, List<ScanResult> scanResults) {
for (ScanResult scanResult : scanResults) {
Log.d(TAG, "SCAN-RESULT: " + scanResult);
if (scanResult.SSID.toLowerCase().contains(MainActivity.ARDRONE2_HOTSPOT_NAME) && WifiUtilities.getScanResultSecurity(scanResult) == WifiUtilities.NetworkSecurity.OPEN) {
Log.d(TAG, "Trying Connecting to ARDrone2");
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = String.format("\"%s\"", scanResult.SSID);
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfiguration.priority = Integer.MAX_VALUE - 1;
List<WifiConfiguration> wifiConfigList = wifiManager.getConfiguredNetworks();
int networkId = -1;
for (WifiConfiguration wifiConfig : wifiConfigList) {
if (wifiConfig != null) {
if (wifiConfig.SSID.equals("\"" + scanResult.SSID + "\"")) {
networkId = wifiConfig.networkId;
} else {
wifiManager.disableNetwork(wifiConfig.networkId);
}
}
}
if (networkId == -1) {
networkId = wifiManager.addNetwork(wifiConfiguration);
} else {
networkId = wifiManager.updateNetwork(wifiConfiguration);;
}
wifiManager.saveConfiguration();
wifiManager.disconnect();
wifiManager.enableNetwork(networkId, true);
wifiManager.reconnect();
return true;
}
}
return false;
}
The debug log: "Trying Connecting to ARDrone2" appears and yet it doesn not connect!!!
A similar question has been asked here Android, automatically connecting to wifi networks that have no internet access but no comments or answers were provided.
It seems like the problem was with my own phone. I have CM13.0 and apparently they don't allow connecting to networks that don't have Internet access. Even manual connecting to a network without Internet is a lot of trouble.
I tried it on other phones with non-custom ROMs and they all worked as expected according to the code above:
Disable all saved networks (this could be improved)
Disconnect from currently connected network
Connect to the ARDrone2

Make Android simultaneously use WiFi to talk to a device and mobile data to talk to a server?

I'm developing an Android application which connects to an OBD2 device by Wifi and app can read Speed, RPM, Engine coolant temperature details etc. So wifi is used only for connecting with the OBD2 device(it doesn't have facility to connect with internet, only for communication with local clients). I also need an internet connection for web services. But after connecting my wifi I am not able to connect internet via my mobile data network in android.
The similar application is also developed for iOS. In iOS, I can use device over Wifi (Static Wifi setting) and Internet connection from my cellular network. It means configure my wifi with some static ip I am able to use mobile data network for Internet connection in iOS.
But in Android, If I use static wifi and check for Internet connection, it is not available.
How can I use Wifi and Internet connection both run parallel or any other way by configuring wifi settings in android ?
Firstly, the problem we may face here is that because there is no internet connection on WiFi network, HTTP data will not go through that connection. See Send request over WiFi (without connection) even if Mobile data is ON (with connection) on Android M for solution
However, I have faced issue where sometimes no HTTP request is successful. To solve this problem, we can use ConnectivityManager.requestNetwork() and Network.openConnection() to achieve this.
Make sure that Mobile data and WiFi network is enabled and Android Manifest has proper connections:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
Variables:
private ConnectivityManager.NetworkCallback mWifiNetworkCallback, mMobileNetworkCallback;
private Network mWifiNetwork, mMobileNetwork;
Get the connectivity manager:
final ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Build network callbacks:
if(mWifiNetworkCallback == null){
//Init only once
mWifiNetworkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(final Network network) {
try {
//Save this network for later use
mWifiNetwork = network;
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
};
}
if(mMobileNetworkCallback == null){
//Init only once
mMobileNetworkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(final Network network) {
try {
//Save this network for later use
mMobileNetwork = network;
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
};
}
Request networks:
NetworkRequest.Builder wifiBuilder;
wifiBuilder = new NetworkRequest.Builder();
//set the transport type do WIFI
wifiBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
manager.requestNetwork(wifiBuilder.build(), mWifiNetworkCallback);
NetworkRequest.Builder mobileNwBuilder;
mobileNwBuilder = new NetworkRequest.Builder();
//set the transport type do Cellular
mobileNwBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
manager.requestNetwork(mobileNwBuilder.build(), mMobileNetworkCallback);
Make the appropriate request like this:
public void makeHTTPRequest(final String httpUrl, final String payloadJson, final int timeout,
final boolean hasHeaders, final String header1, final String header2) {
try {
URL url = new URL(httpUrl);
HttpURLConnection conn = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
conn = (HttpURLConnection) mWifiNetwork.openConnection(url);
//Or use mMobileNetwork, if and when required
//conn = (HttpURLConnection) mMobileNetwork.openConnection(url);
} else {
conn = (HttpURLConnection) url.openConnection();
}
conn.setRequestProperty("Content-Type", "application/json");
conn.setReadTimeout(timeout * 1000);
conn.setConnectTimeout(timeout * 1000);
conn.setDoInput(true);
conn.setDoOutput(true);
if(hasHeaders){
conn.setRequestProperty("header1", header1);
conn.setRequestProperty("header2", header2);
}
conn.setRequestMethod("PUT");
OutputStream os = conn.getOutputStream();
os.write(payloadJson.getBytes());
os.close();
final int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
final String statusMessage = conn.getResponseMessage();
//Log this
}
} catch (SocketException se){
se.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
Note:
These functions are avaialble from Android Lollipop and above. So, it is necessary to use Build.Version.SDK_INT at appropriate place, like this:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
You can request for a certain hostAddress that it must use that type of connectivity.
IF you use Hipri then it will take the mobile network.
But this can fail ! If it works, then ALL connections to that address will go over that type of connectivity.
You might have to activate it first.
int resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
This can take a couple of seconds, since the hardware modules has to start up.
I've use this on several projects and works great.
On old device such as 2.2 it will react really unstable !
But I haven't found any problems on 4.0+

Categories

Resources