本文翻譯自 http://androidinternalsblog.blogspot.com/2014/03/split-screens-in-android-exist.html
很多 Android 廠商已經做了很久的一個功能——分屏
這個功能來源自桌面作業系統,能讓多個应用以窗口的形式同时显示在一个屏幕上。
有人已經做了出來:http://www.onskreen.com/cornerstone (他們的方案前不久也被 CyanogenMod 所採納了)
要把它做成三星那樣的多窗口功能,我相信還是有很多工作要做的,比如在移動設備界面上做得更人性化。 然而,我現在要談的是,Google自己的解決方案。WindowsManagerService 當我在比較KitKat和JellyBean代碼 ActivityManagerService.java 時注意到有幾個方法:Android這種新的功能已經存在了一段時間,但似乎沒有人在意。不知爲何,新的 API似乎總是容易被忽略。
createStack, resizeStackBox 和 getStacks
KitKat版本的 ActivityManagerService 和 WindowsManagerService 是如何交互的,超出了本文的範圍,但我可以說2點:
- Android4.4版本以來,以上兩個系統Service有了更多的交互,WindowsManagerService 改進了堆棧式的管理 (became stack-aware)
- 這樣的改進遠未達到可以Release(比如說,這個分屏解決方案還不能正常工作,但其實已經在正確的方向上了)
* 在下文的描述中,我把 WindowManagerService 的 'stack box' 稱之爲 'stack'. 我把它這樣寫只是爲了方便。 但其實 ActivityManagerService 中的 stack 其實是另一個不同的類.
我用模擬器跑 原生KitKat 系統,打開了電子郵件和通訊錄兩個應用(打開前一個應用按Home鍵使之不退出)
# am stack boxes
![]()
注意上面的輸出,你會發現實際上有兩個stack,JellyBean只有一個 ActivityStack, KitKat開始有兩個:
這兩個stack都由 ActivityStackSupervisor 控制。
- HOME stack: id = 0,用於啓動器的界面顯示,當設備上有數個啓動器時都會使用這個stack,除此之外,系統界面(猜測是提示框,輸入法等)也是從這個stack啓動的
- Applications stack: id可能是任意值,所有由啓動器啓動的應用界面或是一些系統界面,都使用這個stack來運行
爲了能夠手動分屏,我只需輸入以下命令:
# am stack create 3 2 4 0.5
結果如下圖:
這些數字的含義:
語法: am stack create <int1> <int2> <int3> <float1>
創建一個新的stack以運行指定的程式(由TASK_ID指定),與已存在的stack相關聯(以分屏的形式同時顯示)
- <int1>: TASK_ID - 希望在新的stack上運行的任務Id.
- <int2>: RELATIVE_STACK_BOX_ID - 以上任務所在的StackBox的Id.
- <int3>: POSITION - 與相關聯的stack的相對位置:
- 0: 在相關聯 stack 之前(取決於 on RTL/LTR 設定)
- 1: 在相關聯 stack 之後(取決於 RTL/LTR 設定)
- 2: 在相關聯 stack 的左側
- 3: 在相關聯 stack 的右側
- 4: 在相關聯 stack 的上方
- 5: 在相關聯 stack 的下方
- 6: displayed on a higher layer than the relative stack (未使用)
- 7: displayed on a lower layer than the relative stack (未使用)
- <float1>: WEIGHT - 權重值,[0.2, 0.8]
我所執行的命令是將 任務Id3(Email) 移動到 stackId 2(People)上方的新創建的stackId 3中,並使之同時顯示在屏幕上. 現在屏幕上就有了大小相同的兩塊:第一塊顯示 Email界面,第二塊顯示聯繫人界面。
將權值改爲0.7以後的結果:
正如所見,權重參數控制着每個 stack區域能夠顯示的相對大小。
各種問題:
這裏並沒有討論所有的新功能(包括重定義stack的大小,更改Task在同一個stack中的順序)。實際上我不討論的原因是當我做以上嘗試時,對應的顯示區域就會消失。一頭霧水中...
- 這些功能在隱藏的API中,當我嘗試寫個應用來做些調整時需要用到JAVA反射
- 更糟的是,需要的權限級別爲'signature',除非你自己創建ROM,或者你有ROM的簽名,否則普通的程式無法做到。
- 如果你在設備上執行am命令,你必須有ROOT權限,或者設備已經ROOT過(如果你選擇這種方式,下面還有一件事需要注意)
- 最重要的,這個功能經常有問題。
儘管已經可以在設備上運行了,出來的結果卻常常不是我們希望的那樣。
呵呵。
如果有人在已ROOT的設備上執行am命令,即便加了'su',可能也會沒有任何打印輸出.
需要先執行以下命令:
# setprop log.redirect-stdio true
然後你才能在logcat下看到 am 的執行結果。
====================================================================================
其實此時的三星在Galaxy NoteII及GalaxyS4等設備上已集成了多窗口功能(类似的分屏功能):![]()
個人實際使用的感覺,功能受到限制,操作略顯複雜。在手持設備性能日益強大的今後,真正的多窗口一定會在大屏幕Android設備上實現,類似PC桌面作業系統的窗口那樣,哈哈。
就像下面這兩張圖那樣:
我看好你哦,小米!