¿Hacer un enlace en el navegador de Android inicia mi aplicación?

229

¿Es posible hacer un enlace como:

<a href="anton://useful_info_for_anton_app">click me!</a>

hacer que mi aplicación Anton se inicie?

Sé que esto funciona para la aplicación Android Market con el protocolo de mercado, pero ¿se puede hacer algo similar con otras aplicaciones?

Aquí hay un ejemplo de un enlace que iniciará Android Market:

<a href="market://search?q=pname:com.nytimes.android">click me!</a>

Actualización: la respuesta que acepté proporcionada por eldarerathis funciona muy bien, pero solo quiero mencionar que tuve algunos problemas con el orden de los subelementos de la <intent-filter>etiqueta. Le sugiero que simplemente haga otro <intent-filter>con los nuevos subelementos en esa etiqueta para evitar los problemas que tuve. Por ejemplo mi se AndroidManifest.xmlve así:

<activity android:name=".AntonWorld"
          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>
        <data android:scheme="anton" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
Anton
fuente
Esto resolvió mi problema cuando no puedo abrir la aplicación en mi móvil.
Unomono
99
+1 por mencionar el orden de las etiquetas xml. No tiene ningún sentido y no está documentado en ninguna parte, pero descubrí que cuando tenía la etiqueta de datos debajo de las etiquetas de acción y categoría, simplemente no funcionaba.
Adam
Redirigir a la aplicación y retroceder correctamente si la aplicación no está presente también puede ser una pesadilla, dada la complejidad de todos los diferentes navegadores de Android (Chrome, Predeterminado, Webviews, Firefox, etc.). El servicio branch.io ayuda a hacer esto y es gratis.
Alex Austin
@ Anton ... hola señor ... por el código anterior, solo entiendo cómo manejar los datos del enlace ... ¿Puede decirme cómo puedo crear un enlace que contenga mis datos ... ayuda? yo ... Quiero crear el enlace con datos sobre el evento de clic del botón ...
Ravindra Kushwaha
1
⚠️Me tropecé con un obstáculo de depuración que otros también deberían tener en cuenta: los enlaces funcionan desde <a href=""> enlaces en páginas web y cuando se inician con adb, pero ahora cuando solo escribes la URL en el móvil barra de direcciones del navegador.⚠️
Johannes Brodwall

Respuestas:

96

Creo que querrás ver el <intent-filter>elemento de tu archivo Mainfest. Específicamente, eche un vistazo a la documentación del <data>subelemento.

Básicamente, lo que tendrá que hacer es definir su propio esquema. Algo en la línea de:

<intent-filter>
    <data android:scheme="anton" />
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" /> <--Not positive if this one is needed
    ...
</intent-filter>

Entonces debería poder iniciar su aplicación con enlaces que comienzan con el anton:esquema URI.

eldarerathis
fuente
3
Intenta echar un vistazo a este hilo. Tiene un buen ejemplo: stackoverflow.com/questions/2958701/…
eldarerathis
3
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
3
Esto funciona perfectamente en versiones anteriores de Android, pero no en lollipop, ¿alguna solución?
Salmaan
1
@eldareraesto esto funciona si la aplicación está cerca, pero si la aplicación se está ejecutando en segundo plano y la actividad es diferente de la que tiene el filtro de intención adjunto, no podría manejarlo. ¿Cómo logras que esto funcione en todas las actividades? ¿Pones filtro de intención en todos ellos?
Mustafa Güven
55
Esta respuesta está desactualizada ... esto no funcionará después de Chrome 40. El esquema personalizado se ha deshabilitado en Chrome debido a problemas de seguridad
Utsav Gupta
280

¡NO utilices tu propio esquema personalizado así! Los esquemas de URI son un espacio de nombres global de red . ¿Es dueño del esquema "anton:" en todo el mundo? ¿No? Entonces NO lo uses.

Una opción es tener un sitio web y tener un filtro de intención para un URI particular en ese sitio web. Por ejemplo, esto es lo que Market hace para interceptar los URI en su sitio web:

        <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="http" android:host="market.android.com"
                android:path="/search" />
        </intent-filter>

Alternativamente, existe el esquema "intento:". Esto le permite describir casi cualquier Intención como un URI, que el navegador intentará iniciar cuando se haga clic. Para construir dicho esquema, la mejor manera es simplemente escribir el código para construir la intención que desea lanzar, y luego imprimir el resultado de intent.toUri (Intent.URI_INTENT_SCHEME).

Puede usar una acción con esta intención para encontrar cualquier actividad que respalde esa acción. El navegador agregará automáticamente la categoría NAVEGABLE a la intención antes de iniciarla, por razones de seguridad; también eliminará cualquier componente explícito que haya proporcionado por el mismo motivo.

