最近在作一個項目,該項目的前身是爲mobile browser量身打造的一個網站。如今有這樣一個需求:javascript
當用戶在用mobile browser瀏覽該網站的時候會點擊一個按鈕/超連接,經過這個按鈕的點擊事情須要打開安裝在本機的應用程序,或者若是本機沒有安裝該應用程序則打開應用商店並打開該程序在商店中的搜索結果頁面。html
剛開始的時候iPhone team的人給出一個solution,下面是實施跳轉的HTML + JavaScript源代碼。java
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
<h2><a id="applink1" href="mtcmtc://profile/116201417">Open scheme(mtcmtc) defined in iPhone with parameters </a></h2>
<h2><a id="applink2" href="unknown://nowhere">open unknown with fallback to appstore</a></h2>
<p><i>Only works on iPhone!</i></p>
<script type="text/javascript">
// To avoid the "protocol not supported" alert, fail must open another app.
var appstore = "itms://itunes.apple.com/us/app/facebook/id284882215?mt=8&uo=6";
function applink(fail){
return function(){
var clickedAt = +new Date;
// During tests on 3g/3gs this timeout fires immediately if less than 500ms.
setTimeout(function(){
// To avoid failing on return to MobileSafari, ensure freshness!
if (+new Date - clickedAt < 2000){
window.location = fail;
}
}, 500);
};
}
document.getElementById("applink1").onclick = applink(appstore);
document.getElementById("applink2").onclick = applink(appstore);
</script>
</body>
</html>android
其原理就是爲HTML頁面中的超連接點擊事件增長一個setTimeout方法.web
若是在iPhone上面500ms內,本機有應用程序能解析這個協議並打開程序,則這個回調方法失效;若是本機沒有應用程序能解析該協議或者500ms內沒有打開個程序,則執行setTimeout裏面的function,就是跳轉到apple的itunes。app
我用一樣的原理來處理android的javascript跳轉,發現若是本機沒有程序註冊intent-filter for 這個協議,那麼android內置的browser就會處理這個協議而且當即給出反應(404,你懂的),不會像iPhone同樣去執行setTimeout裏面的function,即使你把500ms改爲0ms也無論用。less
我就開始了個人Google search之旅,最終在stackoverflow一個不起眼的地方找到solution。jsp
不解釋,先給出源代碼網站
Android裏面androidManifest.xml文件對activity的配置,如何配置就不表述了,表達能力有限,請參考developer.android.comui
<activity android:name=".ui.UploadActivity" android:screenOrientation="portrait">
<intent-filter>
<data android:scheme="http" android:host="192.168.167.33" android:port="8088" android:path="/mi-tracker-web/download.html"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
HTML頁面中指向該應用程序的hyperlink
<a id="applink1" href="http://192.168.167.33:8088/mi-tracker-web/download.html">
Open Application</a>
不難發現,在androidManifest.xml中配置的filter中data的屬性表述,在下面的HTML.href中所有看到了。請注意,這兩個路徑要所有一致,不能有差異,不然android系統就不會攔截這個hyperlink。
好了,爲何我說這個solution能解決咱們當初提出來的需求呢,答案在這裏:
若是說本機安裝了這個應用程序
在android browser中點擊HTML中的applink1,browser會重定向到指定的連接,可是因爲咱們的應用程序在android OS中配置了一個intent-filter,也是針對這個制定的連接。就是說如今android系統有兩個程序能處理這個連接:一個是系統的browser,一個是配置了intent-filter的activity。如今點擊這個連接,系統就會彈出一個選擇:是用browser仍是你指定的activity打開。若是你選擇你的activity,系統就會打開你的應用程序,若是你繼續選擇用browser,就沒有而後了。
若是說本機木有安裝這個應用程序
那麼這個HTML裏面的這個超連接就起很重要的左右了,這個download.html裏面能夠forward到android的應用商店
download.jsp源代碼以下。具體爲何請求的是download.html這個地址卻訪問到了download.jsp,就不解釋了,struts2的東西。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<script type="text/javascript">
<span style="white-space:pre"> </span>window.location="market://search?q=com.singtel.travelbuddy.android";</script>
</body>
</html>
唉,文筆不行,估計我寫出來本身都不怎麼看得懂。就再把跳轉的關鍵點說一下:
在androidManifest.xml中定義intent-filter的時候定義的scheme,host,port,path拼湊起來是一個有用的HTTP路徑,這樣就算本機沒有activity定義了intent-filter來捕獲這個連接,那這個連接也會重定向到打開android market place的頁面,繼而打開應用商店。由於每一個android手機都會捕獲到market這個協議(若是android手機裏面沒有market商店,不怪我哈),系統就會自動打開market place應用商店並根據參數進入搜索頁面並顯示結果。