Solução Deeplink para aplicativos IOS e Android funciona no Facebook

Há muitos tutoriais do Deep Linking (links universais ou links de aplicativos). Mas a maioria deles mostra como ativá-lo no Android ou no IOS Apps. Também existem soluções de nuvem pagas, mas elas oferecem muitos resources. Mas há três problemas principais que enfrentei na vida real:

  1. Alguns navegadores não permitem que os links de aplicativos funcionem. Por exemplo, você pode configurar http://example.com para ser pego no aplicativo, mas se esse link for clicado pelo usuário através do aplicativo do Facebook, ele não será tratado e o navegador do Facebook mostrará o site.
  2. Não existe uma solução padrão exclusiva para lidar com links para aplicativos Android e IOS.
  3. Nenhuma solução prática se o aplicativo não estiver instalado no dispositivo móvel e o usuário clicar em um link do aplicativo.

Eu escrevi este Q & A que é o resultado dos meus estudos (passei muitas horas) para ter uma solução única e funcional para todos os casos.

Os códigos estão vindo da minha solução de trabalho, mas eu removi algumas partes apenas para mostrar a ideia. Se houver alguns problemas de compilation, siga o algoritmo e escreva seu próprio código

Aqui está a solução, vá passo a passo, mesmo que você saiba alguns passos, porque existem truques nos códigos. Além disso, algumas explicações estão nas linhas de comentário das partes do código, por favor, leia-as.

Os exemplos são para lidar com deeplink http://example.com/v/ pelos seus aplicativos Android e IOS com um argumento no final, por exemplo, http://example.com/v/id-of-user?key=value.

1. Configurando o Android

1.1 Adicione informações de atividade ao seu arquivo AndroidManifest.xml:

              

1.2 Crie uma atividade chamada appLinkHandlerActivity que manipulará os links clicados

  public class appLinkHandlerActivity extends AppCompatActivity { /* assume that user is clicked http://example.com/v/my-user-id actCode will be “v”, pCode will be “my-user-id” */ String actCode="", pCode=""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ATTENTION: This was auto-generated to handle app links. Intent appLinkIntent = getIntent(); String appLinkAction = appLinkIntent.getAction(); Uri appLinkData = appLinkIntent.getData(); String code = null; try { code = getIntent().getData().getLastPathSegment(); } catch (Exception e) { } if (code == null) { Intent i = new Intent(this, {your main activity.class}); startActivity(i); } List params=appLinkData.getPathSegments(); if (params.size()>0) actCode=params.get(0); if (params.size()>=2) pCode=params.get(1); /* assume that user is clicked http://example.com/v/my-user-id actCode is “v”, pCode is “my-user-id” Do now whatever you need. */ } } 

2. Configurando o IOS

Isso é mais complexo que o Android, vou explicar os pontos necessários aqui. Consulte os documentos: https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW1

https://www.raywenderlich.com/128948/universal-links-make-connection

2.1 Você precisa ativar os domínios associados ao criar um ID de aplicativo no Apple Developer Portal. Problema importante: você precisa ter uma Conta de Desenvolvedor da Apple comprada para ativar essa opção, o que significa que, sem comprar uma conta de desenvolvedor, você não pode experimentar os AppLinks em seu projeto do IOS.

2.2 No projeto XCode, abra a guia “Capabilites” e altere Associated Domains para On. Se você não habilitou Domínios Associados na seção ID do Aplicativo do Apple Developer Portal, isso pode não ser selecionável. Adicione um direito clicando no botão + na opção Domínios Associados, escreva “applinks: exemplo.com”.

2.3 Crie um arquivo no seu servidor web chamado “apple-app-site-association” e este arquivo deve ser acessado através de https://example.com/apple-app-site-association HTTPS é obrigatório e se não for válido O certificado SSL App Link pode não funcionar. Adicione as seguintes linhas no arquivo apple-app-site-association:

 { "applinks": { "apps": [], "details": [ { "appID": "6HY7TF56.com.example.app", "paths": [ "/ios/*", "/v/*" ] } ] } } 

appID é o formato de {“ID da equipe”. ”ID do pacote do seu aplicativo”}. Você pode encontrar seu teamID na seção Detalhes do membro no Portal do desenvolvedor.

Nós lidamos com o link http://example.com/v/parameters, mas aqui você vê que há outra configuração de caminho para “/ ios / *”. É necessário contornar navegadores não suportados, explicarei mais tarde.

