Android我還能夠相信你多少系列文章四之懸浮窗

我即將在2017.7.8號開一個直播講堂,感興趣的同窗點擊快來參加吧:https://segmentfault.com/l/15...
內容包括:面試

  1. Android 知識體系分享segmentfault

  2. 從入門到提升的學習路徑微信

  3. 如何進一步突破瓶頸,進一步提高學習

  4. 充足的時間和你們討論,回答你們問題ui

自我介紹:this

網易 Android 專家工程師,網易雲音樂 Android 負責人,主導從零開發了網易雲音樂 Android
客戶端,目前是杭州研究院專業委員會成員,負責每一年的評級,規範起草,面試招聘等相關工做。參與並製做了網易雲課堂 Android
微專業相關課程,反響不錯。spa

懸浮窗應該算各大廠商最早開始對應用下手的地方。設計

懸浮窗之因此討人厭一樣是由於被濫用,就像狗皮膏藥同樣貼在屏幕的上下左右,無論切換到哪一個應用始終顯示在最上層。懸浮窗的需求有點從電腦端延續的味道,之前桌面上常常跑出來個獅子,有個懸浮球,或者歌詞。但那個時候佔用桌面面積小,相比手機屏幕尺寸,如今的懸浮窗很容易覆蓋住真正內容。那Android上面懸浮窗最初設計是想解決什麼問題呢?3d

懸浮窗也即一個Window。Window Type有不少種,好比TYPE_PHONE,TYPE_TOAST,TYPE_SYSTEM_ALERT等,用在來電,低電量顯示,狀態欄,短暫toast提醒等。Android系統給每一種Window類型定義了一個高度,依次從上往下顯示。官方文檔描述是這樣的:
v2-467a286945b81153f80c99603d7c8555_b.pngcode

下面這些值是系統定義的window類型,他們不是給普通應用用的。

既然不是預約義給應用用的,爲啥應用能用呢?
v2-bcb54ba3add46c2995452759502795bc_b.png

從源碼來看(摘自4.4版本,6.0之後版本權限管理更加嚴格),TYPE_TOAST的註釋代表彷佛是一段未寫完的代碼。而像TYPE_PHONE這類則是須要SYSTEM_ALERT_WINDOW權限,在6.0以前這是很是容易獲取到的,只要在Manifest裏面申明下便可。6.0之後須要運行時動態申請這個權限,申請方式跟普通的地理位置權限還不太同樣,以下的方式:

if (!Settings.canDrawOverlays(MainActivity.this)) {
  Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
   startActivityForResult(intent, 10);
}

爲何TYPE_TOAST不須要權限仍然不得而知。事實上從某一次跟官方的現場交流會上,官方人員也認可懸浮窗事實上也不是設計給應用用的。並且當他們驚訝的發現國內市場懸浮窗的需求如此強大以後,他們作了一件驚人的改變:就是在Android O上面針對國內市場懸浮窗需求特別修改了懸浮窗的設計。

v2-52dee01583cab2048edb02329fbee064_b.png

在Android O上面特別增長了TYPE_APPLICATION_OVERLAY來知足懸浮窗需求。須要注意的是即便你的應用TargetSdk不是等於O版本,能夠繼續使用TYPE_PHONE(O版本已廢棄),但會顯示在TYPE_APPLICATION_OVERLAY下面(因此想要顯示在最上面要儘快適配O版本)。在使用TYPE_APPLICATION_OVERLAY的時候,系統還會進行提示是否容許該應用顯示懸浮窗。

懸浮窗在國內的市場環境下有幾個問題:

6.0如下即便Manifest裏面定義了,也會被廠商本身擴展出來的懸浮窗開關默認禁掉

TYPE_TOAST在MIUI等機器上面被當作等同於TYPE_PHONE須要SYSTEM_ALERT_WINDOW權限

開發者須要作的事情:

優先使用TYPE_TOAST,但須要注意4.4版本以前沒法接收事件也即沒法交互以及MIUI問題。

6.0及之後使用動態權限申請通常不會有問題,6.0以前能夠根據機型動態下發權限打開頁面的路徑,來作到提醒用戶去打開權限。儘量引導用戶,不然就等着來反饋爲啥顯示不了。

留意Android O對懸浮窗作出的重大修改對本身形成的影響

TYPE_TOAST在7.1版本上面還有一些小修改,一個uid只能加一個;曾經比較流行將Toast做爲一個單例,隱藏toast的時候修改view的visibility爲gone來替換removeView,而後經過不斷setText和setVisibility爲VISIBILE來實現Toast內容快速切換(原生Toast必需要等duration時長消失後再出現下一個)。使用這種方式在7.1版本上面會出現問題,該版本上面在應用失去焦點的時候會有個定時器自動隱藏掉這個Toast Window,setText和setVisibility沒法恢復顯示這個Window了。
v2-f581b898818b1ddfd6ccca2565ec4770_b.png
v2-7bda4ec729a2a6d055e428418c8d4194_b.png
v2-48f2bba37362efddf88f0cd80ce4fe60_b.png
v2-cf3c6f23b9cd78d086987970d02f3abf_b.png

WindowManagerService裏面有兩處判斷焦點失去以後起定時器隱藏Toast Window。咱們能夠顯示removeView以後再addView來進行兼容。

更多文章請關注微信公衆號:anzhuozhimei

相關文章
相關標籤/搜索