Thursday, November 28, 2013

Android: Starting Wifi scan and using ScanResult

For scanning wifi access points at interval of 30 seconds, I have the following code. However I strongly discourage frequent scanning as it will drain the battery very fast.
Following code registers for a broadcast receiver and requests the Wifi scan.

new Thread( ) {
 public void run( ) {
  WifiManager manager = (WifiManager) Main.getInstance( ).getContext( )
  .getSystemService( Context.WIFI_SERVICE );
  while ( true ) {
   IntentFilter i = new IntentFilter( );
   i.addAction( WifiManager.SCAN_RESULTS_AVAILABLE_ACTION );
   Main.getInstance( ).getContext( ).registerReceiver( new WifiScanCompleteReceiver( ), i );
   boolean a = manager.startScan();
   try {
    Thread.sleep( 30000 );
   }
   catch ( InterruptedException e ) {
   }
   Log.d( HelperUtils.getInstance( ).getApplicationName( ), "New Wifi scan started." );
  }
 }
}
.start( );
In this code Main.getInstance( ).getContext( ) returns _context = getApplicationContext( ).
Next write a broadcast receiver to listen the results available event.

public class WifiScanCompleteReceiver extends BroadcastReceiver {
    
    public WifiScanCompleteReceiver( ) {
    }
    
    @Override
    public void onReceive( Context context, Intent intent ) {
        Log.d( HelperUtils.getInstance( ).getApplicationName( ), "Wifi scan result received." );
        Main.getInstance( ).getContext( ).unregisterReceiver( this );
        
        Vector< String > WifiNames = new Vector< String >( );
        WifiManager manager = (WifiManager) Main.getInstance( ).getContext( ).getSystemService( Context.WIFI_SERVICE );
        List< ScanResult > scanResults = manager.getScanResults( );
        if ( scanResults != null ) {
            for ( int i = scanResults.size( ) - 1; i >= 0; i-- ) {
                ScanResult result = scanResults.get( i );
                WifiNames.add( result.SSID );
                Log.d( HelperUtils.getInstance( ).getApplicationName( ),
                        "Scanned SSID is:" + showOnlySSIDAndLevel( result.SSID, result.level ) );
            }
        }
    }
    
    private String showOnlySSIDAndLevel( String name, int strength ) {
        int level = WifiManager.calculateSignalLevel( strength, 5 ) + 1;
        String content = name + " \tSignal strength: " + level;
        return content;
    }
}
Its necessary to unregister the broadcast receiver using the same Context, otherwise Android will throw exception saying BroadcastReceiver leaked.

Finally add the following line in manifest.
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

A good link for Android developers. Power usage by various components in Android.

https://source.android.com/devices/tech/power.html

Types of coroutine scopes
https://vladsonkin.com/android-coroutine-scopes-how-to-handle-a-coroutine/

Android aar deployment in Maven - 2022

Introduction If you are working on android library project, you might be wondering how to publish it on Maven like this . Earl...