Android官方文檔之Activity和Task – Android移動開發技術文章_手機開發 Android移動開發教學課程

什麼知識,看官方的API是最好的瞭。但是鑒於很多人英語不好,便轉載瞭這篇文章,翻譯的非常好瞭。搞不懂Activity聲明周期,和程序框架設計的,最好看一看。
Activity 和 task 的設計摘要
Activity 是 Android 應用的主要組成部分。
除瞭自己寫Activity之外,你還可以利用intent,輕松地重用其它應用的Activity。
你可以讓你應用裡的Activity能被其它應用通過intent使用。
系統的Activity棧幾乎可以處理所有的情況。不過有兩種情況你大概需要自己設置flag之類,來確定the right thing happens。
在本文檔中
Applications,Activity,Activity棧和Task
Activity和Task的一個例子
從主屏開始一個Activity
離開一個Activity
重用一個Activity
替換Activity
多Task
從兩個進入點啟動應用
Intent
在Task之間切換
設計建議
如果你不想你的Activity被重用,不要使用intent filter
註意處理用intent找不到activity的情況
考慮啟動應用的方式
允許Activity加入到當前Task中來
Notification應該讓你的用戶很容易離開
使用Notification系統
如果不是絕對必要,不要自己控制BACK鍵
參考
Application基礎
這個文檔,從高層的、以用戶為中心的視角,描述瞭Android應用框架的 核心原則。這對交互和應用設計者和應用開發者是有用的。
本文用多個例子說明瞭Activity和Task,而且描述瞭一些它們的底層原則和 機制,像導航,多Task,Activity重用,Intent和Activity棧。 文檔還強調瞭一些你能用到的設計結論,和你如何控制你應用的UI。
這個文檔使用瞭很多Android應用作為例子,包括一些默認應用, 例如Dialer,以及Google應用,例如Maps。你可以在你的Android模擬器 或者Android的手機上試試它們。註意你的手機或許隻提供一部分這些文檔 中的例子應用。
在設計建議部分中,會提到一些原則、 建議、和要避免的事情。Application基礎覆蓋瞭程序的底層 機制,本文檔是對它的補充和完善。
Applications,Activity,Activity棧和Task
以下四個基本概念有助於你的理解:
Application
Activitie
Activity棧
Task
Application
一個典型的Android Application由一個或多個相關的、松耦合的、用戶可以 與之互動的Activity組成。典型的情況,是一個Application打包進 一個單獨的apk文件裡。Android會伴隨著一大票的應用,可能包括電子郵件、日歷、瀏覽器、地圖、 短信、聯系人、拍照、撥號、音樂播放、設置等等。
Android主屏一般就是應用啟動者。一般來說,是一個有很多應用圖標的滑動抽屜(就是默認Android系統下面那個,用手指往上一拖就出現很多圖標的那個東西。),用戶可以從上面啟動應用。
Activity
Activity是Android應用的主要組成部分。 當你建立Apllication的時候,你可以自己建立的Activity或者重用其它Application的Activity,來組裝Application。 這些Activity是在運行時綁定在一起的,所以,新安裝的Application能從已安裝的Activity中獲益。 一旦組合在一起,這些Acitivity會像一個整體那樣一起工作。 一個Activity擁有一個獨立的可視UI,這個UI應該基於單獨的、明確界定的意圖。 例如看圖、編輯、撥號打電話、拍照、搜索、發送數據、語音命令等等其他用戶行為。 一個需要界面顯示的Application至少要有一個Activity。
當使用一個Android設備時,用戶會從一個界面跳到另一個界面,這種跳轉應該是流暢的。 不應該讓用戶察覺那些底層的行為,比如Activity間或者Task間的切換。
一個Activity持有瞭一種特定種類的內容(數據),以及接受一系列相關的用戶動作。 一般來說,每個Activity的生命周期,與其他的同一個Application或Task內的Activity是無關的。 每一個Activity獨立地被運行,用戶或者系統可以按需要start、run、pause、resume、stop或者restart這些Activity。 由於這種獨立的特性,有很多種方法可以覆蓋或者重用Activity。
Android提供的撥號程序就是一個Activity組合的例子。這個程序是由4個Activity組合成的: 撥號,聯系人列表,聯系人詳情,和新建聯系人。如下所示:

