Inicie la aplicación de Android personalizada desde el navegador de Android

Respuestas:

616

Use un <intent-filter>con un <data>elemento. Por ejemplo, para manejar todos los enlaces a twitter.com, debe poner esto dentro de su <activity>en su AndroidManifest.xml:

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

Luego, cuando el usuario hace clic en un enlace a Twitter en el navegador, se le preguntará qué aplicación usar para completar la acción: el navegador o su aplicación.

Por supuesto, si desea proporcionar una estrecha integración entre su sitio web y su aplicación, puede definir su propio esquema:

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

Luego, en su aplicación web puede poner enlaces como:

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

Y cuando el usuario hace clic en él, su aplicación se iniciará automáticamente (porque probablemente será la única que puede manejar el my.special.scheme://tipo de uris). El único inconveniente de esto es que si el usuario no tiene la aplicación instalada, recibirá un error desagradable. Y no estoy seguro de que haya alguna forma de verificarlo.


Editar: para responder a su pregunta, puede usar getIntent().getData()que devuelve un Uriobjeto. Luego puede usar Uri.*métodos para extraer los datos que necesita. Por ejemplo, supongamos que el usuario hizo clic en un enlace 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"

Puedes hacer lo anterior en cualquier lugar de tu Activity, pero probablemente quieras hacerlo onCreate(). También puede usar params.size()para obtener el número de segmentos de ruta en Uri. Busque en javadoc o en el sitio web para desarrolladores de Android otros Urimétodos que puede usar para extraer partes específicas.

Felix
fuente
66
Muchas gracias por su pronta respuesta. Pero, ¿puede decirme cómo acceder a los parámetros después de "my.special.scheme: //".
Parimal Modi
44
Edité mi respuesta para incluir instrucciones sobre cómo extraer los datos del Uri. Marque esta respuesta como aceptada (solo) si lo considera así haciendo clic en la marca de verificación junto a ella.
Felix
99
¿Qué pasa si la aplicación de Android objetivo no está instalada? Cómo manejar esto.
Nemo
13
Cualquiera que, como yo, no pueda hacer funcionar este esquema, necesita agregarlo android:exported="true"a su Activitymanifiesto. Comprueba esta respuesta stackoverflow.com/a/13044911/1276636
Sufian
44
No estoy seguro de cómo funciona esto para todo el mundo. Simplemente no funciona en Chrome y siempre abre el enlace en el navegador hasta que coloque el elemento "android: pathPrefix". La respuesta de todos modos no tiene los valores de categoría como se menciona en la documentación. Si todavía no funciona para alguien, consulte esto por favor: stackoverflow.com/a/21727055/2695276 PD: luché durante días por esto.
Rajat Sharma
71

Todas las respuestas anteriores no funcionaron para mí CHROMEal 28 de enero de 2014

mi aplicación se inició correctamente desde http://example.com/someresource/ enlaces desde aplicaciones como hangouts, gmail, etc. pero no desde el navegador Chrome.

para resolver esto, para que se inicie correctamente desde CHROME, debe establecer un filtro de intención 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>

tenga en cuenta el pathPrefixelemento

su aplicación ahora aparecerá dentro del selector de actividad cuando el usuario solicite el patrón http://example.com/someresource/ del navegador Chrome haciendo clic en un enlace de los resultados de búsqueda de Google o en cualquier otro sitio web

AndroidGecko
fuente
Esto me ayudó mucho. ¡Muchas gracias! ¡Por favor publique su respuesta aquí para que pueda otorgarle la recompensa! stackoverflow.com/questions/21663001/…
Vlad Schnakovszki
¿Qué lenguaje es este?
Atenúa el
Hola, sé que es muy viejo. También estoy sorprendido en el mismo escenario. He especificado pathPrefix, esquema y host, pero no funciona. Lo intenté solo con el esquema, luego funcionó. Pero cuando agregué host, dejó de funcionar. ¿Alguna idea de cuál puede ser el problema?
seema
Pasé días sobre eso hasta que llegué a esta respuesta. No estoy seguro de cómo funcionó para todo el mundo sin el elemento pathPrefix. Nunca funcionó para mí en Chrome a pesar de hacer todo según la documentación. Muchas gracias.
Rajat Sharma
66

Por favor vea mi comentario aquí: ¿ Hacer un enlace en el navegador de Android inicia mi aplicación?

Recomendamos encarecidamente a las personas que no usen sus propios esquemas, a menos que estén definiendo un nuevo esquema mundial de Internet.

hackbod
fuente
10
Hackbod es uno de los ingenieros de Google detrás de la plataforma Android. Probablemente sea una buena idea seguir este consejo. De hecho, parece que el soporte de esquemas personalizados como este se rompió en Honeycomb.
RMN
23
No me hago responsable de las limitaciones impuestas a los desarrolladores por iOS. ;)
Hackbod
12
¿considerada responsable? No. Pero podría tenerlo en cuenta ya que, independientemente de si le gusta o no, esas limitaciones se imponen a muchos de sus desarrolladores
ByteMe
66
hackbod está respondiendo una pregunta específicamente para Android. No se menciona iOS, por lo que no es necesario tenerlo en cuenta.
nilskp
44
@hackbod sería un buen esquema de espacios de nombres (es decir, href = "com.ourdomain.myapp // lo que sea") una buena práctica, suponiendo que se pueda encontrar un enlace como ese en diferentes sitios web.
Julien Bérubé
48

