Mobile - Detectando se o dispositivo é mobile ou não por php e javascript


Se antigamente nosso problema era saber se a meia duzia de browsers rodaria direito nosso javascript ou não (o que o JQuery resolveu para nós) hoje temos uma fauna gigantesca de dispositivos e browsers, fruto da expansão do mobile.

Nosso desafio é conseguir detectar que dispositivo está acessando o site ou aplicação e redirecionar o usuário para uma página ou URL que possua as configurações e layout corretos para o mesmo.

Existem algumas linhas de pensamento que acreditam que o que deve se adaptar automaticamente às dimensões do dispositivo é o css, sem muita ou nenhuma interferência de detecção (design responsivo) como a que proponho aqui, porém eu prefiro utilizar a abordagem da detecção e de versões diferentes do site para dispositivos mobile e web convencional, pois acredito que o problema não é somente o layout mas também o peso da navegação, o tipo de conteúdo direcionado e etc.

Há um bom tempo que venho pesquisando um meio bacana de fazer isto, que fosse confiável e que não exigisse passar várias horas programando ou reinventando a roda. Claro que muitas vezes temos que fazer aquela adaptada aqui e ali para funcionar "redondo" em nosso caso de uso. Com base nesta pesquisa é que posto aqui para vocês o que descobri.

Existem, básicamente, três abordagens para o problema:

Redirecionamento manual, redirecionamento por javascript e redirecionamento Server Side.

Redirecionamento Manual


O primeiro, redirecionamento manual, é o mais óbvio. Em algum lugar, posicionado estrategicamente no site, colocamos um link para a versão mobile, quando na versão web, ou um link para a versão web quando na versão mobile.

Esta abordagem pode parecer estúpida mas não é, pois pode ser que um usuário deseje navegar de maneira diferente dependendo do dispositivo ou mesmo caso o sistema automático de detecção não funcione para algum dispositivo muito específico.

É sempre uma boa alternativa dar a opção para que o próprio usuário selecione o dispositivo adequado. Sendo assim, independente das demais abordagens, acredito que esta deva ser considerada obrigatória.

Apenas lembre-se de utilizar algum tipo de session ou parâmetro via URL para indicar que o usuário selecionou esta ou aquela opção pois se não a cada link navegado ele terá de selecionar, novamente, a versão desejada.

Via Javascript


A segunda abordagem, via Javascript, é indicada para o pessoal que trabalha mais com Front End, que não tem acesso ao server side ou que o server não roda nenhum tipo de tecnologia PHP, Java, Rubi, etc.

Dentro desta abordagem existe a técnica da verificação das dimensões da tela. Telas menores que um certo padrão podem ser direcionadas para o mobile e as maiores para web. Apesar de ter sua utilidade não vou aborda-la pois não a considero tão elegante (apesar de útil).

O meio que considero mais elegante é trabalhar com a verificação do User Agent. Se abrirmos o console do Chrome e digitarmos:

"navigator.userAgent"

Veremos informações como:

"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22"

Baseado nesta idéia podemos criar o seguinte script:

(function(url){ if( /iPhone|iPad|iPod|Android|webOS|BlackBerry/i.test(navigator.userAgent) ) {
window.location=url;
}})('http://www.google.com')

A função anônima acima é executada assim que carregada. .test() faz a verificação da existência de qualquer uma das strings 'iPhone', 'iPad', etc. dentro da string retornada por 'navigator.userAgen'. Em caso positivo 'window.location' é ativado com o parâmetro url, que possui o valor 'http://www.google.com'.

Baseado nesta ideia podemos utilizar script abaixo, mais completo:

(function(a,B)
{
if  (/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile|o2|opera m(ob|in)i|palm( os)?|p(ixi|re)\/|plucker|pocket|psp|smartphone|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce; (iemobile|ppc)|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))
{
window.location = B;
}
}
)(navigator.userAgent||navigator.vendor||window.opera,'http://www.google.com');

Aqui o problema é que você terá de atualizar manualmente a lista de dispositivos. Consultar um Web Service com uma lista de dispositivos pode ser uma alternativa, porém teremos sempre o problema da latência na consulta a este serviço, além do que se o mesmo ficar fora do ar nosso script não terá como efetuar a consulta.

Via Server


A Terceia abordagem, via server, acredito ser melhor do que a via Javascript pois temos sempre mais controle no server do que no client.

Além disto acaba sendo mais leve e rápido para o usuário pois ele não precisa carregar um script para, só depois, ser redirecionado. O Server, ao ler o User Agent, já carrega a URL correta.

Para este exemplo utilizei o UASparder (http://user-agent-string.info/) que achei interessante. Ele é bem tranquilo de utilizar. Sua tabela de User Agents é atualizada uma vez por dia e ele utiliza um cache local para o processo de validação ser mais rápido.

Ao baixar o pacote ele traz um exemplo mais completo mas aqui vai um exemplo simples e funcional, que acredito ser o que a maioria vai precisar para seus projetos.

<?php

// Carrega a Classe de detecção
require 'UASparser.php';

// Instancia a classe
$parser = new UASparser();
$parser->SetCacheDir(getcwd()."/cache/");

// Recupera o User  Agent
$user_agent = $parser->Parse();

// Redireciona o usuário segundo critério de dispositivo
if  ($user_agent['typ'] == 'Mobile Browser')  {

header("Location: http://m.seusite/");

}

O Script acima instancia o Objeto '$parser' e, baseado na leitura do header, feita pelo método 'Parse()', extrai várias informações. Para nós a mais importante é $user_agent['typ'], que nos informa se é um dispositivo 'Mobile Browser' ou 'Browser'.

Por hoje é isto. Abraço!

Comentários

Postagens mais visitadas deste blog

MySQL - Completando quantidades fixas de caracteres com as funções LPAD() e RPAD()

MySQL - Clonando tabelas na linha de comando

PHP - Gerando arquivo em UTF-8 com fwrite() e utf8_encode()