Iniciar aplicativo android personalizado a partir do navegador android

416

Alguém pode me orientar sobre como iniciar meu aplicativo Android a partir do navegador Android?

Parimal Modi
fonte

Respostas:

616

Use um <intent-filter>com um <data>elemento Por exemplo, para lidar com todos os links para twitter.com, você deve colocar isso dentro do seu <activity>no seu AndroidManifest.xml:

<intent-filter>
    <data android:scheme="http" android:host="twitter.com"/>
    <action android:name="android.intent.action.VIEW" />
</intent-filter>

Em seguida, quando o usuário clicar em um link para o Twitter no navegador, será perguntado qual aplicativo usar para concluir a ação: o navegador ou seu aplicativo.

Obviamente, se você deseja fornecer uma forte integração entre seu site e seu aplicativo, pode definir seu próprio esquema:

<intent-filter>
    <data android:scheme="my.special.scheme" />
    <action android:name="android.intent.action.VIEW" />
</intent-filter>

Em seu aplicativo da web, você pode colocar links como:

<a href="my.special.scheme://other/parameters/here">

E quando o usuário clicar nele, seu aplicativo será iniciado automaticamente (porque provavelmente será o único que pode lidar com o my.special.scheme://tipo de uris). A única desvantagem disso é que, se o usuário não tiver o aplicativo instalado, eles receberão um erro grave. E não tenho certeza de que haja alguma maneira de verificar.


Editar: para responder sua pergunta, você pode usar o getIntent().getData()que retorna um Uriobjeto. Você pode usar Uri.*métodos para extrair os dados necessários. Por exemplo, digamos que o usuário clicou em um link para http://twitter.com/status/1234:

Uri data = getIntent().getData();
String scheme = data.getScheme(); // "http"
String host = data.getHost(); // "twitter.com"
List<String> params = data.getPathSegments();
String first = params.get(0); // "status"
String second = params.get(1); // "1234"

Você pode fazer o que precede em qualquer lugar do seu computador Activity, mas provavelmente desejará fazê-lo onCreate(). Você também pode usar params.size()para obter o número de segmentos de caminho no Uri. Procure no javadoc ou no site do desenvolvedor do Android outros Urimétodos que você pode usar para extrair partes específicas.

Felix
fonte
6
Muito obrigado pela sua pronta resposta. Mas você pode me dizer como acessar os parâmetros após "my.special.scheme: //".
Parimal Modi
4
Editei minha resposta para incluir instruções sobre como extrair os dados do Uri. Marque esta resposta como aceita (somente) se você o considerar clicando na marca de seleção ao lado.
Felix
9
e se o aplicativo android direcionado não estiver instalado? Como lidar com isso.
Nemo
13
Qualquer pessoa que, como eu, seja incapaz de fazer esse esquema funcionar, precisa adicionar android:exported="true"ao Activitymanifesto deles . Verifique esta resposta stackoverflow.com/a/13044911/1276636
Sufian
4
Não tenho certeza de como isso está funcionando para o mundo inteiro. Apenas não funciona no chrome e sempre abre o link no navegador até você colocar o elemento "android: pathPrefix". De qualquer forma, a resposta não possui os valores de categoria mencionados na documentação. Se ainda não funcionar para alguém, consulte isso por favor: stackoverflow.com/a/21727055/2695276 PS: lutou durante dias por isso.
Rajat Sharma
70

Todas as respostas acima não funcionaram para mim CHROMEem 28 de janeiro de 2014

meu aplicativo foi iniciado corretamente a partir de http://example.com/someresource/ links de aplicativos como hangouts, gmail etc., mas não no navegador Chrome.

para resolver isso, para que seja iniciado corretamente a partir do CHROME, você deve definir um filtro de intenção como este

<intent-filter>
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <data
        android:host="example.com"
        android:pathPrefix="/someresource/"
        android:scheme="http" />
    <data
        android:host="www.example.com"
        android:pathPrefix="/someresource/"
        android:scheme="http" />
</intent-filter>

observe o pathPrefixelemento

seu aplicativo agora será exibido dentro do seletor de atividades sempre que o usuário solicitar http://example.com/someresource/ padrão no navegador Chrome clicando em um link dos resultados de pesquisa do Google ou em qualquer outro site

AndroidGecko
fonte
Isso me ajudou muito. Muito obrigado! Poste aqui sua resposta para que eu possa lhe dar a recompensa! stackoverflow.com/questions/21663001/…
Vlad Schnakovszki 12/02
Que língua é essa?
Dims
Olá, eu sei que é muito velho. Também estou impressionado com o mesmo cenário. Especifiquei pathPrefix, schema e host, mas não está funcionando. Eu tentei apenas com esquema, então funcionou. Mas quando adicionei host, ele parou de funcionar. Alguma idéia do que pode ser o problema?
Seema
Passei dias até chegar a essa resposta. Não tenho certeza de como funcionou para o mundo inteiro sem o elemento pathPrefix. Nunca trabalhei para mim no chrome, apesar de fazer tudo de acordo com a documentação. Muito obrigado.
Rajat Sharma
66

Por favor, veja meu comentário aqui: Faça um link no navegador Android iniciar meu aplicativo?

Nós desencorajamos fortemente as pessoas a usarem seus próprios esquemas, a menos que estejam definindo um novo esquema de internet em todo o mundo.

hackbod
fonte
10
O Hackbod é um dos engenheiros do Google por trás da plataforma Android. Provavelmente, é uma boa ideia seguir este conselho. De fato, parece que o suporte ao esquema personalizado quebrou no Honeycomb.
Nr3 de
23
Não posso ser responsabilizado por limitações impostas aos desenvolvedores pelo iOS. ;)
hackbod 15/05
12
responsabilizado? não. Mas você pode ter isso em conta, pois, independentemente de se você goste ou não, essas limitações são impostas em muitos de seus desenvolvedores
ByteMe
6
O hackbod está respondendo uma pergunta especificamente para o Android. Não há menção ao iOS; portanto, não é necessário levar isso em consideração.
Nilskp 29/07/2012
4
O @hackbod classificaria o namespace de um esquema (por exemplo, href = "com.ourdomain.myapp // qualquer que seja") uma boa prática, supondo que um link como esse pudesse ser encontrado em sites diferentes?
Julien Bérubé
48

