AndroidManifest.xml初识
AndroidManifest.xml这个文件用来告诉android系统,这里面有关于APP的配置信息,你需要根据里面的设置的配置信息来运行这个app。
——根节点 ——应用节点,必须有 , , 描述应用的组件,作为 的子节点 ——用户特征标签,描述应用所依赖的硬件或者软件条件。在应用商店搜索的时候进行过滤。 ——用户权限标签,描述应用需要的权限
minSdkVersion 和 targetSdkVersion 和 compileSdkVersion
minSdkVersion和targetSdkVersion设置的值表示这两个区间的设备能正常使用这个app,表示您已经在您指定的版本上测试了应用程序(大概包括该版本)。这更像是一个认证或签署,你是给Android操作系统作为一个提示,它应该如何处理您的应用程序的操作系统功能。
(设备的android系统版本的使用的sdkversion是不一样的,比如Android5.0对应的targetSDK设置为21)。一般来说每次发布新的版本,targetSdkVersion应该递增以匹配最新的api级别,如果有变,然后在相应的平台版本上彻底测试应用程序。
而compileSdkVersion可以不变,除非你需要要最新的sdk中功能,那么需要相应的改变compileSdkVersion,举一个样例:
假如你想给你的app增加大量的手势操作(sdk
7才引入的),然而这些手势操作能够被Button啊或menu等取代,在这样的情况下,手势操作就是一个额外的加分功能,而不是一个必须的功能。然后你所要做的就是要在代码里推断版本号,假设是大于等于7的版本号中就使用手势操作,小于7的版本号中就使用button等取代。然后你把targetSDK设置为7,把minSDK设置为低一些。这样使用了新手机的用户就能够体验到你app中酷炫的新功能了,老用户也能正常运行。
Android 10.0 修改导航栏横屏固定在底部显示
路径:framework/base/core/res/res/values/config.xml -true +false
DisplayPolicy(WindowManagerService service, DisplayContent displayContent) { mService = service; mContext = displayContent.isDefaultDisplay ? service.mContext : service.mContext.createDisplayContext(displayContent.getDisplay()); mDisplayContent = displayContent; mLock = service.getWindowManagerLock(); final int displayId = displayContent.getDisplayId(); mStatusBarController = new StatusBarController(displayId); mNavigationBarController = new BarController("NavigationBar", displayId, View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_UNHIDE, View.NAVIGATION_BAR_TRANSLUCENT, StatusBarManager.WINDOW_NAVIGATION_BAR, FLAG_TRANSLUCENT_NAVIGATION, View.NAVIGATION_BAR_TRANSPARENT); final Resources r = mContext.getResources(); mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer); mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService( Context.ACCESSIBILITY_SERVICE); if (!displayContent.isDefaultDisplay) { mAwake = true; mScreenOnEarly = true; mScreenOnFully = true; } final Looper looper = UiThread.getHandler().getLooper(); mHandler = new PolicyHandler(looper); mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler, new SystemGesturesPointerEventListener.Callbacks() { @Override public void onSwipeFromTop() { if (mStatusBar != null) { requestTransientBars(mStatusBar); } } @Override public void onSwipeFromBottom() { if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) { requestTransientBars(mNavigationBar); } } @Override public void onSwipeFromRight() { final Region excludedRegion; synchronized (mLock) { excludedRegion = mDisplayContent.calculateSystemGestureExclusion(); } final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture || mNavigationBarPosition == NAV_BAR_RIGHT; if (mNavigationBar != null && sideAllowed && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) { requestTransientBars(mNavigationBar); } } @Override public void onSwipeFromLeft() { final Region excludedRegion; synchronized (mLock) { excludedRegion = mDisplayContent.calculateSystemGestureExclusion(); } final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture || mNavigationBarPosition == NAV_BAR_LEFT; if (mNavigationBar != null && sideAllowed && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) { requestTransientBars(mNavigationBar); } } @Override public void onFling(int duration) { if (mService.mPowerManagerInternal != null) { mService.mPowerManagerInternal.powerHint( PowerHint.INTERACTION, duration); } } @Override public void onDebug() { // no-op } private WindowOrientationListener getOrientationListener() { final DisplayRotation rotation = mDisplayContent.getDisplayRotation(); return rotation != null ? rotation.getOrientationListener() : null; } @Override public void onDown() { final WindowOrientationListener listener = getOrientationListener(); if (listener != null) { listener.onTouchStart(); } } @Override public void onUpOrCancel() { final WindowOrientationListener listener = getOrientationListener(); if (listener != null) { listener.onTouchEnd(); } } @Override public void onMouseHoverAtTop() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; mHandler.sendMessageDelayed(msg, 500 ); } @Override public void onMouseHoverAtBottom() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; mHandler.sendMessageDelayed(msg, 500 ); } @Override public void onMouseLeaveFromEdge() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); } }); displayContent.registerPointerEventListener(mSystemGestures); displayContent.mAppTransition.registerListenerLocked( mStatusBarController.getAppTransitionListener()); mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper, mService.mVrModeEnabled); mAcquireSleepTokenRunnable = () -> { if (mWindowSleepToken != null) { return; } mWindowSleepToken = service.mAtmInternal.acquireSleepToken( "WindowSleepTokenOnDisplay" + displayId, displayId); }; mReleaseSleepTokenRunnable = () -> { if (mWindowSleepToken == null) { return; } mWindowSleepToken.release(); mWindowSleepToken = null; }; // TODO: Make it can take screenshot on external display mScreenshotHelper = displayContent.isDefaultDisplay ? new ScreenshotHelper(mContext) : null; if (mDisplayContent.isDefaultDisplay) { mHasStatusBar = true; mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar); // Allow a system property to override this. Used by the emulator. // See also hasNavigationBar(). String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { mHasNavigationBar = false; } else if ("0".equals(navBarOverride)) { mHasNavigationBar = true; } } else { mHasStatusBar = false; mHasNavigationBar = mDisplayContent.supportsSystemDecorations(); } mRefreshRatePolicy = new RefreshRatePolicy(mService, mDisplayContent.getDisplayInfo(), mService.mHighRefreshRateBlacklist); } void systemReady() { mSystemGestures.systemReady(); if (mService.mPointerLocationEnabled) { setPointerLocationEnabled(true); } } private int getDisplayId() { return mDisplayContent.getDisplayId(); } public boolean hasNavigationBar() { return mHasNavigationBar; } public boolean hasStatusBar() { return mHasStatusBar; } public boolean navigationBarCanMove() { return mNavigationBarCanMove; } @NavigationBarPosition int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { if (navigationBarCanMove() && displayWidth > displayHeight) { if (displayRotation == Surface.ROTATION_270) { return NAV_BAR_LEFT; } else if (displayRotation == Surface.ROTATION_90) { return NAV_BAR_RIGHT; } } return NAV_BAR_BOTTOM; } boolean canNavigationBarMove() { return mNavigationBarCanMove; } void updateConfigurationAndScreenSizeDependentBehaviors() { final Resources res = getCurrentUserResources(); mNavigationBarCanMove = mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight && res.getBoolean(R.bool.config_navBarCanMove); mAllowSeamlessRotationDespiteNavBarMoving = res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving); } 从上述代码可以看出 在navigationBarPosition(int displayWidth, int displayHeight, int displayRotation)中 来判断导航栏显示的方向 当navigationBarCanMove()为false的时候 就会显示在底部 所以就是 boolean canNavigationBarMove() { return mNavigationBarCanMove; } 就是mNavigationBarCanMove的参数值 mNavigationBarCanMove = mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight && res.getBoolean(R.bool.config_navBarCanMove); 就是由config_navBarCanMove 属性值决定的 查看config.xml 路径:framework/base/core/res/res/values/config.xmltrue 在config中为true