下面是一些其它的由多個Activity組合的Application的例子:
電子郵件 – 查看目錄、查看消息列表、查看消息、寫消息、配置賬號。
日歷 – 查看日、周、月、計劃,編輯時間,設置屬性,提醒
攝像拍照 – 運行照相機,看圖片列表,看圖,切圖,運行攝像機,看視頻列表,看視頻
遊戲 – 遊戲本身,以及安裝設置
地圖 – 查看當前位置,列表(turn list或者好友列表),詳細資料(好友位置、狀態、照片)
Activity,是組成Application的四種組件中,最重要的一個。另外的組件是, Service,ContentProvider,BroadcaseReceiver。更多關於Activity的細節,請參考 Application組件中的Activity部分。
Activity棧
當用戶在Application中,從一個Activity跳到另一個時,Android系統會 保存一個用戶訪問Activity的線性導航歷史。 這就是activity棧,也被稱為返回棧。 一般來說,當用戶運行一個新的Activity,這個Activity就會被加到Activity棧裡。因此,當用戶 按BACK鍵的時候,棧中的上一個Activity就會被展示出來。 用戶可以一直按BACK鍵,直到返回到瞭主屏。 The adding of an activity to the current stack happens whether or not that activity begins a new task (as long as that task was started without going Home), so going back can let the user go back to activities in previous tasks. 把Activity加入到當前棧裡的操作,與Activity是否啟動瞭一個新Task無關。 返回操作可以使用戶從當前Task回到上一個Task。 用戶可以在應用管理器、主屏、或者“最近Task”屏幕,恢復到剛剛的Task。
隻有Activity可以加到Activity棧裡去,其它的,包括View、Window、Menu或者Dialog都不行。 這就是說,假設,界面A跳到界面B,然後用戶可以用BACK跳回界面A。這種情況下,A和B都要被實現成Activity。 這個規則有一個例外的情況。那就是除非你的應用 控制瞭BACK鍵並且自己管理界面導航。
Task
一個Task是用戶可以完成一個特定目標的一組Activity。與Activity屬於哪個Application無關。 除非明確地新建一個Task,(參考打斷Task),用戶啟動的所有Activity都默認是當前Task的一部分。 需要註意的是,這些Activity可能屬於任何一個Application — 屬於同一個Application或者屬於不同的Application。 這就是說,一個Task可以是,從聯系人列表開始,然後選擇一個郵箱地址(通過電郵Activity),然後附加一個照片(通過圖片Activity)。 聯系人列表、電郵、圖片,這些都存在於不同的Activity中。
啟動Task的Activity被稱作根Activity。 通常,Task是從應用管理器、主屏或者最近Task(長按HOME鍵)開始的。 用戶可以通過點擊根Activity的圖標回到Task裡去,就像啟動這個Activity一樣。 在這個Task中,BACK鍵可以回到這個Task的前一個Activity裡。 Activity棧可以由一個或多個Task組成。
一些關於Task的例子:
發送一個有附件的短信
看YouTube,然後通過Email分享這個視頻
打斷Task – Task的一個重要的特性就是,用戶可以中斷他當前正在做的事(他的任務),去進行另一個Task,然後可以返回到原來的那個Task去完成它。 這個特性的意圖,就是用戶可以同時運行多個任務,並且可以在這些任務間切換。 有兩種主要的的方法離開一個Task,這兩種情況中,應該讓用戶能夠返回到他們離開的那個任務:
用戶被Notification打斷 – 來瞭一個通知,用戶開始關註處理這個通知
用戶決定開始另一個任務 – 用戶按瞭HOME鍵,然後開始瞭另一個Application
當然,規則總是有例外。除瞭上面提到瞭兩種方法,確實存在第三種方法開始一個新任務,即,在代碼中startActivity的時候,定義它要開始一個新Task。 地圖和瀏覽器兩個應用就是這麼做的。 例如,在電郵中點擊一個地址,會在新Task調出地圖Activity,在電郵中點擊一個鏈接,會在新的Task中調出瀏覽器。 在這種情況下,BACK鍵會回到上一個Activity(另一個Task中的電郵Activity),因為它不是從主屏啟動的。
Activity和Task的一個例子
接下來的例子,說明瞭Application、Activity、Activity棧、BACK鍵、Task和Intent的基本原理。 它展示瞭系統響應用戶操作的方式,包括啟動Activity和在Task之間切換。 你可以在你的Android手機上,按照下面指示的那樣,執行這些例子。
從主屏啟動一個Activity
主屏是絕大部分Application啟動的地方。(某些應用隻能從其它應用進入。) 當用戶點擊應用管理器的一個圖標(或者主屏上的一個快捷方式),這個應用的主Activity會被啟動到前臺,並擁有用戶的焦點。 像下面圖標展示的那樣,用戶進入主屏並點擊電郵圖標的行為,啟動瞭電郵Application的消息列表Activity。 主屏Activity被置到後臺,stop。當用戶重新進入主屏時,restart。

