/*
* Copyright (C) 2012, Katy Hilgenberg.
* Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de).
* Contact: sdcf@cs.uni-kassel.de
*
* This file is part of the SDCFramework (Sensor Data Collection Framework) project.
*
* The SDCFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The SDCFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SDCFramework. If not, see <http://www.gnu.org/licenses/>.
*/
package de.unikassel.android.sdcframework.util;
import java.util.concurrent.atomic.AtomicBoolean;
import de.unikassel.android.sdcframework.util.facade.EventObserver;
import de.unikassel.android.sdcframework.util.facade.NetworkStateChangeEvent;
import de.unikassel.android.sdcframework.util.facade.ObservableEventSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
/**
* Implementation of an observer for network connection state changes as global singleton.
*
* @author Katy Hilgenberg
*
*/
/**
* @author Katy Hilgenberg
*
*/
/**
* @author Katy Hilgenberg
*
*/
public class NetworkConnectionObserver
extends BroadcastReceiver
implements ObservableEventSource< NetworkStateChangeEvent >
{
/**
* The observable event source
*/
private final ObservableEventSource< NetworkStateChangeEvent > eventSource;
/**
* Observation state flag
*/
private boolean isObserving;
/**
* last connection state
*/
private final AtomicBoolean isNotConnected;
/**
* The application context.
*/
private Context context;
/**
* The singleton instance
*/
private static NetworkConnectionObserver instance;
/**
* Getter for the instance
*
* @param context
* the application context.
*
* @return the instance
*/
public synchronized static NetworkConnectionObserver getInstance(
Context context )
{
if ( instance == null )
{
instance = new NetworkConnectionObserver( context );
}
return instance;
}
/**
* Constructor
*
* @param context
* the application context.
*/
private NetworkConnectionObserver( Context context )
{
super();
eventSource = new ObservableEventSourceImpl< NetworkStateChangeEvent >();
isObserving = false;
isNotConnected = new AtomicBoolean();
this.context = context;
}
/**
* Setter for the not connected state
*
* @param isNotConnected
* the not connected state to set
*/
private synchronized void setNotConnected( boolean isNotConnected )
{
this.isNotConnected.set( isNotConnected );
}
/**
* Getter for the not connected state
*
* @return the not connected state
*/
private synchronized boolean isNotConnected()
{
return isNotConnected.get();
}
/**
* Getter for the last known connection state
*
* @return the last known connection state
*/
public boolean isConnected()
{
return !isNotConnected();
}
/**
* Does start network state observation
*/
private synchronized void startObservation()
{
if ( !isObserving )
{
IntentFilter filter = new IntentFilter();
filter.addAction( ConnectivityManager.CONNECTIVITY_ACTION );
context.registerReceiver( this, filter );
setNotConnected( true );
isObserving = true;
Logger.getInstance().info( this, "Observation started" );
}
}
/**
* Does stop network state observation
*/
private synchronized void stopObservation()
{
if ( isObserving )
{
context.unregisterReceiver( this );
isObserving = false;
Logger.getInstance().info( this, "Observation stopped" );
}
}
/*
* (non-Javadoc)
*
* @see android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
@Override
public void onReceive( Context context, Intent intent )
{
String action = intent.getAction();
if ( action.equals( ConnectivityManager.CONNECTIVITY_ACTION ) )
{
boolean noConnectivity =
intent.getBooleanExtra( ConnectivityManager.EXTRA_NO_CONNECTIVITY,
false );
if ( isNotConnected() != noConnectivity )
{
Logger.getInstance().info( this, "Network state changed: connected = " + isConnected() );
setNotConnected( noConnectivity );
notify( new NetworkStateChangeEventImpl( !isNotConnected() ) );
}
}
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObserverRegistration
* #registerEventObserver(de.unikassel.android.sdcframework.util.facade.
* EventObserver)
*/
@Override
public void registerEventObserver(
EventObserver< ? extends NetworkStateChangeEvent > observer )
{
eventSource.registerEventObserver( observer );
startObservation();
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObserverRegistration
* #unregisterEventObserver(de.unikassel.android.sdcframework.util.facade.
* EventObserver)
*/
@Override
public void unregisterEventObserver(
EventObserver< ? extends NetworkStateChangeEvent > observer )
{
eventSource.unregisterEventObserver( observer );
if ( !eventSource.hasObservers() )
stopObservation();
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObserverRegistration
* #removeAllObservers()
*/
@Override
public void removeAllObservers()
{
eventSource.removeAllObservers();
stopObservation();
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.facade.ObservableEventSource#notify
* (de.unikassel.android.sdcframework.util.facade.ObservableEvent)
*/
@Override
public void notify( NetworkStateChangeEvent data )
{
eventSource.notify( data );
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObservableEventSource#
* hasObservers()
*/
@Override
public boolean hasObservers()
{
return eventSource.hasObservers();
}
}