Skip to content

Tutorial: Detect and display the connected WIFI network

Scott Moyer edited this page Nov 26, 2013 · 96 revisions

Our goal

We want to detect and display the currently connected WIFI network. On the way we will learn how to change the app name and icon.

Prerequisites

This tutorial has been tested with the following setups

Platform JDK ant Ruby ruboto jruby-jars Device API level Tester
OS X 10.8.3 1.7.0_21 1.8.4 MRI 2.0.0 0.13.0 RubotoCore Samsung Glxy S3 android-16 donv
OS X 10.7.4 1.6.0_33 1.8.4 MRI 1.8.7 0.7.0.rc.1 ASUS TF101 android-15 donv
OS X 10.8.0 1.6.0_33 1.8.2 MRI 1.8.7 0.7.1.rc.0 HTC Desire HD android-10 donv

Setup

Connect your device

Package and deploy

Generate the application

ruboto gen app --package org.ruboto.examples.wifi_detector

Install the apk into your device

cd wifi_detector
rake install

You should see an application called "Wifi Detector" in your application list on the device. Try starting it. You should eventually get "What hath Matz wrought?" and a button. Clicking the button displays a short notification (toast) "Flipped a bit via butterfly".

A fresh app

Do some small changes

Change the name of the application

Edit the application name in res/values/strings.xml Change "Wifi Detector" to "My Wifi Detector".

<?xml version='1.0' encoding='UTF-8'?>
<resources>
    <string name='app_name'>
        My Wifi Detector
    </string>
</resources>

Change the title of the generated screen

Edit the file src/wifi_detector_activity.rb Change the line

    set_title 'Domo arigato, Mr Ruboto!'

to

    set_title 'My WIFI Detector'

Update the app icons

Download these images and place in res/drawable-hdpi , res/drawable-mdpi , and res/drawable-ldpi .

Ruboto Logo 72x72 => res/drawable-hdpi/ic_launcher.png

Ruboto Logo 48x48 => res/drawable-mdpi/ic_launcher.png

Ruboto Logo 36x36 => res/drawable-ldpi/ic_launcher.png

Update and admire the changes

Build and install the app and verify that the application name, screen title, and application icons have changed.

rake install start

Display WIFI state

Add the following permissions to AndroidManifest.xml just below the uses-sdk tag.

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

Edit the file src/wifi_detector_activity.rb to

require 'ruboto/widget'
require 'ruboto/util/toast'

ruboto_import_widgets :Button, :LinearLayout, :TextView

class WifiDetectorActivity
  def onCreate(bundle)
    super
    
    set_title 'My WIFI Detector'

    self.content_view = linear_layout :orientation => :vertical, :gravity => android.view.Gravity::CENTER do
      button :text => 'Show WIFI state', :layout => {:width => :wrap_content}, :on_click_listener => proc{show_wifi_state}
    end
  end

  private

  def show_wifi_state
    wifi_service = getSystemService(android.content.Context::WIFI_SERVICE)
    ssid = wifi_service.connection_info.getSSID
    if ssid
      toast "Connected to #{ssid}"
    else
      toast 'Not connected to any WIFI network'
    end
  end

end

Build and install the app and verify that WIFI connection state is displayed correctly when you press the button.

rake update_scripts:restart

Notify of WIFI changes

Generate the broadcast receiver

ruboto gen class BroadcastReceiver --name WifiReceiver

Change the generated file src/wifi_receiver.rb to

import android.app.Notification
import android.app.PendingIntent
import android.content.Intent
import android.content.Context
import android.net.wifi.WifiManager
import android.view.View
import android.widget.Toast
import android.util.Log