按著Activity導航,通過BACK鍵和HOME鍵離開Activity
一個Activity是否保持它的狀態,取決於用戶離開它的方式 – 是通過HOME鍵還是BACK鍵。
默認情況下,按BACK鍵會finish(destroy)當前Activity,然後顯示上一個Activity給用戶。 在下面的圖中,用戶通過在主屏點擊電郵圖標啟動瞭顯示出電郵消息列表的電郵應用。 用戶滾動列表(改變瞭初始狀態)。 點擊BACK鍵銷毀瞭消息列表Activity,然後回到瞭上一個Activity,即是主屏。 用戶重新啟動電郵應用後,電郵應用展示出來的列表,是重新初始化,沒有經過滾動的。

在上面的例子中,按BACK鍵會回到主屏,是因為主屏是用戶能看到的最後一個Activity。 要是用戶是從其它Activity進到消息列表Activity的,那麼按BACK鍵會回到來的地方。
作為對比,下一個圖表展示瞭用戶用HOME鍵而不是BACK鍵來離開消息列表Activity的情況 – 消息列表Activity會stop然後移到後臺,不會被銷毀。從快捷方式重新啟動電郵Application,會把後臺的這個應用 置到前臺(從stop變成running)。滾動狀態會跟用戶離開的時候一樣。

有例外情況。 某些後臺Activity回到前臺後,會進到它的初始界面(而不是離開時的狀態)。 聯系人應用和看圖應用就是這種Activity。 當用戶從主屏進入聯系人應用,然後選擇一個聯系人看詳細資料。(然後HOME鍵)。 如果用戶再次從主屏進入,就會回到聯系人列表而不是離開時的詳細資料。 這樣設計聯系人應用,是因為聯系人列表是整個應用4個Tab的主進入點。
另外,不是所有的Activity都會在按BACK的時候被銷毀。 當用戶使用音樂應用播放音樂,然後按BACK鍵時,應用重寫瞭後退的行為,Activity沒被銷毀,而僅僅是變得不可見。(所以保存瞭狀態)。 音樂繼續播放,並出現一個Notification,讓用戶可以回到音樂Activity去控制音樂的播放。 註意,你可以寫不可見就銷毀的Activity,也可以寫像音樂Activity一樣僅僅會切到後臺的Activity。
重用一個Activity
假設Activity A啟動瞭另一個Application中的Activity B,就說Activity B被重用瞭。 在Activity A廣播查找能力然後B有這個能力時,這種情況就會發生。
Contacts重用瞭Gallery來取圖片 – Contacts Activity有一塊區域用來顯示聯系人的圖片,而一般來說,所有的圖片都保存在Gallery裡。 於是Contacts可以重用Gallery Activity來取圖片。 這是一個重用Gallery Activity的很好的例子。 下面的圖表說明瞭這個流程(主要部分)。 流程是這樣的:用戶點擊Contacts,然後點選一個聯系人查看詳細資料,按MENU鍵,編輯聯系人,點擊圖片區域, 於是就會啟動Gallery Activity。用戶找到想要的圖片後,裁剪並保存。保存這個動作,會導致圖片被插入到聯系人詳情的圖片區域中。
Gallery會返回圖片給啟動自己的Contact Application。 下面一個例子說明瞭重用Activity但沒有返回的情況。 還要註意下面的圖標是一個對Activity導航歷史(即Activity棧)的說明。用戶可以一直按BACK直到回到主屏。
設計Application的時候,考慮如何能夠重用其他Application中的Activity, 以及考慮自己的Activity如何被其它Application重用,是一個很好的思路。 如果你的Activity擁有一個和已存在的Activity一樣的Intent Filter, 系統會提供給用戶一個對這些Activity的選擇界面。