En mi caso, tuve que establecer dos categorías para el <intent-filter>y luego funcionó:

<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
fuente
2
Lo mismo aquí, necesario para agregar la categoría adicional.
KPK
¿Alguien puede explicar cuál es el proceso real de hacer esto? Cualquier enlace a la implementación exacta, los requisitos previos serán útiles. Gracias
Ankit Garg
Probado en la configuración de desarrollo. En realidad estaba dando un nombre de dominio incorrecto. Culpa mía.
Ankit Garg
La respuesta mejor calificada no funcionó para mí, pero esto sí. Gracias.
EL45
25

Por ejemplo, tienes las siguientes cosas:

Un enlace para abrir su aplicación: http://example.com

El nombre del paquete de su aplicación: com.example.mypackage

Entonces debes hacer lo siguiente:

1) Agregue un filtro de intención a su Actividad (puede ser cualquier actividad que desee. Para obtener más información, consulte la documentación ).

        <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) Cree un archivo HTML para probar el enlace o use estos 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 Mobile Chrome para probar

4) Eso es todo.

Y no es necesario publicar aplicaciones en el mercado para probar enlaces profundos =)

Además, para obtener más información, consulte la documentación y la presentación útil .

Denshov
fuente
Tuve que crear un archivo html y subirlo para que funcione. Me pregunto por qué, espacialmente el segundo, no funciona directamente desde un navegador (Chrome).
Makalele
18

También debe <category android:name="android.intent.category.BROWSABLE"/>agregarse al filtro de intención para que la actividad se reconozca correctamente desde el enlace.

georgij
fuente
44
Como referencia, agregar CATEGORY_BROWSABLE significa que "el navegador puede invocar de manera segura la actividad objetivo para mostrar los datos a los que hace referencia un enlace, por ejemplo, una imagen o un mensaje de correo electrónico".
greg7gkb
¿Es esta una categoría existente o está proponiendo una nueva?
Anish
Existe. Aparentemente, debe tener un host de sitio web separado en diferentes etiquetas de filtro de intención, o puede causar problemas.
NoBugs
2
No solo NAVEGABLE, sino también android.intent.category.DEFAULT, por lo que el enlace se puede abrir cuando se inicia en otras aplicaciones, como el correo electrónico (no solo navegadores)
AlikElzin-kilaka
8

El siguiente enlace proporciona información sobre cómo iniciar la aplicación (si está instalada) directamente desde el navegador. De lo contrario, abre directamente la aplicación en Play Store para que el usuario pueda descargar sin problemas.

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