La mejor manera de usar esto, si desea asegurarse de que solo se inicie su aplicación, es con su propia acción de alcance y usando Intent.setPackage () para decir que la intención solo coincidirá con el paquete de su aplicación.

Compromisos entre los dos:

  • Los URI http requieren que tengas un dominio de tu propiedad. El usuario siempre tendrá la opción de mostrar el URI en el navegador. Tiene propiedades de respaldo muy agradables donde, si su aplicación no está instalada, simplemente aterrizarán en su sitio web.

  • Los URI intencionados requieren que su aplicación ya esté instalada y solo en teléfonos Android. Permiten casi cualquier intento (pero siempre tienen la categoría NAVEGABLE incluida y no admite componentes explícitos) Le permiten dirigir el inicio solo a su aplicación sin que el usuario tenga la opción de ir al navegador o cualquier otra aplicación.

hackbod
fuente
32
Por otro lado, la aplicación Market también maneja market://enlaces :)
Felix
38
Fue un error utilizar market :, y esto se está eliminando.
hackbod
82
La razón de por qué las personas utilizan esquemas personalizados en Android es porque la mayoría de los proyectos se desarrollan en paralelo con (o después) de la versión para iPhone, y esta es la única manera de hacer que funcione allí ...
LambergaR
12
de acuerdo con @LambergaR. Ahora necesitamos encontrar una forma de hacer que un enlace en un correo electrónico funcione en 3 plataformas (BB, iphone, Android)
Maragues
77
Cualquier URI que coloque en su página web con un esquema personalizado no funcionará en ningún navegador web que no tenga instalada también su aplicación. ¿No te parece roto?
Hackbod
13

Pido disculpas por promocionarme, pero tengo un complemento jQuery para iniciar aplicaciones nativas desde enlaces web https://github.com/eusonlito/jquery.applink

Puedes usarlo fácilmente:

<script>
$('a[data-applink]').applink();
</script>

<a href="https://facebook.com/me" data-applink="fb://profile">My Facebook Profile</a>
Lito
fuente
12

También me enfrenté a este problema y veo muchas páginas absurdas. Aprendí que para hacer que su aplicación sea navegable, cambie el orden de los elementos XML, esto:

<activity
    android:name="com.example.MianActivityName"
    android:label="@string/title_activity_launcher">

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

    <intent-filter>                
        <data android:scheme="http" />     
        <!-- or you can use deep linking like  -->               

        <data android:scheme="http" android:host="xyz.abc.com"/>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>

    </intent-filter>
</activity>

Esto funcionó para mí y podría ayudarte.

ashwani
fuente
Escribo la etiqueta XML en la misma secuencia pero no puedo abrir el diálogo del selector cuando escribo mi url en el navegador de Android.
Sunit Kumar Gupta
no vi mucha diferencia, y si uso este está funcionando perfectamente ... Gracias :)
Muthu S
6

Aquí está mi receta:

Cree un HTML estático que redirija a la URL de la aplicación solicitada, coloque esa página en la web.

De esa manera, los enlaces que comparte son enlaces 'reales' en lo que respecta a Android (serán 'clicables').

Usted 'comparte' un enlace HTTP normal, www.your.server.com/foo/bar.html Esta URL devuelve un HTML simple de 8 líneas que redirige al URI de su aplicación (window.location = "blah: // kuku") ( tenga en cuenta que 'bla' ya no tiene que ser HTTP o HTTPS).

Una vez que tenga esto en funcionamiento, puede aumentar el HTML con todas las capacidades elegantes como se sugirió anteriormente.

Esto funciona con el navegador incorporado, Opera y Firefox (no he probado ningún otro navegador). Firefox pregunta 'Este enlace debe abrirse con una aplicación' (ok, cancelar). Otros navegadores aparentemente no se preocupan tanto por la seguridad, solo abren la aplicación, sin hacer preguntas.

JRun
fuente
¡Excelente! Funcionó para mi. Entonces agregamos la página html con un enlace a un esquema personalizado que redirige a mi aplicación. Mi enlace es<a href="iamnearby://register_activate">Activate</a>
S. Koshelnyk
4

Una vez que tenga la intención y el esquema de URL personalizado para la configuración de su aplicación, este código JavaScript en la parte superior de una página receptora me ha funcionado tanto en iOS como en Android:

