Ajuda com bindService

5 respostas
Heartbreaker

Estou estudando pelo livro do Ricardo Lecheta e estou tento algumas dificuldades pra entender o bindService. Usando o startService eu entendi tranquilo, porém com o bindService eu já li, reli, treli, etc, o trecho que explica mas não consegui entender. Apesar do autor explicar bem o funcionamento, o código é muito complexo.

Esta é a classe do Service que ele usa pra explicar o startService:
package br.livro.android.cap11.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * Service simples que exibe logs no método onCreate, onDestroy
 * 
 * O onCreate cria uma Thread para demonstrar um processamento em background
 * 
 * @author ricardo
 *
 */
public class ExemploServico extends Service implements Runnable {
	private static final int MAX = 50;
	private static final String CATEGORIA = "livro";
	protected int count;
	private boolean ativo;
	@Override
	public IBinder onBind(Intent i) {
		Log.i(CATEGORIA, "ExemploServico.onBind()");
		//null aqui nao queremos interagir com o service
		return null;
	}
	@Override
	public void onCreate() {
		Log.i(CATEGORIA, "ExemploServico.onCreate()");
		ativo = true;
		//Delega para uma thread
		new Thread(this).start();
	}
	@Override
	public void onStart(Intent intent,int startId) {
		Log.i(CATEGORIA, "ExemploServico.onStart()");
	}
	@Override
	public void onDestroy() {
		//Ao encerrar o serviço, altera o flag para a thread parar
		ativo = false;
		Log.i(CATEGORIA, "ExemploServico.onDestroy()");
	}
	/**
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		while (ativo && count < MAX) {
			fazAlgumaCoisa();

			Log.i(CATEGORIA, "ExemploServico executando... " + count);

			count++;
		}

		Log.i(CATEGORIA, "ExemploServico fim.");

		//Auto-Encerra o service se o contadador chegou a 10
        stopSelf();
	}
	private void fazAlgumaCoisa() {
		try {
			//simula algum processamento
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
Esta é a classe do Service e a interface que ele usa pra explicar o bindService, que eu pouco entendi:
package br.livro.android.cap11.service;

import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

/**
 * Service simples que faz bind para a interface Contador
 * 
 * @author ricardo
 * 
 */
public class ServicoComConexao extends ExemploServico implements Contador {
	private final IBinder conexao = new LocalBinder();
	private static final String CATEGORIA = "livro";
	// Implementação de IBinder, retorna a interface para interagir com o serviço
	public class LocalBinder extends Binder {
		public Contador getContador() {
			// Retorna o serviço SimplesBindService para a Activity
			return ServicoComConexao.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(CATEGORIA, "ServicoComConexao.onBind() conexao");
		// Retorna o Binder para a Activity utilizar
		return conexao;
	}

	/**
	 * @see br.livro.android.cap11.service.Contador#count()
	 */
	public int count() {
		// Retorna um contador
		return count;
	}
}
package br.livro.android.cap11.service;

/**
 * Interface para utilizar com o método binService para invocar
 * métodos do Service
 * 
 * @author ricardo
 *
 */
public interface Contador {
	public int count();
}
Esta é a classe da Activity que chama o bindService:
package br.livro.android.cap11;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import br.livro.android.cap11.service.Contador;
import br.livro.android.cap11.service.ServicoComConexao;
import br.livro.android.cap11.service.ServicoComConexao.LocalBinder;

/**
 * Exemplo de utilização do bindService, para interagir com um Service que
 * utiliza a interface CountService
 * 
 * @author ricardo
 * 
 */
public class ExemploBindService extends Activity implements ServiceConnection {
	private static final String CATEGORIA = "livro";
	private Contador contador;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		setContentView(R.layout.form_bind);

		// A classe implementa a interface ServiceConnection
		final ServiceConnection conexao = this;

		// Iniciar o serviço
		Button bIniciar = (Button) findViewById(R.id.btIniciar);
		bIniciar.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				Log.i(CATEGORIA, "Iniciar serviço - bindService");
				Class classeServico = ServicoComConexao.class;
				bindService(new Intent(ExemploBindService.this, classeServico), conexao, Context.BIND_AUTO_CREATE);
			}
		});

		// Parar o service, usa a connection
		Button bParar = (Button) findViewById(R.id.btParar);
		bParar.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				Log.i(CATEGORIA, "Parar serviço - unbindService");
				unbindService(conexao);
			}
		});

		// Ver o retorno do método "count" da interface do serviço
		Button b = (Button) findViewById(R.id.btContador);
		b.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				int count = contador.count();
				Log.i(CATEGORIA, "Contador: " + count);
				Toast.makeText(ExemploBindService.this, "Contador: " + count, Toast.LENGTH_SHORT).show();
			}
		});
	}

	public void onServiceConnected(ComponentName className, IBinder service) {
		// Recupera a interface para interagir com o serviço
		LocalBinder binder = (LocalBinder) service;
		contador = binder.getContador();
	}

	public void onServiceDisconnected(ComponentName className) {
		contador = null;
	}
}
Se alguém souber algum jeito melhor de explicar, algum vídeo-tutorial, algum diagrama, qualquer coisa que ajude a entender como tudo isso funciona, eu agradeço muito.[color=red] [/color]

5 Respostas

Heartbreaker

Pra ser mais especifico, eu entendo que o onBind() tem que retornar uma interface, mas da linha 15 a 23 do ServicoComConexao eu não entendo nada.

delki8

Se te conforta saber, estou estudando o mesmo capítulo aqui e por algum motivo misterioso ele não reconhece a classe LocalBinder;

Heartbreaker

ctz que vc fez a classe interna certinho?

delki8

Tinha não cara, eu fiz uma linha, ele não achou a classe e eu achei que fosse pau no problema, quando comecei a ler a linha seguinte vi que estava fazendo besteira. Valeu ai.

A

Olá
A confusão é devido à Orientação a Objetos.
A variável conexão é instanciado com o LocalBinder, que extende Binder que implementa IBinder.
O service implementa a interface Contador, então o seu service também é Contador.
No LocalBinder o getContador retorna o seu service como Contador
Tudo isso para que na activity voce possa usar o método count da interface Contador.

Na verdade você não precisaria da interface Contador, poderia simplesmente retornar o service como service e usar a referência do próprio service para acessar algum método público do service.
Mas, é bom entender o uso de interfaces.

Espero que ajude!

Criado 15 de agosto de 2012
Ultima resposta 16 de ago. de 2012
Respostas 5
Participantes 3