1. 程式人生 > >關於 Android N 那些你不知道的事兒

關於 Android N 那些你不知道的事兒

今年3月,Google 破天荒提前半年釋出了 Android N 開發者預覽版。當然,作為一個不合格的穀粉並沒有第一時間體驗安裝,因為至今仍然能夠回憶起來去年今日此門中(霧)興沖沖刷了 Android M Preview 的時候發現各種 Crash 就連微信也(不出所料得)中招時自己一臉懵逼的心情。當然,為自己的機智而慶幸並沒有過多久,很快就有微信好友(當然也是純純的穀粉)反饋微信又雙叒叕在 Android 新版本下 Crash了……好吧這次我們的時間很充裕,因為 5 個 preview 之後才會釋出最終 release 版本。令人失望(咦)的是,我們的工程師在一天之內就修復了這個 bug 並且趕在當天 6.3.15 alpha 版本釋出之前修復併合入主線,辜負了 Google 的一片苦心。

痛定思痛,當天我就拎起來麒麟臂,在 Chrome 的位址列重重得敲入:http://developer.android.com/preview/overview.html ,並且聽說Google 在北京舉辦了 Android 開發者大會的時候,屁顛屁顛得過去了。

假如我是產品經理
在這個『人人都是產品經理』的年代,作為程式設計師當然是敲得起程式碼,當得起經理(。。。)。如果我是產品經理,Android N 的更新無非是以下三個點:
預設多視窗支援
強化通知,裡邊有你最喜歡的直接回復
沒了…當然不是:Android Developer 一筆帶過的重磅 feature:允許第三方應用在快速設定中新增自己的服務

預設多視窗支援
注意『預設』二字:這很重要,這很重要,這很重要。

Android M 裡邊,系統允許應用在啟動某 Activity(對於 PM 來說可以不嚴謹得理解成介面)時帶上特殊引數,該應用可以在最近任務視窗中和主應用分開顯示,即 multi-tasking 支援。當然,並沒有多少應用鳥這個 Android M 中為數不多的新特性之一,因為效果實在是不明顯。也有一定的原因是在這個大部分產品經理不會關注 Android Developer 的年代,這個非預設的特性實在不會引起他們的注意。

在 Android N 中,竟然直接支援了 multi-window!雖然這個特性並不驚豔,在 iOS 和三星的機型中早已支援,甚至在 Android M 中,也可以預埋了這個特性,並可以通過某些特殊方法開啟。然而,和 iOS 應用需要特殊宣告才能支援多視窗的特性不同,Android N竟然預設支援了多視窗。這意味著任何一個應用,無論 target-api 是否是 Android N,都支援從最近任務中長按應用標題欄進入多視窗模式。這裡是個 Demo。

預設支援也就意味著除非特殊宣告,任何應用都支援前述視屏所示效果,也就是說如果應用不針對這種模式進行完美適配,或者說用了絕對佈局的話,你的應用就會。。。。呵呵呵。

當然,這種老掉牙的特性是不會引起高冷的 PM 的注意的,只會扔給開發狗交給我們去適配。那好吧,來一個 one more thing 刺激一下你:
在 Android N 中,將支援分屏情況下 drag and drop,讓這個4.0開始就支援 faeture 煥發了新生。這也就意味著你可以將一個應用內、甚至不同應用間的分屏情況將一個分螢幕控制元件拖拽到另外一個分螢幕。也許可以用來拖拽圖片快速發圖,或者。。隨便你想幹什麼。
當然,從開發狗的角度來說,這裡有一點安全隱患:如果通過拖拽將資料傳遞過來,你甚至不知道來源是什麼。但是想想也是,畢竟用的和貼上板一樣的介面,還能指望什麼呢?

另外,作為分屏的一種特殊形式,畫中畫(picture in picture)也得到了相應的支援。不過據 Google 的工程師說,畫中畫模式主推 Android TV 中應用(也許 Google 認為在手持裝置上場景不足)。不過 whatever,現在很多功能已經可以通過浮窗介面實現。畫中畫對於做視訊應用或者有視訊支援功能的應用非常有幫助。

此外,給程式設計師朋友們幾個小貼士
雖然分屏狀態下兩個應用都可見,但是對於非 Focus 狀態的應用當前是處於 onStop 狀態的,也就是說,並沒有實際在執行中。原本 onStop 的時候應用應該是不可見,但是現在可見了。。。原本的一些噁心邏輯注意修改下。
雖然分屏狀態下的應用不會 double 記憶體佔用,但是記憶體佔用肯定會比正常狀態大,注意分屏模式下即時釋放記憶體。
適配好你的程式,該加 scroll 的地方加 scroll。當然,如果原本的你的程式就已經針對多尺寸螢幕有了處理,就已經完美適配了這個模式

