Broadcasts

Propaganda
Programação
para
a
Plataforma
Android
–
Aula
17
Broadcasts
•  O
que
são
eventos
de
difusão?
•  Como
capturar
eventos
de
chamadas
telefônicas?
•  Como
verificar
o
estado
da
bateria?
•  Como
implementar
receptores
de
eventos
de
difusão?
•  O
que
são
intenções
assíncronas?
•  O
que
são
intenções
pendentes?
Intenções
de
Difusão
•  Intenções
de
Broadcast
são
entregues
para
todos
os
receptores
de
broadcast
registrados
no
disposiGvo
Android.
–  Por
exemplo,
quando
uma
chamada
é
recebida,
todos
os
receptores
desse
Gpo
de
evento
serão
acordados
para
tratá‐lo.
Qual a diferenç
a
entre receptore
s de
broadcast e
provedores de
serviço?
Exemplos
de
Broadcast
•  ACTION_BATTERY_LOW:
um
aviso
que
a
bateria
está
quase
descarregada.
•  ACTION_HEADSET_PLUG:
um
fone
de
ouvido
foi
conectado
(ou
desconectado).
•  ACTION_SCREEN_ON:
a
tela
foi
ligada.
•  ACTION_TIMEZONE_CHANGED:
o
aparelho
passou
de
um
fuso
para
outro.
Recebendo
Chamadas
•  Chamadas
telefônicas
são
capturadas
como
eventos
de
difusão
(broadcast).
Lendo números:
Escreva uma aplicação
que leia o número
recebido em uma
chamada, e o imprima
na tela de log.
MyPhoneReceiver
public
class
MyPhoneReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Bundle
extras
=
intent.getExtras();
if
(extras
!=
null)
{
String
state
=
extras.getString(TelephonyManager.EXTRA_STATE);
Log.w("DEBUG",
state);
if
(state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
String
phoneNumber
=
extras
.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.w("DEBUG",
phoneNumber);
}
}
}
}
MyPhoneReceiver.java
Broadcast
Receivers
não
são
aGvidades
•  Para
usarmos
nosso
receptor,
precisamos
implementar
uma
aGvidade.
–  Toda
aplicação
possui
uma
aGvidade.
a
Existe algum
o
relação entre
receptor de
intenções, e
e?
essa atividad
public
class
MainAcGvity
extends
AcGvity
{
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
Como "lig
amos"
setContentView(R.layout.acGvity_main);
o recepto
r de
}
eventos
de
}
difusã
MainAcGvity.java
o?
O
Manifesto
<applicaGon
AndroidManifest.xml
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
Como simular a
android:theme="@style/AppTheme"
>
recepção de
<acGvity
uma chamada?
android:name=".MainAcGvity"
android:label="@string/Gtle_acGvity_main"
>
<intent‐filter>
<acGon
android:name="android.intent.acGon.MAIN"
/>
<category
android:name="android.intent.category.LAUNCHER"
/>
</intent‐filter>
</acGvity>
<receiver
android:name=".MyPhoneReceiver"
>
<intent‐filter>
<ac=on
android:name="android.intent.ac=on.PHONE_STATE"
>
</ac=on>
</intent‐filter>
</receiver>
</applicaGon>
<uses‐permission
android:name="android.permission.READ_PHONE_STATE"
/>
Controle
de
Emulação
•  O
plugin
Android
para
Eclipse
provê
uma
interface
para
a
emissão
de
sinais
ao
emulador.
Estados
de
uma
Chamada
public
class
MyPhoneReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Bundle
extras
=
intent.getExtras();
if
(extras
!=
null)
{
String
state
=
extras.getString(TelephonyManager.EXTRA_STATE);
Log.w("DEBUG",
state);
if
(state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
String
phoneNumber
=
extras
.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.w("DEBUG",
phoneNumber);
}
}
}
}
Encontrando
seu
Número
public
class
MainAcGvity
extends
AcGvity
{
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
TelephonyManager
tm
=
(TelephonyManager)
getSystemService(TELEPHONY_SERVICE);
String
phonenumber
=
tm.getLine1Number();
Log.v("Phone_data",
phonenumber
==
null
?
"No
number"
:
phonenumber);
}
}
MainAcGvity.java
Encontrando
Informações
de
Operador
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
TelephonyManager
tm
=
(TelephonyManager)
getSystemService(TELEPHONY_SERVICE);
String
phonenumber
=
tm.getLine1Number();
Log.v("Phone_data",
phonenumber);
String
operatorname
=
tm.getNetworkOperatorName();
Log.v("Phone_data",
operatorname);
String
operatorcode
=
tm.getNetworkOperator();
Log.v("Phone_data",
operatorcode);
String
operatoriso
=
tm.getNetworkCountryIso();
Log.v("Phone_data",
operatoriso);
}
Disparando
Eventos
de
Difusão
•  Além
de
receber
intenções
de
difusão,
o
usuário
pode
também
disparar
esse
Gpo
de
intenção.
•  URIs
são
usados
para
qualificar
essas
intenções.
Difundindo eventos:
Defina um evento de
difusão "br.com.dcc052.
aula17" e implemente
um receptor que o
capture.
Registrando
a
Intenção
no
Manifesto
<applicaGon
android:icon="@drawable/ic_launcher"
Para que serve
android:label="@string/app_name"
essa declaração?
android:theme="@style/AppTheme"
>
<acGvity
android:name=".MainAcGvity"
O que é
android:label="@string/Gtle_acGvity_main"
>
esse
<intent‐filter>
nome?
<acGon
android:name="android.intent.acGon.MAIN"
/>
<category
android:name="android.intent.category.LAUNCHER"
/>
</intent‐filter>
</acGvity>
Como uma
<receiver
android:name=".MyBroadcastReceiver"
>
intenção do
<intent‐filter>
tipo "br.com.
<ac=on
android:name="br.com.dcc052.aula17"
/>
dcc052.aula17"
</intent‐filter>
Poderia ser
</receiver>
disparada?
</applicaGon>
AndroidManifest.xml
Difundindo
uma
Intenção
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
Intent
intent
=
new
Intent();
intent.setAc=on("br.com.dcc052.aula17");
sendBroadcast(intent);
}
O que está
faltando
implementar?
Definindo
um
Receptor
MyBroadcastReceiver.java
public
class
MyBroadcastReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Log.v("MyReceiver",
intent.toString());
}
}
O que deverá ser
impresso?
Definindo
um
Receptor
MyBroadcastReceiver.java
public
class
MyBroadcastReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Log.v("MyReceiver",
intent.toString());
Como pa
}
ssa
r
dados pa
ra o
receptor
?
}
MyReceiver1
Intent { act=br.com.dcc052.aula17
flg=0x10
cmp=com.dcc052.aula17/.MyBroadcastReceiver
(has extras) }
Comunicando
Dados
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
Será que é possível
Intent
intent
=
new
Intent();
termos mais de um
intent.setAcGon("br.com.dcc052.aula17");
receptor para a
intent.putExtra("Arg1",
"Oi");
mesma intenção
sendBroadcast(intent);
difundida?
}
MyBroadcastReceiver.java
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
String
arg
=
intent.getStringExtra("Arg1");
Log.v("MyReceiver0",
arg);
}
MúlGplos
Receptores
•  Podemos
registrar
vários
receptores
para
uma
mesma
intenção
difundida.
•  Cada
receptor
deve
ser
registrado
no
manifesto
da
aplicação.
AndroidManifest.xml
<receiver
android:name=".MyBroadcastReceiver0"
>
<intent‐filter>
<acGon
android:name="br.com.dcc052.aula17"
/>
O que mais
</intent‐filter>
precisa ser
</receiver>
implementado?
<receiver
android:name=".MyBroadcastReceiver1"
>
<intent‐filter>
<acGon
android:name="br.com.dcc052.aula17"
/>
</intent‐filter>
</receiver>
MúlGplos
Receptores
public
class
MyBroadcastReceiver1
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Log.v("Receiver1",
intent.toString());
}
}
MyBroadcastReceiver0.java
MyBroadcastReceiver1.java
public
class
MyBroadcastReceiver0
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
String
arg
=
intent.getStringExtra("Arg1");
Log.v("Receiver0",
arg);
}
}
Intenções
Assíncronas
•  Algumas
intenções,
chamadas
assíncronas
(s3cky)
não
desaparecem
tão
logo
são
lançadas.
•  É
possível
consultar
a
úlGma
instância
de
uma
intenção
desse
Gpo.
•  Os
eventos
de
bateria
são
anunciados
via
intenções
assíncronas.
Escreva uma
atividade que
determine o estado da
bateria do dispositivo.
Lendo
o
Estado
da
Bateria
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
IntentFilter
filter
=
new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent
baveryStatus
=
this.registerReceiver(null,
filter);
int
status
=
baveryStatus.getIntExtra(BaveryManager.EXTRA_STATUS,
‐1);
boolean
isCharging
=
status
==
BaveryManager.BATTERY_STATUS_CHARGING;
Log.v("Bavery",
"Estah
carregando?
"
+
isCharging);
boolean
isFull
=
status
==
BaveryManager.BATTERY_STATUS_FULL;
Log.v("Bavery",
"Estah
carregado?
"
+
isFull);
int
chargePlug
=
baveryStatus.getIntExtra(BaveryManager.EXTRA_PLUGGED,
‐1);
boolean
usbCharge
=
chargePlug
==
BaveryManager.BATTERY_PLUGGED_USB;
Log.v("Bavery",
"Estah
carregando
via
USB?
"
+
usbCharge);
boolean
acCharge
=
chargePlug
==
BaveryManager.BATTERY_PLUGGED_AC;
Log.v("Bavery",
"Estah
carregando
via
tomada?
"
+
acCharge);
}
Lendo
o
Estado
da
Bateria
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
IntentFilter
filter
=
new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent
baveryStatus
=
this.registerReceiver(null,
filter);
int
status
=
baveryStatus.getIntExtra(BaveryManager.EXTRA_STATUS,
‐1);
boolean
isCharging
=
status
==
BaveryManager.BATTERY_STATUS_CHARGING;
Qual argumento
E porque estamos
Log.v("Bavery",
"Estah
carregando?
"
+
isCharging);
é esperado
passando o objeto
boolean
isFull
=
status
==
BaveryManager.BATTERY_STATUS_FULL;
nessa posição?
nulo aqui?
Log.v("Bavery",
"Estah
carregado?
"
+
isFull);
int
chargePlug
=
baveryStatus.getIntExtra(BaveryManager.EXTRA_PLUGGED,
‐1);
boolean
usbCharge
=
chargePlug
==
BaveryManager.BATTERY_PLUGGED_USB;
Log.v("Bavery",
"Estah
carregando
via
USB?
"
+
usbCharge);
boolean
acCharge
=
chargePlug
==
BaveryManager.BATTERY_PLUGGED_AC;
Log.v("Bavery",
"Estah
carregando
via
tomada?
"
+
acCharge);
}
Lendo
o
Estado
da
Bateria
MainAcGvity.java
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
Como saber a
super.onCreate(savedInstanceState);
Que informações
quantidade de
setContentView(R.layout.acGvity_main);
serão
energia que resta
IntentFilter
filter
=
new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
impressas?
na bateria?
Intent
baveryStatus
=
this.registerReceiver(null,
filter);
int
status
=
baveryStatus.getIntExtra(BaveryManager.EXTRA_STATUS,
‐1);
boolean
isCharging
=
status
==
Ba\eryManager.BATTERY_STATUS_CHARGING;
Log.v("Ba\ery",
"Estah
carregando?
"
+
isCharging);
boolean
isFull
=
status
==
Ba\eryManager.BATTERY_STATUS_FULL;
Log.v("Ba\ery",
"Estah
carregado?
"
+
isFull);
int
chargePlug
=
ba\eryStatus.getIntExtra(Ba\eryManager.EXTRA_PLUGGED,
‐1);
boolean
usbCharge
=
chargePlug
==
Ba\eryManager.BATTERY_PLUGGED_USB;
Log.v("Ba\ery",
"Estah
carregando
via
USB?
"
+
usbCharge);
boolean
acCharge
=
chargePlug
==
Ba\eryManager.BATTERY_PLUGGED_AC;
Log.v("Ba\ery",
"Estah
carregando
via
tomada?
"
+
acCharge);
}
Energia
Restante
MainAcGvity.java
@Override
Explique
public
void
onCreate(Bundle
savedInstanceState)
{
essa conta…
super.onCreate(savedInstanceState);
setContentView(R.layout.acGvity_main);
IntentFilter
filter
=
new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent
baveryStatus
=
this.registerReceiver(null,
filter);
...
int
level
=
ba\eryStatus.getIntExtra(Ba\eryManager.EXTRA_LEVEL,
‐1);
int
scale
=
ba\eryStatus.getIntExtra(Ba\eryManager.EXTRA_SCALE,
‐1);
float
ba\eryPct
=
level
/
(float)
scale;
Log.v("Ba\ery",
"Level
=
"
+
ba\eryPct);
}
Intenções
Pendentes
•  É
possível
programar
intenções
para
acontecer
em
algum
momento
no
futuro.
–  Esse
Gpo
de
intenção
chama‐
se
intenção
pendente.
•  Existe
um
controlador
de
eventos
futuros,
AlarmManager,
que
pode
ser
usado
para
disparar
intenções
pendentes.
Definindo um alarme:
Crie uma atividade que
leia uma quantidade
de segundos X, e
programe uma
intenção para X
segundos no futuro.
alarm.xml
Definindo
um
Layout
<?xml
version="1.0"
encoding="u<‐8"?>
<LinearLayout
xmlns:android="hBp://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientaGon="ver3cal"
>
<EditText
android:id="@+id/3me"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:focusable="true"
android:inputType="numberDecimal"
>
</EditText>
<Buvon
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="startAlert"
android:text="@string/alarm_buBon_label"
>
</Buvon>
</LinearLayout>
Precisamos
definir um
receptor para a
intenção futura.
Recebendo
Intenções
de
Alarme
MyAlarmReceiver.java
O que esse
código está
buscando?
public
class
MyAlarmReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Toast.makeText(context,
context.getString(R.string.alarm_fired_message),
Toast.LENGTH_LONG).show();
Vibrator
vibrator
=
(Vibrator)
context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
}
Para que
}
serve essa
classe?
Para vibrar
é preciso
permissão.
Permissão
para
Vibrar
MyAlarmReceiver.java
Como a
intenção
será
disparada?
public
class
MyAlarmReceiver
extends
BroadcastReceiver
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
Toast.makeText(context,
context.getString(R.string.alarm_fired_message),
Toast.LENGTH_LONG).show();
Vibrator
vibrator
=
(Vibrator)
context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
}
}
AndroidManifest.xml
<uses‐permission
android:name="android.permission.VIBRATE"
/>
…
<receiver
android:name=".MyAlarmReceiver"
/>
Criando
uma
Intenção
Pendente
public
class
AlarmAcGvity
extends
AcGvity
{
Grande mistério:
@Override
como/quando o
public
void
onCreate(Bundle
savedInstanceState)
{
método
super.onCreate(savedInstanceState);
startAlert é
setContentView(R.layout.alarm);
chamado?
}
public
void
startAlert(View
view)
{
EditText
text
=
(EditText)
findViewById(R.id.Gme);
int
i
=
Integer.parseInt(text.getText().toString());
Intent
intent
=
new
Intent(this,
MyAlarmReceiver.class);
PendingIntent
pendingIntent
=
PendingIntent.getBroadcast(this.getApplicaGonContext(),
234324243,
intent,
0);
AlarmManager
alarmManager
=
(AlarmManager)
getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis()
+
(i
*
1000),
pendingIntent);
Toast.makeText(this,
i
+
getString(R.string.alarm_started_message),
Lembra de
Toast.LENGTH_LONG).show();
registrar a
}
intenção no
}
manifesto
AlarmAcGvity.java
Mais
Manifesto
<acGvity
android:name=".AlarmAcGvity"
android:label="@string/Gtle_acGvity_main"
>
<intent‐filter>
<acGon
android:name="android.intent.acGon.MAIN"
/>
<category
android:name="android.intent.category.LAUNCHER"
/>
</intent‐filter>
</acGvity>
AndroidManifest.xml
Amarração
entre
XML
e
Java
<Buvon
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="startAlert"
android:text="@string/alarm_buvon_label"
>
</Buvon>
Como se dá a
amarração entre
Java e XML
nesse exemplo?
alarm.xml
AlarmAcGvity.java
public
class
AlarmAcGvity
extends
AcGvity
{
@Override
public
void
onCreate(Bundle
savedInstanceState)
{...}
public
void
startAlert(View
view)
{...}
}
A
Ordem
dos
Eventos
public
class
AlarmAcGvity
extends
AcGvity
{
* O que acontecerá
@Override
tão logo o usuário
public
void
onCreate(Bundle
savedInstanceState)
{
clique no botão?
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
* Qual a ordem dos
}
eventos?
public
void
startAlert(View
view)
{
EditText
text
=
(EditText)
findViewById(R.id.Gme);
int
i
=
Integer.parseInt(text.getText().toString());
Intent
intent
=
new
Intent(this,
MyAlarmReceiver.class);
PendingIntent
pendingIntent
=
PendingIntent.getBroadcast(this.getApplicaGonContext(),
234324243,
intent,
0);
AlarmManager
alarmManager
=
(AlarmManager)
getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis()
+
(i
*
1000),
pendingIntent);
Toast.makeText(this,
i
+
getString(R.string.alarm_started_message),
Toast.LENGTH_LONG).show();
}
}
AlarmAcGvity.java
A
Ordem
dos
Eventos
public
class
AlarmAcGvity
extends
AcGvity
{
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
}
public
void
startAlert(View
view)
{
EditText
text
=
(EditText)
findViewById(R.id.Gme);
int
i
=
Integer.parseInt(text.getText().toString());
Intent
intent
=
new
Intent(this,
MyAlarmReceiver.class);
PendingIntent
pendingIntent
=
PendingIntent.getBroadcast(this.getApplicaGonContext(),
234324243,
intent,
0);
AlarmManager
alarmManager
=
(AlarmManager)
getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis()
+
(i
*
1000),
pendingIntent);
Toast.makeText(this,
i
+
getString(R.string.alarm_started_message),
Toast.LENGTH_LONG).show();
}
}
AlarmAcGvity.java
strings.xml
strings.xml
<resources>
<string
name="app_name">Aula17</string>
<string
name="Gtle_acGvity_main">MainAcGvity</string>
<string
name="main_acGvity_label">AGvidade
Principal</string>
<string
name="alarm_buvon_label">Iniciar</string>
<string
name="alarm_fired_message">Hora
de
acordar!</string>
<string
name="alarm_started_message">
segundos
para
alarme
disparar.</string>
</resources>

Download