Comunicação e Sockets em Android
Comunicação e Sockets em Android
Como criar
esse
layout em X
ML?
<LinearLayout xmlns:android="h7p://[Link]/apk/res/
android"
android:id="@+id/root"
Layout do Cliente
android:orientaBon="ver>cal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/txtId"
android:focusable="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lblResults"/>
<LinearLayout
android:orientaBon="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/txtName"
p r e c i s ar
Vamos
android:focusable="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
a l g u m as
android:layout_weight="0.3"/> de
ts
constan
<EditText
android:id="@+id/txtGrade"
.
strings…
android:focusable="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
<Bu|on
android:id="@+id/read"
android:text="@string/read"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout> [Link]
<LinearLayout xmlns:android="h7p://[Link]/apk/res/
android"
android:id="@+id/root"
Layout do Cliente
android:orientaBon="ver>cal"
android:layout_width="fill_parent"
[Link]
android:layout_height="wrap_content">
<EditText
android:id="@+id/txtId"
android:focusable="true"
<?xml version="1.0" encoding="u}‐8"?>
android:layout_width="fill_parent" <resources>
android:layout_height="fill_parent"
android:layout_weight="1"/> <string name="app_name">Aula9</string>
<TextView
android:layout_width="fill_parent"
<string name="client_name">DaoClient</string>
android:layout_height="wrap_content"<string name="read">R</string>
android:text="@string/lblResults"/>
<LinearLayout <string name="write">W</string>
android:orientaBon="horizontal" <string name="lblResults">Nome e Nota:</string>
android:layout_width="fill_parent"
<string name="get">G</string>
android:layout_height="wrap_content">
<EditText
android:id="@+id/txtName" <string name="add">A</string>
android:focusable="true" <string name="upd">U</string>
android:layout_width="fill_parent"
android:layout_height="fill_parent" <string name="del">D</string>
android:layout_weight="0.3"/>
<EditText
<string name="cln">C</string>
android:id="@+id/txtGrade" <string name="siz">S</string>
android:focusable="true"
android:layout_width="fill_parent"</resources>
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout> E como
<Bu|on
android:id="@+id/read" implementa
android:text="@string/read" ra
android:layout_width="fill_parent" atividate?
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout> [Link]
@Override
public void onCreate(Bundle savedInstanceState) {
[Link](savedInstanceState);
setContentView([Link]);
final EditText txtId = (EditText) findViewById([Link]);
final EditText txtName = (EditText) findViewById([Link]);
final EditText txtGrade = (EditText) findViewById([Link]);
Essa ativid
((Bu|on) findViewById([Link])) ade
precisa de
.setOnClickListener(new Bu|[Link]() { p
ermissões
public void onClick(View arg0) { especiais. Q
String strId = [Link]().toString(); uais?
long id = [Link](strId);
Dao1 d = new Dao1();
Student s = [Link](id); E como
i n d icamos que
[Link]([Link]);
e s s a s permissões
[Link]([Link]([Link])); s s á r i as?
sã o n e c e
}
});
} [Link]
Agora temo
s de
[Link]
Manifesto! testar noss
atividade!
a
nte
Simplesme sse
ra e
• Note que nosso DAO olha n d o p a
é p o s s ível
código, n ã o
funciona como um sabe r q u e o ob j eto é
objeto remoto. Ele é remoto.
usado como se seus public void onClick(View arg0) {
dados esBvessem String strId = [Link]().toString();
long id = [Link](strId);
disponíveis Dao1 d = new Dao1();
localmente, ainda Student s = [Link](id);
[Link]([Link]);
que esses dados [Link]([Link]([Link]));
estejam distribuídos! }
Ligando o Servidor
• Podemos abrir uma nova instância de Eclipse,
ou simplesmente iniciar o servidor a parBr da
linha de comando:
~/workspace/server$ cd bin/
~/workspace/server/bin$ java [Link]
Waiting for connection
Agora já
podemos us
ar o
cliente!
Testando a Aplicação
Precisamos
implementa Mas o nosso
r os Existem Mas também
outros méto programa possui falhas no
dos: existem falhas
add, update várias falhas de servidor…
, no cliente!
delete. projeto! Quais?
Analisando a Camada de Comunicação
public Student get(Long key) {
Student s = null; Há um grande
Socket socket; desperdício de
ObjectOutputStream out; recursos aqui.
ObjectInputStream in;
try {
socket = new Socket("[Link]", 4444);
d e s p e rd ício
out = new ObjectOutputStream([Link]()); Que
in = new ObjectInputStream([Link]()); é esse?
[Link](new Long(key));
s = (Student) [Link]();
[Link](new Long(0L));
[Link]();
[Link]();
[Link]();
} catch (ExcepBon e) {
[Link]();
}
return s;
} server/server1/[Link]
Analisando a Camada de Comunicação
public Student get(Long key) {
Student s = null; Há um grande
Socket socket; desperdício de
ObjectOutputStream out; recursos aqui.
ObjectInputStream in;
try {
socket = new Socket("[Link]", 4444);
d e s p e rd ício
out = new ObjectOutputStream([Link]()); Que
in = new ObjectInputStream([Link]()); é esse?
[Link](new Long(key));
s = (Student) [Link](); E como reusa
r os
[Link](new Long(0L)); canais de
[Link]();
comunicação
[Link](); ?
[Link]();
} catch (ExcepBon e) { Como garantir que
[Link](); o canal aberto seja
} eventualmente
return s; fechado?
} server/server1/[Link]
O padrão Command
Esse padrão é uma
server/server2/[Link]
forma de inversão de
public interface Command { dependências.
void execute(Dao6 d); O que é isso?
}
public class Invoker {
…
Temos um “mini-
public void invoke(Dao6 d, Command c) {
arcabouço”. Vocês
openConnecBon();
lembram o que é um
arcabouço? [Link](out, in);
[Link](d);
closeConnecBon();
}
}
server/server2/[Link]
O padrão Command
server/server2/[Link]
public interface Command {
void execute(Dao6 d);
}
public class Invoker {
…
Como estão sendo public void invoke(Dao6 d, Command c) {
divididas as openConnecBon();
responsabilidades? [Link](out, in);
[Link](d);
closeConnecBon();
}
}
server/server2/[Link]
Command Como transcrever
esses elementos
para nossa
aplicação?
server/server2/[Link] O Invocador
public class Invoker {
public void invoke(Dao6 d, Command c) {...}
private void openConnecBon() {...}
private void closeConnecBon() {...}
public Invoker(String host, int port) {
[Link] = host;
[Link] = port;
} public class Invoker {
} …
public void invoke(Dao6 d, Command c) {
openConnecBon();
[Link](out, in);
[Link](d);
closeConnecBon();
}
}
O Invocador
private void openConnecBon() {
s
try { Quais os campo
socket = new Socket(host, port);
out = new ObjectOutputStream([Link]());
de objetos
in = new ObjectInputStream([Link]()); invokers?
} catch (ExcepBon e) {
[Link](); private void closeConnecBon() {
} Como seria o
try {
} [Link](new Integer(EOF));
construtor da
out.flush(); classe Invoker?
[Link]();
[Link]();
[Link]();
} catch (ExcepBon e) { public void invoke(Dao6 d, Command c) {
[Link](); openConnecBon();
} [Link](out, in);
} [Link](d);
closeConnecBon();
server/server2/[Link] }
Ainda o Invocador
public class Invoker {
private staBc final int EOF = ‐1;
private String host;
private int port;
private Socket socket = null;
Quais são as
private ObjectOutputStream out = null; es
responsabilidad
private ObjectInputStream in = null;
do DAO?
public Invoker(String host, int port) {
[Link] = host;
[Link] = port;
}
private void closeConnecBon() {}
private void openConnecBon() {}
public void invoke() {}
}
Inversão de Dependência
• Antes o DAO Bnha a responsabilidade de abrir
a conexão de rede.
– O DAO dependia da conexão de rede para
funcionar.
– Agora o DAO recebe uma conexão já aberta. A
dependência não mais existe.
– A enBdade responsável por abrir essas conexões,
o Invoker, agora depende do DAO.
– A criação e liberação de recursos já não é mais
responsabilidades dos usuários do DAO.
server/server2/[Link]
public class Dao6 implements DAO<Long, Student> {
private ObjectOutputStream out;
private ObjectInputStream in;
O Novo DAO
public void setChannels
(ObjectOutputStream out, ObjectInputStream in) {
[Link] = out;
[Link] = in;
}
public Student get(Long key) { Qual é o protocolo
Student s = null; de comunicação?
try {
[Link](new Integer([Link]));
[Link](new Long(key));
s = (Student) [Link](); Que constante é
out.flush(); essa aqui? Para
} catch (ExcepBon e) {
que ela serve?
[Link]();
}
return s;
}
}
Constantes para a Comunicação
public interface DAO<K, V> {
final int GET = 1;
final int ADD = 2; Nós já vimos a
implementação
final int DELETE = 3; desse método.
final int UPDATE = 4; Como ficam os
final int SIZE = 5; outros?
final int PORT = 4444;
final String HOST = "[Link]";
V get(K key);
void add(K key, V value);
void delete(K key);
void update(K key, V value);
int size();
} server/[Link]
server/server2/[Link]
O Novo DAO
public void add(Long key, Student value) { public void update(Long key, Student value) {
try { try {
[Link](new Integer([Link])); [Link](new Integer([Link]));
[Link](new Long(key)); [Link](new Long(key));
[Link](value); [Link](value);
out.flush(); out.flush();
} catch (ExcepBon e) { } catch (ExcepBon e) {
[Link](); [Link]();
} }
} }
public void delete(Long key) {
try {
[Link](new Integer([Link]));
[Link](new Long(key)); Como é a
out.flush(); implementação
} catch (ExcepBon e) { do protocolo no
[Link](); lado servidor?
}
}
public void run() {
try {
Integer request = (Integer) [Link]();
boolean isWorking = true;
while (isWorking) {
switch ([Link]()) {
O Servidor
case [Link]:
[Link](get((Long) [Link]()));
break; public Student get(Long key) {
case [Link]:
delete((Long) [Link]());
Student s = null;
break; if ([Link](key)) {
case [Link]:
update((Long) [Link](), (Student)[Link]());
s = [Link](key);
break; } else {
case [Link]:
add((Long) [Link](), (Student)[Link]()); s = new Student(‐1, "", 0.0);
break; }
default:
isWorking = false; return s;
}
return; }
request = (Integer) [Link]();
}
[Link](); private Socket socket = null;
[Link](); Fecho, mas
[Link](); onde abro?
private Map<Long, Student> students;
} catch (ExcepBon e) {
[Link]();
private ObjectOutputStream out;
} private ObjectInputStream in;
}
server/server2/[Link]
public void run() {
try {
Integer request = (Integer) [Link]();
boolean isWorking = true;
while (isWorking) {
switch ([Link]()) {
O Servidor
case [Link]:
[Link](get((Long) [Link]()));
break; Temos, é claro,
case [Link]:
delete((Long) [Link]()); outros métodos
break; para
case [Link]:
update((Long) [Link](), (Student)[Link]()); implementar…
break;
case [Link]:
add((Long) [Link](), (Student)[Link]());
break;
default:
isWorking = false; public StudentHandlerThread(Socket socket, Map<Long, Student> students) {
return; [Link]("Got conecBon!");
} [Link] = socket;
request = (Integer) [Link](); [Link] = students;
} try {
[Link](); out = new ObjectOutputStream([Link]());
[Link](); in = new ObjectInputStream([Link]());
[Link](); } catch (ExcepBon e) {
} catch (ExcepBon e) { [Link]();
[Link](); }
} }
}
server/server2/[Link]
O Servidor
public void add(Long key, Student value) {
[Link](key, value);
} gora,
Prcisamos, a
vo
escrever o no
public void update(Long key, Student value) { cliente.
add(key, value);
} Temos quatro
eventos para tratar.
public void delete(Long key) { Quais são eles?
[Link](key);
} E como seria o
layout do novo
programa?
server/server2/[Link]
Quatro Botões
m
Como fazer u
?
layout assim
Quantos layouts
lineares temos aqu
i?
E como seria a
e?
atividade client
s
Quantos evento
precisam ser
tratados?
Layout
<LinearLayout xmlns:android= <LinearLayout
"h|p://[Link]/apk/res/android" android:orientaBon="horizontal"
android:id="@+id/root" android:layout_width="fill_parent"
android:orientaBon="verBcal" android:layout_height="wrap_content">
android:layout_width="fill_parent" <Bu|on
android:layout_height="wrap_content"> android:id="@+id/get"
<EditText android:text="@string/get"
android:id="@+id/txtId" android:layout_width="fill_parent"
android:focusable="true" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_weight="1"/>
android:layout_height="fill_parent" <Bu|on
android:layout_weight="1"/> android:id="@+id/add"
<TextView android:text="@string/add"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:text="@string/lblResults"/> android:layout_weight="1"/>
<LinearLayout <Bu|on
android:orientaBon="horizontal" android:id="@+id/del"
android:layout_width="fill_parent" android:text="@string/del"
android:layout_height="wrap_content"> android:layout_width="fill_parent"
<EditText android:layout_height="fill_parent"
android:id="@+id/txtName" android:layout_weight="1"/>
android:focusable="true" <Bu|on
android:layout_width="fill_parent" android:id="@+id/upd"
Escreva agora a
android:layout_height="fill_parent" android:text="@string/upd"
android:layout_weight="0.3"/> android:layout_width="fill_parent"
<EditText android:layout_height="fill_parent"
atividade.
android:layout_weight="1"/> android:layout_width="fill_parent"
</LinearLayout> android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
[Link] </LinearLayout>
@Override
public void onCreate(Bundle savedInstanceState) {
[Link](savedInstanceState);
setContentView([Link]);
onCreate
txtId = (EditText) findViewById([Link]);
txtName = (EditText) findViewById([Link]);
txtGrade = (EditText) findViewById([Link]);
((Bu|on) findViewById([Link]))
.setOnClickListener(new Bu|[Link]() {
public void onClick(View arg0) {
[Link](""); Precimos
[Link](""); implementar todos
[Link](""); esses eventos!
}
});
} [Link]
class UpdCmd implements Command, Bu|[Link] {
public void onClick(View arg0) {
Invoker i = new Invoker([Link], [Link]);
Dao6 d = new Dao6();
Já podemos
[Link](d, this); testar nossa
} aplicação!
public void execute(Dao6 d) {
long id = [Link]([Link]().toString());
String name = [Link]().toString();
double grade = [Link]([Link]().toString());
Student std = new Student(id, name, grade);
[Link](id, std);
class GetCmd implements Command, Bu|[Link] {
}
public void onClick(View arg0) {
}
Invoker i = new Invoker([Link], [Link]);
s s a a l t e r n a t iva é Dao6 d = new Dao6();
E
i t o r e d u n d a nte. [Link](d, this);
mu }
public void execute(Dao6 d) {
String strId = [Link]().toString();
Como fatora long id = [Link](strId);
r Student s = [Link](id);
onClick(…)
? [Link]([Link]);
[Link]([Link]([Link])); }
}
[Link]
Classes Abstratas
abstract class AbstractCommand implements
Command, Bu|[Link] { s t r a ta dores
To d o s o
e e v e n t o v ã o usar
d
public abstract void execute(Dao6 d); m é t o d o o n Click
esse
public void onClick(View arg0) {
Invoker i = new Invoker([Link], [Link]);
Dao6 d = new Dao6();
[Link](d, this); Eles terão somente
} Como seria o de implementar o
} tratador do e método execute.
vento
de adição de
novo
dado?
[Link]
AddCmd
class AddCmd extends AbstractCommand implements Command {
cliente.
Exercício: Size
• Adicione um botão size à interface do cliente.
Quando esse botão receber um clique, o
número de elementos armazenados no banco
de dados deverá ser impresso na caixa de
texto em que são
impressas as notas: