Curso de Android
Fevereiro de 2011
Cristiano Expedito Ribeiro
Fabrício Firmino de Faria
Agenda das próximas aulas [excluir]







Intent filter
BroadcastReceiver, Threads, Services e Notification
AlarmManager e Handler
Banco de Dados e ContentProvider
Mapas e GPS
Sockets e Web Services
Projeto
2
Agenda da Aula 2
 Intent filter
 Aplicações em segundo plano




BroadcastReceiver
Threads e Services
Notification
AlarmManager
 Handler
 Persistência
 Arquivos e preferências
 Banco de Dados SQLite
 ContentProvider
 Mapas e GPS
3
Intent Filter
 Criação de filtros que determinam quais Intents devem
ser executadas para cada mensagem
<activity android:name=".HelloActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
 Action = MAIN
 Diz que activity é um ponto de partida, semelhante ao
public static void main() da Java
 Category = LAUNCHER
 Indica que o ícone da activity deverá aparecer na tela
pode ser aberta pelo usuário
4
IntentFilter - Exercício 17
 Volte ao projeto LayoutSamples
 Abra o AndroidManifest.xml
• Remova o elemento <action> e salve
• Tente rodar a aplicação pelo eclipse
• Tente rodar a aplicação pelo menu do emulador
• Desfaça a remoção (Ctrl+Z)
• Remove o elemento <category> e salve
• Tente rodar a aplicação
• Desfaça a remoção (Ctrl+Z)
• Tente rodar a aplicação. Apenas com os dois elementos
que a aplicação rodará normalmente.
5
Ações de Intent úteis
 Lembra das ações “nativas” do Android?
Action
URI - chamar Uri.parse(uri)
Descrição
ACTION_VIEW
http://www.gmail.com
Abre browser na página
ACTION_VIEW
ACTION_EDIT
content://com.android.contacts/contacts/1
Mostra ou edita o contato
solicitado
ACTION_VIEW
geo:0,0?q=Presidente+Vargas,Rio+de+Ja
neiro
Busca no Google Maps
ACTION_CALL
ACTION_DIAL
tel:12345678
Liga ou apenas disca para o
número
ACTION_INSERT
content://com.android.contacts/contacts
Abre activity padrão para
inserir contatos
ACTION_PICK
ContactsContract.Contacts.CONTENT_URI
Abre lista de contatos do
celular
ACTION_SET_WALLPAPER
-
Abre lista para escolha de
papéis de parede
6
Ações de Intent – Exercício 18
 Crie um novo projeto chamado IntentFilterTest
 Experimente chamar activities usando a tabela anterior
 Exemplo:
Uri uri = Uri.parse("content://com.android.contacts/contacts");
Intent intent = new Intent(Intent.ACTION_INSERT, uri);
startActivity(intent);
intent = new Intent(Intent.ACTION_SET_WALLPAPER);
startActivity(intent);
 Experimente também:
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, "Maria");
startActivity(intent);
 Sim, você pode passar parâmetros via Intent,
dependendo de qual ação está sendo executada!
7
Ações de Intent – Exercício 18
 ACTION_CALL não irá funcionar pois é necessário
pedir permissão através do AndroidManifest.xml
• Adicione esta permissão e tente novamente
<uses-permission android:name="android.permission.CALL_PHONE”/>
 Outras permissões úteis
android.permission.READ_CONTACTS
android.permission.VIBRATE
android.permission.INTERNET
android.permission.BATTERY_STATS
android.permission.BLUETOOTH
android.permission.CAMERA
android.permission.REBOOT
android.permission.SEND_SMS
 Além disso, para usar o Google Maps é necessário
rodar o emulador com Google Maps.
8
Categorias e parâmetros para Intent
 Algumas vezes Ação e URI não são suficientes
 É possível adicionar tantas categorias e parâmetros
extras quanto forem necessários, além de outros dados:
Método da Intent
Descrição
addCategory(String)
Adiciona mais uma categoria à Intent
putExtra(String, ...)
Adiciona um parâmetro à Intent
setData(Uri)
Define o Uri. Equivalente ao parâmetro URI do construtor
setType(String)
Define o tipo MIME: text/plain, image/jpeg, etc
setFlags(int)
addFlags(int)
Define os flags da Intent. Um flag útil é o FLAG_ACTIVITY_NEW_TASK,
que faz a activity iniciar numa nova tarefa
setAction(String)
Define a ação desta intent. Note que, diferentemente de categorias e
extras, apenas uma ação pode ser definida por intent.
 Os métodos setData() e setType() são antagônicos, ou
seja, chamar um deles implica em limpar o outro.
9
Substituindo ações nativas
 Tecla Home
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
 Tecla discar (call)
