4.2 Implementa¸ c˜ ao do ComuniCAR
4.2.2 Implementa¸ c˜ ao da Camada de Interfaces de Desenvol- Desenvol-vimentoDesenvol-vimento
A implementa¸c˜ao da camada de Interfaces de Desenvolvimento implicou a cria¸c˜ao de fun¸c˜oes de mais alto n´ıvel, levando em conta as fun¸c˜oes dispon´ıveis atrav´es da API do Android.
Figura 4.2: Diagrama de classe da biblioteca.
Servi¸co de localiza¸c˜ao
Normalmente, a maioria dos dispositivos Android permitem determinar a sua localiza¸c˜ao geogr´afica atual. Isto pode ser realizado atrav´es da utiliza¸c˜ao de um m´odulo GPS, normalmente interno, rede GSM ou atrav´es de redes Wi-Fi [2].
O Google Play Services facilita a conex˜ao com os servi¸cos do Google, al´em de v´arias API’s como localiza¸c˜ao, Google Fit, Google+. GoogleDrive, Games, entre outros [2]. A API de localiza¸c˜ao que foi utilizada nesta disserta¸c˜ao ´e conhecida comoFused Location Provider. O Google Play Services precisou ser declarado como dependˆencia no projeto localizado no ficheiro AndroidManifest.xml.
C´odigo 1. Trecho de c´odigo para declara¸c˜ao de dependˆencias no projeto
1 d e p e n d e n c i e s {
2 c o m p i l e ’ com . g o o g l e . a n d r o i d . g m s : p l a y−s e r v i c e s : 8 . 4 . 0 ’
3 }
Foi desenvolvida uma classe chamada de Sensors que ´e respons´avel por facili-tar o desenvolvimento de uma aplica¸c˜ao que necessita dos dados de localiza¸c˜ao do GPS em tempo real. Abaixo, segue a explica¸c˜ao de todos os m´etodos que foram implementados nesta classe.
Para utilizar qualquer uma das API’s gerenciadas pelo Google Play Services, foi necess´ario se conectar aos servi¸cos do Google. A classe respons´avel por fazer esta conex˜ao ´e aGoogleApiClient, que encapsula toda a comunica¸c˜ao com os servidores do Google. O C´odigo 2 apresenta o m´etodovoid callConnection() que foi implementado para construir um objeto do tipoGoogleApiClient.
C´odigo 2. Trecho de c´odigo utilizado para conectar com os servidores do Google
1
2 p u b l i c G o o g l e A p i C l i e n t m G oo g l e Ap i C l ie n t ;
3
4 p r o t e c t e d s y n c h r o n i z e d v o i d c a l l C o n n e c t i o n ( ) {
5 Log . i (”LOG”, ” c a l l C o n n e c t i o n ( ) ”) ;
6 m G o og l e A pi C l i en t = new G o o g l e A p i C l i e n t . B u i l d e r ( m A c t i v i t y )
7 . a d d O n C o n n e c t i o n F a i l e d L i s t e n e r (t h i s)
8 . a d d C o n n e c t i o n C a l l b a c k s (t h i s)
9 . addApi ( L o c a t i o n S e r v i c e s . API )
10 . b u i l d ( ) ;
11 }
Depois de construir o objeto GoogleApiClient no m´etodo callConnection(), o m´etodoonCreate()daActivity ´e respons´avel por chamar o m´etodocallConnection().
C´odigo 3. Trecho de c´odigo que invoca o m´etodo callConnection()
1 p u b l i c v o i d o n C r e a t e ( ) {
2 c a l l C o n n e c t i o n ( ) ;
3 }
Depois dessa etapa, foi chamado o m´etodo GoogleApiClient.connect() que ´e res-pons´avel para realizar a conex˜ao no m´etodo onStart() e onRestart() da activity e fechar a conex˜ao no m´etodo onStop(), conforme demonstrado no C´odigo 4.
C´odigo 4. Trecho de c´odigo que invoca o m´etodo GoogleApiClient.connect()
1 p u b l i c v o i d o n S t a r t ( ) {
2 m G o og l e A pi C l i en t . c o n n e c t ( ) ;
3 }
4
5 p u b l i c v o i d o n R e s t a r t ( ) {
6 m G o og l e A pi C l i en t . c o n n e c t ( ) ;
7 }
8
9 p u b l i c v o i d onStop ( ) {
10 s t o p L o c a t i o n U p d a t e ( ) ;
11 m G o og l e A pi C l i en t . d i s c o n n e c t ( ) ;
12 }
Para receber o resultado da conex˜ao, sendo com sucesso ou falha, foi implemen-tado os m´etodos das interfacesConnectionCallbacks eOnConnectionFailedListener.
C´odigo 5. M´etodos da ConnectionCallbacks e OnConnectionFailedListener
1 p u b l i c v o i d onConnected ( Bundle b u n d l e ) {
2 // Conectado ao Google Play S e r v i c e s !
3 // Pode u t i l i z a r q u a l q u e r API a g o r a .
4 s t a r t L o c a t i o n U p d a t e ( ) ; // I n i c i a o GPS
5 }
6
7 p u b l i c v o i d o n C o n n e c t i o n S u s p e n d e d ( i n t i ) {
8 // A c o n e x a o f o i i n t e r r o m p i d a .
9 // A a p l i c a c a o p r e c i s a a g u a r d a r a t e a c o n e x a o s e r r e s t a b e l e c i d a
10 Toast . makeText ( m A c t i v i t y . g e t A p p l i c a t i o n C o n t e x t ( ) , ” Conexao i n t e r r o m p i d a ! ”, Toast .LENGTH SHORT) . show ( ) ;
11 }
12
13 p u b l i c v o i d o n C o n n e c t i o n F a i l e d ( C o n n e c t i o n R e s u l t c o n n e c t i o n R e s u l t ) {
14 // Erro na c o n e x a o .
15 // Pode s e r uma c o n f i g u r a c a o i n v a l i d a ou f a l t a de c o n e c t i v i d a d e no d i s p o s i t i v o .
16 Toast . makeText ( m A c t i v i t y . g e t A p p l i c a t i o n C o n t e x t ( ) , ” Erro ao c o n e c t a r : ” + c o n n e c t i o n R e s u l t , Toast .LENGTH SHORT) . show ( ) ;
17 }
Depois que a aplica¸c˜ao est´a conectada aos servi¸cos do Google, foi implementado o m´etodo startLocationUpdate(). Este m´etodo foi criado para configurar e iniciar o GPS. Neste m´etodo foi criado um ojeto LocationRequest, que cont´em as confi-gura¸c˜oes referentes a precis˜ao e ao intervalo de tempo com que o utilizador deseja receber as coordenadas. O m´etodo setPriority(int) define a precis˜ao do GPS. As constantes mais utilizadas s˜aoPRIORITY HIGH ACCURACY ePRIORITY LOW POWER. A primeira tem como objetivo retornar a localiza¸c˜ao mais precisa poss´ıvel.
A segunda visa obter uma localiza¸c˜ao aproximada a fim de economizar a bateria.
O m´etodo setInterval(long) recebe o intervalo de tempo em milissegundos em que a aplica¸c˜ao deseja receber atualiza¸c˜oes do GPS. O m´etodo setFastestInterval(long) recebe o intervalo m´ınimo no qual a aplica¸c˜ao consegue receber e tratar os eventos corretamente, sem afetar a performance da aplica¸c˜ao. Outro m´etodo importante ´e OFusedLocationApi que foi utilizado para recuperar a ´ultima localiza¸c˜ao conhecida
pelo sistema.
C´odigo 6. Implementa¸c˜ao do m´etodo startLocationUpdate()
1 p r o t e c t e d v o i d s t a r t L o c a t i o n U p d a t e ( ) {
2 mLocationRequest = new L o c a t i o n R e q u e s t ( ) ;
3 mLocationRequest . s e t I n t e r v a l ( 0 ) ;
4 mLocationRequest . s e t F a s t e s t I n t e r v a l ( 0 ) ;
5 mLocationRequest . s e t P r i o r i t y ( L o c a t i o n R e q u e s t . PRIORITY HIGH ACCURACY) ;
6 // r e g i o n f o o
7 i f ( ActivityCompat . c h e c k S e l f P e r m i s s i o n ( m A c t i v i t y , M a n i f e s t . p e r m i s s i o n . ACCESS FINE LOCATION)
8 != PackageManager . PERMISSION GRANTED &&
9 ActivityCompat . c h e c k S e l f P e r m i s s i o n ( m A c t i v i t y , M a n i f e s t . p e r m i s s i o n . ACCESS COARSE LOCATION)
10 != PackageManager . PERMISSION GRANTED) {
11 r e t u r n ;
12 }
13 L o c a t i o n S e r v i c e s . F u s e d L o c a t i o n A p i . r e q u e s t L o c a t i o n U p d a t e s ( mGoogleApiClient , mLocationRequest , S e n s o r e s . t h i s ) ;
14 }
O c´odigo 7 abaixo apresenta o m´etodo stopLocationUpdate() que ´e respons´avel por parar o GPS.
C´odigo 7. Implementa¸c˜ao do m´etodo stopLocationUpdate()
1 p r o t e c t e d v o i d s t o p L o c a t i o n U p d a t e ( ){
2 L o c a t i o n S e r v i c e s . F u s e d L o c a t i o n A p i . r e m o v e L o c a t i o n U p d a t e s ( mGoogleApiClient , S e n s o r e s . t h i s ) ;
3 }
Segundo Lecheta[2], o momento correto de iniciar o GPS ´e logo depois de a conex˜ao com o Google Play Services ´e realizada, portanto isso deve ser feito no m´etodo onConnected() citado anteriormente.
Para parar o GPS, pode-se utilizar os m´etodos do ciclo de vida daactivity, como oonPause() ou onStop().
C´odigo 8. Implementa¸c˜ao dos m´etodos onPause() e onStop()
1 p u b l i c v o i d onPause ( ) {
2 i f ( m G o og l e A pi C l i en t != n u l l ) {
3 s t o p L o c a t i o n U p d a t e ( ) ; // Para o GPS
4 }
5 }
6
7 p u b l i c v o i d onStop ( ) {
8 s t o p L o c a t i o n U p d a t e ( ) ; // Para o GPS
9 m G o og l e A pi C l i en t . d i s c o n n e c t ( ) ; // Desconexao da API
10 }
Foi implementado tamb´em o m´etodo onLocationChanged(location) que ´e res-pons´avel por receber as localiza¸c˜oes provenientes do GPS. Sempre que o Android tiver uma nova localiza¸c˜ao, este m´etodo ser´a invocado passando como parˆametro um objetoandroid.location.Location. Este m´etodo pertence a interfaceLocationListener e est´a representado no C´odigo 9.
C´odigo 9. Implementa¸c˜ao do m´etodo onLocationChanged(location)()
1 p u b l i c v o i d onLocationChanged ( L o c a t i o n l o c a t i o n ) {
2 mLocation = l o c a t i o n ;
3 i f ( m I n t e r f a c e != n u l l )
4 m I n t e r f a c e . seekingGPSData ( l o c a t i o n ) ;
5 }
Uma localiza¸c˜ao pode ser constitu´ıda pela latitude, longitude, data e hora, e outras informa¸c˜oes tais como altitude e velocidade. Para obter esses dados foi ne-cess´ario utilizar `a classe Location que ´e uma classe de dados que representa uma localiza¸c˜ao geogr´afica [14]. Esta classe possui alguns m´etodos como:
• getAccuracy() - Devolve a precis˜ao estimada de localiza¸c˜ao, em metros.
• getLatitude() - Devolve a Latitude, em graus.
• getLatitude() - Devolve a Longitude, em graus.
• getAltitude() - Devolve a altitude, em metros.
• getBearing() - Devolve a dire¸c˜ao (sentido) do dispositivo, em graus.
• getSpeed() - Velocidade em metros por segundo;
• getTime() - Tempo Universal Coordenado da localiza¸c˜ao, em milisegundos desde 01/01/1970.
No c´odigo 10, s˜ao apresentadas as implementa¸c˜oes das fun¸c˜oes que chamam os m´etodos da classe Location.
C´odigo 10. Implementa¸c˜ao dos m´etodos da classe Location
1 p u b l i c d o u b l e g e t L a t i t u d e ( ) {
2 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t L a t i t u d e ( ) ;
3 }
4
5 p u b l i c d o u b l e g e t L o n g i t u d e ( ) {
6 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t L o n g i t u d e ( ) ;
7 }
8
9 p u b l i c d o u b l e g e t A l t i t u d e ( ) {
10 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t A l t i t u d e ( ) ;
11 }
12
13 p u b l i c S t r i n g g e t O r i e n t a t i o n ( ) {
14 r e t u r n c o n v e r t D i r O r i e n t ( mLocation ) ;
15 }
16
17 p u b l i c f l o a t g e t S p e e d ( ) {
18 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t S p e e d ( )∗( f l o a t ) 3 . 6 ;
19 }
20
21 p u b l i c f l o a t g e t P r e c i s i o n ( ) {
22 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t A c c u r a c y ( ) ;
23 }
24
25 p u b l i c f l o a t g e t D i r e c t i o n ( ) {
26 r e t u r n mLocation==n u l l ? n u l l : m L o c a t i o n . g e t B e a r i n g ( ) ;
27 }
28
29 p u b l i c S t r i n g getTime ( ) {
30 r e t u r n mLocation==n u l l ? n u l l : n e w SimpleDateFormat (” hh:mm:ss ”) . f o r m a t ( new Date ( mLocation . getTime ( ) ) ) ;
31 }
Foi implementada tamb´em uma nova fun¸c˜ao que n˜ao pertence a classe Loca-tion, chamada de getOrientation(). Esta fun¸c˜ao realiza uma chamada para ou-tra fun¸c˜ao convertDirOrient(location) que recebe como parˆametro um objeto an-droid.location.Location e realiza uma convers˜ao do sentido em graus para as siglas dos pontos cardeais (Norte, Sul, Leste e Oeste), colaterais (nordeste, sudeste, no-roeste e sudoeste) e subcolaterais (norte-nordeste, norte-nono-roeste, leste-nordeste, leste-sudeste, sul-sudeste, sul-sudoeste, oeste-sudoeste e oeste-noroeste).
getOrientation()
C´odigo 11. Interface SensorsInterface
1 p u b l i c S t r i n g c o n v e r t D i r O r i e n t ( L o c a t i o n l o c a t i o n ) {
2 mLocation = l o c a t i o n ;
3 S t r i n g o r i e n t a c a o = ”Nao o b t i d a ”;
4 i f ( mLocation == n u l l){
5 o r i e n t a c a o = ” n u l l ”;
6 }
7 e l s e i f ( mLocation . h a s B e a r i n g ( ) != f a l s e) {
8 f l o a t s e n t i d o = mLocation . g e t B e a r i n g ( ) ;
9 i f ( s e n t i d o >= 0 && s e n t i d o <= 1 0 ) {
10 o r i e n t a c a o = ”N”;
11 } e l s e i f ( s e n t i d o >= 11 && s e n t i d o <= 3 3 ) {
12 o r i e n t a c a o = ”N−NE”;
13 } e l s e i f ( s e n t i d o >= 34 && s e n t i d o <= 5 5 ) {
14 o r i e n t a c a o = ”NE”;
15 } e l s e i f ( s e n t i d o >= 56 && s e n t i d o <= 7 8 ) {
16 o r i e n t a c a o = ”E−NE”;
17 } e l s e i f ( s e n t i d o >= 79 && s e n t i d o <= 1 0 0 ) {
18 o r i e n t a c a o = ”E”;
19 } e l s e i f ( s e n t i d o >= 101 && s e n t i d o <= 1 2 3 ) {
20 o r i e n t a c a o = ”E−SE”;
21 } e l s e i f ( s e n t i d o >= 124 && s e n t i d o <= 1 4 5 ) {
22 o r i e n t a c a o = ”SE”;
23 } e l s e i f ( s e n t i d o >= 146 && s e n t i d o <= 1 6 8 ) {
24 o r i e n t a c a o = ”S−SE”;
25 } e l s e i f ( s e n t i d o >= 169 && s e n t i d o <= 1 9 0 ) {
26 o r i e n t a c a o = ”S”;
27 } e l s e i f ( s e n t i d o >= 191 && s e n t i d o <= 2 1 3 ) {
28 o r i e n t a c a o = ”S−SO”;
29 } e l s e i f ( s e n t i d o >= 214 && s e n t i d o <= 2 3 5 ) {
30 o r i e n t a c a o = ”SO”;
31 } e l s e i f ( s e n t i d o >= 236 && s e n t i d o <= 2 5 8 ) {
32 o r i e n t a c a o = ”O−SO”;
33 } e l s e i f ( s e n t i d o >= 259 && s e n t i d o <= 2 8 0 ) {
34 o r i e n t a c a o = ”O”;
35 } e l s e i f ( s e n t i d o >= 281 && s e n t i d o <= 3 0 3 ) {
36 o r i e n t a c a o = ”O−NO”;
37 } e l s e i f ( s e n t i d o >= 304 && s e n t i d o <= 3 2 5 ) {
38 o r i e n t a c a o = ”NO”;
39 } e l s e i f ( s e n t i d o >= 326 && s e n t i d o <= 3 4 8 ) {
40 o r i e n t a c a o = ”N−NO”;
41 } e l s e i f ( s e n t i d o >= 349 && s e n t i d o <= 3 5 9 ) {
42 o r i e n t a c a o = ”N”;
43 }
44 }
45 r e t u r n o r i e n t a c a o ;
46 }
Para utilizar o GPS na aplica¸c˜ao ´e necess´ario declarar algumas permiss˜oes ne-cess´arias no ficheiroAndroidManifest.xml que podem ser:
• ACCESS FINE LOCATION- Permite a aplica¸c˜ao receber `a localiza¸c˜ao atrav´es de GPS por hardware.
• ACESS COARSE LOCATION - Permite a aplica¸c˜ao receber `a localiza¸c˜ao atrav´es do Wi-Fi ou triangula¸c˜ao de antenas.
A permiss˜ao a ser escolhida vai depender das configura¸c˜oes de precis˜ao feitas no objeto LocationRequest. O c´odigo 10 apresenta o trecho de c´odigo utilizado no ficheiro AndroidManifest.xml.
C´odigo 12. Declara¸c˜ao das permiss˜oes no ficheiro AndroidManifest.xml
1 <m a n i f e s t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d . com/ apk / r e s / a n d r o i d ”
2 p a c k a g e=” g t a . ComuniCAR”>
3 <u s e s−p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . p e r m i s s i o n . ACCESS GPS” />
4 <u s e s−p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . p e r m i s s i o n . ACCESS FINE LOCATION”
/>
Depois de implementar a classeSensors, foi desevolvida uma interface chamada deSensorsInterface. Esta interface implementa o m´etodo seekingGPSData(), que ´e chamado dentro do m´etodo onLocationChanged(location) da classe Sensors.
C´odigo 13. Interface SensorsInterface
1 p u b l i c i n t e r f a c e S e n s o r s I n t e r f a c e {
2 v o i d seekingGPSData ( L o c a t i o n n e w L o c a t i o n ) ;
3 }
Repare que ao utilizar esta interface o utilizador ir´a implementar somente o m´etodo seekingGPSData() para obter os dados de localiza¸c˜ao do GPS, pois todos os outros m´etodos j´a est˜ao encapsulados na classe Sensors. O c´odigo 10 apresenta o uso da biblioteca ComuniCAR e a implementa¸c˜ao do m´etodo seekingGPSData da interface SensorsInterface.
C´odigo 14. Obtendo os dados do GPS utilizando o ComuniCAR
1 i m p o r t g t a . ComuniCAR . S e n s o r s ;
2 i m p o r t g t a . ComuniCAR . S e n s o r s I n t e r f a c e ;
3
4 p u b l i c c l a s s A p S e n s o r e s e x t e n d s A c t i v i t y i m p l e m e n t s S e n s o r s I n t e r f a c e {
5
6 S e n s o r e s mS e ns o re s ; // C r i a uma nova i n s t a n c i a de S e n s o r e s
7
8 p u b l i c v o i d seekingGPSData ( L o c a t i o n n e w L o c a t i o n ) {
9 t x t L a t i t u d e . s e t T e x t ( S t r i n g . v a l u e O f ( m S en so r es . g e t L a t i t u d e ( ) ) ) ;
10 t x t L o n g i t u d e . s e t T e x t ( S t r i n g . v a l u e O f ( mS e ns or e s . g e t L o n g i t u d e ( ) ) ) ;
11 t x t A l t i t u d e . s e t T e x t ( S t r i n g . v a l u e O f ( m S en so r es . g e t A l t i t u d e ( ) ) ) ;
12 t x t V e l o c i d a d e . s e t T e x t ( S t r i n g . v a l u e O f ( mS e ns or e s . g e t S p e e d ( ) ) ) ;
13 t x t O r i e n t a c a o . s e t T e x t ( m S en s or es . g e t O r i e n t a t i o n ( ) ) ;
14 t x t P r e c i s a o . s e t T e x t ( S t r i n g . v a l u e O f ( mS en s or e s . g e t P r e c i s i o n ( ) ) ) ;
15 t x t H o r a . s e t T e x t ( mS e ns or e s . getTime ( ) ) ;
16 t x t D i r e c a o . s e t T e x t ( S t r i n g . v a l u e O f ( m S en s or es . g e t D i r e c t i o n ( ) ) ) ;
17 }
18 }
Mecanismo de comunica¸c˜ao
Para a constru¸c˜ao do ComuniCAR foi utilizado a API do Wi-Fi Direct dispo-nibilizado pelo SDK Android. Esta API permite ao aplicativo, instalado no
sis-tema operacional Android 4.0 ou vers˜oes posteriores com hardware apropriado se conectar diretamente com outros dispositivos via Wi-Fi, sem um ponto de acesso intermedi´ario.
C´odigo 15. M´etodo Construtor da classe Neighbors
1 p u b l i c N e i g h b o r s ( A c t i v i t y m A c t i v i t y , V i z i n h o s I n t e r f a c e m I n t e r f a c e ){
2 t h i s. m A c t i v i t y = m A c t i v i t y ;
3 t h i s. m I n t e r f a c e = m I n t e r f a c e ;
4 s e t W i f i D i r e c t ( ) ; // chama o metodo s e t W i f i D i r e c t ( )
5 }
6 }
No m´etodo setWifiDirect() foi realizado uma instˆancia do WifiP2pManager que ir´a ser utilizado para registrar a aplica¸c˜ao ao Wi-Fi Direct, atrav´es do m´etodo ini-tialize(). Este m´etodo retorna umWifiP2pManager.Channel, que foi utilizado para ligar a aplica¸c˜ao com o Wi-Fi Direct. Foi criado tamb´em o WiFiDirectBroadcas-tReceiver, onde foi registrado os seus respectivos Intents como exemplo: WIFI P2P STATE CHANGED ACTION de forma a permitir que a aplica¸c˜ao receba noti-fica¸c˜oes de eventos do seu interesse, como por exemplo: saber se o Wi-Fi Direct dos dispositivos encontram-se ligados/desligados ou se um dispositivo perdeu uma conex˜ao Wi-Fi Direct.
C´odigo 16. Obtendo os dados do GPS utilizando o ComuniCAR
1
2 p u b l i c c l a s s V i z i n h o s i m p l e m e n t s
3 WifiP2pManager . P e e r L i s t L i s t e n e r ,
4 WifiP2pManager . C o n n e c t i o n I n f o L i s t e n e r , S o c k e t I n t e r f a c e {
5
6 A c t i v i t y m A c t i v i t y ;
7 WifiP2pManager mManager ;
8 WifiP2pManager . Channel mChannel ;
9 B r o a d c a s t R e c e i v e r mReceiver ;
10 I n t e n t F i l t e r m I n t e n t F i l t e r ;
11 W i f i P 2 p D e v i c e mDevice ;
12
13 p u b l i c v o i d s e t W i f i D i r e c t ( ) {
14 mManager = ( WifiP2pManager ) m A c t i v i t y . g e t S y s t e m S e r v i c e ( Context . WIFI P2P SERVICE ) ;
15 mChannel = mManager . i n i t i a l i z e ( m A c t i v i t y , m A c t i v i t y . getMainLooper ( ) , n u l l) ;
16 mReceiver = new W i F i D i r e c t B r o a d c a s t R e c e i v e r ( mManager , mChannel , m A c t i v i t y , t h i s) ;
17 m I n t e n t F i l t e r = new I n t e n t F i l t e r ( ) ;
18 m I n t e n t F i l t e r . addAction ( WifiP2pManager . WIFI P2P STATE CHANGED ACTION) ;
19 m I n t e n t F i l t e r . addAction ( WifiP2pManager . WIFI P2P PEERS CHANGED ACTION) ;
20 m I n t e n t F i l t e r . addAction ( WifiP2pManager . WIFI P2P CONNECTION CHANGED ACTION) ;
21 m I n t e n t F i l t e r . addAction ( WifiP2pManager . WIFI P2P THIS DEVICE CHANGED ACTION) ;
22 }
23 }
Tendo os dois objetos criados do WifiP2pManager e WifiP2pManager.Channel, as aplica¸c˜oes j´a podem chamar os m´etodos da classeWifiP2pManager para utiliza-rem as funcionalidades fornecidas pelo Wi-Fi Direct. Foi utilizado o BroadcastRe-ceiver ´e utilizado para a aplica¸c˜ao receber notifica¸c˜oes de eventos importantes, como por exemplo: saber se o Wi-Fi est´a ligado ou n˜ao, se o dispositivo perdeu a conex˜ao a uma rede ou conectou-se a uma rede, entre outras notifica¸c˜oes [14].
Utilizando as API’s Wi-Fi Direct do SDK Android, existe duas formas de se conectar um dispositivo P2P Group. Estes s˜ao realizadas atrav´es da chamada aos m´etodos connect() e createGroup() da classe WifiP2pManager [14].
No m´etodo createGroup(), ser´a realizado a t´ecnica de forma¸c˜ao de grupo Au-tonomous, portanto o dispositivo ir´a criar um P2P Group onde ele ´e P2P GO. E atrav´es do m´etodo connect() um dispositivo ir´a conectar-se a um outro dispositivo previamente descoberto no processo de descoberta dos vizinhos. Para chamar o m´etodo connect() ´e necess´ario passar como parˆametro o objeto WifiP2pConfig que cont´em a configura¸c˜ao para estabelecer a conex˜ao com o dispositivo desejado.
C´odigo 17. Implementa¸c˜ao do m´etodo onConnectionInfoAvailable()
1 p u b l i c v o i d o n C o n n e c t i o n I n f o A v a i l a b l e ( W i f i P 2 p I n f o i n f o ) {
2 mInfo = i n f o ;
3 i f ( i n f o . isGroupOwner ) {
4 t (”Owner”) ;
5 i f( mServerThread !=n u l l && mServerThread . i s A l i v e ( ) ){
6 mServerThread . i n t e r r u p t ( ) ;
7 }
8 i f( mClientTimer !=n u l l){
9 mClientTimer . c a n c e l ( ) ;
10 mClientTimer . p u r g e ( ) ;
11 }
12 mServerThread = new S o c k e t S e r v e r T h r e a d (t h i s) ;
13 mServerThread . s t a r t ( ) ;
14 } e l s e {
15 t (”member”) ;
16 i f( mServerThread !=n u l l && mServerThread . i s A l i v e ( ) ){
17 mServerThread . i n t e r r u p t ( ) ;
18 }
19 i f( mClientTimer !=n u l l){
20 mClientTimer . c a n c e l ( ) ;
21 mClientTimer . p u r g e ( ) ;
22 }
23 mClientTimer = new Timer ( ) ;
24 mClientTimer . s c h e d u l e A t F i x e d R a t e (new TimerTask ( ) {
25 @Override
26 p u b l i c v o i d run ( ) {
27 i f ( ( m C l i e n t S o c k e t == n u l l | | m C l i e n t S o c k e t . g e t S t a t u s ( ) != S o c k e t C l i e n t T h r e a d . S t a t u s . RUNNING) && ! mInfo . isGroupOwner && mInfo .
groupFormed ) {
28 m C l i e n t S o c k e t = new S o c k e t C l i e n t T h r e a d ( mInfo . groupOwnerAddress . g e t H o s t A d d r e s s ( ) . t o S t r i n g ( ) , V i z i n h o s .t h i s) ;
29 m C l i e n t S o c k e t . e x e c u t e ( ) ;
30 }
31 }
32 }, postTime , postTime ) ;
33 }
34
35 Toast . makeText ( m A c t i v i t y ,” Seu s t a t u s de c o n e x a o mudou”, Toast . LENGTH LONG) . show ( ) ;
36 }
Foram implementados fun¸c˜oes e m´etodos para trocar mensagens dos dados de localiza¸c˜ao entre os dispositivos.
C´odigo 18. Implementa¸c˜ao dos m´etodos para troca de mensagens
1 p u b l i c S t r i n g g e t S e r v e r M e s s a g e ( ) {
2 r e t u r n mGson . t o J s o n (new MyLocation ( mLocation ) ) ;
3 }
4
5 p u b l i c v o i d o n C l i e n t R e s p o n s e ( S t r i n g r e p o n s e ) {
6 t (”CL ”+r e p o n s e ) ;
7 }
8
9 p u b l i c S t r i n g g e t C l i e n t M e s s a g e ( ) {
10 r e t u r n mGson . t o J s o n (new MyLocation ( mLocation ) ) ;
11 }
12
13 p u b l i c v o i d o n S e v e r R e s p o n s e ( S t r i n g r e s p o n s e ) {
14 t (”SV ”+r e s p o n s e ) ;
15 }
Na conex˜ao atrav´es da chamada ao m´etodoconnect(), os dispositivos ir´ao formar umP2P Group, negociando entre si qual deles ´e que ir´a realizar o papel deP2P GO, caso o dispositivo que ir´a realizar connect(), j´a se encontra num P2P Group e este
for P2P GO, a fun¸c˜ao connect() efetua um convite ao dispositivo que este deseja conectar, para se juntar ao grupo. Um dispositivo que n˜ao se encontra num P2P GO, juntando assim ao seuP2P Group, sendo irrefut´avel que o dispositivo ter´a que descobrir o dispositivoP2P GO antes de executar a fun¸c˜ao connect().
Segundo a especifica¸c˜aoWi-Fi Direct, para realizar uma conex˜ao com um outro dispositivoWi-Fi Direct, ´e preciso que este seja antes descoberto. Nas API’s Wi-Fi Direct dosdk Android, a descoberta dos pares pode ser realizada atrav´es da chamada do m´etodo discoverPeers() da classe WifiP2pManager.
C´odigo 19. M´etodo discoverPeers()
1 p u b l i c v o i d d i s c o v e r P e e r s ( ) {
2 mManager . d i s c o v e r P e e r s ( mChannel , new WifiP2pManager . A c t i o n L i s t e n e r ( ) {
3 @Override
4 p u b l i c v o i d o n S u c c e s s ( ) {
5 }
6
7 @Override
8 p u b l i c v o i d o n F a i l u r e (i n t r e a s o n C o d e ) {
9 }
10 }) ;
11 }
Depois de implementar a classeNeighbors, foi desevolvida uma interface chamada deNeighborsInterface. Esta interface implementa o m´etodo onNeighborsUpdate(),
C´odigo 20. Interface NeighborsInterface
1 p u b l i c i n t e r f a c e N e i g h b o r s I n t e r f a c e {
2 v o i d onNeighborsUpdate ( C o l l e c t i o n<WifiP2pDevice> n e w L i s t ) ;
3 }
Repare que ao utilizar a interfaceNeighborsInterfaceo utilizador ir´a implementar somente o m´etodoonNeighborsUpdate() para obter a lista dos vizinhos encontrados, pois todos os outros m´etodos j´a est˜ao encapsulados na classe Neighbors. O c´odigo 10 apresenta o uso da biblioteca ComuniCAR e a implementa¸c˜ao do m´etodo see-kingGPSData da interface SensorsInterface.
C´odigo 21. Obtendo a lista de vizinhos em um dado momento
1
2 i m p o r t g t a . ComuniCAR . S e n s o r s ;
3 i m p o r t g t a . ComuniCAR . S e n s o r s I n t e r f a c e ;
4 i m p o r t g t a . ComuniCAR . N e i g h b o r s ;
5 i m p o r t g t a . ComuniCAR . N e i g h b o r s A d a p t e r ;
6 i m p o r t g t a . ComuniCAR . N e i g h b o r s I n t e r f a c e ;
7
8 p u b l i c c l a s s N e i g h b o r s e x t e n d s A c t i v i t y i m p l e m e n t s N e i g h b o r s I n t e r f a c e , S e n s o r s I n t e r f a c e {
9 p u b l i c v o i d onNeighborsUpdate ( C o l l e c t i o n<WifiP2pDevice> n e w L i s t ) {
10 mAdapter = new V i z i n h o s A d a p t e r (t h i s , new A r r a y L i s t<
WifiP2pDevice>( n e w L i s t ) ) ;
11 mListView . s e t A d a p t e r ( mAdapter ) ;
12 }
Cap´ıtulo 5
Estudo de Caso
Neste cap´ıtulo ´e apresentado um exemplo de aplicativo denominado SmartCAR, o qual foi desenvolvido utilizando os recursos da biblioteca ComuniCAR. A imple-menta¸c˜ao dessa aplica¸c˜ao possibilita que se avalie os ganhos trazidos pela biblioteca tanto no processo de desenvolvimento quanto na gera¸c˜ao de cen´arios para a avalia¸c˜ao em redes m´oveis.