<script type="text/javascript">
// if iPod / iPhone, display install app prompt
if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i) ||
    navigator.userAgent.match(/android/i)) {
  var store_loc = "itms://itunes.com/apps/raditaz";
  var href = "/iphone/";
  var is_android = false;
  if (navigator.userAgent.match(/android/i)) {
    store_loc = "https://play.google.com/store/apps/details?id=com.raditaz";
    href = "/android/";
    is_android = true;
  }
  if (location.hash) {
    var app_loc = "raditaz://" + location.hash.substring(2);
    if (is_android) {
      var w = null;
      try {
        w = window.open(app_loc, '_blank');
      } catch (e) {
        // no exception
      }
      if (w) { window.close(); }
      else { window.location = store_loc; }
    } else {
      var loadDateTime = new Date();
      window.setTimeout(function() {
        var timeOutDateTime = new Date();
        if (timeOutDateTime - loadDateTime < 5000) {
          window.location = store_loc;
        } else { window.close(); }
      },
      25);
      window.location = app_loc;
    }
  } else {
    location.href = href;
  }
}
</script>

Esto solo se ha probado en el navegador de Android. No estoy seguro acerca de Firefox u Opera. La clave es que aunque el navegador de Android no arroje una buena excepción para usted window.open(custom_url, '_blank'), fallará y volverá, nulllo que puede probar más tarde.

Actualización: usando store_loc = "https://play.google.com/store/apps/details?id=com.raditaz";para vincular a Google Play en Android.

Pete
fuente
1
¿Cuál es el punto de loadDateTime / timeOutDateTime? ¿Esto de alguna manera evita los bloqueadores de ventanas emergentes o algo así?
Matt Wolfe el
Esto no parece funcionar en mis pruebas, window.open (...) siempre abrirá una nueva ventana, incluso si el esquema no se maneja.
jtomson
@MattWolfe lo siento por la respuesta tardía. En iPhone (Safari) no se produce ninguna excepción. El tiempo de espera está ahí para cerrar la ventana obsoleta en Safari que queda después de que la página ha redirigido a la aplicación. No he encontrado una manera de abrir una URL sin pasar por Safari y la mayoría de las otras aplicaciones que reconocen URL como esta hacen lo mismo. Esa fue una de las ventajas de los "enlaces profundos" de Facebook: no se obtiene esa ventana sobrante obsoleta al pasar por Safari móvil.
Pete
@ jtomson: interesante. Probé en el emulador y en varios dispositivos de Android 2.1 a 3 (en ese momento). ¿En qué dispositivo y versión de Android estabas probando?
Pete
4

Es posible que desee considerar una biblioteca para manejar el enlace profundo a su aplicación:

https://github.com/airbnb/DeepLinkDispatch

Puede agregar el filtro de intención en una Actividad anotada como las personas sugeridas anteriormente. Manejará el enrutamiento y el análisis de parámetros para todos sus enlaces profundos. Por ejemplo, su MainActivity podría tener algo como esto:

@DeepLink("somePath/{useful_info_for_anton_app}")
public class MainActivity extends Activity {
   ...
}

También puede manejar parámetros de consulta también.

cristiano
fuente
1

Prueba mi simple truco:

        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if(url.startsWith("classRegister:")) {                  
                Intent MnRegister = new Intent(getApplicationContext(), register.class); startActivity(MnRegister);
            }               
            view.loadUrl(url);
            return true;
        }

y mi enlace html:

<a href="classRegister:true">Go to register.java</a>

o se puede hacer <a href = "classRegister: verdad "> <- "verdadero" valor para el nombre del archivo de clase

sin embargo, este script funciona para mailto link :)

        if (url.startsWith("mailto:")) {
            String[] blah_email = url.split(":");
            Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
            emailIntent.setType("text/plain");
            emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{blah_email[1]});
            emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, what_ever_you_want_the_subject_to_be)");
            Log.v("NOTICE", "Sending Email to: " + blah_email[1] + " with subject: " + what_ever_you_want_the_subject_to_be);
            startActivity(emailIntent);
        }
IRvanFauziE
fuente
Esto es esencialmente una llamada a una JavascriptInterfacesolución alternativa, esta es la solución correcta si necesita admitir 2.3 donde JavaScriptInterface tiene errores.
EpicPandaForce
1

Este método no llama al cuadro de diálogo de desambiguación que le pide que abra su aplicación o un navegador.

Si registra lo siguiente en su manifiesto

<manifest package="com.myApp" .. >
  <application ...>
    <activity ...>
      <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="gallery"
          android:scheme="myApp" />
      </intent-filter>
    </activity>
    ..

y haga clic en esta URL de un correo electrónico en su teléfono, por ejemplo

<a href="intent://gallery?directLink=true#Intent;scheme=myApp;package=com.myApp;end"> 
  Click me 
</a>

entonces Android intentará encontrar una aplicación con el paquete com.myApp que responda a la intención de su galería y tenga un esquema myApp . En caso de que no pueda, lo llevará a la tienda, buscando com.myApp , que debería ser su aplicación.

gato marino
fuente
¿Cómo ir a una actividad de Android?
Mohsen Emami