class WifiReceiver
  HELLO_ID = 1

  def onReceive(context, intent)
    Log.v 'WifiDetector', 'Woohoo!  Network event!'
    if intent.action == WifiManager::NETWORK_STATE_CHANGED_ACTION
      wifi_service = context.getSystemService(Context::WIFI_SERVICE)
      if (ssid = wifi_service.connection_info.getSSID)
        if ssid != @ssid
          Toast.makeText(context, "Connected to #{ssid}", 5000).show
          @notification_manager = context.getSystemService(Context::NOTIFICATION_SERVICE)
          icon                  = $package.R::drawable::ic_launcher
          tickerText            = 'In the right place!'
          notify_when           = java.lang.System.currentTimeMillis
          notification          = Notification.new(icon, tickerText, notify_when)
          contentTitle          = 'You are in the right place!'
          contentText           = "You are connected to #{ssid}."
          notificationIntent    = Intent.new(context, $package.WifiDetectorActivity.java_class)
          contentIntent         = PendingIntent.getActivity(context, 0, notificationIntent, 0)
          notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent)

          @notification_manager.notify(HELLO_ID, notification)
          @ssid = ssid
        end
      else
        remove_notification(context)
      end
    elsif intent.action == WifiManager::WIFI_STATE_CHANGED_ACTION
      info = intent.getIntExtra(WifiManager::EXTRA_NETWORK_INFO, WifiManager::WIFI_STATE_DISABLED)
      Log.d('WifiDetector', "WIFI state change: #{info}")
      remove_notification(context) if info == WifiManager::WIFI_STATE_DISABLED
    end
  end

  private

  def remove_notification(context)
    return unless @notification_manager
    return unless @ssid
    Log.v 'WifiDetector', 'Removing notification.'
    @ssid = nil
    Toast.makeText(context, 'Not connected to any WIFI network', 5000).show
    @notification_manager.cancel(HELLO_ID)
  end

end

Insert the following code into src/wifi_detector_activity.rb inside the WifiDetectorActivity class, just before the private line.

  def onResume
    super
    @receiver = $package.WifiReceiver.new
    filter = android.content.IntentFilter.new(android.net.wifi.WifiManager::NETWORK_STATE_CHANGED_ACTION)
    registerReceiver(@receiver, filter)
  end

  def onPause
    super
    unregisterReceiver(@receiver)
    @receiver = nil
  end

Rebuild and install, and restart the application.

rake update_scripts:restart

You should now see a toast whenever your application is running and the WIFI connection state changes.

Detect changes in the background

Generate a service

ruboto gen class Service --name WifiDetectorService

This will generate the files src/org/ruboto/examples/wifi_detector/WifiDetectorService.java and src/wifi_detector_service.rb The former will run the latter on service lifecycle events.

Change the content of src/wifi_detector_service.rb to this

import android.util.Log

class WifiDetectorService
  def onStartCommand(intent, flags, startId)
    Log.i('WifiDetector', 'Service command started')
    super
    @receiver = $package.WifiReceiver.new
    registerReceiver(@receiver, android.content.IntentFilter.new(android.net.wifi.WifiManager::WIFI_STATE_CHANGED_ACTION))
    registerReceiver(@receiver, android.content.IntentFilter.new(android.net.wifi.WifiManager::NETWORK_STATE_CHANGED_ACTION))
    android.app.Service::START_STICKY
  end

  def onDestroy
    Log.i('WifiDetector', 'Service destroyed')
    super
    unregisterReceiver(@receiver)
    @receiver = nil
  end

end

Start the service by adding the following line to the end of the on_create method in src/wifi_detector_activity.rb

  startService(android.content.Intent.new(application_context, $package.WifiDetectorService.java_class))

Rebuild, install, and restart the application

rake update_scripts:restart

You should now see a toast whenever the WIFI connection state changes, regardless of if your application is showing.

Start the service when the device is turned on

Generate another broadcast receiver

ruboto gen class BroadcastReceiver --name BootReceiver

Change the generated file src/boot_receiver.rb to

require 'ruboto/base'

import android.util.Log

class BootReceiver
  def onReceive(context, intent)
    Log.v 'WifiDetector', 'Boot detected!'
    $package_name = context.package_name
    $package      = eval("Java::#{$package_name}")
    context.startService(android.content.Intent.new(context, $package.WifiDetectorService.java_class))
  end
end

Now edit AndroidManifest.xml, and add an intent filter to the newly generated BootReceiver entry

        <receiver android:name="BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.HOME" />
            </intent-filter>
        </receiver>

Finally add the permission to receive the broadcast after boot in the AndroidManifest.xml file:

    <uses-permission android:name='android.permission.RECEIVE_BOOT_COMPLETED'/>

Rebuild, install, and restart the application

rake update_scripts:restart

The WIFI detector will now be started automatically whenever you start your device.

TODO

  • Ensure only one instance of the main activity is active at any time
Clone this wiki locally