Gallery重用Messaging來分享圖片 – Sharing is 分享圖片是另一個很好的關於在不同的Application重用Activity的例子。 如下圖所示,用戶啟動Gallery,選一個圖,按MENU鍵,選Share,選Messaging。 這就會啟動Messaging Activity,然後建立一個新的消息並把圖片附在上面。 然後用戶填寫“收件人”、寫個短消息然後發送。 用戶的關註點現在在Messaging程序上。 如果用戶想回到Gallery,他必須按BACK鍵。(用戶可以通過BACK鍵從任何一個Activity一路返回到主屏。)
與上一個例子不同,這個對Messaging Activity的重用什麼都沒有返回給啟動它的Gallery Activity。

兩個例子實際上都說明瞭Task — 為瞭完成一個目標的一系列Activity。 每個例子都是用瞭來自不同的Application的Activity來完成任務。
代替一個Activity
下面這個情況,是Activity A在不同的Application裡代替瞭Activity B。 這種情況一般發生在Activity A做某項工作比Activity B好的時候。 換句話講,A的功能足夠代替B。 與重用不同的是,重用的時候,A和B做的是不同的事情。
在本例中,用戶下載瞭一個PhoneRingtone Activity的替代品,叫做RingsExtended。 現在,當用戶進入Setting,SoundDisplay,PhoneRingtone,系統會提供一個選擇界面,讓用戶選擇是使用Android系統的電話鈴Activity還是新的這個。 這個對話框有一個多選框,讓用戶可以選擇“這種情況下默認使用這個選項”。 用戶選瞭RingsExtended,然後新的Activity被啟動,代替瞭原來的Android系統電話鈴Activity。

多Task
上面說過,用戶可以從一個Activity通過HOME切到主屏,然後進入另一個Activity,而前一個Activity不會被銷毀。 下面演示瞭進入Map Application的情況。
State 1 – 用戶進入ViewMap Activity,搜索一個地址。假設網絡非常慢,應用需要異常長的時間來搜索。
State 2 – 用戶想在等待的時候做一些其它事情,所以他按HOME鍵,離開Map,但是沒有打斷網絡連接。現在Map在後臺繼續工作。
註意,你可以自己決定,在程序被挪到後臺後,是繼續運行還是停止。 (參考onStop(),Activity生命周期)。 對於從網絡上下載數據這類Activity來說,建議還是讓它們在後臺的時候,繼續工作。用戶就可以多任務瞭。
State 3 – 現在,Map Activity在後臺運行瞭。主屏到瞭前臺。 然後,用戶運行Calendar Activity,把Calendar置到前臺。現在用戶關註Calendar,並瀏覽今天的日程。(如圖中粗線所示)

 
State 4 – 用戶按HOME鍵,然後點擊Map,回到Map Activity,看到地圖已經讀取完瞭。

 
主屏的應用啟動器,在兩個不同的Task裡,啟動瞭ViewMap和DayView兩個Activity。 這個時候,系統就是多任務的 — 運行瞭多個Task。
Launching from Two Entry Points
每個Application必須至少有一個進入點 — 好讓系統或者用戶進到Application的Activity裡。 在主屏的ApplicationLauncher,每一個圖標表示瞭一個進入點。 Application也可以從其他Application進入。 每個Activity都是一個Application的潛在進入點。
Android提供的PhoneApplication有兩個進入點:Contact和Dialer。 一個在Contact中的用戶可以點選一個電話號碼,來進入Dialer。 如下圖所示,用戶能點擊Contact的圖標來進入ContactActivity,然後點擊一個電話號碼,來進入DialerActivity,撥打電話。
一旦用戶進入到瞭Application裡,就可以通過tabs、menu items、list items、buttons或者其他界面控制元素, 來進入其它的Activity,例如NewContact或者EditContact之類。