<action android:name="android.intent.action.CALL_BUTTON" />
<category android:name="android.intent.category.DEFAULT" />
 Intent.ACTION_SEARCH
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
 Intent.ACTION_WEB_SEARCH
<action android:name="android.intent.action.WEB_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
10
Ações nativas - Exercícios 19 e 20
 Exercício 19
 Crie um projeto IntentFilterNativeSubst
 Modifique o manifest e rode a aplicação para cada
exemplo do slide anterior
 Exercício 20
 Após o último exemplo (web search) edite o projeto
IntentFilterTest para chamar web search:
intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, "Maria");
startActivity(intent);
 Execute IntentFilterTest
 Veja que o emulador irá perguntar
qual aplicação executar
11
Ações e categorias próprias e filtragem
 Para criar as próprias ações e categorias, faça:
 Configurá-las no manifest usando <intent-filter>
 Criar a Intent e executá-la
• Isto pode ser feito na mesma aplicação ou não
 Filtragem
 Ao executar uma Intent, uma activity só rodará caso seu
intent-filter satisfaça a ação e todas as categorais
definidas na Intent.
 Exemplos:
• Considere intent-filter: ACAO1, CATEG1, CATEG2
1. Intent: ACAO1, CATEG1  Executa
2. Intent: ACAO1, CATEG1, CATEG2  Executa
3. Intent: ACAO1, CATEG3  Não executa!
12
Ações próprias e filtragem – Exercício 21
 No manifest de IntentFilterNativeSubst
<action android:name="com.example.intentfilter.nativesubst.ACTION" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.intentfilter.nativesubst.CATEG1" />
<category android:name="com.example.intentfilter.nativesubst.CATEG2" />
 Dê play na aplicação IntentFilterNativeSubst para
instalá-la, note que nada rodará na tela, pois não há
MAIN e LAUNCHER
 Em IntentFilterTest
intent = new Intent("com.example.intentfilter.nativesubst.ACTION");
intent.addCategory("com.example.intentfilter.nativesubst.CATEG1");
intent.addCategory("com.example.intentfilter.nativesubst.CATEG2");
startActivity(intent);
 Rode IntentFilterTest e IntentFilterNativeSubst rodará
 Remova CATEG2 do manifest e repita a operação...
13
Intent filter e permissões
 Caso um <intent-filter> não seja definido para uma
activity apenas a própria aplicação poderá iniciá-la
 Mas é possível exportá-la
<activity ... android:exported=“true” > ...
 Mesmo assim, é necessário que a aplicação que queira
iniciá-la use Intent.setComponentName() ou
setClassName() e conheça o nome da classe completo
• Exemplo: “com.example.application.ActivityName”
 O uso de <intent-filter> no manifest exporta a activity
automaticamente
 Usar setClassName() ou setComponentName() para
iniciar uma activity não exportada lançará uma
SecurityException
14
Intent filter e permissões
 É possível criar sua própria permissão
<manifest ... >
<permission android:label="@string/..."
android:name="application_package.PERMISSION_NAME" />
<application ... >
<activity ...
android:exported="true"
android:permission="application_package.PERMISSION_NAME" >
</activity>
</application>
</manifest>
 Se uma aplicação diferente quiser acessar esta activity
será necessário usar um elemento <uses-permission>
para a permissão definida pela aplicação
<uses-permission android:name="application_package.PERMISSION_NAME"/>
15
BroadcastReceiver
 Chamado pelo Android para reagir a mensagens
broadcast
 Usado para executar tarefas rápidas em segundo plano
 Não interromper o usuário por meio de activities
 Use notificações! (Serão explicadas em breve)
 O que são mensagens broadcasts?
 São mensagens enviadas pelo Android quando ocorre
algum evento do sistema ou de uma aplicação
 Interceptada pelos BroadcastReceiver’s apropriados
• Definido pelos <intent-filter>
16
Tipos de broadcast
 Ordered ou Síncrono
 Os receivers são executados em sequência e a falha de
um interrompe o processamento dos demais
 Não está no escopo deste curso
 Normal ou Assíncrono
 Todos os receivers executam simultaneamente em
paralelo e de forma independente
 Método para disparar: Context.sendBroadcast(Intent)
BroadcastReceiver1
Evento
Mensagem
...
BroadcastReceiverN
17
Configurando um receiver
 É necessário adicionar o elemento <receiver> dentro
de <aplication> no AndroidManifest.xml
<receiver android:name="NomeReceiver">
<intent-filter>
<action android:name="com.example.broadcastreceiver.ACTION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
 Implementar uma classe filha de BroadcastReceiver
com o callback onReceive(Context, Intent)
public class NomeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// ...
}
}
 Atenção: onReceive deve retornar em menos de 10 s.
18
Disparando mensagens broadcast
 Criar uma Intent com a mensagem
 Enviar via Context.sendBroadcast(Intent)
 Context é uma classe base de activity, logo o método
pode ser chamado diretamente
Intent intent =
new Intent("com.example.broadcastreceiver.ACTION");
sendBroadcast(intent);
19
Broadcast Receiver – Exercício 22
 Crie um projeto chamado ReceiverTest
 Crie um broadcast conforme slide anterior
 Dentro do método onReceive escreva algo no log
 Edite o projeto IntentFilterTest para enviar o broadcast
20
Mensagens broadcast do sistema
 Mensagens broadcast enviadas apenas pelo sistema
 Não podem ser enviadas pelo método sendBroadcast()
android.intent.action
Condição de envio (pelo sistema)
WALLPAPER_CHANGED
Papel de parece alterado
BOOT_COMPLETED*
Sistema concluiu o bootstrap
ACTION_SHUTDOWN
Sistema está desligando (antes de desligar o aparelho)
BATTERY_CHANGED**
Estado de carga da bateria mudou
BATTERY_LOW
Estado de carga da bateria baixo
BATTERY_OKAY
Estado de carga da bateria voltou a níveis normais
ACTION_POWER_CONNECTED
Carregador conectado
ACTION_POWER_DISCONNECTED Carregador desconectado
* Requer permissão android.permission.RECEIVE_BOOT_COMPLETED
** Não podem ser usados com <intent-filter> serão mostrados em breve 21
Mensagens broadcast do sistema
android.intent.action.*
Condição de envio (pelo sistema)
TIME_SET
Data e/ou hora do sistema foram alterados
TIMEZONE_CHANGED
Fuso horário foi modificado
TIME_TICK**
Hora do sistema mudou normalmente (enviado a cada minuto)
SCREEN_ON
Tela do dispositivo acendeu (estava inativa, mas usuário ativou)
SCREEN_OFF
Tela do dispositivo apagou (normal para economizar bateria)
PACKAGE_ADDED
Uma nova aplicação foi instalada no dispositivo
PACKAGE_REMOVED
Uma aplicação foi removida do dispositivo
PACKAGE_REPLACED
Uma aplicação foi substituída. Normalmente por upgrade de versão.
PACKAGE_RESTARTED
Uma aplicação foi reiniciada, tendo seus processados terminados.
PACKAGE_DATA_CLEARED
Dados de uma aplicação foram apagados. Enviado após
PACKAGE_RESTARTED
** Não podem ser usados com <intent-filter> serão mostrados em breve
22
Broadcast de sistema – Exercício 23
 Adicione mais um receiver no projeto ReceiverTest
<receiver android:name="WallpaperReceiver">
<intent-filter>
<action android:name="android.intent.action.WALLPAPER_CHANGED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
 Adicione o seguinte no callback onReceive()
Log.i(this.getClass().getCanonicalName(), intent.getAction());
 Instale a aplicaçao
 Tenta mudar o papel de parede no emulador
 Menu > Wallpaper > Wallpapers
 Analise o LogCat.
23
Configuração de receivers via código
 Indicado quando um receiver deve executar apenas
quando uma acitivity está executando
 É possível registrar dinamicamente via código
 registerReceiver(BroadcastReceiver, Intent)
 unregisterReceiver(BroadcastReceiver)
 Recomendável:
 Registrar em Activity.onCreate() ou onResume()
 Desregistrar no Activity.onDestroy() ou onPause()
 Note que são necessários para actions TIME_TICK e
BATTERY_CHANGED da tabela
24
Threads
 São linhas ou fluxos de execução de código que rodam
em “paralelo” numa mesma aplicação
 Usadas para executar tarefas independentes entre si.
 Sempre há uma thread inicial ou principal
 Interface gráfica sempre executa nesta thread
 Exemplo:
 Uma aplicação pode usar 3 threads, assim distribuídas:
• Interface gráfica
• Reprodução de música
• Download de arquivo da Internet
25
Exemplo de aplicação multithread
26
Classe Thread e Interface Runnable
 Métodos da classe Thread
Thread(Runnable)
Construtor de thread que recebe um objeto Runnable contendo o
código a ser executado
static void sleep(long milis)*
Faz thread que chamar este dormir milis milissegundos.
void start()
Inicia thread
void join(long milis, int nanos)*
Aguarda término da thread por tantos milissegundo. Ambos os
argumentos são opcionais.
bool isAlive()
Retorna true se thread ainda está em execução
void run()
Deve ser implementado com o código da thread. A interface
Runnable também possui este método. Não chamar diretamente.
* Cuidado ao chamar métodos bloqueantes em threads que recebem callbacks, pois
estes devem retornar rapidamente.
 Objetos modificados por mais de uma thread:
