Service startet erst nach onCreate bzw. onResume in Activity

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von dronox, 05.11.2010.

  1. dronox, 05.11.2010 #1
    dronox

    dronox Threadstarter Neuer Benutzer

    Beiträge:
    3
    Erhaltene Danke:
    0
    Registriert seit:
    05.11.2010
    Hallo,

    ich bin neu im Android Forum und auch in der Android Entwicklung. Daher sag ich erstmal: Hallo :)

    Ich bin mir nicht im Klaren, welche Wörter bei einer Suche zum Erfolg geführt hätten, daher eröffne ich mal ein neues Thema - ich nehme an, dass irgendjemand schonmal dieses Problem hatte.

    Und zwar ist es so, dass ich im Prinzip einen TabHost habe mit 3 TabActivities. Einer der 3 TabHosts ist im Prinzip eine Art Logger, d.h. er zeigt von mir generierte Nachrichten tabellarisch an. Dazu gehört dann auch im Background ein Logging-Service, der die Nachrichten empfängt, in eine Datenbank einträgt und der dann die Liste für die Activity zurückgibt.

    Mein Problem was ich habe ist folgendes: Der Service wird erfolgreich generiert durch

    Code:
    this.connectionMonitor = new MonitorServiceConnection(this);
    final Intent intentMonitor = new Intent(this, MonitorService.class);
    getApplicationContext().bindService(intentMonitor,
    					this.connectionMonitor, Context.BIND_AUTO_CREATE)
    
    (also es gibt keine Fehlermeldung).

    Der ConnectionMonitor schaut folgendermaßen aus:

    Code:
    public class MonitorServiceConnection implements ServiceConnection {
    
    	private MonitorServiceBinder binder;
    
    	private Context context;
    
    	public MonitorServiceConnection(Context context){
    		this.context = context;
    	}
    	
    	public void onServiceConnected(ComponentName name, IBinder binder) {
    		this.binder = (MonitorServiceBinder) binder;
    		this.binder.initializeDB(context);
    	}
    
    	public void onServiceDisconnected(ComponentName name) {
    
    	}
    
    	public MonitorServiceBinder getBinder() {
    		return this.binder;
    	}
    }
    
    Das Problem ist, dass beim Aufruf von getBinder direkt nach bindService ein Null-Objekt zurückkommt, da onServiceConnected erst nach onResume aufgerufen wird. D.h. ich müsste einen Page Reload machen. Das ist aber wohl nicht Sinn der Sache (hoffe ich ^^) und wollte daher fragen, wo mein Denkfehler liegt?

    Viele Grüße
    Dustin
     
  2. dronox, 08.11.2010 #2
    dronox

    dronox Threadstarter Neuer Benutzer

    Beiträge:
    3
    Erhaltene Danke:
    0
    Registriert seit:
    05.11.2010
    Hallo,

    hat denn niemand eine Idee?

    Ich habe jetzt den Service einfach mal soweit programmiert, dass er einige Funktionen erfüllt. Ich habe 2 Activities - Starter + Monitor (über einen TabHost getrennt)

    Starter beherbergt nun 2 Buttons "Start" und "Stop".

    Das schaut dann so aus:

    Code:
    public class TabStarter extends Activity {
    
    	/**
    	 * 
    	 */
    	private LoggingServiceConnection mLoggingServiceConnection = new LoggingServiceConnection();
    
    	/** Called when the activity is first created. */
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		final Intent loggingIntent = new Intent(this, LoggingService.class);
    		getApplicationContext().bindService(loggingIntent,
    				this.mLoggingServiceConnection, Context.BIND_AUTO_CREATE);
    		this.setContentView(R.layout.starter);
    		TextView text = (TextView) this.findViewById(R.id.TextViewStarter);
    		text.setText("Starter");
    		this.instantiateButtons();
    	}
    
    	/**
    	 * test method
    	 */
    	private void instantiateButtons() {
    		Button startButton = (Button) this.findViewById(R.id.btnStart);
    		Button stopButton = (Button) this.findViewById(R.id.btnStop);
    		startButton.setOnClickListener(new OnClickListener() {
    			public void onClick(View v) {
    				mLoggingServiceConnection.getLoggingServiceBinder().put(
    						new LogEntry("Starter", "Starte Applikation"));
    			}
    		});
    		stopButton.setOnClickListener(new OnClickListener() {
    			public void onClick(View v) {
    				mLoggingServiceConnection.getLoggingServiceBinder().put(
    						new LogEntry("Starter", "Stoppe Applikation"));
    			}
    		});
    	}
    
    }
    
    Funktioniert auch wunderbar, ich starte die Applikation, die Activity Starter wird geladen und ich kann den Service mit Hilfe der 2 Buttons wunderbar ansprechen.
    Wenn ich aber nun auf den Tab/Activity Monitor gehe, wo ich die Sachen anzeigen möchte, dann muss ich zuerst auf das Tab gehen, dann zurück zu Starter switchen und dann wieder zu Monitor - erst dann kann ich aus der onResume auf den Service drauf zugreifen (ich möchte ja die ListView mit den Logdaten befüllen).

    Code hierfür:

    Code:
    package dronox.kmod.gui;
    
    import dronox.kmod.R;
    import dronox.kmod.monitoring.LogEntry;
    import dronox.kmod.monitoring.LoggingService;
    import dronox.kmod.monitoring.LoggingServiceConnection;
    
    import android.app.ListActivity;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.os.Bundle;
    import android.widget.SimpleCursorAdapter;
    
    /**
     * 
     * @author dupeter
     * 
     */
    public class TabMonitor extends ListActivity {
    
    	/**
    	 * 
    	 */
    	private LoggingServiceConnection mLoggingServiceConnection = new LoggingServiceConnection();
    
    	private static final String[] SHOW_COLUMNS = new String[] {
    			LogEntry.COLUMN_TIMESTAMP, LogEntry.COLUMN_TAG,
    			LogEntry.COLUMN_MESSAGE };
    	private static final int[] SIMPLE_LIST_VIEW_IDS = new int[] {
    			R.id.monitor_item_date, R.id.monitor_item_tag,
    			R.id.monitor_item_message };
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		final Intent loggingIntent = new Intent(this, LoggingService.class);
    		getApplicationContext().bindService(loggingIntent,
    				this.mLoggingServiceConnection, Context.BIND_AUTO_CREATE);
    	}
    
    	@Override
    	protected void onResume() {
    		super.onResume();
    		if (this.mLoggingServiceConnection.getLoggingServiceBinder() != null) {
    			Cursor cursor = this.mLoggingServiceConnection
    					.getLoggingServiceBinder().getCursorOfAll();
    			final SimpleCursorAdapter logAdapter = new SimpleCursorAdapter(
    					this, R.layout.monitor_item, cursor, SHOW_COLUMNS,
    					SIMPLE_LIST_VIEW_IDS);
    			this.setListAdapter(logAdapter);
    		}
    	}
    }
    
    Hat jemand eine Idee, wieso onServiceConnected beim Binden des Service stets nach onResume erst aufgerufen wird?

    Gruß Dustin
     
  3. pabbatz, 23.11.2010 #3
    pabbatz

    pabbatz Neuer Benutzer

    Beiträge:
    1
    Erhaltene Danke:
    0
    Registriert seit:
    23.11.2010
    Hallo Dustin,
    ich habe im Prinzip ein ähnliches Problem und glaube, dass es daran liegt, dass der Context einfach "noch nicht fertig" ist, wenn man einen Service in der onCreate() der Activity aufruft. Ich habe es gelöst, indem ich einen TimerTask verwendet habe und den Service einfach 5 Sek. nach Start der Activity starte. Gut ist das aber in meinen Augen nicht.

    Vielleicht kennt ja noch jemand eine bessere Lösung.

    Gruß pabbatz
     
  4. dronox, 23.11.2010 #4
    dronox

    dronox Threadstarter Neuer Benutzer

    Beiträge:
    3
    Erhaltene Danke:
    0
    Registriert seit:
    05.11.2010
    Hi pabbatz,

    meine Idee bzw. wie ich das gelöst habe, war folgende:

    Jede der Activites, die das Service-Modul benutzen wollen, implementieren ein Interface namens ServiceARegistrator, das die Methode "serviceARegistered()" enthält. In der ServiceConnection habe ich dann eine Methode registerClient(ServiceARegistor reg). In der ServiceConnection-Klasse lege ich dann eine Liste mit allen registrierten ServiceARegistrator-Objekten an, die - sobald onServiceConnected aufgerufen wird - durchlaufen wird und bei allen Objekten serviceARegistered() aufgerufen wird. Dann kann jede Activity etc. selbst entscheiden, was es mit der Information anfangen will.

    Ich finde das auch etwas umständlich, aber trotz Versionsnummer 2.2 halte ich Android für noch lange nicht ausgereift ;-) (siehe auch die Behandlung von ClickEvents bei Items und Buttons, einmal durch OnClickListener und einmal durch eine integrierte Methode per Switch/Case oder auch diverse Probleme bei der Verwendung von TabHost).

    Vielleicht hat das ja jetzt die Idee gebracht - die obige Variante ist auf jeden Fall sicherer, als eine fixe Zeit zu warten - in Ausnahmefällen (z.B. wenn eine Activity den UI-Thread blockiert) kann es durchaus passieren, dass die 5 Sekunden zu wenig sind. Dann fliegt dir eine NullPointerException um die Ohren ;-)

    Gruß Dustin
    Gruß Dustin
     

Diese Seite empfehlen