Cap´ıtulo 5
5.2 Aplica¸ c˜ ao m´ ovel para passageiros
O prot´otipo desenvolvido, ´e uma vers˜ao simplificada da aplica¸c˜ao m´ovel de passageiros projetada na sec¸c˜ao 4.3, tendo como objetivo disponibilizar as principais funcionalidades
1Software Development Kits
desejadas, testar as comunica¸c˜oes com o servidor do operador e com a rede Hedera Hashgraph.
Este prot´otipo abdica das comunica¸c˜oes com a aplica¸c˜ao dedicada a revisores. Em vez de receber eventos de check-in/out de outro m´odulo a executar no smartphone, por exemplo, com base em BLE e inteligˆencia artificial, a solu¸c˜ao adoptada para este prot´otipo recebe informa¸c˜oes de an´uncios diretamente via BLE, sendo estes enviados por um computador port´atil que simula os eventos de check-in/out.
Figura 5.7: Bibliotecas que constituem o prot´otipo da aplica¸c˜ao HederaPass.
A aplica¸c˜ao m´ovel para os passageiros foi implementada atrav´es do Android Studio em Java, sendo compat´ıvel com Android 5.0, mas projetada tendo o Android 10 como principal vers˜ao do sistema operativo.
Antes de descrever cada atividade (activity) e fragmento (fragment) da aplica¸c˜ao, ´e im-portante referir que foi usado o Gradle na sua compila¸c˜ao, tendo sido adicionados recursos que permitiram `a aplica¸c˜ao comunicar com a rede Hedera Hashgraph (Hedera Java SDK), fazer requests HTTP para interagir com a serializa¸c˜ao do servidor (Retrofit com conversor GSON), simular a encripta¸c˜ao ECDSA que seria efetuada pela Unidade de Bordo (Bouncy Castle Crypto) e simular a rece¸c˜ao de mensagens atrav´es de BLE (Android Beacon / AltBe-acon). O conjunto de funcionalidades da aplica¸c˜ao, est´a representado na Figura 5.7, que ser´a descrita com mais detalhe ao longo da sec¸c˜ao.
5.2.1 Comunica¸c˜ao com o servidor
Para estabelecer a comunica¸c˜ao com o servidor, foi criada na aplica¸c˜ao uma interface Java
“JsonPlaceHolderApi” onde se definem os campos e m´etodo de cada request HTTP (POST ou GET) requisitados pelas classes da aplica¸c˜ao, como demonstra o seguinte trecho de c´odigo:
@POST("api/register/")
Call<PostReg> createPost(@Body PostReg postReg);
Neste caso, a fun¸c˜ao Call() cont´em o URL e os campos associado `a classe do servidor “Re-gisterAPI”, com a qual a aplica¸c˜ao comunica para efetuar o registo de um utilizador.
Em todas as classes que fazem requests POST ao servidor, nomeadamente a de registo do utilizador (“RegistrationActivity”), login (“LoginActivity”), logout (“LogoutActivity”) e de envio de an´uncios de paragem (“AnnouncementFragment”), os requests s˜ao enviados atrav´es de uma sequˆencia que inicia com a defini¸c˜ao dos parˆametros do Retrofit: URL do servidor, a forma como a informa¸c˜ao ´e desserializada (neste caso atrav´es de um conversor Gson) e a interface Java referida anteriormente, que cont´em os campos do serializer, neste caso provenientes de uma classe definida como PostReg:
Retrofit retrofit = new Retrofit.Builder()
O Retrofit funciona como um intermedi´ario entre a aplica¸c˜ao e o servidor, como est´a representado na Figura 5.7.
No caso da classe que faz um request GET para obter o hist´orico de viagens do utiliza-dor (“HistoryFragment”) ´e usado o mesmo processo, com a diferen¸ca de na interface Java (“JsonPlaceHolderApi”) usar-se a annotation GET, que neste caso acede `a classe “Announ-cementAPI” do servidor:
@GET("api/announcement/")
5.2.2 Registo e Login
Inicialmente, o utilizador entra na aplica¸c˜ao e ´e-lhe apresentada a atividade de login da Figura 5.8. Para aceder `a atividade de registo, da Figura 5.9, este deve clicar na ´ultima palavra da sugest˜ao “Ainda n˜ao tem conta? Registe-seaqui”, onde o utilizador preenche um formul´ario com os campos descritos na sec¸c˜ao 5.1 (n´umero de telem´ovel, nome de utilizador, email, palavra-passe e ID da sua conta Hedera Hashgraph), mais a private key da sua conta Hedera Hashgraph. Ao submeter o formul´ario, a aplica¸c˜ao envia todos campos para a o servidor, com exce¸c˜ao daprivate key que fica guardada localmente. Atrav´es do POST para o URL correspondente `a classe “RegisterAPI”, recebe a resposta do servidor que, no caso de indicar a validade do registo, leva a que a atividade de registo dˆe lugar `a delogin.
A atividade delogin ´e fundamental para o funcionamento do sistema, sendo que ´e a partir da resposta ao request para a “LoginAPI” do servidor, que o utilizador obt´em o ID da sua sess˜ao, que ´e armazenado localmente na aplica¸c˜ao (SharedPreferences), e fica autorizado a aceder ao menu principal da sua conta (“MainActivity”).
A classe do logout, por sua vez, faz o request para a “LogoutAPI” e elimina os dados armazenados localmente pelo login.
Figura 5.8: Ecr˜a delogin implementado.
Figura 5.9: Ecr˜a de registo implementado.
Figura 5.10: Ecr˜a do menu implementado.
5.2.3 Menu
A classe “MainActivity” ´e respons´avel pela organiza¸c˜ao da estrutura do menu dividido em separadores recorrendo a uma classe do tipo FragmentStateAdapter, que atribui a cada separador um determinado fragmento, permitindo ao utilizador aceder ao estado da viagem, hist´orico de viagens, saldo da sua conta Hedera Hashgraph e outros detalhes da viagem, clicando diretamente no t´ıtulo dos separadores ou deslizando o ecr˜a para os lados. O menu est´a representado na Figura 5.10. Esta classe, tamb´em foi usada para simular o desempenho da aplica¸c˜ao enquanto recebe an´uncios BLE embackground, atrav´es da biblioteca AltBeacon.
5.2.4 Processamento dos an´uncios de paragem
E importante referir que, para efeitos de teste, os an´´ uncios de paragem, que numa vers˜ao completa seriam gerados por uma Unidade de Bordo, foram gerados pela pr´opria aplica¸c˜ao atrav´es da biblioteca Bouncy Castle Crypto. Inicialmente foi criado um par de chaves ECDSA com parˆametros secp256k1, em que a public key foi guardada na tabela UBKey da base de dados do servidor do operador e aprivate key serviu para produzir as assinaturas digitais dos an´uncios. Posteriormente, cada an´uncio completo, com os dados de uma paragem simulada e assinatura digital, foi dividido em 5 partes, de forma a que cada parte pudesse ser enviada por um endere¸co UUID de um iBeacon, que neste caso foi simulado por um computador port´atil com a aplica¸c˜ao “Beacon Simulator”. Tamb´em foram utilizados o Major e Minor do iBeacon, com o Major a representar o tipo de an´uncio (check-in, paragem interm´edia ou check-out) e o Minor a representar, por ordem, que parte do an´uncio ´e que estava a ser enviado (de 1 a 5).
A classe “MainActivity” foi a respons´avel por juntar as 5 partes e enviar o an´uncio
com-Figura 5.11: Ecr˜a implementado para o envio de an´uncios.
pleto para uma classe respons´avel por enviar os an´uncios para o servidor (“Announcement-Fragment”). Outra diferen¸ca crucial entre este prot´otipo e uma vers˜ao completa, ´e o facto desta aplica¸c˜ao recorrer ao clique num bot˜ao, nesta classe, para enviar os an´uncios, como se pode verificar na Figura 5.11. Numa vers˜ao completa da aplica¸c˜ao, esta enviaria os an´uncios de paragem sem a necessidade de qualquer intera¸c˜ao com o passageiro, atrav´es de um m´odulo complementar desenvolvido para melhorar a comunica¸c˜ao da aplica¸c˜ao com osbeacons BLE, que n˜ao ´e estudado nesta disserta¸c˜ao.
Atrav´es da identifica¸c˜ao da flag recebida junto com o an´uncio de paragem, a classe “An-nouncementFragment” trata an´uncios de paragem em situa¸c˜oes de check-in (flag=0), para-gens interm´edias (flag=1) e check-out (flag=2) de formas diferentes.
5.2.5 Paragem interm´edia
Em situa¸c˜oes de paragens interm´edias, a classe envia umrequest para a classe “Announce-mentAPI” do servidor, com os campos comuns a todos os an´uncios, nomeadamente o pr´oprio an´uncio de paragem, a flag, o ID da sess˜ao e o timestamp que indica o momento em que a aplica¸c˜ao recebeu o an´uncio, ao que o servidor responde com o nome da ´ultima paragem efetuada pelo passageiro e o nome da paragem seguinte.
5.2.6 Check-in
Em situa¸c˜oes de check-in a complexidade aumenta. Al´em do processo de valida¸c˜ao do an´uncio de paragem, que neste caso obt´em informa¸c˜ao necess´aria para efetuar o pagamento da viagem, a aplica¸c˜ao necessita de fazer a transa¸c˜ao de HBARs “virtuais” na Testnet da
rede Hedera Hashgraph. Para isso, come¸ca por aceder ao ID da conta Hedera Hashgraph do passageiro e correspondente private key guardados localmente, que garantem o acesso `a Testnet atrav´es da seguinte linha de c´odigo:
Client client = Client.forTestnet().setOperator(passengerID, privateKey);
Com a informa¸c˜ao do montante a pagar pelo passageiro e endere¸co Hedera Hashgraph para o qual ser´a transferido, obtidos anteriormente, ´e iniciada a transa¸c˜ao:
TransferTransaction transaction = new TransferTransaction() .addHbarTransfer(passengerID,Hbar.fromTinybars(amountOut)) .addHbarTransfer(serverID, Hbar.fromTinybars(amountIn));
Ao ser conclu´ıda, ´e obtida a resposta da pr´opria transa¸c˜ao atrav´es da rede Hedera Hash-graph, onde a aplica¸c˜ao verifica se a transa¸c˜ao foi bem sucedida atrav´es do seu estado (tran-sactionStatus = “SUCCESS”):
TransactionResponse txResponse = transaction.execute(client);
TransactionReceipt receipt = txResponse.getReceipt(client);
com.hedera.hashgraph.sdk.Status transactionStatus = receipt.status;
A confirma¸c˜ao de que o pagamento foi efetuado, al´em de poder ser acedido pelo servidor diretamente atrav´es da rede Hedera Hashgraph, a aplica¸c˜ao tamb´em envia esta informa¸c˜ao para o servidor atrav´es de um request com o ID da sess˜ao, quantia e o ID da transa¸c˜ao, acedido atrav´es de:
String transactionID = txResponse.transactionId.toString();
terminando assim o processo de check-in na aplica¸c˜ao.
5.2.7 Check-out
O processo de check-out, do lado da aplica¸c˜ao, apenas envia ao servidor um request se-melhante a um de paragem interm´edia, com a diferen¸ca de obter da reposta do servidor o estado da transa¸c˜ao do reembolso, que no caso de ter sido bem sucedido ser´a uma String
“SUCCESS”.
5.2.8 Hist´orico de viagens
Para o passageiro verificar o seu hist´orico de viagens, foi desenvolvida uma classe “His-toryFragment” onde, no separador “Hist´orico” mostra detalhes de cada viagem que fez. Esta classe envia o ´unico request do tipo GET feito pela aplica¸c˜ao que o servidor, atrav´es do ID da sess˜ao, responde com a hora e data de cada check-in e check-out efetuados, o nome das paragens correspondentes e o pre¸co cobrado por cada viagem. Na Figura 5.12 est´a represen-tado o hist´orico de um utilizador ap´os 2 viagens. Os resultados iguais devem-se ao envio dos mesmos an´uncios de paragens, apenas para simular a estrutura da interface.
Figura 5.12: Ecr˜a do hist´orico de viagens implementado.
Figura 5.13: Ecr˜a de Estado durante uma viagem com 1 paragem interm´edia.
5.2.9 Estado
As respostas aosrequests decheck-in, paragens interm´edias echeck-out da classe “Announ-cementFragment”, fornecem informa¸c˜ao crucial para as classes que constituem os separadores do menu da aplica¸c˜ao. O separador “Estados”, ´e constitu´ıdo pelo nome da ´ultima paragem feita pelo passageiro, o nome da paragem seguinte e pelo estado da viagem - que indica se o passageiro ingressou numa viagem e se, caso tenha ingressado, a viagem est´a em progresso ou se foi terminada. Caso n˜ao haja qualquer check-in a registar desde a nova sess˜ao, aparecem h´ıfenes no estado e paragens, que desde o check-in at´e `a paragem anterior aocheck-out ser˜ao substitu´ıdos por “Em viagem”, no caso do estado, e o nome das paragens. A paragem de check-out altera o estado para “Terminada”, indica a ´ultima paragem feita e apresenta um h´ıfen `a frente de “Pr´oxima paragem:”. Esta sequˆencia est´a representada na Figura 5.13.
5.2.10 Detalhes
Figura 5.14: Ecr˜a de Detalhes implementado.
Outra classe que n˜ao necessita de fazer requests, por aceder a toda a informa¸c˜ao local-mente, ´e a classe dos “Detalhes”. Aqui, tendo em conta que a aplica¸c˜ao do revisor n˜ao foi desenvolvida, a comunica¸c˜ao com a mesma tamb´em n˜ao foi implementada, o que fez com que este separador apenas disponibilize a informa¸c˜ao acerca da Internet e BLE do smartphone estarem a funcionar e a informa¸c˜ao proveniente do fragmento “AnnouncementFragment”, que mostra se foi feito o check-in, pagamento, check-out e recebido o reembolso. A Figura 5.14 demonstra o ecr˜a numa situa¸c˜ao em que o passageiro ainda n˜ao deu in´ıcio a uma viagem.
Figura 5.15: Ecr˜a de Saldo implementado.
5.2.11 Saldo
Por fim, h´a mais uma classe que comunica com a rede Hedera Hashgraph, desta vez para obter o saldo da conta do passageiro. Aqui, a aplica¸c˜ao volta a aceder `a Testnet atrav´es do ID da conta e respetiva private key, o que antecede o acesso ao montante atrav´es de uma query da seguinte forma:
AccountBalanceQuery query = new AccountBalanceQuery() .setAccountId(this.passengerID);
AccountBalance accountBalance = query.execute(client);
O valor obtido ´e convertido numa vari´avelDouble para que seja disponibilizado ao utiliza-dor o valor em HBARs e Euros. Esta convers˜ao foi feita manualmente atrav´es do valor atual de mercado, podendo no futuro ser implementada uma funcionalidade que permita obter o valor em tempo-real. Al´em de mostrar a quantia, foi ainda adicionada a funcionalidade do uti-lizador poder aceder aos pre¸cos das viagens, para confirmar se o seu saldo ´e suficiente. Como exemplo, a aplica¸c˜ao abre o URL “https://rede-expressos.pt/pt/horarios-bilhetes” quando o utilizador clica em “Pre¸cos”. O ecr˜a de Saldo est´a representado na Figura 5.15.