synchronized (objeto) {
// modifica objeto
}
27
Usando threads
 Em um método qualquer (criação e execução)
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
 Em outro método (aguardar término)
try {
thread.join(1000);
} catch (InterruptedException e) {}
 Classe que contém o código
class MyRunnable implements Runnable {
public void run() {
// codigo da thread que pode ser um loop ou não
}
}
28
Threads e interfaces gráficas
 Callbacks sempre rodam na thread principal da
aplicação
 Todos os objetos de View e subclasses são atrelados à
thread que o criou também conhecida como UI Thread
 Chamar um método de View que a modifique resultará
no lançamento de uma exceção
 ViewRoot.CalledFromWrongThreadException: Apenas
a thread que criou a view pode modificá-la
 Para isso deve-se usar um Handler que será mostrado
posteriormente
29
Serviços
 Usado para executar tarefas em segundo plano
 Estas tarefas não possuem um tempo definido de
execução (podendo ser demoradas)
 Não deve iniciar activities: use notificações (em breve)
 Configuração no AndroidManifest.xml
<application ... >
<service android:name="ServiceName">
<intent-filter>
<action android:name="com.example.serviceapp.ACTION" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
 Caso se queira iniciar o serviço de outra aplicação sem
um <intent-filter> deve-se usar android:exported="true"
30
Formas de iniciar um serviço
 Pode ser iniciado de dentro de activity, broadcast receiver ou
outro serviço
 Duas formas:
 Desacoplado: serviço é iniciado e fica independente do
contexto (activity, receiver ou serviço) chamador
 Com conexão: serviço é iniciado, retorna uma interface de
acesso e fica associado ao contexto chamador. Usado quando
precisa-se “conversar” com o serviço.
 Métodos para inicialização (classe Context)
Método
Descrição
startService(Intent)
Inicia um serviço desacoplado
bindService(Intent, ServiceConnection, flags)
Inicia um serviço conectado. O segundo
parâmetro é um objeto com métodos
callbacks para notificar conexão e desconexão
31
Ciclo de vida de um serviço
32
Classe Service
 Classe base para qualquer serviço
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// Inicializar varíaves e criar uma thread (opcional)
}
@Override
public void onDestroy() {
super.onDestroy();
// Terminar a thread aqui, caso esteja rodando
}
}
33
Compatibilidade com versões anteriores
// Método onStart antigo que é chamado nas
// plataformas anteriores a 2.0
@Override
public void onStart(Intent intent, int startId) {
processaStart(intent);
}
// Método chamado a partir da plataforma 2.0
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
processaStart(intent);
// Retorne isto para que o serviço rode até ser
// explicitamente terminado
return START_STICKY;
}
// Método para onde onStart e onStartCommand converge
protected void processaStart(Intent intent) {
// Processa independente de versão de plataforma
}
34
Inicialização de serviços desacoplados
 Método startService(Intent)
 Inicia o serviço determinado pela intent.
 O serviço roda independente do chamador e por tempo
indeterminado
 Se o contexto chamador terminar o serviço continua
rodando normalmente
 Pode ser chamado inúmeras vezes
• Apenas na primeira o callback onCreate() é chamado
• O método onStart/onStartCommand sempre é chamado
 Método stopService(Intent)
 Termina o serviço chamando onDestroy()
 Não importa quantas vezes startService() foi chamado,
uma única chamada a este encerra o serviço
35
Como e quando terminar serviços
 Método stopSelf()
 Chamar quando serviço terminar o processamento
 Boa prática para evitar consumo de bateria
 Caso queira que o serviço volte a executar de forma
automática no futuro usar AlarmManager (em breve)
36
Serviços - Exercício 24
 Crie um projeto chamado ServiceTest sem activitty
 Adicione uma classe ServiceTest que extenda Service
 Implemente onCreate() e onDestroy() escrevendo no
LogCat uma mensagem dizendo em qual deles está
 No manifest, coloque um <intent-filter> dentro de
<service> com o seguinte par action-category:
 "com.example.servicetest.SERVICE“
 "android.intent.category.DEFAULT"
 No projeto ReceiverTest, adicione as seguintes linhas
no final do método WallpaperReceiver.onReceive()
intent = new Intent("com.example.servicetest.SERVICE");
context.startService(intent);
 Instale, mude o papel de parede e olhe o LogCat
37
Serviços e threads – Exercício 25
 Ainda na classe ServiceTest
 Implemente a interface Runnable
 Crie uma thread e a inicie no onCreate()
• Ela deve incrementar um contador a cada 250 ms até 40
• Ao terminar chamar stopSelf() dentro de run()
 Instale o serviço
 No emulador, mude o papel de parede
 Olhe o LogCat e veja que, deta vez, o método