Intent
當用戶要對某類數據做出行為時,例如,點擊一個mailto:info@example.com鏈接, 他們實際上是初始化瞭一個Intent對象(一個Intent)。這個Intent會被解決成為一個特定的Commpnent。 (這裡我們隻說ActivityComponent)。 (翻譯成人話:用戶要做一件事情,實際上會初始化出來一個Intent,廣播詢問系統,然後最終導致一個特定的Activity被調用。) 進而,用戶點擊mailto:鏈接的結果,是一個Intent對象。系統會嘗試用這個Intent來匹配一個Activity。 如果這個Intent明確地指名瞭一個Activity(一個明確Intent),系統會立即進入這個Activity來響應用戶動作。 然而,如果這個Intent沒有指名Activity(一個不明確Intent),系統會比較這個Intent和所有可用的Activity的IntentFilter 。 要是多個Activity都能處理這個動作和數據,系統會讓用戶選擇一個。
下圖展示的就是點擊mailto:鏈接的例子。 如果設備上有兩個處理Email的應用,當用戶點擊電郵地址的結果,是出現一個對話框,讓用戶在兩個應用中間選一個。(Gmail和Email兩個應用)。

Here are some examples of Intent objects and the activities they resolve to: 這裡是一些Intent對象(不明確的)和Intent對應Activity的例子:
看聯系人列表 – resolves to a contact list viewer activity
看特定聯系人 – resolves to a contact viewer activity
編輯特定聯系人 – resolves to a contact editor activity
向一個特定地址發電郵 – resolves to an email activity
撥打電話 – resolves to a phone dialer activity
看圖列表 – resolves to an image list viewer activity
看圖 – resolves to an image viewer activity
裁剪圖片 – resolves to an image cropper activity
註意,Intent對象指定瞭兩件事:行為和數據:
一個需要進行的行為。上面的例子中,看、編輯、撥號、裁剪都是行為。
要進行這種行為的特定的數據。上面的例子中,聯系人列表,特定聯系人,電話號碼,圖列表,特定的圖都是數據。
任何一個在主屏上啟動Activity的Intent都是明確的Intent。 靈位,一些Activity進入自己Application內部的Activity使用的也是明確Intent。
Intent的詳情,參見Intent class和 intent filters.
在Task間切換
下面一系列圖展示瞭用戶如何在兩個Task間轉換。 在這個例子中,用戶寫瞭一個文本消息,然後附上一張照片。在做這些事兒的時候,用戶看瞭一眼日歷。 然後,用戶回來,繼續附照片和發送消息。
開始第一個Task。 為瞭發送一個附加瞭圖片的消息,你需要如下操作:
主屏 > Messaging > NewMessage > MENU > Attach > Pictures 最後一步操作啟動瞭Gallery來取照片。 註意到,Gallery是在另外一個Application中。

在用戶取圖之前,用戶決定去看一眼日歷,這就是另一個Task瞭。 但是當前界面沒有一個直達Calendar的按鈕,所以用戶必須回到主屏去。
開始第二個Task。 用戶按HOME鍵 > 點Calendar來看日歷。 Calendar作為一個新的Task被啟動。ApplicationLauncher啟動的Application都是新的Task。

