Este artigo é o sétimo de uma série sobre como a equipe de engenharia mobile da Uber desenvolveu a versão mais recente do nosso aplicativo de motorista, de codinome Carbon, um componente essencial de nosso negócio de compartilhamento de viagens.
Entre outros novos recursos, o app permite que nossa população de mais de três milhões de motoristas parceiros encontre tarifas, obtenha direções e acompanhe seus ganhos.
Começamos a projetar o novo aplicativo em conjunto com o feedback de nossos motoristas parceiros em 2017 e começamos a implementá-lo para produção em setembro de 2018.
As coletas de passageiros são um ponto de dor particularmente difícil para motoristas e passageiros devido a fatores técnicos e físicos. Do lado técnico, precisamos que os apps do motorista e do passageiro sejam devidamente sincronizados.
No espaço físico, como uma rua cheia de gente à noite, pode ser um desafio para o motorista e o passageiro se encontrarem. Ajudar os passageiros a identificarem facilmente seu motorista é a chave para uma viagem bem-sucedida e prazerosa em nossa plataforma.
O Uber Beacon representa uma extensão natural de nossos aplicativos para o mundo físico, um dispositivo que fornece uma correspondência de cores intuitiva entre um passageiro e um motorista, onde o passageiro pode escolher qualquer cor no espectro permitido.
Algo tão intuitivo quanto escolher uma cor e vê-la iluminar o para-brisa de seu motorista em uma noite escura e tempestuosa pode fazer uma grande diferença, mesmo que pareça simples.
E, de fato, a engenharia que conduz essa experiência é tudo menos simples. Vamos dar uma olhada mais profunda em como alavancamos nosso aplicativo de motorista mais recente para dar vida a essa experiência.
Pegada de carbono
A maior parte da engenharia mobile do Beacon está no nosso app de motorista. A implementação usa dois conjuntos de recursos: o SDK do Beacon, responsável pela comunicação com o Beacon através do Bluetooth LE, e uma série de objetos Worker na arquitetura RIBs do aplicativo que utiliza o SDK do Beacon para orientar a funcionalidade.
SDK do Beacon
A experiência de todo o usuário do Beacon é o SDK do Beacon, que lida com a conectividade Bluetooth LE e a comunicação entre o aplicativo do motorista e o Beacon. Ao projetar o SDK do Beacon, aderimos a três princípios:
- Plataforma agnóstica
- Independente da aplicação
- Interfaces reativas
Plataforma agnóstica
Como a arquitetura mobile da Uber é de plataforma agnóstica, oferecendo suporte para motoristas com telefones iOS e Android, era importante que o projeto de arquitetura do SDK do Beacon fosse também de plataforma agnóstica. Ao permitir que os engenheiros falassem em termos que são de plataforma cruzada, conseguimos nos mover mais rapidamente e fornecer integração mais fácil para outras equipes que precisavam alavancar o Beacon.
Independente da aplicação
Um princípio importante do desenvolvimento do SDK é garantir que o SDK não seja dependente do aplicativo consumidor. Isso foi crucial para nós quando lançamos o novo aplicativo de motorista.
Manter o SDK independente do consumidor nos permitiu fazer uma iteração no SDK e fornecer melhorias aos novos e antigos aplicativos de motorista em produção para ajudar a evitar interrupções para os motoristas.
Interfaces reativas
A Uber adotou a programação reativa em seus aplicativos móveis, por isso foi importante projetar o SDK do Beacon para expor Observables que aderissem ao Observable Contract.
Os engenheiros que usam o SDK podem se concentrar em interagir com o Beacon de maneira reativa. As complexidades das APIs Bluetooth de baixo nível são abstraídas.
O resultado
Criamos o SDK do Beacon para expor uma série de objetos gerenciadores, em que cada gerente é responsável por um subconjunto da funcionalidade do Beacon, como conectividade, controle de LED, atualizações OTA (over-the-air) e sensores.
Cada conjunto de gerentes é responsável pela interoperabilidade com um único Beacon, e o aplicativo do motorista pode operar qualquer número de Beacons, instanciando um conjunto de gerenciadores para cada dispositivo.
Cada gerente é definido por interface e o SDK fornece implementações dessas interfaces. Esses gerentes fornecem a ponte reativa para as APIs Bluetooth imperativas no nível da plataforma, que permitirão que os comandos passem do telefone do motorista para um Beacon.
Workers Carbon
Como o Beacon não possui uma interface de usuário dedicada, quase todas as funcionalidades do Beacon são fornecidas por meio dos Workers. Workers são essencialmente interatores que não possuem nenhum componente de UI dedicado, então a lógica não está vinculada à interação com visualizações no app.
O Carbon une os Workers no RIB mais baixo necessário para uma determinada funcionalidade, e os Workers são desanexados e disponibilizados para coleta de lixo à medida que o RIB é removido da árvore RIB.
Cada um desses Workers depende de um ou mais gerentes do SDK do Beacon. Os gerentes são fornecidos pelo RIB parental mais próximo compartilhado por esses Workers. Quando um Worker é instanciado, ele é injetado com gerentes fornecidos pelo escopo upstream.
Dessa forma, os gerentes do Beacon são compartilhados entre todos os Workers, e os Workers não são responsáveis pelo ciclo de vida desses gerentes.
A árvore RIBs permite habilitar e desabilitar os pontos de plugin para esses Workers, dependendo se um motorista está usando o Beacon ou não.
Se o motorista não estiver usando o Beacon, esses pontos de plugin serão desativados, os Workers nunca serão criados e os gerentes do SDK do Beacon nunca serão instanciados, essencialmente eliminando a pegada de tempo de execução do Beacon.
Quando um motorista está usando o Beacon, nós aderimos ao contrato no qual nossos Workers devem estar conectados no RIB mais baixo possível. Um exemplo disso é o nosso Worker Beacon Alerts, que produz alertas no aplicativo para o Beacon, como “Bateria fraca” ou “Beacon Not Found”.
Imagine um motorista verificando seus ganhos no app em casa, um status ao qual nos referimos como Offline desde que o motorista não esteja sendo combinado com passageiros; o motorista não está usando o Beacon e não deve receber esses tipos de alertas.
Nós só acionamos o Worker Beacon Alerts quando o motorista está na estrada pegando passageiros, chamado de Online, já que é quando esses alertas são importantes.
Correspondência de cores de ponta a ponta
Com o framework do Beacon implementado, podemos aproveitar o aplicativo do motorista para orientar a experiência do usuário do Color Matching.
Esse fluxo começa com o motorista conectando-se ao Beacon e ficando online. Quando o motorista está online, anexamos um Worker Beacon Capability ao RIB online, que atualiza nosso backend com o recurso de Beacon do motorista.
Conforme o motorista se conecta e desconecta do Beacon, atualizamos o recurso. Quando o motorista fica offline, o backend atualiza automaticamente o recurso para falso.
Então, quando o motorista aceita uma corrida, o aplicativo do passageiro recebe o nome do motorista e as informações do veículo, juntamente com o recurso do Beacon. Se o recurso for verdadeiro, exibiremos um ícone do Beacon no aplicativo do passageiro.
Em troca, o app do passageiro envia automaticamente uma cor previamente selecionada (ou uma cor selecionada aleatoriamente se o passageiro nunca tiver escolhido uma cor antes) para o nosso backend, que notifica o aplicativo do motorista sobre a cor desejada.
Enquanto aguarda para pegar o Uber, o passageiro pode tocar no ícone do Beacon e exibimos uma roda de cores de 24 bits (com certas cores, como vermelho e azul, removidas para segurança e conformidade), na qual o passageiro pode escolher qualquer cor desejada.
Cada vez que o passageiro seleciona uma cor, enviamos essa cor para o backend, o que, por sua vez, notifica o aplicativo do motorista.
No lado do motorista, temos um Worker Beacon Color que ouve essas notificações de cor sempre que o motorista está online. À medida que recebemos as cores, armazenamos um mapa local dos pares Rider + Color (Passageiro + Cor).
Dessa forma, se o motorista aceitou vários despachos – como um cenário do uberPOOL -, nós rastreamos a última cor original para cada passageiro que será coletado.
Como o backend informa o aplicativo do motorista, entramos na zona de coleta para um passageiro específico, enviamos um comando do nosso Worker Beacon Color para o gerenciador de LED do Beacon, informando para exibir a cor do passageiro e – voilá! – combinamos com o passageiro com o motorista através da nossa tecnologia de correspondência de cores.
Cada coleta subsequente exibirá a cor desse passageiro. Além disso, durante a coleta, pulamos o mapa de cores e exibimos imediatamente qualquer cor que o passageiro escolher posteriormente, mantendo os aplicativos e, consequentemente, o passageiro e o motorista em sincronia.
A fusão de dispositivos móveis e hardware
A Uber está sempre procurando maneiras de melhorar nossa experiência em plataformas. Estender a plataforma para o mundo físico através de hardware conectado a dispositivos móveis é uma progressão natural.
A fusão de dispositivos móveis e hardware cria novos e empolgantes desafios para conectar nossos aplicativos ao mundo físico, e o Uber Beacon é apenas um exemplo de como a Uber está inovando nesse espaço. É um momento emocionante para ser engenheiro mobile na Uber!
Referências
- Por que decidimos reescrever o aplicativo do motorista Uber
- Architecting Uber’s New Driver App in RIBs
- How Uber’s New Driver App Overcomes Network Lag
- Dimensionamento de pagamentos em dinheiro na Uber Eats
- How to Ship an App Rewrite Without Risking Your Entire Business
- Construindo uma interface de mapa escalável e confiável para motoristas
***
Este artigo é do Uber Engineering. Ele foi escrito por Kevin Babcock. A tradução foi feita pela Redação iMasters com autorização. Você pode conferir o original em: https://eng.uber.com/uber-beacon-bluetooth-mobile-app/