onDestroy() será chamado (em aproximadamente 10s)
38
Serviços e permissões – Exercício 26
 No manifest de ServiceTest adicione <permission>
<permission android:label="@string/service_perm_label"
android:name="com.example.servicetest.permission.SERVICE" />
 Note que android:label deve ser um recurso string
 No elemento <service>
 Remova <intent-filter>
 Adicione android:exported=“true” android:permission
<service ...
android:exported="true"
android:permission="com.example.servicetest.permission.SERVICE" >
 No manifest do projeto ReceiverTest adicione
<uses-permission
android:name="com.example.servicetest.permission.SERVICE”/>
(continua)
39
Serviços e permissões – Exercício 26
 Em WallpaperReceiver.java altera a linha que cria
intent por
intent = new Intent();
intent.setClassName("com.example.servicetest",
"com.example.servicetest.ServiceTest");
 Instale ambas as aplicações
 No emulador mude o papel de parede
 Veja pelo LogCat que o serviço foi normalmente
criado e finalizado
 Remova o elemento <uses-permission> do manifest
 Veja agora que ao mudar o papel de parede é lançado
um SecurityException
40
Uso de serviços com conexão
 Método bindService(Intent, ServiceConnection, flags)
 Associa o contexto ao serviço, ou seja, serviço é útil até
que o contexto termine ou chame unbindService()
 Se o serviço não estiver rodando e flags for igual a
BIND_AUTO_CREATE o serviço será iniciado
 Não pode ser chamado de um BroadcastReceiver
 Chama onCreate() e onBind() mas não chama
onStartCommand() nem onStart()
 Método unbindService(ServiceConnection)
 Desconecta o contexto atual do serviço
 Se não houver outras aplicações conectadas ao serviço
nem startService() tiver sido usado então o método
onDestroy() será chamado e o serviço terminado
41
Interface ServiceConnection
 É uma interface com métodos callback para notificar a
aplicação sobre conexão e desconexão do serviço
Método callback
Descrição
onServiceConnected(ComponentName, IBinder) Evento: foi estabelecida uma nova conexão ao
serviço definido pelos argumentos do método.
Ação: fazer type cast para a classe Binder do
serviço e obter sua interface.
onServiceDisconnected(ComponentName name) Evento: a conexão com o serviço foi perdido
devido a uma chamada a unbindService() ou o
término do serviço. No segundo caso, a
associação ao serviço continua ativa e caso o
serviço volte a executar o método
onServiceConnected será chamado novamente.
Ação: remover todas as referências para a
interface obtida anteriormente.
42
Classe Binder e interface IBinder
 IBinder é usada apenas como retorno de onBind() e
argumento de onServiceConnected()
 Binder é uma classe que implementa os métodos de
IBinder para simplificar a criação de binders por parte
dos serviços
 Binder deve ser usada como classe base para o binder
do serviço quando este não é remoto (em breve)
43
Serviços com conexão – Exercício 27
 No projeto ServiceTest
 Crie uma interface chamada Contador com os métodos
int get(), void set(int) e void reset()
 Crie uma nova classe nomeada ServiceBindTest
• Faça-a estender ServiceTest e implementar Contador
• Crie um classe interna chamada ContadorBinder
• Faça-a estender Binder
• Crie um método Contador getInterface() que retorna a
intância do serviço
• Crie um campo para guardar a instância de
ContadorBinder e crie o método onBind() que a retorne
• Implemente os métodos get, set e reset que alteram a
variável de contagem da classe ServiceTest
44
Serviços com conexão – Exercício 27
 Adicione um <service> para o novo serviço no
manifest
 Legal o serviço está pronto, mas como conectar-se à
interface?
 Uma activity!
 Crie uma activity chamada ServiceBinderActivity
 Pegue o arquivo de XML de layout do próximo slide
 Adicione um <activity> no manifest
 Crie um campo para guardar a interface do serviço
• Contador contador;
 Pegue o código de onCreate() dos slide seguintes
 Herde de ServiceConnection e adicione seus métodos
