Como compartilhei o local por meio da API VK

Decidi recentemente tentar implementar a ideia de como compartilhar um local por meio da API VK com amigos no modo quase em tempo real. A saída foi um aplicativo Qt de plataforma cruzada para iOS / Android, um aplicativo da Web para o VKontakte e algumas solicitações pull para a API do VK. Neste artigo, gostaria de compartilhar alguns pontos de implementação não óbvios que podem ser do interesse de alguém. Então, interessado por favor, pergunte para o gato.

Por que eu precisava disso?


Mais cedo ou mais tarde, as crianças crescem. Verdade banal. Então minha filha de dez anos disse um dia: "Pai, não me leve mais de carro, eu quero ir para a escola sozinha!" Bem, então, achei a reivindicação justa, pedi um período de carência de duas semanas e comecei os preparativos.

Como tenho alguma experiência em escrever aplicativos, e minha filha carrega constantemente no bolso do iPhone SE, como preparação, decidiu-se escrever rapidamente um aplicativo que mostrasse onde a filha está nesse momento específico. Sim, eu sei que agora existem muitos aplicativos desse tipo (até uma funcionalidade semelhante apareceu recentemente no Google Maps) e foi possível usar alguma solução pronta, mas estava interessado em escrever algo próprio.

Porquê VKontakte?


Como não gostaria de me associar ao processamento e armazenamento de dados pessoais de outras pessoas (em uma possível perspectiva) em meu equipamento com todos os "encantos" resultantes disso, pensei em como fazer isso sem a minha própria parte de servidor. E então me dei conta - afinal, existe um monstro como o VKontakte! É elegante, poderoso e com sua própria API desenvolvida e, o mais importante, todos os nossos filhos estão sentados nela há um longo tempo e são apertados (não posso dizer que gostei, mas é uma realidade). Mas, caramba, Holmes, como posso inserir dados de localização para que, em primeiro lugar, eles não apareçam onde não são necessários e, em segundo lugar, para que você possa controlar o acesso a esses dados para que os maus pedobors neles não chegou lá?

Notas vieram ao resgate. Sim, a mesma wikipedia observa que uma vez (segundo os rumores) eram muito populares e agora estão na caneta, na maioria das vezes eles pararam de piscar nas fitas e se mudaram para uma seção separada do site, que você não encontrará em uma cabra coxa. Você pode colocar dados de texto arbitrários neles, mas o principal é que eles podem receber listas de acesso que listam pessoas e grupos que podem ver e comentar esta nota.

O esquema geral da aplicação aos meus olhos começou a ficar assim:

  • Crie uma lista de amigos com quem você deseja compartilhar dados de localização (eu chamei de "Amigos de Confiança");
  • Criamos uma nota com um nome específico, concedemos direitos para visualizá-la na lista acima, anotamos os dados de localização e os atualizamos periodicamente;
  • Revisamos regularmente a lista de amigos confiáveis, verificando se eles também têm uma nota com esse nome específico, se tiver, tentamos extrair dados sobre a localização do amigo a partir de seu conteúdo e, se for bem-sucedido, mostramos no mapa;
  • ???
  • LUCRO!

Então, existe uma idéia, cabe à pequena coisa perceber isso.

iOS


Como a filha usa o iPhone, era lógico iniciar a implementação com a versão iOS. Com vista à plataforma cruzada, o Qt foi escolhido como estrutura, porque eu o conheço há muito tempo, e o bom e velho Open Street Map, para o qual existe um plug-in no Qt Location, foi escolhido como o mecanismo do mapa. Como o aplicativo foi originalmente criado como código aberto, as restrições de licenciamento do Qt não me assustaram.

A GUI foi escrita em QML, para trabalhar com a VK, eu conectei e usei o VK iOS SDK normal, está escrita em Objective-C, portanto, sua integração não causou problemas. O trabalho em segundo plano no iOS é implementado por meio do Serviço de Localização de Mudança Significativa. Para reduzir o consumo de energia, o aplicativo monitora a atividade dos movimentos e, se entender que uma pessoa fica sentada por aproximadamente um lugar por um longo período de tempo (por exemplo, ele estudou na escola ou no escritório), reduz a precisão necessária para determinar a geolocalização, forçando o sistema operacional a mudar para formas menos intensivas de energia para determiná-la (como via de regra, em torres de celular). Se o aplicativo entender que a pessoa começou a se mover ativamente, a precisão aumentará novamente.

O código fonte completo para a versão iOS está disponível no GitHub . Aqui estão alguns pontos não óbvios que encontrei no processo de implementação:

Substituindo métodos NSApplicationDelegate em um aplicativo Qt

O SDK do iOS do VKontakte requer a adição de chamadas para algumas de suas funções no aplicativo: didFinishLaunchingWithOptions: e application: openURL: options: métodos. Antes de alguma versão do Qt (na minha opinião, antes da 5.11), bastava criar uma categoria para o QIOSApplicationDelegate assim:

@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate> @end @interface QIOSApplicationDelegate (QIOSApplicationDelegateVKGeoCategory) @end @implementation QIOSApplicationDelegate (QIOSApplicationDelegateVKGeoCategory) - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [...] } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { [...] } @end 