強化通知
通知欄一直是 Android 引以為豪的方面。相對於 iOS 的通知欄來說, Android 的通知欄具有幾乎完爆的功能:自定義控制元件,自定義 Action,可以定義下來拓展的控制元件……除了快速回復。
在這之前,先上一段 Android N 新版本的通知欄和快速設定欄,至於為什麼放視訊,嗯。。。因為我覺得很好看:點我看視訊

如今,這一點已經被 Google 迎頭趕上,並且體驗絕不亞於 iOS,甚至好很多。
當然,如果一次來了多條訊息並且都不是一個會話中,快速回復也是毫無壓力:
這個新特性簡而言之就是滿足了快速回復的一切需求,也許從此再也不用擔心沉浸式閱讀時需要跳出回覆訊息這種傷害體驗的情況。
當然了,除了快速回復,還有根據應用歸檔通知,這無疑是一個大殺器:

同時,這裡需要同時提醒PM和開發同學的是:如果真的需要在通知上設定自定義控制元件,請呼叫DecoratedCustomViewStyle()。它會讓你的自定義控制元件在通知欄顯得更加和諧。Sample:
[Java] 純文字檢視 複製程式碼
?
1
2
3
4
5
6
Notification noti = new Notification.Builder()
.setSmallIcon(R.drawable.ic_stat_player)
.setLargeIcon(albumArtBitmap))
.setCustomContentView(contentView);
.setStyle(new Notification.DecoratedCustomViewStyle())
.build();
『何必這樣,我寫一個BroadcastReceiver監聽CONNECTIVITY_ACTION然後處理不就行了,naive!』
科科。
為了防止這個沒有節操的事情發生,Google 在 Android N中拿掉了這三個廣播:
CONNECTIVITY_ACTION:網路變化
ACTION_NEW_PICTURE:新增新圖片
ACTION_NEW_VIDEO:新增新視訊

這也是我非常佩服 Google 的一個點,敢於做減法。當然,留下的坑就多了,比如 CONNECTIVITY_ ACTION,很多應用(包括微信)都會監聽。今後需要使用 JobScheduler 實現相同的邏輯了。JobScheduler 有非常多的好處,他會根據使用者當前裝置的情況,比如當前 RAM、電量、模式、是否應用在前臺等等,決定是否執行該邏輯。你也不希望自己的程式變成使用者手機變卡的罪魁禍首,從而讓使用者怒刪,對吧?

當然了,不允許監聽 CONNECTIVITY_ ACTION 針對的是靜態註冊的 BroadcastReceiver,如果是動態註冊的 BroadcastReceiver 則並不會受到影響。

