移動互聯網發展到今天,一個移動app需要和各種各樣的外部鏈接關聯,它不再僅僅從手機的桌面啟動,更多的將會從其他的應用、瀏覽器鏈接、短信、二維碼或者微信分享等渠道啟動,這里涉及到的是各種各樣的營銷渠道和方式。
那么從我們的技術角度來說,我們今天要說明一下的是,從外部鏈接的方式啟動app需要注意的地方。我們都是知道,在Android上外鏈方式啟動app的方式是在manifest文件中的某個activity的intent-filter標簽中設置好標簽action、category和data的屬性。
<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="scheme"/>
</intent-filter>
瀏覽器頁面代碼加載協議為android:scheme屬性值的鏈接向系統發起調用服務請求,系統的廣播系統就會匹配當前系統中的intent-filter,如果其子標簽的action、category和data都匹配的話,則會調起此activity,如果app沒有加載,則先加載app的apk到進程,再啟動對應的activity。
坑和經驗
問題來了,很多app的首頁activity都是在顯示完SplashActivity后再啟動的,首頁activity的launchMode都是設置為singleTask,確保實例的唯一性,當我們的app已經啟動了的情況下,再次通過外鏈的方式啟動首頁activity是無法啟動的。
從android的task堆棧角度來說,瀏覽器activity所在task是在瀏覽器的process當中的,而起啟動SplashActivity后此activity是在瀏覽器所在的task,此時在SplashActivity中啟動app的首頁activity,而首頁activity是在另外的process的task當中,故無法切換這個task到前台。
此時的解決方案是在啟動首頁activity的intent對象中添加FLAG_ACTIVITY_NEW_TASK,在瀏覽器器task中通過FLAG_ACTIVITY_NEW_TASK啟動首頁activity,此時系統會尋找和首頁activity具有相同的taskAffinity的task,即找到app的process中首頁所在的task,將此task推到前台,到此實現了通過外鏈的方式再次現身app首頁activity的功能。
總結一下,FLAG_ACTIVITY_NEW_TASK針對啟動的activity是否在同一個process中處理方式不一樣,因為默認情況下相同應用中所有的activity的taskAffinity都相同,故如果是存在且在同一應用中,直接將被啟動的activity入棧,否則新建一個task並入棧,故在我們的開發中,對於activity間的切換以及task間的切換需要深入理解才能做出優秀的軟件。