Search code examples
javaandroidsingletonandroid-wifirunnable

Using context and executor service (Android Wi-Fi)


I am trying to get the signal strengths of various Access Points in the vicinity.

My scanWifi() function is doing most of the processing for this in a separate class. As a result I have a need to use Context as a parameter for this function.

In the WiFi class:

public class Wifi {

    public void scanWifi(Context context, String APName, ArrayList<Integer> accessPointMeanRSSArrayList, ArrayList<Integer> accessPointRSSFrequencyArrayList) throws Exception {

        ArrayList<Integer> tempRSSArrayList = new ArrayList<Integer>();
        boolean AP_found = false;

        WifiManager myWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

Currently I am implementing this as follows in my Main Activity:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    Runnable periodicTask = new Runnable() {
        public void run() {
            Wifi wifiObject = new Wifi();
            // For each AP in the database, we will fill the AP's ArrayList with their corresponding RSS values
            for (Map.Entry<String, String> entry : AccessPoints.entrySet()){
                int APNoToBeSent = 0;

                try {
                    wifiObject.scanWifi(getApplicationContext(), entry.getKey(), accessPointMeanRSSArrayList, accessPointRSSFrequencyArrayList);
                }

                catch(Exception e) {
                }

                ++APNoToBeSent;
            }


            System.out.println("Mean AP0 = " + accessPointMeanRSSArrayList.get(0));
            System.out.println("Frqcy AP0 = " + accessPointRSSFrequencyArrayList.get(0));
        }
    };

    executor.scheduleAtFixedRate(periodicTask, 0, 2, TimeUnit.SECONDS);

I am unsure whether I am using getApplicationContext() correctly here as I've read of people using Singletons and also heard that using getApplicationContext() is not the correct method nor are using Singletons.

All of this has me a little confused as to what the best practice is in this instance. Should I be passing Context to my scanWifi() function in a different manner?


Solution

  • You don't have a singleton you are creating one every two seconds.

    I'd pass the context to the constructor, not the method:

    public class Wifi {
    
        private final WifiManager wifiManager;
    
        public Wifi(Context context){
            wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        }
    
        public void scanWifi(String APName, ArrayList<Integer> accessPointMeanRSSArrayList, ArrayList<Integer> accessPointRSSFrequencyArrayList) throws Exception {
    
            ArrayList<Integer> tempRSSArrayList = new ArrayList<Integer>();
            boolean AP_found = false;
    

    Create from inside runnable like this:

    Wifi wifiObject = new Wifi(Activity.this);
    

    Alternative:

    public class Wifi {
    
        private final WifiManager wifiManager;
    
        public Wifi(WifiManager wifiManager){
            this.wifiManager = wifiManager;
        }
    

    Create like this:

     Wifi wifiObject = new Wifi((WifiManager) getSystemService(Context.WIFI_SERVICE));
    

    It's a matter or personal preference to an extent.

    First option: Context is readily available in android. This method hides away the code you need to use to get to the wifi service making it simpler to remember how to use it.

    The second option however has minimal dependencies (fewer import statements). If context was not so ubiquitous or I already had a reference to the wifi service ready to pass in I'd probably go for the second option. I'd also favour this option if there were multiple ways to get access to the WifiManager.