Wednesday, August 19, 2015

Reading Wifi Ap Connection parameters from Android device


I would like to talk about fetching the Wifi Access Points parameters that are currently accessible from Android device. To make everything crystal clear, I would shed some light on the meaning of the various properties that we receive from Wifi routers.

1. SSID : Service Set Identifier. It represents a network name or network service profile created by the network admin. This is  the name that you see on your device when you scan for Wifi APs. Farely simple, I guess.

2. BSSID: Base Service Set Identifier. It is not a visible entity on the wireless device. It is the actual MAC address of the Router to which you are connected wirelessly. Multiple routers can be identified by one service profile but every router has a unique BSSID. Got it? (This means that multiple routers can have same SSID but their BSSID will be always unique)

3. Capabilities: Every Access Point has a profile which means that it has set mechanism for authentication, encryption, session management and other configuration properties. This is what is known as the AP's capabilities.

4. Signal Level: The signal level identifies the strength of the signal received from AP. The signal power of electromagnetic aka wireless waves is very low. It is measured in dBm and is relative to 1mW power.

I hope the above details will help you understand the WiFi AP properties. Now, moving on to the Android code for reading this values from the device. Android developer guide provides a fairly cool explanation of doing it. For step by step procedure, you can follow this blog. :)

Step 1. Create a WifiManager to leverage the Android WiFi APIs.

WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);

Step 2. Create a BroadcastReceiver to listen to WiFi scanning event.
BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            List<ScanResult> wifiResults = wifiManager.getScanResults();
            for (ScanResult result: wifiResults)
            {
                String SSID = result.SSID;
                String BSSID =  result.BSSID; 
                String capabilities = result.capabilities;
                int frequency =result.frequency;
                int level = result.level;
            }



Step 3. Register the above BroadcastReceiver for the Scan event.
IntentFilter action = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
registerReceiver(receiver, action);


 
Step 4. Start scanning the avalaible WiFi APs.
wifiManager.startScan();

Step 5. Last, but the most important part of this module. If you don't setup the permission to use the WIFI state changes, then boom, none of the above makes any sense. I hope you got it. For the lazy ones, I am providing the code snippet. ;) Please add the following to the Android Manifest file.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>

Alright guys. Time to take a break. Thanks for reading it and I would be glad if it comes to use.

Wednesday, July 22, 2015

Force media through speaker in Android activity


In one of my projects, one of the requirements was to force the audio through speaker when a temperature measuring device (Thermodo) was plugged into headset jack. This device fits in the 3.5mm jack and causes the audio to be routed to the headset instead of speaker.

After attempting a number of workarounds for more than a week, I was able to play the sound through speaker even if the headset or any 3.5mm device is plugged into the jack.

There are two methods of doing it as mentioned below.

1. Activity
2. Background Service

I will explain the first way of doing it in this blog when you wish to play audio in an Activity using its context. This can include playing short audios on click of a button, or a welcome audio when an activity is launched and so on. I would provide sample for playing audio only.

Set the audio Uri according to your audio file. You can also use system ringtones.
Uri uri = Uri.parse("android.resource://" + MainApplication.getContext().getPackageName() + "/" + resId




Create a MediaPlayer instance. You can do that locally if you wish to use this instance locally. In most of the cases, you might need to stop or pause media based on some events. It is preferable to create the instance as a global one and use it wherever needed.
MediaPlayer player = new MediaPlayer();


Reset the media player to clear all settings. The next step is the most important part as it allows you to set the audio stream type for your media player. You can set it to the following streams:
1. STREAM_ALARM //plays in both headset and speaker
2. STREAM_MUSIC // only plays in headset
3. STREAM_NOTIFICATION // plays in both headset and speaker
4. STREAM_RING // plays in both headset and speaker (I used this)
5. STREAM_SYSTEM
6. STREAM_VOICE_CALL
The code is as below:
player.reset();
player.setAudioStreamType(AudioManager.STREAM_RING);

After setting the stream, you need to set the data source of the audio and prepare the player.
try {
     player.setDataSource(context, uri);
     player.prepareAsync();
}
catch (IOException e) {
      e.printStackTrace();
}

That covers most of the work. When the audio devices are ready to play, you can call play on the Media Player instance and that will play the sound.
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
        if(! mp.isPlaying())
        mp.start();
       }
    });

You can release the player when the audio has played completely. You can also stop the audio anywhere during its play duration by calling stop() api of Media Player.
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
           mp.stop();
           mp.release();
        }
    });

That's pretty much all about playing audio through different audio devices in a proper way. I will discuss about achieving the same using a Service in the next post. Catch you soon.