45
Exercício 27 – XML de layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent" >
<Button android:id="@+id/btnBind“ android:text="Conectar ao serviço"
android:layout_width="wrap_content“ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<Button android:id="@+id/btnUnbind“ android:text="Desconectar do serviço"
android:layout_width="wrap_content“ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<Button android:id="@+id/btnZerarContador“ android:text="Zerar contador"
android:layout_width="wrap_content“ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<Button android:id="@+id/btnLerContador“ android:text="Ler contador“
android:layout_width="wrap_content“ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<TextView android:id="@+id/valorContador“ android:text="0"
android:layout_width="wrap_content“ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
46
Exercício 27 - Método onCreate()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView text = (TextView) findViewById(R.id.valorContador);
Button btnBind = (Button) findViewById(R.id.btnBind);
btnBind.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// bindService
}
});
Button btnUnbind = (Button) findViewById(R.id.btnUnbind);
btnUnbind.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// unbindService
}
});
47
Exercício 27 - Método onCreate()
Button btnGet = (Button) findViewById(R.id.btnLerContador);
btnGet.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// ler contador aqui
int count = 0;
text.setText("" + count);
}
});
}
Button btnReset = (Button) findViewById(R.id.btnZerarContador);
btnReset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// zerar contador aqui
}
});
// Fim onCreate()
48
Exercício 27 – Conclusão
 Adicione códigos necessários nos callbacks onClick()




bindService(intent,ServiceBinderActivity.this,BIND_AUTO_CREATE);
unbindService(ServiceBinderActivity.this);
int count = contador.get();
contador.reset();
 Implemente os métodos de ServiceConnection
 onServiceConnected(ComponentName, IBinder service)
ContadorBinder binder = (ContadorBinder) service;
contador = binder.getInterface();
 onServiceDisconnected(ComponentName)
contador = null;
 Instale a aplicação e execute sua activity
49
Serviços remotos e AIDL
 Serviços remotos são aqueles executados em uma
aplicação diferente da que chama bindService()
 Necessário dizer ao Android qual é a interface do
serviço
 Android Interface Definition Language (AIDL)
 Criar uma interface com extensão *.aidl
 Ao criar a interface AIDL no projeto, o eclipse cria
automaticamente uma classe de mesmo nome
• Esta classe não pode ser alterada
• O serviço deve herdar da classe interna Stub e
implementar os métodos definidos pela interface AIDL
 A aplicação que se conectar ao serviço deve conhecer
apenas a interface AIDL
50
Serviços remotos - Exercício 28
 No projeto ServiceTest, crie ContadorRemoto.aidl
 O package pode ser com.example.servicetest.aidl
 Os métodos devem ser os mesmo da interface Contador
 Não é possível usar extends com AIDL
 Na classe ServiceBindTest
 Crie um classe interna que herde ContadorRemoto.Stub
• Chame-a de ContadorRemotoBinder
• Crie construtor que guarde uma instância de Contador
• Implemente os métodos de ContadorRemoto usando a
instância de Contador obtida
 Crie campo para uma instância de ContadorRemotoBinder
 No método onBind(), retorne esta instância
51
Serviços remotos – Exercício 28
 Crie um projeto chamado ActivityForRemoteService
 Copie o layout de ServiceTest para main.xml do novo
projeto
 Substitua o conteúdo da nova activity pelo existente na
ServiceBinderActivity
 Corrija os erros de nome de activity (ficam destacados)
 Faça-a implementar ServiceConnection
 Substitua o tipo do contador para ContadorRemoto
 Copie o pacote com.example.servicetest.aidl de
ServiceTest para a pasta src do novo projeto
 Adicione try...catch nas chamadas do ContadorRemoto
52
Serviços remotos – Exercício 28
 Substitua o código de onServiceConnected
void onServiceConnected(ComponentName name, IBinder service) {
contador = ContadorRemoto.Stub.asInterface(service);
}
 No manifest do projeto ServiceTest remova <intentfilter> da activity
 Instale ServiceTest novamente
 Execute ActivityForRemoteService
 Pelo LogCat pode-se ver que o resultado é igual, mas a
activity roda em uma aplicação e o serviço em outra.
 Note que este método também pode ser usado com
activity e serviço na mesma aplicação, permitindo
criação de interfaces de serviço genéricas
53
Notificações
 Mensagem que aparece na barra de status
 Permite avisar o usuário sobre
algo sem pertubá-lo
 Pode disparar uma intent
ao ser selecionada
 Motivo para usar
 Não pertubar o usuário com a
apresentação de uma Activity
 O usuário só irá abrir a activity
quando e se quiser
54
Classe NotificationManager
 Classe responsável por gerenciar notificações
 Cada notificação é identificada por um par (tag, id)
 Id é um identificador inteiro
 Tag é uma string que pode ser null
 Usar getSystemService(NOTIFICATION_SERVICE)
Método
Descrição
notify(int id, Notification)
Adiciona uma notificação à barra de status associando-a ao id
notify(tag, id, Notification)
Semelhante ao anterior, porém associa a notificação a um par
(tag, id)
cancel(id)
Cancela uma notificação, ou seja, remove da barra da status
cancel(tag, id)
Semalhante ao anterior, porém a notifacação precisa ter sido
criado com notify(tag, id, Notification)
cancelAll()
Cancela todas as notificações
55
Classe PendingIntent
 Permite definir que uma intent seja executada por
