Recentemente, tenho trabalhado com aplicativos móveis corporativos. Esses aplicativos não são distribuídos usando qualquer mercado, então eu preciso lidar com o processo de distribuição. Com o Android, você pode compilar seus aplicativos, criar seus arquivos APK e distribuí-los. Você pode enviar os arquivos por e-mail, usar um link para download, enviar o arquivo com bluetooth, ou qualquer outra coisa. Com o iOS é um pouco diferente. Você precisa comprar uma licença da empresa, compilar o aplicativo e distribuir seus arquivos IPA usando padrões da Apple.
OK, mas este artigo não é sobre como distribuir aplicativos fora dos mercados. Este artigo é sobre um grande problema que aparece quando precisamos atualizar nossos aplicativos: como é que o usuário sabe que tem uma nova versão do aplicativo e que precisa fazer o upgrade? Quando trabalhamos dentro da Google Play Store, não precisamos nos preocupar com isso, mas se nós distribuímos nossos aplicativos manualmente precisamos fazer alguma coisa. Podemos enviar notificações push ou e-mails para o usuário para informar sobre a nova versão. Deixe-me mostrar como estou fazendo isso.
Meu problema não é só informar o usuário sobre uma nova versão. Às vezes, eu também preciso garantir que o usuário execute a última versão do app. Imagine um bug crítico (corrigido no último lançamento), mas o usuário não atualiza.
Primeiro, precisamos criar uma página HTML estática, na qual o usuário pode baixar o arquivo APK. Imagine que esta é a URL na qual o usuário pode fazer o download da última versão do app:
http://192.168.1.1:8888/app.apk
Podemos verificar a versão do app em relação ao servidor cada vez que o usuário abre o aplicativo, mas essa verificação significa que a comunicação de rede e é lenta. Precisamos reduzir a comunicação entre o cliente e o servidor para a menor expressão, e somente quando for estritamente necessário. Verificar a versão cada vez pode ser bom para um aplicativo de desktop, mas reduz a experiência do usuário com os aplicativos móveis. Minha abordagem é um pouco diferente. Normalmente usamos a autenticação baseada em tokens dentro de aplicativos móveis. Isso significa que precisamos enviar o nosso token com toda solicitação. Se o enviarmos, podemos também enviar a versão.
Em um app angular, podemos definir a versão e caminho do nosso apk usando um armazenamento valor-chave.
.value('config', { version: 4, androidAPK: "http://192.168.1.1:8888/app.apk" })
Agora precisamos adicionar o parâmetro da versão a cada pedido (que pode criar facilmente um serviço http personalizado para anexar esse parâmetro automaticamente para cada solicitação, na verdade):
$http.get('http://192.168.1.1:8888/api/doSomething', {params: {_version: config.version}}) .success(function (data) { alert("OK"); }) .error(function (err, status) { switch (status) { case 410: $state.go('upgrade'); break; } });
Podemos criar um backend simples para cuidar da versão e gerar uma exceção HTTP (um erro HTTP 410, por exemplo), caso as versões não coincidam. Aqui você pode ver um exemplo Silex simples:
<?php include __DIR__ . "/../vendor/autoload.php"; use Silex\Application; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; $app = new Application([ 'debug' => true, 'version' => 4, ]); $app->after(function (Request $request, Response $response) { $response->headers->set('Access-Control-Allow-Origin', '*'); }); $app->get('/api/doSomething', function (Request $request, Application $app) { if ($request->get('_version') != $app['version']) { throw new HttpException(410, "Wrong version"); } else { return $app->json('hello'); } }); $app->run();
Como você pode ver, precisamos tomar cuidado com CORS.
Com esse exemplo simples, podemos ver se o usuário tem uma versão errada dentro de cada pedido do servidor. Se as versões não corresponderem, podemos, por exemplo, redirecionar para uma rota específica a fim de informar que o usuário precisa atualizar o aplicativo e fornecer um link para executar a ação.
Com o Android, não podemos criar um link para o arquivo APK. Não funciona. Precisamos fazer o download do APK (usando o plugin FileTransfer) e abrir o arquivo usando o plugin webintent.
O código é muito simples:
var fileTransfer = new FileTransfer(); fileTransfer.download(encodeURI(androidUrl), "cdvfile://localhost/temporary/app.apk", function (entry) { window.plugins.webintent.startActivity({ action: window.plugins.webintent.ACTION_VIEW, url: entry.toURL(), type: 'application/vnd.android.package-archive' }, function () { }, function () { alert('Failed to open URL via Android Intent.'); console.log("Failed to open URL via Android Intent. URL: " + entry.fullPath); }); }, function (error) { console.log("download error source " + error.source); console.log("download error target " + error.target); console.log("upload error code" + error.code); }, true);
E, basicamente, isso é tudo. Quando o usuário atualizar o app, ele fecha automaticamente e o usuário precisa abri-lo novamente, mas agora com a versão correta.
***
Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://gonzalo123.com/2014/07/28/upgrading-android-apps-outside-google-play-store-with-angularjs/