版權(quán)聲明:本文為CSDN博主「尹中文」的原創(chuàng)文章蛹找,遵循CC 4.0 BY-SA版權(quán)協(xié)議膘滨,轉(zhuǎn)載請附上原文出處鏈接及本聲明筷狼。
原文鏈接:https://blog.csdn.net/yzwfeng/article/details/130148427
前言
進行公司車機設(shè)備開發(fā)時,由于屏幕比例比較特殊(1920x720)引润,導(dǎo)致部分應(yīng)用顯示時左側(cè)和底部有很大的黑邊宪赶,使用dumpsys分析黑邊的View宗弯,移除后發(fā)現(xiàn)仍存在,后確定為低版本默認(rèn)比例問題搂妻,耗費了幾個小時蒙保,記錄下這個問題。
出現(xiàn)問題的條件:
- Android 應(yīng)用:targetSdkVersion < 24 (Android N)欲主;
- 設(shè)備的分辨率寬高比大于1.86(1.86為Android低版本最大寬高比)邓厕;
- Android 應(yīng)用的AndroidManifest.xml內(nèi)未設(shè)置android:resizeableActivity="true"屬性;
問題解決方案
問題根據(jù)不同的情況有不同的解決方式
- 若擁有應(yīng)用源碼岛蚤,則可以直接將targetSdkVersion設(shè)置為大于等于24即可邑狸;
- 若擁有應(yīng)用源碼,但不能修改targetSdkVersion版本涤妒,那么就在
應(yīng)用的AndroidManifest.xml內(nèi)設(shè)置android:resizeableActivity="true"屬性单雾; - 若擁有應(yīng)用源碼,但不能修改targetSdkVersion版本,但compileSdkVersion=26時硅堆,
可以嘗試在的AndroidManifest.xml內(nèi)設(shè)置android:maxAspectRatio=""="寬高比"屬性屿储; - 若沒有應(yīng)用源碼,則需要嘗試修改系統(tǒng)層來達到適配的作用渐逃,具體修改見如下代碼:
系統(tǒng)層修改
/frameworks/base/core/java/android/content/pm/PackageParser.java
PackageParser在解析APK的AndroidManifest.xml文件時够掠,有如下代碼:
public class PackageParser {
....
private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
....
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
....
// 這里會去判斷xml內(nèi)是否有設(shè)置android:resizeableActivity屬性
if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
// 設(shè)置該標(biāo)志位后,應(yīng)用的Activity可調(diào)整大小
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
} else {
// 設(shè)置該標(biāo)志位后茄菊,應(yīng)用的Activity不可調(diào)整大小
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
}
} else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
// 若應(yīng)用未設(shè)置android:resizeableActivity屬性疯潭,且其targetSdkVersion >= Android N (24)
// 設(shè)置該標(biāo)志位后,應(yīng)用的Activity可調(diào)整大小
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
- }
+ }else {
+ ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
+ }
}
}
根據(jù)以上代碼可以看到面殖,默認(rèn)情況下沒有對未設(shè)置android:resizeableActivity屬性竖哩,且targetSdkVersion < 24的應(yīng)用不會設(shè)置其Activity可調(diào)整大小,所以我們需要為這種情況加上對應(yīng)的配置脊僚,即添加上述代碼中的相應(yīng)內(nèi)容相叁。修改后編譯進設(shè)備,即可看到應(yīng)用全屏顯示了辽幌。
問題分析
除了上面分析到的沒有Activity可調(diào)整大小標(biāo)志位導(dǎo)致的無法全屏問題增淹,還有一個是關(guān)于默認(rèn)最大寬高比(DEFAULT_PRE_O_MAX_ASPECT_RATIO)的問題,通過修改該值也可以實現(xiàn)應(yīng)用的全屏乌企,不過有時候屏幕比例變化較大時該值可能要經(jīng)常改動虑润,有點麻煩。下面主要是從源碼來分析下該值是如何起作用的逛犹。
/frameworks/base/core/java/android/content/pm/PackageParser.java
public class PackageParser {
....
private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
....
private void setMaxAspectRatio(Package owner) {
// 對于 O 之前的應(yīng)用程序默認(rèn)為 (1.86) 16.7:9 縱橫比端辱,對于 O 及更高版本則未設(shè)置梁剔。
float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
if (owner.applicationInfo.maxAspectRatio != 0) {
// 如果應(yīng)用設(shè)置了android:maxAspectRatio 屬性值虽画,則使用應(yīng)用程序所配置的最大寬高比。
maxAspectRatio = owner.applicationInfo.maxAspectRatio;
} else if (owner.mAppMetaData != null
&& owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
// 未設(shè)置則設(shè)置為默認(rèn)的1.86
maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
}
for (Activity activity : owner.activities) {
// If the max aspect ratio for the activity has already been set, skip.
if (activity.hasMaxAspectRatio()) {
continue;
}
// 這里可以獲取activity設(shè)置的maxAspectRatio屬性荣病,若應(yīng)用和activity都設(shè)置了码撰,則以activity的優(yōu)先
final float activityAspectRatio = activity.metaData != null
? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
: maxAspectRatio;
// 將最大寬高比設(shè)置給activity
activity.setMaxAspectRatio(activityAspectRatio);
}
}
}
以上就是為何應(yīng)用無法全屏顯示的原因,以及另外一種修改為何也能生效的原因个盆。
————————————————
版權(quán)聲明:本文為CSDN博主「尹中文」的原創(chuàng)文章脖岛,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明颊亮。
原文鏈接:https://blog.csdn.net/yzwfeng/article/details/130148427