Criando um Service em Android

Um dos principais componentes de uma aplicação Android são os Services.

Assim como as Activities, os Services são componentes fundamentais em um aplicação, possuindo ciclo de vida próprio. Porém, são diferentes das Activities nos seguintes pontos:

  • Não possuem interface com o usuário.
  • Sua execução continua mesmo quando o usuário inicia outra aplicação.

Por conta dessas características, os Services são geralmente utilizados para realizar tarefas de sincronização (com um servidor, por exemplo) podendo ter sua execução agendada e não dependendo de nenhuma ação do usuário. Por isso, são chamados de componentes de background.

 

Tipos de Serviços

Existem dois principais tipos de serviços:

  • Started (unbounded): são serviços iniciados através de outros componentes (activities, por exemplo) através do método startService(). Após o seu início, o serviço pode continuar sendo executado indefinidamente.
  • Bounded: são serviços iniciados através do método bindService(). Os Bound Services interagem com os outros componentes através de uma interface cliente-servidor, que inclusive podem ocorrer entre diferentes processos (IPC). Um Bound Service é executado enquanto possuir requisições a serem tratadas.

Ciclo de vida

O ciclo de vida de um serviço é análogo ao de uma Activity, porém um pouco mais simples. O diagrama abaixo ilustra o fluxo de chamadas de métodos para ambos os tipos de serviço:

Ciclo de vida de um Service

Erros comuns

Muitos desenvolvedores cometem alguns erros ao implementar os serviços por conta de conceitos errados. São eles:

● Um serviço NÃO é um processo separado. Ele pode ser executado em um processo separado, mas por padrão não é.

● Um serviço NÃO é uma thread separada. Por padrão, seu código é executado na Main Thread.

Implementação

Nas aulas anteriores do Curso de Desenvolvimento Android, criamos uma implementação de HttpUrlConnection que faz backup das notas inseridas pelo usuário em um servidor remoto. (Se você não estava acompanhando o curso, sugiro fazer o download do projeto aqui)

Agora, ao invés de enviar as notas através de uma AsyncTask, iremos fazê-lo através de um Service.

Para isso, crie o arquivo QuickNotesSyncService.java com o seguinte conteúdo:


package android.helloworld;

import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;

public class QuickNotesSyncService extends Service {

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		DataSync d = new DataSync(QuickNotesSyncService.this);
		d.syncPendingNotes();
		return START_NOT_STICKY;
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// Neste exemplo, iremos supor que o service será invocado apenas
		// atraves de startService()
		return null;
	}

	private class SyncDataTask extends AsyncTask<Void, Integer, Void> {
		protected Void doInBackground(Void... p) {
			DataSync d = new DataSync(QuickNotesSyncService.this);
			d.syncPendingNotes();
			return null;
		}
	}
}

E a chamada para o serviço será através do método startService, no método doInBackground da AddNoteAsyncTask da MainActivity, que deixará de usar a classe DataSync diretamente

	private class AddNoteTask extends AsyncTask<String, Void, Uri> {
		@Override
		protected Uri doInBackground(String... string) {
			ContentValues values = new ContentValues();
			values.put(QuickNotesProvider.Notes.TEXT, string[0]);
			// Gravando a flag SYNCED com o valor 0, significando que
			// a nota ainda não foi enviada ao servidor
			values.put(QuickNotesProvider.Notes.SYNCED, "0");

			Uri inserted = getContentResolver().insert(
					QuickNotesProvider.Notes.CONTENT_URI, values);

	    	ConnectivityManager cm =
	    	        (ConnectivityManager)context.getSystemService(
	    	        		Context.CONNECTIVITY_SERVICE);
	    	NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

	    	boolean isConnected = (activeNetwork != null) && activeNetwork.isConnected();
	        if (isConnected) {
	        	Intent i = new Intent(context, QuickNotesSyncService.class);
	        	context.startService(i);
	        }

		}

		@Override
		protected void onPostExecute(Uri result) {
			// Após a inserção da nota, vamos mostrar um Toast ao usuário
			Toast toast = Toast.makeText(MainActivity.this,
					"Nota inserida com sucesso!",
					Toast.LENGTH_SHORT);
			toast.show();
		}
	}

Por fim, é necessário registrar o serviço no AndroidManifest:

<application
 android:icon="@drawable/icon"
 android:label="QuickNotes" >
…
<service
android:name="android.helloworld.QuickNotesSyncService" >
</service>
</application>

Vantagens

As principais vantagens de se usar um Service para operações como esta, de sincronização, são:

  • ciclo de vida mais longo: Mesmo que o usuário coloque a aplicação em background, o serviço continuará sua execução (o que não é sempre verdade no caso de AsyncTasks criadas a partir de uma Activity, por exemplo)
  • independência: o Service é um componente independente, desacoplado das Activities. Isso dá mais flexibilidade ao desenvolvedor, permitindo, por exemplo, que ele invoque este serviço de tempos em tempos usando um broadcast receiver, que é o assunto da nossa próxima aula.

Desenvolvendo para Android

3 respostas to “Criando um Service em Android”

  1. wagner disse:

    Felipe Gostaria de saber se vc desenvolve app para empresa no ramo de prestação de serviço. Se possível entre em contato por email, tenho uma idéia é não sei se é possível. Obrigado.

  2. Marcos disse:

    Felipe uma dúvida esse serviço funciona por exemplo como o de notificações do whatsapp, mesmo eu encerrando o app o serviço continua rodando ?

  3. Vernet disse:

    bem, Felip adorei, porem uma perguntinha dessa forma tambem posso criar ou registar servicos de internet?
    agradeço pela resposta….

Deixe um comentário