No meu caso, tive que definir duas categorias para o <intent-filter>e funcionou:

<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
Zaki
fonte
2
O mesmo aqui, necessário para adicionar a categoria adicional.
KPK
Alguém pode explicar qual é o processo real de fazer isso? Qualquer link para a implementação exata, pré-requisitos, será útil. Graças
Ankit Garg
Testado na instalação do desenvolvedor. Na verdade, eu estava dando um nome de domínio errado. Foi mal.
Ankit Garg
A resposta mais votada não funcionou para mim, mas funcionou. Obrigado.
EL45
25

Por exemplo, você tem as seguintes coisas:

Um link para abrir seu aplicativo: http://example.com

O nome do pacote do seu aplicativo: com.example.mypackage

Então você precisa fazer o seguinte:

1) Adicione um filtro de intenção à sua atividade (pode ser qualquer atividade que você deseja. Para obter mais informações, consulte a documentação ).

        <activity
        android:name=".MainActivity">

        <intent-filter android:label="@string/filter_title_view_app_from_web">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <!-- Accepts URIs that begin with "http://example.com" -->

            <data
                android:host="example.com"
                android:scheme="http" />
        </intent-filter>

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity> 

2) Crie um arquivo HTML para testar o link ou use esses métodos.

<a href="intent://example.com#Intent;scheme=http;package=com.example.mypackage;end">Open your Activity directly (just open your Activity, without a choosing dialog). </a>

<a href="http://example.com">Open this link with browser or your programm (by choosing dialog).</a>

3) Use o Chrome móvel para testar

4) é isso.

E não é necessário publicar o aplicativo no mercado para testar links diretos =)

Além disso, para obter mais informações, consulte a documentação e a apresentação útil .

Denshov
fonte
Eu tive que criar um arquivo html e enviá-lo para fazê-lo funcionar. Eu me pergunto por que, espacialmente o segundo, não funciona diretamente de um navegador (chrome).
Makalele
18

Também deve ser <category android:name="android.intent.category.BROWSABLE"/>adicionado ao filtro de intenção para tornar a atividade reconhecida corretamente no link.

georgij
fonte
4
Para referência, adicionar CATEGORY_BROWSABLE significa que "A atividade de destino pode ser invocada com segurança pelo navegador para exibir dados referenciados por um link - por exemplo, uma imagem ou uma mensagem de email".
22612 greg7gkb
Esta é uma categoria existente ou você está propondo uma nova?
Anish
Isso existe. Aparentemente, você deve ter um host de site separado em diferentes tags de filtro de intenção ou isso causa problemas.
NoBugs 13/10/12
2
Não apenas navegável, mas também android.intent.category.DEFAULT - para que o link pode ser aberto quando iniciado em outros aplicativos, como e-mail (e não apenas os navegadores)
AlikElzin-Kilaka
8

O link a seguir fornece informações sobre como iniciar o aplicativo (se instalado) diretamente do navegador. Caso contrário, ele abrirá diretamente o aplicativo na Play Store para que o usuário possa fazer o download sem problemas.

https://developer.chrome.com/multidevice/android/intents

Varun Bhatia
fonte
7

Observe que se seu ícone desaparecer do iniciador de Android quando você implementa esse recurso, é necessário dividir o filtro de intenção.

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="your-own-uri" />
        </intent-filter>
    </activity>
Zoltan
fonte
5

Xamarin porto de Felix resposta

No seu MainActivity, adicione este ( docs: Android.App.IntentFilterAttribute Class ):