alguma aplicação no futuro
Métodos
Descrição
static PendingIntent
Retorna uma PendingIntent que iniciará uma
getActivity(Context, int requestCode, Intent, flags) activity quando for disparada.
Semelhante a startActivity(Intent)
static PendingIntent
getBroadcast(Context, requestCode, Intent, flags)
Retorna uma PendingIntent que ativará um
broadcast quando for disparada.
Semelhante a sendBroadcast(Intent)
static PendingIntent
getService(Context, int requestCode, Intent, flags)
Retorna uma PendingIntent que iniciará um
serviço quando for disparada.
Semelhante a startService(Intent)
void send()
Dispara esta PendingIntent.
FLAG_CANCEL_CURRENT
FLAG_UPDATE_CURRENT
FLAG_NO_CREATE
FLAG_ONE_SHOT
56
Classe Notification
 Representa a notificação propriamente dita
Construtor Notification(int icon,
textoBarraStatus,
long when)
Construtor que define o ícone e o texto que aparece na
barra de status durante alguns segundos. Além do instante
em que a notificação deve aparecer baseado em
System.currentTimeMillis().
Método
setLatestEventInfo
Define o conteúdo da mensagem: título, mensagem e a
(Context, titulo,
PendingIntent que será disparada caso o usuário selecione
mensagem, PendingIntent) a notificação
Campo
public int flags
Flags: FLAG_INSISTENT ou FLAG_AUTO_CANCEL
Campo
public int defaults
Define o que fazer quando a notificação aparece na barra
de status: DEFAULT_SOUND, DEFAULT_LIGHTS,
DEFAULT_VIBRATE, DEFAULT_ALL
Campo
public long [] vibrate
Define padrão de vibração: sequência de números inteiros
de definem tempo de vibração e parada
Notification.FLAG_INSISTENT
Vibração e/ou áudio contínuos
Notification.FLAG_AUTO_CANCEL
Cancela notificação quando usuário seleciona
57
Etapas para mostrar uma notificação




Criar um Intent para activity, service ou broadcast
Obter uma PendingIntent associada à intent
Criar uma instância de Notification
Configurar a notificação com setLatestEventInfo(),
flags e defaults
 Obter a intância NotificationManager (nm)
 Chamar nm.notify(...)
 Quando o usuário selecionar a notificação a intent
definida será disparada (activity, service ou broadcast)
 O alvo da intent pode cancelar a notificação se esta não
for mais necessária ou colocar FLAG_AUTO_CANCEL
no flags da notificação antes de chamar nm.notify()
58
Notificação – Exercício 29
 Criar uma aplicação que cria uma notificação
 A notificação deverá abrir uma segunda activity quando
selecionada
 Expanda o exercício para enviar parâmetros para a
segunda activity usando Intent.putExtra() ou putExtras
 Você pode usar flags e defaults (embora algumas
funcionalidades não possam ser vistas no emulador)
59
AlarmManager
 Permite agendar intents paras serem executadas
 Em um momento futuro, ou
 Em intervalos regulares
 Agendamentos são preservados enquanto dispositivo
estiver ligado (em uso ou stand-by) mas são
cancelados quando é desligado e ligado novamente ou
é reiniciado (reboot)
 Para obter a instância classe use
 AlarmManger am = (AlarmManager)getSystemService(ALARM_SERVICE)
60
Classe AlarmManager
set(int tipo, long instante, PendingIntent) Agenda um alarme para ser disparado no instante
especificado e a intent que será disparada.
setRepeating(int tipo, long instante, long
intervalo, PendingIntent)
Agenda um alarme para ser disparado no instante
especificado e o intervalo para disparos subsequentes.
cancel(PendingIntent)
Cancela um alarme previamente configurado
Tipo
Instante de tempo do alarme
Acorda o dispositivo?
ELAPSED_REALTIME
Relativo
Sim
ELAPSED_REALTIME_WAKEUP
Relativo
Não
RTC
Absoluto
Sim
RTC_WAKEUP
Absoluto
Não
Absoluto
Baseado em SystemClock.elapsedRealtime(), i.e, milissegundos desde o boot.
Relativo
Baseado em System.currentTimeMillis(), i.e, milissegundos desde 01/01/1970
Acorda
Caso o dispositivo esteja dormindo será acordado para tratar o alarme.
Não acorda
Caso o dispositivo esteja dormindo ele não será acordado e o alarme será disparado
apenas quando o dispositivo acordar normalmente.
61
AlarmManager – Exercício 30
 Criar um alarme para iniciar ServiceTest e reativá-lo a
cada 30 segundos
 Na activity WallpaperReceiver do projeto ReceiverTest
