├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── com │ └── intentfilter │ └── wificonnect │ ├── AdvancedConnectionState.java │ ├── ScanResultsListener.java │ ├── WifiConnectionManager.java │ ├── WifiHelper.java │ ├── WifiUtil.java │ └── helpers │ ├── Logger.java │ └── StringUtil.java └── res └── values └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Nishkarsh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-wificonnect [ ![Download](https://api.bintray.com/packages/nishkarsh/maven/com.intentfilter%3Aandroid-wificonnect/images/download.svg) ](https://bintray.com/nishkarsh/maven/com.intentfilter%3Aandroid-wificonnect/_latestVersion) 2 | An android library to effortlessly connect to available WiFi networks 3 | 4 | Check the demo app for this library [here](https://github.com/nishkarsh/AndroidWifiConnectSample). 5 | 6 | ### Make sure the app has location permission and the location services are enabled for the features to work. 7 | 8 | ## Supported Features 9 | 10 | ### Upcoming 11 | - APIs that enables connection to any network (Open/WEP/WPA etc). There should be APIs that accept password in case network needs authentication. 12 | 13 | ### Version 0.1.2 14 | - Added `WifiConnectionManager#abort()` method. This should be called when your app wants to stop scanning or connecting to WiFi. 15 | - The WiFi is enabled if it was disabled already. This happens if the broadcast that is received is `initialStickyBroadcast`, so if Wifi is disabled again by the user explicitly, `abort()` is called. This will remove all the listeners and the callbacks would no longer be received. 16 | 17 | ### Version 0.1.0 18 | - Initiate a scan for networks explicitly. If WiFi is turned off, it's turned on automatically and an attempt is made to connect to network. 19 | - Scenarios specific to Android L (API Level 21-22) and Android Marshmallow (API Level 23) are handled. In case a user wants to connect to a network that doesn't provide internet connectivity (Captive Portal), `WifiConnectionManager.setBindingEnabled(true)` can be called that would ensure that the app uses the network (to which the device would connect to when `WifiConnectionManager#connectToAvailableSSID(String SSID, WifiConnectionManager.ConnectionStateChangedListener listener)` is called) to route traffic irrespective of whether it provides internet connectivity. 20 | - `WifiConnectionManager#connectToAvailableSSID(List SSIDs, WifiConnectionManager.ConnectionStateChangedListener listener)` accepts a list of SSIDs and can connect to an available network with strongest singal that has an SSID among SSIDs. 21 | - Provide methods like `WifiConnectionManager#checkBoundNetworkConnectivity()` that enabled verifying and switching to using WiFi network to which app is bound currently for sending network traffic for whole device. It makes it as active network if network connectivity is available in case now Captive Portal login has been performed, otherwise it switches from using currently bound network. 22 | - User can listen to `AdvancedConnectionState` that provides callback at different logical points in the process of connecting to a network. 23 | - User receives a callback once either the connection has been successfully established `ConnectionStateListener#onConnectionEstablished()` or an error occurs `ConnectionStateListener#onConnectionError()`. 24 | 25 | ### Limitations as of Now 26 | - As of now user can only connect to an Open Network (that doesn't need any authentication) using `connectToAvailableSSID()` 27 | 28 | ### Including into project 29 | 30 | Make your project-level build.gradle has jcenter() under repositories block. Your build.gradle should look like: 31 | 32 | ``` 33 | buildscript { 34 | repositories { 35 | jcenter() 36 | } 37 | dependencies { 38 | classpath 'com.android.tools.build:gradle:2.1.3' 39 | } 40 | } 41 | ``` 42 | 43 | Gradle: `compile 'com.intentfilter:android-wificonnect:0.1.2'` 44 | 45 | Add as android-wificonnect as dependency inside app module level build.gradle under dependencies block. Your app level build.gradle should look like: 46 | 47 | ``` 48 | dependencies { 49 | compile fileTree(dir: 'libs', include: ['*.jar']) 50 | compile 'com.intentfilter:android-wificonnect:0.1.2' 51 | } 52 | ``` 53 | 54 | **Note:** 55 | 1. Marshmallow dynamic permissions must be handled for the library to work as WiFi scanning starting from Android M needs ACCESS_COARSE_LOCATION permission. 56 | 2. Location should be enabled to get WiFi scan results. 57 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:24.1.1' 25 | } 26 | -------------------------------------------------------------------------------- /proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/nishkarsh/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/AdvancedConnectionState.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect; 2 | 3 | public enum AdvancedConnectionState { 4 | WIFI_ENABLED, WIFI_DISABLED, SCAN_RESULTS_AVAILABLE, NETWORK_CONNECTED, NETWORK_BOUND 5 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/ScanResultsListener.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect; 2 | 3 | import android.net.wifi.ScanResult; 4 | 5 | import java.util.List; 6 | 7 | public interface ScanResultsListener { 8 | void onScanResultsAvailable(List scanResults); 9 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/WifiConnectionManager.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect; 2 | 3 | import android.content.Context; 4 | import android.net.Network; 5 | import android.net.wifi.ScanResult; 6 | import android.net.wifi.WifiManager; 7 | import android.os.Build; 8 | import android.os.Handler; 9 | 10 | import com.intentfilter.wificonnect.WifiUtil.NetworkStateChangeListener; 11 | import com.intentfilter.wificonnect.WifiUtil.WifiStateChangeListener; 12 | import com.intentfilter.wificonnect.helpers.Logger; 13 | 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.concurrent.locks.Lock; 17 | import java.util.concurrent.locks.ReentrantLock; 18 | 19 | import static java.lang.String.format; 20 | 21 | public class WifiConnectionManager 22 | implements NetworkStateChangeListener, WifiStateChangeListener, ScanResultsListener { 23 | 24 | private static boolean shouldBindToNetwork; 25 | private final WifiUtil wifiUtil; 26 | private WifiHelper wifiHelper; 27 | private AdvancedConnectionStateListener advancedStateListener; 28 | private List SSIDs; 29 | private ConnectionStateChangedListener connectionStateListener; 30 | private Logger LOGGER = Logger.loggerFor(WifiManager.class); 31 | private Lock reentrantLock; 32 | private String availableSSID; 33 | 34 | public WifiConnectionManager(Context context) { 35 | this(new WifiUtil(context.getApplicationContext()), 36 | new WifiHelper(context.getApplicationContext()), new ReentrantLock()); 37 | } 38 | 39 | WifiConnectionManager(WifiUtil wifiUtil, WifiHelper wifiHelper, ReentrantLock reentrantLock) { 40 | this.wifiUtil = wifiUtil; 41 | this.wifiHelper = wifiHelper; 42 | this.reentrantLock = reentrantLock; 43 | } 44 | 45 | public static void setBindingEnabled(boolean shouldBindToNetwork) { 46 | WifiConnectionManager.shouldBindToNetwork = shouldBindToNetwork; 47 | } 48 | 49 | public void connectToAvailableSSID(String SSID, ConnectionStateChangedListener connectionStateListener) { 50 | connectToAvailableSSID(Collections.singletonList(SSID), connectionStateListener); 51 | } 52 | 53 | public void connectToAvailableSSID(List SSIDs, ConnectionStateChangedListener connectionStateListener) { 54 | this.SSIDs = SSIDs; 55 | this.connectionStateListener = connectionStateListener; 56 | 57 | wifiUtil.setWifiStateChangeListener(this); 58 | } 59 | 60 | @Override 61 | public void onScanResultsAvailable(List scanResults) { 62 | onConnectionStateChanged(AdvancedConnectionState.SCAN_RESULTS_AVAILABLE); 63 | 64 | availableSSID = wifiHelper.findAvailableSSID(SSIDs, scanResults); 65 | if (reentrantLock.tryLock()) { 66 | wifiUtil.removeWifiScanResultsListener(this); 67 | 68 | if (availableSSID != null) { 69 | onSSIDAvailable(availableSSID); 70 | } else { 71 | String reason = "Couldn't find SSID in which we are interested"; 72 | connectionStateListener.onConnectionError(reason); 73 | LOGGER.i(reason); 74 | } 75 | } 76 | } 77 | 78 | public void abort() { 79 | wifiUtil.removeNetworkStateChangeListener(this); 80 | wifiUtil.removeWifiScanResultsListener(this); 81 | wifiUtil.removeWifiStateChangeListener(this); 82 | wifiUtil.clearNetworkBinding(); 83 | } 84 | 85 | @Override 86 | public void onWifiEnabled(boolean initialStickyBroadcast) { 87 | wifiUtil.removeWifiStateChangeListener(this); 88 | onConnectionStateChanged(AdvancedConnectionState.WIFI_ENABLED); 89 | 90 | LOGGER.d("Wifi is enabled, starting scan"); 91 | wifiUtil.setWifiScanResultsListener(this); 92 | scheduleWifiScan(); 93 | } 94 | 95 | @Override 96 | public void onWifiDisabled(boolean initialStickyBroadcast) { 97 | onConnectionStateChanged(AdvancedConnectionState.WIFI_DISABLED); 98 | if (initialStickyBroadcast) { 99 | wifiHelper.enableWifi(); 100 | } else { 101 | abort(); 102 | } 103 | } 104 | 105 | @Override 106 | public void onNetworkConnected() { 107 | onConnectionStateChanged(AdvancedConnectionState.NETWORK_CONNECTED); 108 | if (isConnectedToSSID(availableSSID)) { 109 | connectionStateListener.onConnectionEstablished(); 110 | } 111 | wifiUtil.removeNetworkStateChangeListener(this); 112 | } 113 | 114 | @Override 115 | public void onNetworkBound() { 116 | onConnectionStateChanged(AdvancedConnectionState.NETWORK_BOUND); 117 | connectionStateListener.onConnectionEstablished(); 118 | wifiUtil.removeNetworkStateChangeListener(this); 119 | } 120 | 121 | private void onSSIDAvailable(String availableSSID) { 122 | LOGGER.i(format("SSID %s is available.", availableSSID)); 123 | 124 | if (isConnectedToSSID(availableSSID)) { 125 | LOGGER.d(format("Current active SSID is already %s.", availableSSID)); 126 | connectionStateListener.onConnectionEstablished(); 127 | return; 128 | } 129 | 130 | if (isVersionEqualsOrAboveLollipop() && shouldBindToNetwork) { 131 | wifiUtil.bindToNetwork(availableSSID, this); 132 | } 133 | 134 | wifiUtil.setNetworkStateChangeListener(this); 135 | boolean connectingToSSID = wifiHelper.connectToSSID(availableSSID); 136 | if (!connectingToSSID) { 137 | String reason = "Error while enabling network."; 138 | connectionStateListener.onConnectionError(reason); 139 | LOGGER.d(reason); 140 | } 141 | } 142 | 143 | public Network getBoundNetworkForProcess() { 144 | return wifiUtil.getBoundNetworkForProcess(); 145 | } 146 | 147 | public void checkBoundNetworkConnectivity() { 148 | wifiUtil.reportBoundNetworkConnectivity(); 149 | } 150 | 151 | public boolean isConnectedToSSID(String availableSSID) { 152 | return wifiUtil.isActiveNetworkWifi() && wifiHelper.hasActiveSSID(availableSSID); 153 | } 154 | 155 | private void scheduleWifiScan() { 156 | //TODO Find out why broadcast for scan results not received when scanning is started just after WiFi is enabled on Sony & One Plus. 157 | // This happens when SSID is already saved 158 | final int TWO_SECONDS = 2000; 159 | new Handler().postDelayed(new Runnable() { 160 | @Override 161 | public void run() { 162 | wifiHelper.startScan(); 163 | } 164 | }, TWO_SECONDS); 165 | } 166 | 167 | private void onConnectionStateChanged(AdvancedConnectionState currentConnectionState) { 168 | if (advancedStateListener != null) { 169 | advancedStateListener.onConnectionStateChanged(currentConnectionState); 170 | } 171 | } 172 | 173 | public void setAdvancedConnectionStateListener(AdvancedConnectionStateListener advancedStateListener) { 174 | this.advancedStateListener = advancedStateListener; 175 | } 176 | 177 | private boolean isVersionEqualsOrAboveLollipop() { 178 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 179 | } 180 | 181 | public void scanForNetworks(ScanResultsListener listener) { 182 | wifiUtil.setWifiScanResultsListener(listener); 183 | wifiHelper.startScan(); 184 | } 185 | 186 | public interface ConnectionStateChangedListener { 187 | void onConnectionEstablished(); 188 | 189 | void onConnectionError(String reason); 190 | } 191 | 192 | public interface AdvancedConnectionStateListener { 193 | void onConnectionStateChanged(AdvancedConnectionState connectionState); 194 | } 195 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/WifiHelper.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.ScanResult; 5 | import android.net.wifi.WifiConfiguration; 6 | import android.net.wifi.WifiManager; 7 | import android.text.TextUtils; 8 | 9 | import com.intentfilter.wificonnect.helpers.Logger; 10 | import com.intentfilter.wificonnect.helpers.StringUtil; 11 | 12 | import java.util.Collections; 13 | import java.util.Comparator; 14 | import java.util.List; 15 | 16 | import static java.lang.String.format; 17 | 18 | class WifiHelper { 19 | private final WifiManager wifiManager; 20 | private final Logger logger; 21 | 22 | WifiHelper(Context context) { 23 | this.wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 24 | this.logger = Logger.loggerFor(WifiHelper.class); 25 | } 26 | 27 | boolean connectToSSID(String SSID) { 28 | WifiConfiguration configuration = createOpenWifiConfiguration(SSID); 29 | logger.d("Priority assigned to configuration is " + configuration.priority); 30 | 31 | int networkId = wifiManager.addNetwork(configuration); 32 | logger.d("networkId assigned while adding network is " + networkId); 33 | 34 | return enableNetwork(SSID, networkId); 35 | } 36 | 37 | String findAvailableSSID(List SSIDs, List scanResults) { 38 | logger.i("Available SSIDs count: " + scanResults.size()); 39 | 40 | sortBySignalStrength(scanResults); 41 | 42 | for (ScanResult scanResult : scanResults) { 43 | if (SSIDs.contains(scanResult.SSID)) { 44 | return scanResult.SSID; 45 | } 46 | } 47 | return null; 48 | } 49 | 50 | public boolean hasActiveSSID(String SSID) { 51 | String currentSSID = wifiManager.getConnectionInfo().getSSID(); 52 | return areEqual(SSID, currentSSID); 53 | } 54 | 55 | public void enableWifi() { 56 | wifiManager.setWifiEnabled(true); 57 | } 58 | 59 | public static boolean areEqual(String SSID, String anotherSSID) { 60 | return TextUtils.equals(StringUtil.trimQuotes(SSID), StringUtil.trimQuotes(anotherSSID)); 61 | } 62 | 63 | public static String formatSSID(String wifiSSID) { 64 | return format("\"%s\"", wifiSSID); 65 | } 66 | 67 | public void startScan() { 68 | wifiManager.startScan(); 69 | } 70 | 71 | public void disconnect() { 72 | wifiManager.disconnect(); 73 | } 74 | 75 | private boolean enableNetwork(String SSID, int networkId) { 76 | if (networkId == -1) { 77 | networkId = getExistingNetworkId(SSID); 78 | logger.d("networkId of existing network is " + networkId); 79 | 80 | if (networkId == -1) { 81 | logger.e("Couldn't add network with SSID: " + SSID); 82 | return false; 83 | } 84 | } 85 | 86 | return wifiManager.enableNetwork(networkId, true); 87 | } 88 | 89 | private WifiConfiguration createOpenWifiConfiguration(String SSID) { 90 | WifiConfiguration configuration = new WifiConfiguration(); 91 | configuration.SSID = formatSSID(SSID); 92 | configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 93 | assignHighestPriority(configuration); 94 | return configuration; 95 | } 96 | 97 | private void sortBySignalStrength(List scanResults) { 98 | Collections.sort(scanResults, new Comparator() { 99 | @Override 100 | public int compare(ScanResult resultOne, ScanResult resultTwo) { 101 | return resultTwo.level - resultOne.level; 102 | } 103 | }); 104 | } 105 | 106 | private int getExistingNetworkId(String SSID) { 107 | List configuredNetworks = wifiManager.getConfiguredNetworks(); 108 | if (configuredNetworks != null) { 109 | for (WifiConfiguration existingConfig : configuredNetworks) { 110 | if (areEqual(StringUtil.trimQuotes(existingConfig.SSID), StringUtil.trimQuotes(SSID))) { 111 | return existingConfig.networkId; 112 | } 113 | } 114 | } 115 | return -1; 116 | } 117 | 118 | private void assignHighestPriority(WifiConfiguration config) { 119 | List configuredNetworks = wifiManager.getConfiguredNetworks(); 120 | if (configuredNetworks != null) { 121 | for (WifiConfiguration existingConfig : configuredNetworks) { 122 | if (config.priority <= existingConfig.priority) { 123 | config.priority = existingConfig.priority + 1; 124 | } 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/WifiUtil.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.net.ConnectivityManager; 9 | import android.net.ConnectivityManager.NetworkCallback; 10 | import android.net.Network; 11 | import android.net.NetworkCapabilities; 12 | import android.net.NetworkInfo; 13 | import android.net.NetworkRequest; 14 | import android.net.wifi.WifiManager; 15 | import android.support.annotation.NonNull; 16 | 17 | import com.intentfilter.wificonnect.helpers.Logger; 18 | 19 | import static android.content.Context.CONNECTIVITY_SERVICE; 20 | import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO; 21 | import static android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION; 22 | import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION; 23 | import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION; 24 | import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 25 | import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 26 | import static android.os.Build.VERSION.SDK_INT; 27 | import static android.os.Build.VERSION_CODES.LOLLIPOP; 28 | import static android.os.Build.VERSION_CODES.M; 29 | import static java.lang.String.format; 30 | 31 | class WifiUtil { 32 | private Context context; 33 | private Logger logger; 34 | private WifiStateChangeListener wifiStateListener; 35 | private NetworkStateChangeListener networkStateListener; 36 | private ScanResultsListener scanResultsListener; 37 | private BroadcastReceiver wifiStateReceiver; 38 | private BroadcastReceiver networkStateReceiver; 39 | private BroadcastReceiver scanResultsReceiver; 40 | private final ConnectivityManager manager; 41 | private NetworkCallback networkCallback; 42 | 43 | WifiUtil(Context context) { 44 | this.context = context; 45 | this.logger = Logger.loggerFor(WifiUtil.class); 46 | this.manager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE); 47 | } 48 | 49 | @TargetApi(LOLLIPOP) 50 | void bindToNetwork(final String networkSSID, final NetworkStateChangeListener listener) { 51 | if (SDK_INT < LOLLIPOP) { 52 | logger.i("SDK version is below Lollipop. No need to bind process to network. Skipping..."); 53 | return; 54 | } 55 | logger.i("Currently active network is not " + networkSSID + ", would bind the app to use this when available"); 56 | 57 | NetworkRequest request = new NetworkRequest.Builder() 58 | .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(); 59 | networkCallback = networkCallback(networkSSID, listener); 60 | manager.registerNetworkCallback(request, networkCallback); 61 | } 62 | 63 | void setWifiStateChangeListener(@NonNull WifiStateChangeListener listener) { 64 | this.wifiStateListener = listener; 65 | wifiStateReceiver = new BroadcastReceiver() { 66 | @Override 67 | public void onReceive(Context context, Intent intent) { 68 | int wifiState = intent.getExtras().getInt(WifiManager.EXTRA_WIFI_STATE); 69 | informWifiStateChanged(wifiState, isInitialStickyBroadcast()); 70 | } 71 | }; 72 | context.registerReceiver(wifiStateReceiver, new IntentFilter(WIFI_STATE_CHANGED_ACTION)); 73 | logger.d("Registered for WiFi State broadcast"); 74 | } 75 | 76 | void setNetworkStateChangeListener(@NonNull NetworkStateChangeListener listener) { 77 | this.networkStateListener = listener; 78 | networkStateReceiver = new BroadcastReceiver() { 79 | @Override 80 | public void onReceive(Context context, Intent intent) { 81 | NetworkInfo networkInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO); 82 | informNetworkStateChanged(networkInfo); 83 | } 84 | }; 85 | context.registerReceiver(networkStateReceiver, new IntentFilter(NETWORK_STATE_CHANGED_ACTION)); 86 | logger.d("Registered for Network State broadcast"); 87 | } 88 | 89 | void setWifiScanResultsListener(final ScanResultsListener scanResultsListener) { 90 | this.scanResultsListener = scanResultsListener; 91 | scanResultsReceiver = new BroadcastReceiver() { 92 | @Override 93 | public void onReceive(Context context, Intent intent) { 94 | WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 95 | scanResultsListener.onScanResultsAvailable(wifiManager.getScanResults()); 96 | } 97 | }; 98 | context.registerReceiver(scanResultsReceiver, new IntentFilter(SCAN_RESULTS_AVAILABLE_ACTION)); 99 | logger.d("Registered for WiFi Scan results broadcast"); 100 | } 101 | 102 | void removeWifiStateChangeListener(@NonNull WifiStateChangeListener listener) { 103 | if (this.wifiStateListener != null && this.wifiStateListener.equals(listener)) { 104 | this.wifiStateListener = null; 105 | context.unregisterReceiver(wifiStateReceiver); 106 | logger.d("Un-registered for WiFi State broadcast"); 107 | } 108 | } 109 | 110 | void removeNetworkStateChangeListener(@NonNull NetworkStateChangeListener listener) { 111 | if (this.networkStateListener != null && this.networkStateListener.equals(listener)) { 112 | this.networkStateListener = null; 113 | context.unregisterReceiver(networkStateReceiver); 114 | logger.d("Un-registered for Network State broadcast"); 115 | } 116 | } 117 | 118 | void removeWifiScanResultsListener(@NonNull ScanResultsListener listener) { 119 | if (this.scanResultsListener != null && this.scanResultsListener.equals(listener)) { 120 | this.scanResultsListener = null; 121 | context.unregisterReceiver(scanResultsReceiver); 122 | logger.d("Un-registered for WiFi Scan results broadcast"); 123 | } 124 | } 125 | 126 | @TargetApi(LOLLIPOP) 127 | NetworkCallback networkCallback(final String networkSSID, 128 | final NetworkStateChangeListener listener) { 129 | return new NetworkCallback() { 130 | @Override 131 | public void onAvailable(Network network) { 132 | NetworkInfo networkInfo = manager.getNetworkInfo(network); 133 | logger.i("Network is Available. Network Info: " + networkInfo); 134 | 135 | if (WifiHelper.areEqual(networkInfo.getExtraInfo(), networkSSID)) { 136 | manager.unregisterNetworkCallback(this); 137 | networkCallback = null; 138 | bindToRequiredNetwork(network); 139 | logger.i(format("Bound application to use %s network", networkSSID)); 140 | listener.onNetworkBound(); 141 | } 142 | } 143 | }; 144 | } 145 | 146 | @TargetApi(LOLLIPOP) 147 | void bindToRequiredNetwork(Network network) { 148 | if (SDK_INT >= M) { 149 | manager.bindProcessToNetwork(network); 150 | } else { 151 | ConnectivityManager.setProcessDefaultNetwork(network); 152 | } 153 | } 154 | 155 | @TargetApi(LOLLIPOP) 156 | void clearNetworkBinding() { 157 | if (networkCallback != null) { 158 | manager.unregisterNetworkCallback(networkCallback); 159 | logger.d("Un-registering for network available callback"); 160 | } 161 | 162 | if (SDK_INT < LOLLIPOP || !isBoundToNetwork()) { 163 | logger.d("Not bound to any network, would not attempt to clear binding"); 164 | return; 165 | } 166 | 167 | bindToRequiredNetwork(null); 168 | logger.d("Cleared network binding. Preference to network would now be given by OS"); 169 | } 170 | 171 | @TargetApi(LOLLIPOP) 172 | boolean isBoundToNetwork() { 173 | return getBoundNetworkForProcess() != null; 174 | } 175 | 176 | @TargetApi(LOLLIPOP) 177 | Network getBoundNetworkForProcess() { 178 | if (SDK_INT >= M) { 179 | return manager.getBoundNetworkForProcess(); 180 | } else { 181 | return ConnectivityManager.getProcessDefaultNetwork(); 182 | } 183 | } 184 | 185 | @TargetApi(LOLLIPOP) 186 | void reportBoundNetworkConnectivity() { 187 | if (SDK_INT < LOLLIPOP) { 188 | return; 189 | } 190 | 191 | if (SDK_INT >= M) { 192 | Network defaultNetwork = manager.getBoundNetworkForProcess(); 193 | manager.reportNetworkConnectivity(defaultNetwork, true); 194 | } else { 195 | Network defaultNetwork = ConnectivityManager.getProcessDefaultNetwork(); 196 | manager.reportBadNetwork(defaultNetwork); 197 | } 198 | } 199 | 200 | private void informNetworkStateChanged(NetworkInfo networkInfo) { 201 | if (networkStateListener == null) { 202 | logger.e("Listener for NetworkStateChange is null, did you forget calling removeNetworkStateChangeListener()?"); 203 | return; 204 | } 205 | 206 | if (networkInfo.isConnected()) { 207 | networkStateListener.onNetworkConnected(); 208 | } 209 | } 210 | 211 | private void informWifiStateChanged(int wifiState, boolean initialStickyBroadcast) { 212 | if (wifiStateListener == null) { 213 | logger.e("Listener for WifiStateChange is null, did you forget calling removeWifiStateChangeListener()?"); 214 | return; 215 | } 216 | 217 | if (wifiState == WIFI_STATE_ENABLED) { 218 | wifiStateListener.onWifiEnabled(initialStickyBroadcast); 219 | } else if (wifiState == WIFI_STATE_DISABLED) { 220 | wifiStateListener.onWifiDisabled(initialStickyBroadcast); 221 | } 222 | } 223 | 224 | public boolean isActiveNetworkWifi() { 225 | NetworkInfo activeNetworkInfo = manager.getActiveNetworkInfo(); 226 | return activeNetworkInfo != null && 227 | activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI; 228 | } 229 | 230 | interface WifiStateChangeListener { 231 | void onWifiEnabled(boolean initialStickyBroadcast); 232 | 233 | void onWifiDisabled(boolean initialStickyBroadcast); 234 | } 235 | 236 | interface NetworkStateChangeListener { 237 | void onNetworkConnected(); 238 | 239 | void onNetworkBound(); 240 | } 241 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/helpers/Logger.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect.helpers; 2 | 3 | import android.util.Log; 4 | 5 | import com.intentfilter.wificonnect.BuildConfig; 6 | 7 | public class Logger { 8 | private String LOG_TAG; 9 | 10 | private Logger(Class clazz) { 11 | this.LOG_TAG = clazz.getSimpleName(); 12 | } 13 | 14 | public static Logger loggerFor(Class clazz) { 15 | return new Logger(clazz); 16 | } 17 | 18 | public void d(String message) { 19 | if (BuildConfig.DEBUG) { 20 | Log.d(LOG_TAG, message); 21 | } 22 | } 23 | 24 | public void d(String message, Throwable throwable) { 25 | if (BuildConfig.DEBUG) { 26 | Log.d(LOG_TAG, message, throwable); 27 | } 28 | } 29 | 30 | public void i(String message) { 31 | if (BuildConfig.DEBUG) { 32 | Log.i(LOG_TAG, message); 33 | } 34 | } 35 | 36 | public void e(String message) { 37 | Log.e(LOG_TAG, message); 38 | } 39 | 40 | public void e(String message, Throwable throwable) { 41 | Log.e(LOG_TAG, message, throwable); 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/intentfilter/wificonnect/helpers/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.intentfilter.wificonnect.helpers; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | public class StringUtil { 6 | @NonNull 7 | public static String trimQuotes(String str) { 8 | if (!isEmpty(str)) { 9 | return str.replaceAll("^\"*", "").replaceAll("\"*$", ""); 10 | } 11 | 12 | return str; 13 | } 14 | 15 | public static boolean isEmpty(CharSequence str) { 16 | return str == null || str.toString().isEmpty(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Wifi Connect 3 | 4 | --------------------------------------------------------------------------------