Varun Bhatia
fuente
7

Tenga en cuenta que si su icono desaparece del iniciador de Android cuando implemente esta función, debe dividir el filtro de intención.

    <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
fuente
5

Xamarin puerto de la respuesta de Félix

En su MainActivity, agregue esto ( docs: Android.App.IntentFilterAttribute Class ):

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

Xamarin agregará lo siguiente AndroidManifest.xmlpara usted:

<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>

Y para obtener parámetros ( probé en 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];
        ...
    }
}

Hasta donde sé, lo anterior se puede agregar en cualquier actividad, no solo en MainActivity

Notas:

  1. Cuando el usuario hace clic en el enlace, el sistema operativo Android reinicia su aplicación (elimine la instancia anterior, si la hay, y ejecute una nueva) , significa que el OnCreateevento de la aplicación se MainLauncher Activityactivará nuevamente.
  2. Con este enlace: <a href="my.special.scheme://host/arg1/arg2">en el último fragmento de código anterior, los valores serán:
scheme: my.special.scheme
host: host
args: ["arg1", "arg2"]
first: arg1
second: arg2

Actualización: si Android crea una nueva instancia de su aplicación, también debe agregarla android:launchMode="singleTask".

Mehdi Dehghani
fuente
3

El enfoque de Felix para manejar enlaces profundos es el enfoque típico para manejar enlaces profundos. También sugeriría revisar esta biblioteca para manejar el enrutamiento y el análisis de sus enlaces profundos:

https://github.com/airbnb/DeepLinkDispatch

Puede usar anotaciones para registrar su Actividad para un URI de enlace profundo particular, y extraerá los parámetros por usted sin tener que hacer el rigmarole habitual de obtener los segmentos de ruta, hacer coincidirlos, etc. Simplemente podría anotar y realizar actividades como esta :

@DeepLink("somePath/{someParameter1}/{someParameter2}")
public class MainActivity extends Activity {
   ...
}
cristiano
fuente
0

Hola, tengo la solución. No configuré la categoría como "Predeterminada". También estaba usando la actividad Principal para los datos de intención. Ahora estoy usando una actividad diferente para los datos de intención. Gracias por la ayuda. :)

Modi Parimal
fuente
Suena poco probable (aunque reconozco que esta es una pregunta antigua y tal vez las cosas han cambiado). De developer.android.com/guide/components/intents-filters.html#ifs "Para intentar pasar la prueba de categoría, cada categoría en el objeto Intención debe coincidir con una categoría en el filtro . El filtro puede enumerar categorías adicionales, pero no puede omitir ninguna que esté en la intención ".
Noach Magedman
0

Debe agregar un pseudonombre de host a CALLBACK_URL 'app: //' no tiene sentido como URL y no se puede analizar.

Paul Lindner
fuente
0

ejemplo.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
fuente
1
Esto crea dos iframes invisibles: enlace profundo y enlace normal. Si la aplicación está instalada, el iframe de enlace profundo la abrirá. Si no, se muestra el enlace normal. Con algo de trabajo adicional, se podría implementar el enlace profundo diferido donde se llama al enlace profundo después de instalar la aplicación.
Dominic Cerisano
0

Mira la respuesta de @JRuns aquí . La idea es crear html con su esquema personalizado y subirlo a alguna parte. Luego, si hace clic en su enlace personalizado en su archivo html, será redirigido a su aplicación. Usé este artículo para Android. Pero no olvide establecer el Name = "MyApp.Mobile.Droid.MainActivity"atributo de nombre completo para su actividad objetivo.

S. Koshelnyk
fuente
0

A partir del 15/06/2019

lo que hice fue incluir las cuatro posibilidades para abrir url.

es decir, con http/ httpsy 2 con wwwprefijo y 2 sinwww

y al usar esto, mi aplicación se inicia automáticamente ahora sin pedirme que elija un navegador y otra opción.

<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
fuente