programacion - ¿Cómo recurrir al mercado cuando no se maneja el esquema de URL personalizado de Android?
open deep link android (7)
¡Esta es la respuesta que los salvará a todos!
https://developers.google.com/chrome/mobile/docs/intents
<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end"> Take a QR code </a>
Su url me enviará si la aplicación está instalada o si no, comenzará el mercado en el paquete indicado
Tenemos una aplicación que maneja un esquema de URL personalizado (vstream: //). Cuando alguien llega a una página web que tiene algún contenido vstream: //, debemos redirigirlo a la tienda si no tiene nuestra aplicación instalada.
En iOS, hacemos esto:
setTimeout(function() {
window.location =
"itms://itunes.apple.com/us/app/kaon-v-stream/id378890806?mt=8&uo=4";
}, 25);
window.location = "vstream:view?code=...stuff...";
Si la asignación de window.location
falla, el tiempo de espera salta sobre App Store antes de que aparezca el cuadro de diálogo. (Encontré esta técnica aquí: ¿Es posible registrar un esquema de URL basado en dominio http + para aplicaciones de iPhone, como YouTube y Maps?. )
Desafortunadamente, este truco no funciona en Android. Detectamos el lado del servidor del dispositivo y escribimos esto en lugar de la línea itms:
"market://details?id=com.kaon.android.vstream";
El problema es que, mientras que iOS arroja un error cuando vas a un esquema de URL no manejado, Android va a una página generada. Por lo tanto, el tiempo de espera nunca tiene la oportunidad de correr.
¿Hay alguna forma en una página web para probar explícitamente si se maneja un esquema de URL personalizado, o alguien puede sugerir un truco como este que funcione en Android? (Por supuesto, supongo que necesito un truco que funcione sin importar qué navegador esté usando, lo que probablemente sea una tarea difícil ...)
ACTUALIZACIÓN: los enfoques a continuación no funcionan en Jelly Bean en un Nexus 7. El nuevo navegador Chrome no va a una página generada (por lo que no es necesario el iFrame), pero no parece haber ninguna forma de saber si la URL esquema fue manejado Si lo fue, el tiempo de espera se dispara de todos modos. Si no se manejó el tiempo de espera se dispara. Si uso un controlador onload y un iframe, el controlador onload nunca se activa (ya sea que la aplicación esté instalada o no). Actualizaré si alguna vez averiguo cómo saber si el esquema fue manejado ...
He eliminado mi "Solucionado" en mi solución anterior, ya que ya no funciona.
ACTUALIZACIÓN 2: Tengo una buena solución multiplataforma ahora que funciona en iOS, Android 4.1 con Chrome y Android pre-Chrome. Vea abajo...
Actualización 3: Google rompió todo de nuevo con intenciones. Echa un vistazo a la MUY bonita solución que he aceptado por amit_saxena en algún lugar /
@jesmith, esta es una versión limpia que corrige la doble acción en Android.
if (navigator.appVersion.indexOf(''iPhone'') > -1) {
setTimeout(function noapp() { window.location="http://itunes.apple.com/app/id378890806?mt=8"; }, 25);
window.location = ''vstream:'';
}
else if (navigator.userAgent.indexOf(''Android'') > -1) {
var iframe = document.createElement(''iframe'');
iframe.style.visibility = ''hidden'';
iframe.src = ''vstream:'';
iframe.onload = function noapp() { window.location="market://details?id=com.kaon.android.vstream"; };
document.body.appendChild(iframe);
}
A continuación se muestra un fragmento de código de trabajo para la mayoría de los navegadores Android:
<script type="text/javascript">
var custom = "myapp://custom_url";
var alt = "http://mywebsite.com/alternate/content";
var g_intent = "intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end";
var timer;
var heartbeat;
var iframe_timer;
function clearTimers() {
clearTimeout(timer);
clearTimeout(heartbeat);
clearTimeout(iframe_timer);
}
function intervalHeartbeat() {
if (document.webkitHidden || document.hidden) {
clearTimers();
}
}
function tryIframeApproach() {
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.onload = function () {
document.location = alt;
};
iframe.src = custom;
document.body.appendChild(iframe);
}
function tryWebkitApproach() {
document.location = custom;
timer = setTimeout(function () {
document.location = alt;
}, 2500);
}
function useIntent() {
document.location = g_intent;
}
function launch_app_or_alt_url(el) {
heartbeat = setInterval(intervalHeartbeat, 200);
if (navigator.userAgent.match(/Chrome/)) {
useIntent();
} else if (navigator.userAgent.match(/Firefox/)) {
tryWebkitApproach();
iframe_timer = setTimeout(function () {
tryIframeApproach();
}, 1500);
} else {
tryIframeApproach();
}
}
$(".source_url").click(function (event) {
launch_app_or_alt_url($(this));
event.preventDefault();
});
</script>
source_url
agregar la clase source_url
a la etiqueta de anclaje.
He blogeado más sobre esto aquí:
http://aawaara.com/post/88310470252/smallest-piece-of-code-thats-going-to-change-the
ACTUALIZACIÓN: Google rompió esto. Ver la nueva respuesta aceptada en su lugar.
La clave, resulta, es la propiedad document.webkitHidden. Cuando configura window.location en un esquema de URL personalizado y se abre, el navegador se sigue ejecutando, pero esa propiedad es falsa. Por lo tanto, puede probarlo para determinar si se manejó el esquema de URL personalizado.
Aquí hay una muestra, que puedes ver en vivo.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Starting App...</title>
<script>
var URL = "kaonkaon://product.html#malvern;6";
var MARKET = "market://details?id=com.kaon.android.lepton.kaon3d";
var ITUNES = "itms://itunes.apple.com/us/app/kaon-interactive-3d-product/id525051513?mt=8&uo=4";
var QR = "http://goo.gl/gz07g"; // this should be a shortened link back to this page
function onLoad() {
if (navigator.userAgent.match(/Android/)) {
if (navigator.userAgent.match(/Chrome/)) {
// Jelly Bean with Chrome browser
setTimeout(function() {
if (!document.webkitHidden)
window.location = MARKET;
}, 1000);
window.location = URL;
} else {
// Older Android browser
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
var t = setTimeout(function() {
window.location = MARKET;
}, 1000);
iframe.onload = function () { clearTimeout(t) };
iframe.src = URL;
document.body.appendChild(iframe);
}
} else if (navigator.userAgent.match(/iPhone|iPad|iPod/)) {
// IOS
setTimeout(function() {
if (!document.webkitHidden)
window.location = ITUNES;
}, 25);
window.location = URL;
} else {
// Not mobile
var img = document.createElement("img");
img.src = "https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl="+encodeURIComponent(QR);
document.body.appendChild(img);
}
}
</script>
</head>
<body onload="onLoad()">
</body>
</html>
Incruste un servidor http en su aplicación como servicio, escuche un puerto local (superior a 1024, ej: 8080), envíe una solicitud desde el navegador al 127.0.0.1:8080. Si su aplicación está instalada (y el servicio se está ejecutando), inícielo, si la solicitud falla, vaya a Google Play.
Por algunas razones, la solución final no funciona para mí en android (¿¡¿Soy yo ?!). La clave es que la función iframe.onload NO se ejecuta cuando su aplicación está instalada, y se ejecuta cuando su aplicación NO está instalada.
La solución se vuelve un poco más simple en realidad. Aquí está el segmento de la parte del "Navegador de Android más antiguo":
} else {
// Older Android browser
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.onload = function () { window.location = MARKET; };
iframe.src = URL;
document.body.appendChild(iframe);
}
Resuelto El truco es abrir mi aplicación en un IFRAME, en lugar de establecer la ubicación:
setTimeout(function() {
window.location =
"market://details?id=com.kaon.android.vstream";
}, 1000);
document.write(''<iframe style="border:none; width:1px; height:1px;" src="vstream:view?code=''+code+''"></iframe>'');
Tenga en cuenta que aumenté el tiempo de espera a 1000, porque Android realiza ambas acciones en todos los casos (no es ideal, pero no es horrible), y este tiempo de espera mayor es necesario para asegurarse de que Market no termine siendo lo que el usuario ve cuando Ya estoy instalado
(Y sí, por supuesto, usar document.write es tan pasado en el siglo pasado, pero así soy de la vieja escuela :)