切換到第一個Task,並完成它。 看完瞭日歷,用戶於是按HOME鍵 > Messging,返回去繼續附加圖片。 這個操作並沒有使用戶進入Messaging,而是進入瞭剛剛離開的Gallery(即使這兩個並不是一個Application!)。 然後用戶選擇一個圖片,加入到消息裡去,發送消息,完成第一個Task。


  
設計建議
以下是對應用設計者和開發者的建議和指示。
當你寫的Activity不希望被重用的時候,不要寫IntentFilter。使用準確的Intent來調用它。
當你不想你的Activity被其它Application重用的時候,要確定這個Activity上沒有定義任何的IntentFilter。 隻能從應用管理器進入,或者隻能從同一個Application進入的Activity,應該應用這種做法。 對於這類Activity,使用目標明確的Intent來進入。(而不是通過Intent向系統查詢能力這種做法)。 這種情況,也沒必要使用IntentFilter。 IntentFilter是發佈給所有其它Application的。 所以,如果你用瞭IntentFilter,你實際上就是在給你的Activity加入瞭一個外部入口,有可能會造成無意識的安全漏洞。
當你重用其它應用的Activity時,不要忘記處理沒有Activity滿足要求的情況。
你的Application可以重用其它的Activity,如果這些Activity可以重用的話。 重用的時候,你不能假設你的Intent一定能匹配到一個外部Activity。你必須考慮沒有合適Activity的情況。
你可以在真正啟動Activity之前測試一下是否有匹配的,也可以直接啟動Activity然後處理異常。 兩種解決方案見博文Can I use this Intent?。
通過查詢PackageManager可以知道一個Intent能否被匹配到一個Activity。 博文提供瞭一個例子,在isIntentAvailable()方法中。 然後,如果無法匹配,你可以停止構造Intent對象,或者再提示給用戶一個地址,例如Market,讓他去下載需要的應用。 如此,你的代碼在調用startActivity()或者startActivityForResult()的時候,可以保證Intent對象都是經過測試的並可以匹配到合適Activity的。
考慮你的Activity如何才能被其它Application重用。
一個設計者,或者開發者,應該清楚用戶可以如何啟動你的Application,以及使用Application內的Activity。 用戶可以通過主屏,或者其他Application來使用你應用裡的Activity。
從主屏啟動你的主Activity- 如果你的應用可以獨立運行, 用戶可能會從ApplicationLauncher(一般來說被實現成為主屏上的滑動抽屜), 或者主屏上的快捷方式,或是是TaskSwitcher,來啟動它。 (這個機制,是對於IntentFilter的動作是MAIN分類是LAUNCHER的Activity。)
在其它應用內部啟動你的Activity – 或許你的Activity是能夠被重用的那種。 例如,很多Application能夠用來和其它用戶分享數據。 分享的方式包括電郵,文字信息或者把數據上傳到某個公共網址。
當你的一個或多個Activity可以替代別的Application已存在的Activity時,在用戶需要這個Activity時你可以讓你的Activity也對用戶可用。   例如,如果你的Activity也可以發送數據(電郵、文字信息或者上傳),要考慮把你的這個Activity作為一個選擇提供給用戶。 給出一個特定的例子。Gallery讓用戶可以分享圖片。 當用戶從菜單選擇“分享”時,系統會比較“分享”請求(一個Intent對象)和可用的Activity(通過它們的IntentFilter),然後提供給用戶來選。 此時,系統匹配到瞭Email,Gmail,Messaging和Picassa。 要是你的Activity也能發送圖片或者上傳圖片的話,隻需要通過配置IntentFilter讓你的Activity可用就可以瞭。
其它Activity啟動你的Activity的時候,可能期望或者沒有期望有返回。
期望有返回 – 這種情況是一個閉環,被啟動的Activity必須或者返回一個確定值,或者被取消。 在上面那個從Gallery分享圖片的例子裡,用戶完成瞭發送或上載操作後,返回到瞭Gallery。 這個就是在Gallery中啟動一個外部Activity的例子。 (通過 startActivityForResult()啟動的Activity就是這樣)。
並不期望有返回 – 這種情況,是開放的。 以在郵件中點擊地址為例,MapActivity會被啟動來顯示地圖。 電郵並不需要Map來返回什麼。用戶可以通過按BACK來返回。 (通過startActivity() 啟動的Activity就是這樣)。
你的Activity僅僅能從其它Application內部啟動。 – 上一個通過Email、Gmail、Messaging或Picass分享圖片的例子中, 所有的Activity也都可以通過點擊主屏上ApplicationLauncher上的圖標來啟動。 與之不同的是,用於裁剪圖片並附加文件的Activity,不能從主屏啟動。它們需要上下文運行環境,不能獨立運行。
實際上,連Application都不是所有的都有圖標並且可以在主屏啟動的。 拿一個不常用的小應用做例子,這個小應用能夠替換一個其它Application中有進入點的功能。 例如,Android一般有一個內建的鈴聲選擇器,用戶可以從設置應用中的聲音設置來進入。 你可以寫一個自己的鈴聲選擇器,可以用跟系統的選擇器同樣的Intent來進入。 如下圖所示,當用戶選擇“電話鈴”的時候,會有一個對話框,來讓他選擇是使用系統的選擇器還是你的選擇器,用戶可以保存他們的選擇。 鈴聲選擇器是一個不怎麼常用,並且有一個已經明確定義的開始點(其它應用中)。所以,其實沒必要在主屏弄一個單獨的圖標給它。
 