Mas nas versões recentes do Qt, o QIOSApplicationDelegate já possui uma implementação do aplicativo: openURL: options:, portanto a opção com categorias não rola mais. Eu tive que criar um herdador de QIOSApplicationDelegate e atribuir um delegado via setDelegate:

 @interface VKGeoApplicationDelegate : QIOSApplicationDelegate @end @implementation VKGeoApplicationDelegate - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { [...] } @end void InitializeVKGeoApplicationDelegate() { [[UIApplication sharedApplication] setDelegate:[[VKGeoApplicationDelegate alloc] init]]; } int main(int argc, char *argv[]) { [...] InitializeVKGeoApplicationDelegate(); [...] } 

Tratamento de erros do VKRequest

Diante do fato de que o VKRequest por erro retornou um NSError vazio (vazio). Fiz um patch que corrige o patch anterior de alguém e solicita o recebimento desse patch, mas ele ainda permanece nos não revisados.

Android


A seguir, a versão para Android. O código da GUI foi reutilizado quase completamente no iOS, para interagir com o VK, o VK Android SDK normal foi novamente usado, a interação com a qual ocorre através da JNI, o trabalho em segundo plano é implementado de acordo com os convênios do Google para tais aplicativos - ou seja, através do Serviço de Primeiro Plano. Obviamente, a lógica para reduzir o consumo de energia, semelhante à usada no iOS, também é implementada.

O conjunto completo de código-fonte da versão Android está disponível novamente no GitHub e aqui estão alguns pontos não óbvios que encontrei durante a implementação desta versão:

Como criar um serviço Android no Qt

Para criar um serviço no Qt 5.10, a classe QAndroidService apareceu, que deve ser usada em vez do QGuiApplication. Você pode compilar .so separado para atividade e serviço, ou pode usar um .so para tudo e, para que o código entenda em que modo ele funciona, você pode especificar esse modo através da tecla de linha de comando, algo como isto:

 <service android:name=".VKGeoService"> <meta-data android:name="android.app.arguments" android:value="-service"/> </service> 

 int main(int argc, char *argv[]) { if (argc == 1) { QGuiApplication app(argc, argv); [...] } else if (argc == 2 && QString(argv[1]) == "-service") { QAndroidService app(argc, argv); [...] } else { return 0; } } 

Atividade estranha "dangling" em onDestroy ()

No processo de implementação do serviço, um problema engraçado ficou claro - o QtActivity “travou” em algum lugar nas entranhas do onDestroy (), sujeito à disponibilidade de um serviço em primeiro plano. Aparentemente, o Qt não espera que, após a conclusão da atividade, algo mais permaneça no aplicativo. O problema foi resolvido espaçando a atividade e o serviço entre diferentes processos através do uso do android: process no manifesto:

 <service android:name=".VKGeoService" android:process=":VKGeoService"> [...] </service> 

e pregar o processo no qual a atividade está em execução, em um onDestroy () substituído:

 @Override public void onDestroy() { [...] /* * This call hangs when foreground service is running, * so we just kill activity process instead (service * is running in a different process). * * super.onDestroy(); */ Process.killProcess(Process.myPid()); } 

Sim, o fiapo jura constantemente, mas como lidar com isso de maneira diferente ainda não é óbvio para mim, mas colocar as mãos no QTBUG com PoC sobre esse tópico ainda não chegou a nada.

UPDATE : no Qt 5.12.3 (talvez um pouco mais cedo - não verifiquei), o bug com a suspensão de QtActivity.onDestroy () foi corrigido quando o serviço foi iniciado, essa solução alternativa não é mais necessária.

Chamada bloqueada ao cancelar o VKBatchRequest

Uso amplamente solicitações em lote para facilitar a carga nos servidores VKontakte e é no Android (tudo funciona bem no iOS) que encontrei um problema no caso de cancelar o VKBatchRequest errorBlocks e de solicitações canceladas. Corrigi esse problema na versão local da biblioteca, fiz o patch apropriado e solicitei esse patch, mas, novamente, ele permanece nos que não foram revisados.

Conclusão


A versão iOS da Apple foi facilmente colocada na App Store, e ainda está disponível lá; a versão Android permaneceu no Google Play por algum tempo até que a Política do Google Play fosse reforçada (ele prescreveu que os aplicativos que acompanham a localização geográfica devem ser explicitamente destinado a uso familiar ou corporativo), após o qual meu aplicativo foi bloqueado com segurança lá. Na minha tentativa de apelar, um funcionário responsável do Google (ou talvez tenha sido um bot, agora não é tão óbvio quem responde exatamente às suas perguntas) afirmou com firmeza que "bem, esse aplicativo NÃO PODE SER USADO SOMENTE para rastreamento familiar ou corporativo" , ao qual não consegui encontrar nada para argumentar - de fato, com um martelo, você pode não apenas martelar pregos, mas também socar a cabeça ... Coloquei a versão Android no Yandex.Store e na Amazon Appstore e como um APK no site do projeto.

Ficarei feliz se este aplicativo for útil a alguém como auxílio visual para esclarecer alguns momentos não óbvios ao escrever um aplicativo Qt para iOS / Android, especialmente aqueles relacionados à implementação do serviço Android no Qt (essa funcionalidade é relativamente nova, exemplos de implementação, quanto Eu não sei muito). Também terei prazer em responder às perguntas nos comentários, se houver.

Source: https://habr.com/ru/post/pt434996/


All Articles