• Aproveite a intent que inicia o serviço
• Crie uma PendingIntent para serviço usando a intent
• Obtenha o AlarmManager via getSystemService()
• Chame setRepeating para agendar o alarme
 Instale a aplicação ReceiverTest
 No emulador, altere o papel de parede
 Observe o LogCat por 1 min para ver as mensagens
• O serviço reiniciará e terminará infinitamente até que o
agendamento seja cancelado ou o emulador reiniciado
62
Handler
 Threads têm filas de mensagens para comunicação
 Um Handler se associa à fila de uma thread e permite
enfileirar mensagens nesta fila
 Enfileira para execução imediata ou agendada
 Estas mensagens serão executadas na thread associada
 As mensagens podem ser enviadas de qualquer thread
 Tipos de mensagens
 java.lang.Runnable
• O método void run() será executado
 android.os.Message
• Necessário estender Handler e implementar void
handleMessage(Message) para executar a mensagem
63
Hander com Message
 Message guarda informações da mensagem
Campo
int what
O código da mensagem definido pelo usuário.
Campo
int arg1, arg2
Argumentos que podem ser definidos para não precisar definir
objetos complexos de dados.
Método
setData(Bundle)
Bundle getData()
Usado quando os parâmetros a serem passados não podem ser
representados como inteiros em arg1 e arg2.
Método
long getWhen()
Retorna o instante, em milisegundos, em que a mensagem será
entregue.
 Forma de uso
 Necessário estender Handler
 Implementar handMessage(Message), e
 Interpretar o atributo what da mensagem
64
Métodos de Handler
sendMessage(Message)
Envia mensagem para ser processada assim que possível.
sendMessageDelayed(Message,
long delay)
Envia mensagem para ser processada após o tempo indicado
ter decorrido.
sendMessageAtTime(Message,
long time)
Envia mensagem para ser processada apenas no instante de
tempo informado.
sendEmptyMessage(int what)
Cria uma mensagem apenas com o campo what preenchido e
adiciona na fila para ser processada assim que possível.
sendEmptyMessageDelayed(int what, Semelhante ao anterior mas processa mensagem apenas após
long delay)
o tempo indicado ter decorrido.
sendEmptyMessageAtTime(int what,
long time)
Semelhante ao anterior mas processa mensagem apenas no
instante informado.
post(Runnable)
Envia Runnable para ser executado assim que possível.
postDelayed(Runnable, long delay)
Envia Runnable para ser executado após o tempo indicado ter
decorrido.
postAtTime(Runnable, long time)
Envia Runnable para ser executado apenas no instante de
tempo informado.
65
Handler – Exercício 31
 Na activity do projeto ActivityForRemoteService
 Crie um campo para armazenar um handler para a
interface gráfica
Handler handler = new Handler();
 Criar uma thread que atualiza a View que mostra o
contador a cada 1000 ms
• Crie uma classe interna chamada ContadorThread que
estenda Thread.
• No método run() faça um loop que poste um Runnable
Thread.sleep(1000)
handler.post(new Runnable() { ... } )
• O Runnable deve atualizar o TextView com o valor do
contador
 Nos exemplos existe um brinde que não usa thread!
66
Persistência
 Existem 3 formas de armazenar dados no dispositivo
 Arquivos comuns (texto ou binário)
• Classes FileInputStream e FileOutputStream
• Armazenados em /data/data/<pacote>/files
 Arquivos de preferências
• Classe SharedPreferences
 Bancos de Dados usando SQLite
• Classes SQLiteDatabase, SQLiteOpenHelper
• Armazenados em /data/data/<pacote>/databases
67
Arquivos comuns
 Métodos da classe Context
FileInputStream
openFileInput(String name)
Abre um arquivo privado associado a aplicação para leitura.
Argumento name não pode conter ‘/’.
FileOutputStream
openFileOutput(String name,
int mode)
Abre um arquivo privado associado a aplicação para escrita.
Argumento mode pode ser Context.MODE_PRIVATE ou
Context.MODE_APPEND
 FileInputStream contém métodos para ler bytes
 FileOutputStream contém métodos para escrever
bytes
 InputStreamReader pode ser construído a partir de um
FileInputStream e contém métodos para ler caracteres
 OutputStreamWriter pode ser construído a partir de
um FileOuputStream e contém métodos para escrever
caracteres
68
Arquivos comuns
 Exemplo de escrita
try {
FileOutputStream fis = openFileOutput(filename, MODE_PRIVATE);
OutputStreamWriter isr = new OutputStreamWriter(fis);
isr.write("Nome: " + nome + "\n");
isr.write("email: " + email + "\n");
isr.close();
} catch (FileNotFoundException e) {
} catch (IOException e) { }
69
SharedPreferences
70
Download

intent-filter - samples-android