一個Application有兩個或多個主Activity,並且這些主Activity都有圖標在主屏上。 – 我們已經定義瞭,單獨apk文件中的所有東西,都屬於一個Application。 你可以寫一個有多個主Activity的Application。
Camera.apk就是一個應用多個分開的主Activity的很好的例子。它有兩個主Activity,Camera和Camcorder, 有不同的圖標,並且可以獨立進入。 在用戶看來,好像是兩個不同的應用。 它們共享同一個鏡頭,而且都把數據(靜態圖片或者動態圖片)存到Gallery裡去。
In order for your application to contain two different, independent activities launchable from Home, you must define them to be associated with different tasks. 如果你希望你的應用包括兩個能從主屏進入的不同的不相關的Activity,你需要定義它們關聯於不同的Task。 (意思就是說,要為每個主Activity設置不同的TaskAffinity。上面這個例子中,是“com.android.camera”和“com.android.videocamera”。)
Contacts和Dialer實際上也是這種情況,在同一個Application的兩個主Activity。
把你的Application做成一個Widget – 一個Application也可以把它自己的一部分作為一個AppWidget來展示,嵌入到主屏,或者其它的應用,並周期性地接收更新。
要允許你的Activity進入當前的Task。(而不是新建一個Task)。
如果你的Activity能夠被其他Application啟動的話,應該允許它們進入到當前Task, 或者一個有TaskAffinity的已經存在的Task。 讓Activity能夠被加到Task裡去,可以讓用戶在包含你的Activity的Task和其它Task之間切換。 除非你的Activity隻允許一個實例。
要達到這種效果,你的Activity的LaunchMode應該是standard或者singleTop,而不是singleTask或者singleInstance。 這些LaunchMode(standard或者singleTop)允許你的Activity有多個實例。
Notification應該能夠讓用戶輕易地返回上一個Activity。
後臺運行的應用,可以用一個Service來向用戶發送Notification,讓他們知道他們感興趣的事件。 Calendar和Email是兩個例子。Calendar會發送Notification作為鬧鈴提醒,而Email會發送Notification來提醒用戶新郵件。 建議,當用戶在ActivityA,收到瞭一個Notification,通過這個Notification進入到ActivityB,再按BACK鍵時,應該回到ActivityA。
下面的流程展示瞭,當用戶處理一個Notification的時候,ActivityStack會如何工作。
用戶在Calendar中新建一個提醒事件,然後發現需要從某封電郵中復制些內容進來。
用戶點擊HOME > Gmail。
在Gmail裡,用戶收到瞭一個從Calendar來的Notification,提醒他馬上要開一個會。
用戶選擇這個Notification,於是用戶進入瞭另一個CalendarActivity,這個Activity顯示瞭這個會議的細節摘要。
用戶選擇瞭這個提醒,想看更多的細節。
看完這個事件後,用戶按BACK鍵。回到瞭Gmail,即是他剛剛離開去看Notification的地方。
上述行為並不是必須的。
Notification一般來說通過下述方式之一來實現:
展示出來的Activity僅僅是為瞭Notification服務的。 – 例如,當用戶收到一個Calendar的Notification,選擇這個Notification會啟動一個特殊的Activity。 這個Activity展示瞭一個即將到來的事件的列表 — 這個視圖僅僅是為瞭展示Notification用的, 在Calendar自己的UI中,沒有入口。 當看完最近事件列表後,要保證用戶可以通過BACK鍵來回到他剛才點擊Notification時的Activity。 你應該保證這個專用的Activity的TaskAffinity與Calendar或者其它任何一個Activity的不同。 (要做到這一點,設置TaskAffinity為空字符串就行瞭,標示這個Activity跟任何其它任務無關)。 下面是解釋。
由於Task的工作方式,如果這個專用Activity的TaskAffinity保持默認的話,在上面的第6步按BACK鍵後, 會回到Calendar,而不是Gmail。 原因是,默認情況下,同一個Application的所有Activity有同一個TaskAffinity。 因此,這個專用的Activity的TaskAffinity會匹配第1步的那個Calendar的Task。 這意味著,選Notification會把已存在的Calendar事件(第1步的那個)拉到前面, 然後把這個專用Activity放到最上面。 這個不是你想要的。把這個專用Activity的TaskAffinity設成空字符串就能修正這個問題。
展示出來的Activity並不是專用的,但是一旦出現到前臺就是初始化狀態。 – 例如,在響應Notification的時候,當Gmail到前臺,它總是會顯示會話列表。 你可以通過把“clear top”flag放到notification的觸發intent裡來保證這個。 這種做法 – 啟動Activity,這個Activity總是展示初始化狀態 – 防止瞭當Gmail進入前臺時處於用戶離開時的狀態。 (你可以把 FLAG_ACTIVITY_CLEAR_TOP放到傳遞到StartActivity()的Intent來做到這一點)。
其它方式也可以用來處理Notification,包括把Activity拉到前臺,展示特定的數據(展示剛剛收到新消息的文字消息線程)
一個Notification總是把Activity啟動到新的Task。(Intent總是帶著FLAG_ACTIVITY_NEW_TASK)。 這是因為,一個對當前任務的打斷,不應該屬於當前任務。
使用Notification系統 — 不要用Diaolog代替Notification。
如果你的後臺Service需要通知用戶什麼的話,使用標準的Notification系統 — 不要使用Dialog或者Toast來通知。 Dialog或者Toast會立即吸引用戶的註意力然後打斷用戶,把他的註意力從他正在做的事情上吸引開: 用戶可能正在輸入文字,此時Dialog出現的話,這些文字會被突然應用到Dialog上。 用戶習慣於在方便的時候再處理你的消息和通知。
如果不是絕對必要,不要接管BACK鍵。
用戶從一個Activity到另一個Activity的時候,系統會把它們放到Activity棧裡去。 這些以一個導航歷史的形式被BACK鍵利用。 大多數的Activity都有有限的目的,有單一系列的數據,例如看一批聯系人,寫郵件,或者拍照。 但是,如果你的應用隻是一個大Activity,其中有一些頁,需要細粒度控制BACK鍵的時候呢? 這樣應用的例子,是瀏覽器和地圖。Google瀏覽器有一系列的web頁,Google地圖有一系列的圖層可以切換。 這兩個應用都接管瞭BACK鍵,有內部的返回棧。
例如,Map使用瞭層在地圖上來展示不同的信息給用戶:展示地址搜索的結果,展示朋友的地址,展示兩點之間的路線等。 Map自己儲存瞭層的棧,所以BACK鍵可以回到上一層。
同樣地,Browser使用瀏覽窗口展示不同的web頁。 每個窗口有它們自己的導航歷史,類似桌面操作系統中瀏覽器的Tab,每個Tab都有不同的返回棧。 For example, if you did a Google web search in one window of the Android Browser, clicking on a link in the search results displays a web page in that same window, and then pressing BACK would to the search results page. Pressing BACK goes to a previous window only if the current window was launched from that previous window. If the user keeps pressing back, they will eventually leave the browser activity and return Home.

發佈留言