....
[IntentFilter(new[] { 
    Intent.ActionView }, 
    Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, 
    DataScheme = "my.special.scheme")
]
public class MainActivity : Activity
{
    ....

O Xamarin adicionará o seguinte no AndroidManifest.xmlpara você:

<activity
    android:label="Something"
    android:screenOrientation="portrait"
    android:theme="@style/MyTheme"
    android:name="blah.MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="my.special.scheme" />
    </intent-filter>
</activity>

E para obter parâmetros ( eu testei no OnCreate of MainActivity ):

var data = Intent.Data;
if (data != null)
{
    var scheme = data.Scheme;
    var host = data.Host;
    var args = data.PathSegments;

    if (args.Count > 0)
    {
        var first = args[0];
        var second = args[1];
        ...
    }
}

Até onde eu sei, acima pode ser adicionado em qualquer atividade, não apenas na MainActivity

Notas:

  1. Quando o usuário clica no link, o sistema operacional Android reinicia seu aplicativo (interrompe a instância anterior, se houver, e execute uma nova) , significa o OnCreateevento deMainLauncher Activity será acionado novamente.
  2. Com este link :, <a href="my.special.scheme://host/arg1/arg2">acima do último valor do snippet de código será:
scheme: my.special.scheme
host: host
args: ["arg1", "arg2"]
first: arg1
second: arg2

Atualização: se o Android criar uma nova instância do seu aplicativo, você deverá adicionar android:launchMode="singleTask"também.

Mehdi Dehghani
fonte
3

A abordagem de Felix para lidar com links diretos é a abordagem típica para lidar com links diretos. Eu também sugeriria verificar esta biblioteca para lidar com o roteamento e análise de seus links diretos:

https://github.com/airbnb/DeepLinkDispatch

Você pode usar anotações para registrar sua Atividade para um URI de link direto específico, e ele extrairá os parâmetros para você sem ter que executar o procedimento usual de obter os segmentos do caminho, combiná-lo etc. Você pode simplesmente fazer anotações e atividades como esta :

@DeepLink("somePath/{someParameter1}/{someParameter2}")
public class MainActivity extends Activity {
   ...
}
cristão
fonte
0

Ei, eu tenho a solução. Eu não defini a categoria como "Padrão". Também estava usando a atividade Main para a intenção Data. Agora estou usando uma atividade diferente para os dados de intenção. Obrigado pela ajuda. :)

Parimal Modi
fonte
Parece improvável (embora reconheça que essa é uma pergunta antiga e que talvez as coisas tenham mudado.) De developer.android.com/guide/components/intents-filters.html#ifs "Para uma intenção de passar no teste de categoria, todas as categorias em o objeto Intent deve corresponder a uma categoria no filtro . O filtro pode listar categorias adicionais, mas não pode omitir nenhum que esteja na intenção. "
Noach Magedman
0

Você precisa adicionar um pseudo-nome de host ao aplicativo CALLBACK_URL ': //' não faz sentido como um URL e não pode ser analisado.

Paul Lindner
fonte
0

example.php:

<?php
if(!isset($_GET['app_link'])){  ?>   
    <iframe src="example.php?app_link=YourApp://blabla" style="display:none;" scrolling="no" frameborder="0"></iframe>
    <iframe src="example.php?full_link=http://play.google.com/xyz" style="display:none;" scrolling="no" frameborder="0"></iframe>
    <?php 
}
else { ?>
    <script type="text/javascript">
    self.window.location        = '<?php echo $_GET['app_link'];?>';
    window.parent.location.href = '<?php echo $_GET['full_link'];?>';
    </script>
<?php 
}
T.Todua
fonte
1
Isso cria dois iframes invisíveis: link direto e link normal. Se o aplicativo estiver instalado, o link direto iframe o iniciará. Caso contrário, o link normal é exibido. Com algum trabalho extra, a vinculação profunda adiada pode ser implementada onde o link direto é chamado após a instalação do aplicativo.
Dominic Cerisano
0

Veja a resposta @JRuns aqui . A idéia é criar html com seu esquema personalizado e enviá-lo para algum lugar. Então, se você clicar no seu link personalizado no seu arquivo html, você será redirecionado para o seu aplicativo. Eu usei este artigo para o Android. Mas não se esqueça de definir o Name = "MyApp.Mobile.Droid.MainActivity"atributo de nome completo para sua atividade de destino.

S. Koshelnyk
fonte
0

A partir de 15/06/2019

o que fiz foi incluir todas as quatro possibilidades para abrir o URL.

ou seja, com http/ httpse 2 com wwwno prefixo e 2 semwww

e, usando isso, meu aplicativo é iniciado automaticamente agora sem me pedir para escolher um navegador e outra opção.

<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <data android:scheme="https" android:host="example.in" />
    <data android:scheme="https" android:host="www.example.in" />
    <data android:scheme="http" android:host="example.in" />
    <data android:scheme="http" android:host="www.example.in" />

</intent-filter>
Vicky Salunkhe
fonte