Android P正式版(如下稱爲Pie)已經正式上線了,各大廠商已經開始了系統升級工做,咱作上層開發的也得跟上節奏。固然了,新版本全部的行爲更改內容均可以在官網上找到,對於其中如何繞開非SDK接口限制的問題,也有各路大神給出瞭解決方案。因此,我只能當搬運工了(偷笑ing)。下面我會結合現有的開發經驗,聊聊Pie中對咱們開發影響較大的一些更新,重頭戲仍是適配齊劉海和非SDK接口限制。java
這裏只會列出部分行爲變動(僅表明我的看法),感興趣的同窗直接去官網查看。linux
Pie官方文檔android
更新內容:
git
影響:APP的推送功能可能須要適配,Pie中能夠知道渠道組的狀態了。github
更新內容:
api
影響:對APP級別的影響應該較小,畢竟大部分都是使用第三方庫來實現圖片資源的加載。可能對SDK影響較大,SDK裏基本都是本身寫Image壓縮解碼邏輯,因此能夠考慮使用。緩存
更新內容:
在 Android 9 中,系統表明您的應用提供生物識別身份驗證對話框。 該功能可建立標準化的對話框外觀、風格和位置,讓用戶更加確信,他們在使用可信的生物識別憑據檢查程序進行身份驗證。安全
影響:接入了生物識別功能的(如:指紋)APP就有統一的提示對話框了,挺好的。就是不知道標準的風格是否適合各類應用。微信
更新內容:
網絡
影響:用戶能夠在關閉自動旋轉的狀況下,手動旋轉屏幕;可否旋轉取決於頂層可見Activity所支持的旋轉設置。
更新內容:
影響:這個無疑強化了TextView的能力,應該比如今設置TextVie的樣式方便。
更新內容:
應用待機羣組
的概念,系統將根據用戶的使用模式限制應用對 CPU 或電池等設備資源的訪問。 影響:無疑,Google在幫Android機省電、省資源,算是一個比較好的更新。可是,我相信廠商會對分組策略稍做修改(或者白名單啥的),以方便自身應用能夠隨時喚起。總的來講,應該對應用的Push類功能影響較大。
更新內容:
影響:權限變動對收集手機應用信息和監聽應用WiFi狀態(主要是位置信息)都有很大影響,特別是對這些信息有依賴的業務。
更新內容:
從 Android 9 開始,默認狀況下Apache網絡庫已從 bootclasspath 中移除且不可用於應用。
影響:終於要完全拋棄Apache庫了,但業務硬要用的話,仍是能夠本身導入jar包或者在AndroidManifest.xml中使用uses-library標籤。
有Pixel的同窗能夠把系統升級到Pie查看效果,也能夠下載相應鏡像用模擬器測試(最好使用AS3.1以上)。Pie提供了三種劉海樣式:
在Pie中,官方提供了DisplayCutout
類來獲取劉海塊相關數據;經過getDisplayCutout()
函數能夠知道劉海是否存在;經過窗口布局屬性layoutInDisplayCutoutMode
可讓應用爲設備屏幕缺口周圍的內容進行佈局。直接上代碼吧:
@TargetApi(28)
public void showDisplayCutout(View view) {
// 注意:getRootWindowInsets()只有在視圖加載完成後,纔會返回,不然返回null
DisplayCutout cutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
if (cutout == null) { // 沒有劉海的時候拿到的DisplayCutout爲null
Log.d(TAG, "showDisplayCutout: 普通屏,沒有劉海");
return;
}
List<Rect> rects = cutout.getBoundingRects(); // 獲取可能的凹凸塊
if (rects.size() == 1) {
Log.d(TAG, "showDisplayCutout: 有劉海");
Rect rect = rects.get(0);
Log.d(TAG, "showDisplayCutout: 劉海區域:" + rect);
} else {
Log.d(TAG, "showDisplayCutout: 有劉海和下巴");
for (Rect rect : rects) {
Log.d(TAG, "showDisplayCutout: 區域:" + rect);
}
}
// 獲取安全區域的數據,單位px
int safeInsetLeft = cutout.getSafeInsetLeft();
int safeInsetTop = cutout.getSafeInsetTop();
int safeInsetRight = cutout.getSafeInsetRight();
int safeInsetBottom = cutout.getSafeInsetBottom();
Log.d(TAG, "showDisplayCutout: 安全區域距離屏幕左邊:" + safeInsetLeft);
Log.d(TAG, "showDisplayCutout: 安全區域距離屏幕頂部:" + safeInsetTop);
Log.d(TAG, "showDisplayCutout: 安全區域距離屏幕右邊:" + safeInsetRight);
Log.d(TAG, "showDisplayCutout: 安全區域距離屏幕底部:" + safeInsetBottom);
int statusBarHeight = getStatusBarHeight();
Log.d(TAG, "showDisplayCutout: 狀態欄高度:" + statusBarHeight);
}
private int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
複製代碼
注意:
設置窗口屬性:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
// 設置全屏
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
//沉浸式狀態欄
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
WindowManager.LayoutParams lp = getWindow().getAttributes();
// 只有當DisplayCutout徹底包含在系統欄中時,才容許窗口延伸到DisplayCutout區域。 不然,窗口布局不與DisplayCutout區域重疊。
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
// 該窗口決不容許與DisplayCutout區域重疊。
// lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
// 該窗口始終容許延伸到屏幕短邊上的DisplayCutout區域。
// lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(lp);
}
複製代碼
部分效果圖:
普通頁面帶狀態欄
全屏頁面默認狀況
全屏頁面強制使用劉海區域
沉浸式
適配方案:
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
,則會強制使用劉海區域,這時頁面要規避劉海塊的那一點區域。Android 9(API 級別 28)引入了針對非 SDK 接口的使用限制,不管是直接使用仍是經過反射或 JNI 間接使用。不管應用是引用非 SDK 接口仍是嘗試使用反射或 JNI 獲取其句柄,均適用這些限制。
若是咱們使用非SDK接口,會出現幾種狀況:
非SDK接口都記錄在了不一樣的名單下:
全部的名單文件都在:android.googlesource.com/platform/pr… ,其中還有一個veridex
檢測工具(目前只支持linux和mac)。
直接借用大佬們的文章: 360奇卓社-Android P 調用隱藏API限制原理
大體過程:
仍是大佬們的文章:
其中替換classloader
的方式目前是最可靠的。