Java 8支援
早在前年開始研究 Annotation 的時候,就在感慨為什麼 Android 一直不支援 Java 8,即使現在 Java 9 都快出了。終於的終於,Android從N 版本開始支援 Java 8的編譯,前提是要在 Gradle 檔案中顯式宣告使用 Jack 編譯器。
這個 Jack 是什麼鬼呢?簡單來說,傳統的編譯工具鏈是將 java 程式碼通過 javac 編譯成.class 檔案,再通過 dx 編譯成 .dex。也就是醬紫的:
[Java] 純文字檢視 複製程式碼
?
1
javac (.java –> .class) –> dx (.class –> .dex)
而 Jack 則是一條龍服務,中間不需要經過其他工具或者命令,一條命令就可以將.java 檔案編譯成.jack 從而程式設計.dex:
[Java] 純文字檢視 複製程式碼
?
1
ack (.java –> .jack –> .dex)
使用 jack 非常簡單,gradle 配置即可
[Java] 純文字檢視 複製程式碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
android {

defaultConfig {

jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
不過,Android N 版本的 Java 8特性並沒有支援全,不過主流的 feature 已經支援,包括:
定義介面預設實現方法
Lamda 表示式支援(喜歡語法糖的同學的福利)
Repeatable annotations。這個已經可以說的內容很多,改天有空給大家慢慢介紹。
Method Reference。這個實話實說我並不是太瞭解,也是語法糖一種。感興趣的同學可以看看這個連結:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

但是現在還沒有支援一個很重要的特性:Stream。但是現在還在 Preview 階段,比如剛剛的第四條 Method Reference 就是 Preview2 支援的,可以期待下 release 中是否會支援(最新訊息:已經支援 java.util.stream 介面,棒棒的!)。

此外還需要注意兩點:
Lamda 表示式本質上回生成匿名類,在效能敏感的模組慎用
由於 Jack 編譯器不會產生.class 中間檔案,因此在.class 上做 trick 的一些庫或者專案可能就會失效或者出問題。因此在使用之前,一定要好好測試。

其他應該注意的事項
Data Saver:乍看上去是一個數據儲存的 API,感覺很興奮,結果點開一看是流量節省。。。好吧,博大精深的英文。從 Android N 開始,系統層級支援使用者針對每一個應用新增自己的流量控制限制。今後開發的時候需要先通過 ConnectivityManager.getRestrictBackgroundStatus() 介面獲取本應用流量控制情況。
Key Attestation:對於絕大部分應用並不需要仔細研究的 feature,甚至可以當做不存在,但是對於我個人所做的生物認證專案來說,可謂是非常重要的 feature。
針對檔案目錄或型別申請許可權:實話實說,這個也算是一個很重要的 feature。從 Android 6.0 開始,如果需要使用儲存空間,包括讀寫,需要動態申請許可權。然而對於大部分應用來說,都需要申請這個許可權,而且一旦使用者允許,應用就可以為所欲為。因此,Android N 中允許應用宣告僅僅授權某個資料夾或者檔案型別的儲存。

禁止 Native 動態連結系統庫
這一點 Android Developer 沒有講,至少暫時沒有講
還記得之前我說的微信升級到 N 會 Crash 麼?實際上就是這個原因。

自 Android N 開始,系統將禁止第三方應用 so 檔案連結系統 lib 庫,包括並不限於 libcrypto.so,libandroidruntime.so,libicu.so,libbinder.so。動態連結上述庫輕則彈 Toast 提示,重則直接 crash。Android 此舉原因大家可以討論,但是事實已然如此,儘管對於大多數應用而言並無妨礙,但是對於類似微信這種在底層做了大量優化和呼叫的應用來說還是很傷腦筋的。至於解決方法。。。暫時只想到了改用靜態連結,對於包的大小增加並不會太大。如果有更好的方法,歡迎大家討論。
實話實說,這次 Android N 的更新對於我們程式設計師來說還是乾貨滿滿,滿到我有些話想說。

扯淡
前面說的都是 Android N,現在終於開始講扯淡了。實際上,從 Android L 開始,Google 就已經開始反省自己過分開放的策略。原本後臺任務滿天飛的系統,現在漸漸地被控制得有序起來。比如 Android L 釋出的 JobScheduler,Android M 釋出的 Doze 模式和 APP Standby,Android N 的 Doze 加強以及瘦身計劃,無一不是在限制系統的後臺任務數量以及計算強度。亡羊補牢,不知是否為時未晚。

同時,關於設計方面,Material Design 推出已經接近兩年,儘管有很多應用已經適配,但是包括微信、Facebook、Twitter 在內的很多主流應用仍然在堅持使用自己的設計語言。誠然,這裡有可以理解的風格統一之考慮, MD 本身也有很多缺陷,但是我們很高興能看到的是 MD 自身在不斷的調整優化,越來越成為一個漂亮的並且優秀的設計,其層次感以及靈動性無處不撩撥著使用者的神經。所以,是不是仍有很多人抱著 2.3 混亂局面或者 4.0 不那麼優秀的 Android Design 來臆測 Android 的設計風格?也許用著 iOS 的諸位對於 Android 的印象依然是 2.x 時代那個臃腫的、落後的以及。。額,難看的形象。就像這樣:

這是2011年左右,畢竟是5年前,那時 iPhone 上的應用也並不好看,不過還是比 Android 要強很多。但是現在 Android 應用已經長這樣了(系統自帶應用):

個人認為比 Apple 的設計。。。(為了防止引戰)至少並不差吧。
其實,這裡說了這麼多,精通讀心術的我也能想到大家心中的疑問:碎片化如此的 Android 市場,我們就算是適配了 N 的特性,大家也沒有這麼快用上,還是歇著吧。嗯,關於碎片化,首先,Android 目前版本分佈是醬紫的(來自 Google 官方,連結 http://developer.android.com/about/dashboards/index.html

也就是說,至少截止到今天,接近40%的人的裝置已經是 Android 5.0 以及以上,按照如今廠商發貨的速度,目測一兩個月內比例就會過半。平心而論,針對這半數使用者,有幾家應用做到了完美支援?無論是 UI 還是具體功能,大部分應用應該都是在4.x,甚至2.x版本的基礎上填坑,fix 新版本上的 crash,有幾家用到了新的特性,新的 feature 呢?而大家以為佔主流的2.3系統,實際上已經不足3%,是不是仍然有很多應用的 target api 仍然是 4.x 以下?
而且 Google 現在很雞賊啊(這一點謝老大提醒),一年釋出一個大版本,前年5.0,去年6.0,今年 7.0,你說 Google 都到 7.0 了你還好意思連 5.0 都不上?這一點實際上對於解決碎片化是非常有幫助的。

面對佔市場份額近 7 成的 Android 裝置本身並不需要救助,一直都沒有放棄發展,欣欣向榮。相反,需要救助的是我們在 Android 上的應用,低質量的應用實現已經威脅到了我們自身。不僅僅是要依靠產品經理,作為程式設計師,我們也要學會自救。
感謝!