2.4 No arquivo AppDelegate.m, adicione dois methods para manipular os cliques do usuário em example.com

 -(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{ if ([userActivity.activityType isEqualToString: NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; [self parseUrl:url]; } return YES; } - (void) parseUrl:(NSURL * )handledUrl { NSString *urlStr=@""; NSString *pCode=@""; NSString *handledUrlStr=[handledUrl parameterString]; NSString *handledUrlQueryPart; NSArray *pathsArray= [handledUrl pathComponents]; //remember that we only added paths “/v/*” and “/ios/*” to handle in apple-app-site-association file. If you want to handle more subpaths you can add them into apple-app-site-association file, then below if-else conditions. Don't touch to config and code for “/ios/*” path, it is needed to bypass unsopported browsers. if ([pathsArray[1] isEqual: @"v"]){ //sample url= http://example.com/v/menu?aaa=bbb pCode = pathsArray[2]; handledUrlQueryPart=[handledUrl query]; } else if ([pathsArray[1] isEqual: @"ios"]){ //sample url= http://example.com/ios/deeplink-ios.php?/v/menu?aaa=bbb NSArray *uriArray = [[handledUrl query] componentsSeparatedByString:@"?"]; NSArray *queryPathsArray = [uriArray[0] componentsSeparatedByString:@"/"]; if ([queryPathsArray count] > 2) pCode = queryPathsArray[2]; if ([uriArray count] > 1 ){ handledUrlQueryPart=uriArray[1]; } } /* here pCode is the parameter what is passed from user. If the link clicked is http://example.com/v/menu it is “menu”. If the link clicked is http://example.com/v/menu?aaa=bbb it is “menu?aaa=bbb”. So you can do now what ever you need. */ } 

3. Gerenciando os cliques não atendidos.

3.1 Ok, seus aplicativos Android e IOS devem manipular os cliques no link http://example.com/v/blabla e passar o parâmetro “blabla” para a variável pCode usada nos methods que mostrei. Mas alguns navegadores, como o aplicativo do Facebook, podem desativar os Links de aplicativos para funcionar. Nesse caso, o clique do usuário vai para o servidor da Web e o navegador tenta mostrar o conteúdo de http://example.com/v/blabla, que provavelmente é 404 Página não encontrada. Para lidar com esses cliques, vamos configurar o servidor web Apache e redirect os usuários para o seu aplicativo. Se você usa o IIS ou outro, eu não sei como fazê-lo, mas você pode pegar isso como exemplo e usar o mesmo algortim para configurar seu servidor web.

3.2 Escreva as linhas abaixo no arquivo .htaccess no diretório raiz de example.com

 #redirect to deeplink  #if there is a request to example.com/v/any-sub-path, redirect them to example.com/deeplink.php file. This rule is for both IOS and Android RewriteRule ^(v)/.* /deeplink.php [L] #if there is a request to example.com/ios/any-sub-path, redirect them to app installation page. That means your app is not installed on IOS device. This rule is for IOS devices only RewriteRule ^(ios)/.* http://itunes.apple.com/install-of-your-app [L]  

4. Redirecionar usuários para aplicativos

4.1 As regras de redirecionamento no arquivo .htaccess mostrado na etapa 3 redirecionam os usuários para o arquivo deeplink.php. Então aqui está o conteúdo desse arquivo para redirect os usuários para o seu aplicativo.

  <?php $request_uri=$_SERVER[REQUEST_URI]; $ua = strtolower($_SERVER['HTTP_USER_AGENT']); if(stripos($ua,'android') == true){ //if user device is android, redirect it to intent url which is handled by Android. $redir_tag=""; //scheme=myapp and host named “share” is configured in AndroidManifest.xml file to be handled by the activity. //fallback url is the url, if your app is not installed on android device, so you can redirect them to a page to install android app. In some cases users are redirected to Play Store directly for application id of com.example.app } else if ( (stripos($ua,'iPhone') == true) || (stripos($ua,'iPad') == true) ) { //if user device is IOS, redirect them to a web page to see. There will be a link here to the another handled link: http://example.com/ios/blabla. // due to my experience there is no way to redirect IOS to app directly at this stage, user must click a link on browser and that link must be different than the link which was shown and clicked at first. // another experience taught me ther ecan be problems if we redirect users to a web page under example.com which is configured as applink, so I redirect users to a page under deep.example.com here $redir_tag=""; } else { //If the device is neither IOS nor Android, redirect users to a web page which gives information that this link is for Android and IOS only $redir_tag=""; } ?>            

5. Mostrar aos usuários do IOS um link para clicar

5.1 Aqui está o conteúdo do arquivo http://deep.example.com/deeplink-ios.php. Os usuários verão uma página como abaixo, quando clicaram no link, essa solicitação deve ser tratada pelo seu aplicativo IOS.

 <?php //we create a link to http://example.com/ios/… which is configure to be handled by IOS app. IOS needs to be a user click in some cases to handle the request, that is why this page is shown to the user $request_uri=$_SERVER[REQUEST_URI]; $link=""; ?>                

6. Análise de Casos:

6.1 Android

6.1.1 Caso 1 – o aplicativo é instalado no dispositivo
• Solicitações do navegador para http://example.com/v/blabla
• Android pega o link e cria a atividade configurada no seu arquivo de manifesto

6.1.2 Caso 2 – o aplicativo é instalado no dispositivo
• Solicitações do navegador para http://example.com/v/blabla
• Android não pode pegar o link.
• Navegador se conecta ao servidor web, solicitação de / v / blabla
• É redirecionado para deeplink.php? / V / blabla devido a configuração no arquivo .htaccess
• deeplink.php descobre que é android e redireciona para: intent: // share / v / blabla / # Intent; scheme = myapp; S.browser_fallback_url = http% 3A% 2F% 2Fexample.com% 2Fget-app% 2F; package = com.example.app
• Android pega a solicitação que é para intenção: //, então devido a configuração no arquivo de manifesto myapp: // share / v / blabla é tratado pela atividade

6.1.3 Caso 3 – o aplicativo não está instalado
• Solicitações do navegador para http://example.com/v/blabla
• Android não pode pegar o link.
• Navegador se conecta ao servidor web, solicitação de / v / blabla
• É redirecionado para deeplink.php? / V / blabla devido a configuração no arquivo .htaccess
• deeplink.php descobre que é android e redireciona para: intent: // share / v / blabla / # Intent; scheme = myapp; S.browser_fallback_url = http% 3A% 2F% 2Fexample.com% 2Fget-app% 2F; package = com.example.app
• Android pega o pedido que é para intenção: //, mas não há aplicativo instalado para id: com.example.app. Falbacks e redirecionam o navegador para http://example.com/get-app ou para a página de instalação da Play Store do seu aplicativo em alguns casos

6,2 IOS

6.2.1 Caso 1 – o aplicativo é instalado no dispositivo
• Solicitações do navegador para http://example.com/v/blabla
• O IOS captura o link e chama o método continueUserActivity em AppDelegate.m

6.2.2 Caso 2 – o aplicativo é instalado no dispositivo
• Solicitações do navegador para http://example.com/v/blabla
• O IOS não pode pegar o link.
• Navegador se conecta ao servidor web, solicitação de / v / blabla
• É redirecionado para deeplink.php? / V / blabla devido a configuração no arquivo .htaccess
• deeplink.php aprende que é o IOS e redireciona para: http://deep.example.com/deeplink-ios.php?/v/blabla
• O arquivo deeplink-ios.php mostra uma URL para o usuário. URL é: http://lify.me/ios/v/blabla
• O usuário clica no URL e nas solicitações do navegador para http://lify.me/ios/v/blabla
• O IOS captura a solicitação devido à configuração do caminho “/ ios / *” no arquivo apple-app-site-association e chama o método continueUserActivity em AppDelegate.m
• Se o IOS não conseguir atender à solicitação de http://lify.me/ios/v/blabla por qualquer motivo, ele se comportará quando o aplicativo não estiver instalado no dispositivo. Veja esse caso.

6.2.3 Caso-2 – o aplicativo não está instalado no dispositivo
• Solicitações do navegador para http://example.com/v/blabla
• O IOS não pode pegar o link.
• Navegador se conecta ao servidor web, solicitação de / v / blabla
• É redirecionado para deeplink.php? / V / blabla devido a configuração no arquivo .htaccess
• deeplink.php aprende que é o IOS e redireciona para: http://deep.example.com/deeplink-ios.php?/v/blabla
• O arquivo deeplink-ios.php mostra uma URL para o usuário. URL é: http://lify.me/ios/v/blabla
• O usuário clica no URL e nas solicitações do navegador para http://lify.me/ios/v/blabla
• Se o IOS não puder atender à solicitação de http://lify.me/ios/v/blabla
• Navegador se conecta ao servidor web, solicitação de / ios / v / blabla
• É redirecionado para http://itunes.apple.com/install-of-your-app devido à configuração no arquivo .htaccess no servidor web

6.3 App Link é clicado no dispositivo não Android ou IOS
• Solicitações do navegador para http://example.com/v/blabla
• O sistema operacional do dispositivo não pode capturar o link.
• Navegador se conecta ao servidor web, solicitação de / v / blabla
• É redirecionado para deeplink.php? / V / blabla devido a configuração no arquivo .htaccess
• deeplink.php aprende que não é nem iOS nem Android, e redireciona para: http://example.com/non-mobile

Intereting Posts