Android Wifi Scan - BroadcastReceiver for SCAN_RESULTS_AVAILABLE_ACTION not getting called
Yes, startScan()
requests only one single scan.
You can get rid of the if (intent.getAction().equals(..))
condition. Anything else seems to be ok.
just to make it clear - my goal to have a receiver that will get called every time the Wifi networks list are changing, without having to click a "start scan" button.
AFAIK it is not possible to get notified whenever any of the wifi networks change. You can only request a scan with startScan
- and of course you can call startScan
repeatedly using a Thread or Handler.
The docs say that SCAN_RESULTS_AVAILABLE_ACTION
is called when "an access point scan has completed, and results are available from the supplicant". How and when a scan is proceeded depends on the implemention of the supplicant. Elenkov writes, that "Android devices rarely include the original wpa_supplicant code; the included implementation is often modified for better compatibility with the underlying SoC".
Scan for access points
This example scans for available access points and ad hoc networks. btnScan
activates a scan initiated by the WifiManager.startScan()
method. After the scan, WifiManager
calls the SCAN_RESULTS_AVAILABLE_ACTION
intent and the WifiScanReceiver
class processes the scan result. The results are displayed in a TextView
.
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
TextView txtWifiInfo;
WifiManager wifi;
WifiScanReceiver wifiReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wifi=(WifiManager)getSystemService(Context.WIFI_SERVICE);
wifiReceiver = new WifiScanReceiver();
txtWifiInfo = (TextView)findViewById(R.id.txtWifiInfo);
Button btnScan = (Button)findViewById(R.id.btnScan);
btnScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "Start scan...");
wifi.startScan();
}
});
}
protected void onPause() {
unregisterReceiver(wifiReceiver);
super.onPause();
}
protected void onResume() {
registerReceiver(
wifiReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
);
super.onResume();
}
private class WifiScanReceiver extends BroadcastReceiver {
public void onReceive(Context c, Intent intent) {
List<ScanResult> wifiScanList = wifi.getScanResults();
txtWifiInfo.setText("");
for(int i = 0; i < wifiScanList.size(); i++){
String info = ((wifiScanList.get(i)).toString());
txtWifiInfo.append(info+"\n\n");
}
}
}
}
Permissions
The following permissions need to be defined in AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
android.permission.ACCESS_WIFI_STATE
is necessary for calling WifiManager.getScanResults()
. Without android.permission.CHANGE_WIFI_STATE
you cannot initiate a scan with WifiManager.startScan()
.
When compiling the project for api level 23 or greater (Android 6.0 and up), either android.permission.ACCESS_FINE_LOCATION
or android.permission.ACCESS_COARSE_LOCATION
must be inserted. Furthermore that permission needs to be requested, e.g. in the onCreate
method of your main activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
String[] PERMS_INITIAL={
Manifest.permission.ACCESS_FINE_LOCATION,
};
ActivityCompat.requestPermissions(this, PERMS_INITIAL, 127);
}
Ofek Agmon
Updated on June 04, 2022Comments
-
Ofek Agmon almost 2 years
Here is my code:
public class FloatWifiManager implements IWifiManager { private WifiManager wifiManager; private BroadcastReceiver wifiScanReceiver; public FloatWifiManager(Context context) { ... wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); // Registering Wifi Receiver wifiScanReceiver = new BroadcastReceiver() { @Override public void onReceive(Context c, Intent intent) { if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { // not getting called, only after running app and manually going to the wifi settings in android } } }; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); context.registerReceiver(wifiScanReceiver, intentFilter); wifiManager.startScan(); }
I registered the
BroadcastReceiver
exactly like I saw in all the examples, and didstartScan
.What happens is, the wifi list is changing (for sure, I tested), but
onReceive
is not called if I just stay in the app.What makes
onReceive
finally to be called - is to launch the app, leave it running, and going in the android phone to Settings -> Wifi settings. when going there, all of the sudden the List is updating andonReceive
is called.What's the problem here?
Does
wifiManager.startScan();
runs the scan only once? or it is a function that keeps listening to incoming "Scan Results"?And obviously, why does the receiver doesn't get called?
-
Ofek Agmon over 7 yearswhat I meant by asking if its a "single scan" was - will I keep getting notified in onResponse when Wifi networks are updating? it seems that it does - because when I run the code and just go to the Settings -> Wifi Settings, the onResponse is getting called multiple times. so, just to make sure, it is not necessary to call startScan() multiple times , once is enough, correct?
-
Ofek Agmon over 7 yearsjust to make it clear - my goal to have a receiver that will get called every time the Wifi networks list are changing, without having to click a "start scan" button.
-
Ofek Agmon over 7 yearsthanks for your answer. so, as far as you know, it can't be done without calling it repeatedly? my goal is actually to listen to changes in availability for only one Specific network with a Specific SSID. I asked about the whole network list because I figured that's the only way to do it (go over the list and check my specific network), but maybe there is a way to listen to availability changes for a specific network? thanks a million
-
gus27 over 7 yearsYes, considering the
xxx_ACTION
s the Android Wifi API provides I don't think there's any other way but scanning repeatedly. You can listen for changes of the current connected network withNETWORK_STATE_CHANGED_ACTION
but you can't restrict this to a specific SSID. -
Ofek Agmon over 7 yearsGot it. Thanks a lot!