/* * 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.service; import java.util.Collections; import java.util.LinkedList; import java.util.List; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import de.unikassel.android.sdcframework.app.facade.ISDCService; import de.unikassel.android.sdcframework.app.facade.SDCService; import de.unikassel.android.sdcframework.util.facade.LifeCycleObject; /** * Implementation of life cycle dependent SDC service connection holder.<br/> * <br/> * This class can establish, destroy and observe a connection with the SDC * service. It does act based on the activity life cycle, thus the connection is * established on creation and destroyed on destruction. The related methods * have to be called by the controlling activity. To get notifications about * related events, the activity should implement the * ServiceConnectionEventReceiver interface. * * * @author Katy Hilgenberg * */ public class SDCServiceConnectionHolder implements LifeCycleObject { /** * Interface for receivers of service connection events * * @author Katy Hilgenberg * */ public interface ServiceConnectionEventReceiver { /** * This event is raised on connection establishment * * @param sdcService */ public abstract void onConnectionEstablished( ISDCService sdcService ); /** * This event is raised right before connection will be closed * * @param sdcService * the AIDL SDC service interface */ public abstract void onAboutToDisconnect( ISDCService sdcService ); /** * This event is raised in case of lost connection */ public abstract void onConnectionLost(); /** * This event is raised if binding failed */ public abstract void onBindingFailed(); /** * This event is raised if the service is not available on the system */ public abstract void onServiceUnavailable(); } /** * The service connection */ private final ServiceConnection serviceConnection; /** * The service availability state flag */ private boolean serviceAvailable; /** * The service interface */ private ISDCService sdcService; /** * The event receiver list */ private final List< ServiceConnectionEventReceiver > listEventReceivers; /** * The service class */ private final Class< ? > serviceClass; /** * The service component name */ private ComponentName serviceComponent; /** * Constructor * * @param receiver * the event receiver * @param serviceClass * the service class */ public SDCServiceConnectionHolder( ServiceConnectionEventReceiver receiver, Class< ? > serviceClass ) { this.serviceClass = serviceClass; this.listEventReceivers = Collections.synchronizedList( new LinkedList< ServiceConnectionEventReceiver >() ); addEventReceiver( receiver ); this.serviceConnection = new ServiceConnection() { /* * (non-Javadoc) * * @see * android.content.ServiceConnection#onServiceDisconnected(android.content * .ComponentName) */ @Override public void onServiceDisconnected( ComponentName name ) { setSdcService( null ); for ( ServiceConnectionEventReceiver receiver : listEventReceivers ) { receiver.onConnectionLost(); } } /* * (non-Javadoc) * * @see * android.content.ServiceConnection#onServiceConnected(android.content * .ComponentName, android.os.IBinder) */ @Override public void onServiceConnected( ComponentName name, IBinder service ) { setSdcService( ISDCService.Stub.asInterface( service ) ); for ( ServiceConnectionEventReceiver receiver : listEventReceivers ) { receiver.onConnectionEstablished( getSdcService() ); } } }; } /** * Getter for the serviceComponent * * @return the serviceComponent */ public ComponentName getServiceComponent() { return serviceComponent; } /** * Setter for the serviceComponent * * @param serviceComponent * the serviceComponent to set */ public void setServiceComponent( ComponentName serviceComponent ) { this.serviceComponent = serviceComponent; } /** * Constructor * * @param serviceClass * the service class * */ public SDCServiceConnectionHolder( Class< ? extends SDCService > serviceClass ) { this( null, serviceClass ); } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.util.facade.LifeCycleObject#onResume( * android.content.Context) */ @Override public void onResume( Context applicationContext ) { } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.util.facade.LifeCycleObject#onPause(android * .content.Context) */ @Override public void onPause( Context applicationContext ) { } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.util.facade.LifeCycleObject#onCreate( * android.content.Context) */ @Override public void onCreate( Context applicationContext ) { // test for service availability first serviceAvailable = ServiceUtils.isServiceAvailable( applicationContext, serviceClass ); if ( serviceAvailable ) { // if service is not running we do start it to avoid service get's // destroyed on unbound if ( !ServiceUtils.isServiceRunning( applicationContext, serviceClass ) ) { ServiceUtils.startService( applicationContext, serviceClass ); } Intent intent = new Intent( serviceClass.getName() ); if ( !applicationContext.bindService( intent, serviceConnection, 0 ) ) { for ( ServiceConnectionEventReceiver receiver : listEventReceivers ) { receiver.onBindingFailed(); } } } else { for ( ServiceConnectionEventReceiver receiver : listEventReceivers ) { receiver.onServiceUnavailable(); } } } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.util.facade.LifeCycleObject#onDestroy * (android.content.Context) */ @Override public void onDestroy( Context applicationContext ) { if ( serviceAvailable ) { if ( getSdcService() != null ) { for ( ServiceConnectionEventReceiver receiver : listEventReceivers ) { receiver.onAboutToDisconnect( getSdcService() ); } } applicationContext.unbindService( serviceConnection ); } } /** * Method to add an event receiver * * @param receiver * the event receiver */ public void addEventReceiver( ServiceConnectionEventReceiver receiver ) { if ( receiver != null ) listEventReceivers.add( receiver ); } /** * Method to remove an event receiver * * @param receiver * the event receiver */ public void removeEventReceiver( ServiceConnectionEventReceiver receiver ) { if ( receiver != null ) listEventReceivers.remove( receiver ); } /** * Setter for the sdcService * @param sdcService the sdcService to set */ private final synchronized void setSdcService( ISDCService sdcService ) { this.sdcService = sdcService; } /** * Getter for the sdcService * @return the sdcService */ private final synchronized ISDCService getSdcService() { return sdcService; } }