适配6.0~8.0的可以看下这个:

适配Android6.0到8.0详细过程——小白教程

注意:10.0到12.0的都是些网上看到的资料,我就适配到10.0的文件存储,如有不对的,可以留言,我会查阅修改,谢谢0.0

Android 9.0适配:

限制明文传输:

当 SDK 版本大于 API 28 时,默认限制了 HTTP 请求,并出现相关日志

java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted
by network security policy

该问题有两种解决方案:
1、在 AndroidManifest.xml 中 Application 节点添加如下代码

<application android:usesCleartextTraffic="true">

2、在 res 目录新建 xml 目录,已建的跳过,在xml目录新建一个network_security_config.xml文件,然后在AndroidManifest.xml 中 Application 添加如下节点代码。


android:networkSecurityConfig="@xml/network_security_config"

network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true" />
</network-security-config>

启动Activity:

在9.0 中,不能直接非 Activity 环境中(比如Service,Application)启动 Activity,否则会崩溃报错,
这类问题一般会在点击推送消息跳转页面这类场景,解决方法就是 Intent 中添加标志FLAG_ACTIVITY_NEW_TASK,

Intent intent = new Intent(this, TestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

适配刘海屏:

使用开源库NotchAdapter,github地址:NotchAdapter

当我们需要以全屏及沉浸的模式显示我们的页面时,就需要适配刘海屏。

1、添加依赖:

  //适配刘海屏的adapterimplementation 'cn.jerechen:notchAdapter:1.0.3'

2、在需要适配刘海的Activity中:

//添加  @RequiresApi(api = Build.VERSION_CODES.P) 注解 表示在9.0以上起效btn_keep_out = findViewById(R.id.btn_keep_out);INotchScreen notchScreen = NotchManager.INSTANCE.getNotchScreen();if (notchScreen!=null){   //notchScreen不为空代表是刘海屏boolean isContainNotch = notchScreen.isContainNotch(this);Log.e("MainActivity", "portrait activity isContainNotch : "+isContainNotch);notchScreen.getNotchInfo(this, new INotchScreen.NotchInfoCallback() {@Overridepublic void getNotchRect(Rect rect) {Log.e("MainActivity", "Rect Bottom : "+rect.bottom);//将被刘海挡住的 btn_keep_out 向下移动一个 刘海高度 距离RelativeLayout.LayoutParams lp  =(RelativeLayout.LayoutParams) btn_keep_out.getLayoutParams();//在原有的 topMargin 基础上再加上 刘海屏的高度lp.topMargin += rect.bottom;btn_keep_out.setLayoutParams(lp);}});}

效果如下:

正常无刘海屏:

9.0手机模拟有刘海屏:

Android 10.0适配:

1、Scoped Storage(分区存储)
在Android 10上即使你拥有了储存空间的读写权限,也无法保证可以正常的进行文件的读写操作。
适配
最简单粗暴的方法就是在AndroidManifest.xml中添加android:requestLegacyExternalStorage="true"来请求使用旧的存储模式。

<applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"android:extractNativeLibs="true"android:usesCleartextTraffic="true"android:requestLegacyExternalStorage="true">

2、权限变化
1)在后台运行时访问设备位置信息需要权限(不建议)
Android 10 引入了 ACCESS_BACKGROUND_LOCATION 权限(危险权限)。

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

该权限允许应用程序在后台访问位置。如果请求此权限,则还必须请求ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION权限。只请求此权限无效果。

官方推荐使用前台服务来实现,在前台服务中获取位置信息。

首先在清单中对应的service中添加 android:foregroundServiceType="location":

<serviceandroid:name="MyNavigationService"android:foregroundServiceType="location" ... >...
</service>

启动前台服务前检查是否具有前台的访问权限:

    boolean permissionApproved = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;if (permissionApproved) {// 启动前台服务} else {// 请求前台访问位置权限}

如此一来就可以在Service中获取位置信息。

2)一些电话、蓝牙和WLAN的API需要精确位置权限

3、后台启动 Activity 的限制(不太需要管,问题不大)
简单解释就是应用处于后台时,无法启动Activity。    这一限制导致最明显的问题就是点击推送信息时,有些应用无法进行正常的跳转(具体的实现问题导致)。所以针对这类问题,可以采取PendingIntent的方式,发送通知时使用setContentIntent方法。

对于全屏 intent,注意设置最高优先级和添加USE_FULL_SCREEN_INTENT权限,这是一个普通权限。比如微信来语音或者视频通话时,弹出的接听页面就是使用这一功能。

 <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>

4、深色主题
适配方法有两种:
1)手动适配(资源替换)(建议使用,可以基本达到预想效果。)

将Application和Activity的主题修改为集成自Theme.AppCompat.DayNight或者Theme.MaterialComponents.DayNight,就可以对于大部分的控件得到较好的深色模式支持。

  <application...android:theme="@style/AppTheme"...>
  <!-- Base application theme. --><!--<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">--><style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar"><!-- Customize your theme here. --><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item></style>
  • 颜色:新建values-night文件夹,里面是深色模式下的colors.xml文件

例如:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#303030</color><color name="colorPrimaryDark">#232323</color><color name="colorAccent">#008577</color>
</resources>
  • 图片:新建drawable-night-xxhdpi图片文件夹

按照ui设计给的深色模式图放进这个文件夹,系统就会在识别到深色模式后加载这个文件夹的资源了。

关键工具类NightModeUtil:

public class NightModeUtil {/*** 当前系统是否是深色模式*/public static boolean isNightMode(Context context) {int uiMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;return uiMode == Configuration.UI_MODE_NIGHT_YES;}/*** 获取是否跟随系统,默认true*/public static boolean getSystemMode() {return SPUtils.getBoolean(Constants.KEY_MODE_SYSTEM, true);}public static void setSystemMode(boolean nightMode) {SPUtils.putBoolean(Constants.KEY_MODE_SYSTEM, nightMode);}/*** 获取是否设置深色模式,默认false*/public static boolean getNightMode() {return SPUtils.getBoolean(Constants.KEY_MODE_NIGHT, false);}public static void setNightMode(boolean nightMode) {SPUtils.putBoolean(Constants.KEY_MODE_NIGHT, nightMode);}public static void initNightMode() {initNightMode(getSystemMode(), getNightMode());}/*** 初始化App深色模式** @param systemMode 是否是跟随系统* @param nightMode  是否是深色模式*/public static void initNightMode(boolean systemMode, boolean nightMode) {if (systemMode) {AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);} else {if (nightMode) {AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);} else {AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);}}}/*** 重启App*/public static void restartApp(Activity activity) {final Intent intent = App.getInstance().getPackageManager().getLaunchIntentForPackage(App.getInstance().getPackageName());if (intent != null) {intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);activity.startActivity(intent);android.os.Process.killProcess(android.os.Process.myPid());}}
}

在Application里初始化

NightModeUtil.initNightMode();

切换状态后重启App

//两个参数分别是 是否跟随系统,是否选择深色模式
NightModeUtil.initNightMode(dayNightSwitch.isChecked, ctvCheckNight.isChecked);
NightModeUtil.restartApp(activity);

WebView的深色模式设置
引入implementation 'androidx.webkit:webkit:1.2.0'后可轻易的实现WebView的深色模式,不过有兼容问题,这和WebView的版本有关,WebView版本独立于Android版本。(亲测在系统6.0和7.1上无效。)

在有WebView的Activity的onCarete里加上如下代码:

WebSettings webSetting = webView.getSettings();
// 检查是否支持暗模式
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {boolean isAppDarkMode;if (NightModeUtil.getSystemMode()) {// 是否是跟随系统isAppDarkMode = NightModeUtil.isNightMode(this);} else {isAppDarkMode = NightModeUtil.getNightMode();}if (isAppDarkMode) {WebSettingsCompat.setForceDark(webSetting, WebSettingsCompat.FORCE_DARK_ON);} else {WebSettingsCompat.setForceDark(webSetting, WebSettingsCompat.FORCE_DARK_OFF);}
}

这就是跟随系统深色模式做的配置了。

效果图如下:

2)自动适配(Force Dark)(不建议使用,效果差。)
应用必须选择启用 Force Dark,方法是在其主题背景中设置 android:forceDarkAllowed="true"。
监听深色主题是否开启
首先在清单文件中给对应的Activity配置 android:configChanges="uiMode":

<activityandroid:name=".MyActivity"android:configChanges="uiMode" />

这样在onConfigurationChanged方法中就可以获取:

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {super.onConfigurationChanged(newConfig);int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;switch (currentNightMode) {case Configuration.UI_MODE_NIGHT_NO:// 关闭break;case Configuration.UI_MODE_NIGHT_YES:// 开启break;default:break;    }
}

判断深色主题是否开启

其实和上面onConfigurationChanged方法同理:

public static boolean isNightMode(Context context) {int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}

5、标识符和数据
对不可重置的设备标识符实施了限制
从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能正常使用以上这些方法。

Android 11 适配:

1、分区存储
Android 10之前,外部存储区的内容主要以两种形式存在,一种是由应用的包名命名,归属于特定应用目录下的内容,另一种是存储在公共存储区域的内容。

在Android 10 中,Google首次引入了分区存储,将公共区域划分成了不同的集合,并且在媒体文件和其他文档之间建立了清楚的分割。经过划分之后应用不可以随意访问外部存储区中的文件,而只能访问媒体文件。如果想访问包含更多细节数据的其他文档,应用专门向用户申请有关文档的访问权限。

分区存储是需要以 Android 10 为目标平台的,系统默认强制执行。

如果在 AndroidManifest 的application中添加了 requestLegacyExternalStorage=true 标志,就可以不受此限制。

但是当 target API 更新为 30 后,系统会忽略该配置。

如果有数据需要迁移,可以在 AndroidManifest 中将 preserveLegacyExternalStorage 属性设为 true ,当用户升级到以 Android 11 为目标平台时,这个配置就会生效。具体而言,这个配置在用户重新安装该应用前都是有效的。
针对以 Android 11 为目标平台的应用 (targetSdkVersion = 30) ,WRITEEXTENRNALSTORAGE 和 WRITEMEDIASTORAGE 不再提供其他任何访问权限 。

某些应用的核心功能可能需要访问大量的文件,例如文件管理操作、备份和恢复操作等等,此时就需要申请 MANAGEEXTERNALSTORAGE 权限。我们可以通过使用 ACTIONMANAGEALLFILESACCESS_PERMISSION intent 操作将用户引导至一个系统设置页面,让用户为应用授予所有文件的管理权限。

2、应用包可见性
在 Android 11 之前,我们可以通过 PackageManager.getInstalledPackages(0) 获取其他所有应用的包名等信息。
Android 11 为了增加安全性,更好地保护用户的隐私,对应用包的可见性做出了一些改动。

当 targetSdkVersion 为 30 时,如果我们用getPackageInfo(“another.app”,0) 获取其他应用包信息时 ,会出现 NameNotFoundException 的异常。

我们可以在 AndroidMainfest 中添加 <queries style="margin: 0px; padding: 0px;">来适配特定的使用场景:(该配置相当于是添加应用白名单)</queries>

3、权限变化
在 Android 11 中,系统为用户的私人数据提供了更多可供选择的授权方式,应用也加大了后台对位置的访问权限限制。

对应摄像头、位置信息和麦克风这几个数据类型,用户可以授予一次性的临时访问权限。

只要是在Android 11 上,该限制都会生效,如下 :
仅使用期间,仅限这一次等。

这个一次性权限的生效周期指的是:

应用 Activity 可见期间
应用转为后台后的短时间内
前台服务存活期间
当用户撤销单次授权后,应用进程退出,再次打开之后需要对应用进行重新授权期间

4、位置权限
在Android10 之前,我们通过ACCESSCOARRSELOCATION 或 ACCESSFINELOCATION(精确位置) 配置即可申请前后台位置权限。

Android 11将位置权限分为前台和后台两种权限。前文说的主要是前台权限,授权方式没有变化。应用想要申请后台权限,除了需要在清单文件中额外添加 ACCESSBACKGROUNDLOCATION 权限外,还需要应用主动引导用户到指定页面授权。

5、新功能
增加应用退出原因功能
在Android 11之前,我们想要了解应用退出的原因以及状态,都比较费劲。现 Android 11 引入了 方法:ActivityManager.getHistoricalProcessExitReasons() ,
可以让我们清楚地了解到应用退出的原因。

6、可变刷新率
应用和游戏现在可以为其窗口设置首选帧率。大多数 Android 设备以 60Hz 的刷新率更新屏幕,但是某些设备支持多种刷新率,例如 90Hz 和 60Hz,并可在运行时切换。在这些设备上,系统会基于首选帧率来为应用选择最佳刷新率。

Android12适配:

targetSdkVersion 31的应用在Android 12上安装时可能会存在两种安装不上的情况。

adb: failed to install xxx.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES:
Scanning Failed.: No signature found in package of version 2 or newer forpackage com.tomes.sharefile]

解决:
 targetSdkVersion 30的应用必须使用v2及以上签名

adb: failed to install xxx.apk: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed
parse during installPackageLI: /data/app/vmdl2054463318.tmp/base.apk (at Binary XML file
line #49): com.tomes.ShareOpenTestActivity: Targeting S+ (version 10000 and above) requiresthat an explicit value for android:exported be defined when intent filters are present]

我们知道,当我们的应用以Android 12为目标,使用的activity,service,broadcast receiver含有intent-filter,则必须显示声明android:exported属性,如果没有声明,则我们的应用不能安装在Android 12上

解决方法:
声明android:exported属性即可解决。

如我上面的错误,只需要对ShareOpenTestActivity增加android:exported属性申明就好

<activity android:name=".ShareOpenTestActivity" android:exported="true"><intent-filter><action android:name="android.intent.action.SEND"/><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="text/*" /></intent-filter></activity>

总结:
targetSdkVersion为31【以Android 12为目标】的应用务必要加入v2签名,务必要对使用的activity,service,broadcast receiver含有intent-filter,显示声明android:exported属性。

Android简单适配9.0~12.0相关推荐

  1. android 11.0 12.0添加系统字体并且设置为默认字体

    1.概述 在11.0 12.0系统定制化开发中,在产品定制中,有产品需求对于系统字体风格不太满意,所以想要更换系统的默认字体,对于系统字体的修改也是常有的功能,而系统默认也支持增加字体,所以就来添加楷 ...

  2. android 11.0 12.0第三方输入法app设置系统默认输入法

    1.概述 在11.0 12.0的产品开发中,有功能需要要求设置默认输入法,替换掉系统的输入法,所以这就需要了解设置 输入法的相关功能需求,然后根据输入法包名来设置默认输入法 2.第三方输入法app设置 ...

  3. android 11.0 12.0设置app为默认浏览器

    1.概述 在11.0 12.0的产品定制化中,如果系统安装多个浏览器时,需要设置默认浏览器来完成需求,这就需要看系统设置中的相关源码 当出现多个浏览器时,该如何设置默认浏览器呢, 其实在Setting ...

  4. Android 11.0 12.0蓝牙遥控器确认键弹不出输入法的解决方法

    1.概述 在android11.0 12.0设备定制化开发时,遥控器是使用红外遥控器,也有使用蓝牙遥控器的,所以出现的问题不一定相同,今天遇到个问题就是蓝牙遥控器在输入数据时弹不出输入法的问题 首选排 ...

  5. android 11.0 12.0自定义开机向导app

    1.概述 在11.0 12.0的系统产品开发中,需要自定义开机向导app页面,而系统源码中只提供了Provision作为开机向导app 有些平台没有把它编译到源码中 作为开机向导,所以自定义开机向导, ...

  6. Android 11.0 12.0系统默认开启wifi

    1.概述 在11.0 12.0的系统中产品开发中,系统的wifi功能是默认关闭的,由于项目需要要求默认打开wifi,开机后直接连wifi就可以了 所以需要找到系统默认的关闭wifi的地方 打开wifi ...

  7. android 11.0 12.0控制屏幕亮屏和灭屏操作

    在11.0 12.0的产品开发中, 需要提供亮屏和灭屏的接口在8.0以后系统对于屏幕亮灭屏做了限制,直接调用亮屏和灭屏的方法就调不到了, 接下来就来看PowerManage.java类 这个是一个电源 ...

  8. Android 10.0 11.0 12.0 启动模拟器教程

    <<返回总目录 Android 10.0 11.0 12.0 启动模拟器教程 一.android 12.0 模拟器 二.安装android 10.0 11.0 12.0 SDK平台 三.创 ...

  9. Android 11.0 12.0屏蔽Launcher3桌面app图标的长按功能

    1.概述 在11.0 12.0的产品定制化开发中,系统默认的Launcher3在workspace 第二屏通常都会显示app列表 点击进入app 列表页,长按app的icon图标会弹出 应用信息 弹窗 ...

  10. Android 11.0 12.0设置默认息屏时间

    1.概述 在11.0 12.0定制化开发中,在系统设置中,息屏时间默认为1分钟,对于这个息屏时间感觉太短了,所以系统默认息屏时间修改也是常见的修改功能,在系统Settings中屏幕超时会根据默认息屏时 ...

最新文章

  1. 程序员编程时戴耳机是在听什么?
  2. Nature:人体菌群研究的25个里程碑
  3. apache http server指的是什么
  4. 二叉树深度和平衡二叉树的判定
  5. html5块元素代码,html5 区块与内联div 与span html块级元素(示例代码)
  6. Simulink之三相半波可控整流电路
  7. Visual C++ 设置适合自己的解决方案目录结构
  8. spring之Bean的生命周期
  9. pandownload事件_pandownload被执法背后是中国盗版的末路
  10. 考软件测试初学者眼影,Summer 大讲堂第一期:如何制作出版级的高分辨率图表?...
  11. xp系统能不能安装mysql_XP系统如何安装SQL2005?XP系统安装SQL2005图文教程
  12. 大学计算机与应用软件,深圳大学
  13. 原生JS与其他JS 区别
  14. 离散数学(第二版) 第一章、第二章习题
  15. 四川大学计算机学院研究生推免细则,四川大学计算机学院2012届硕士研究生推荐免试实施细则...
  16. CAD创建组却没有组合在一起?
  17. 计算机上机考试自我检查800字,检讨书自我反省800字考试没考好
  18. ElasticSearch集群黄色原因以及解决方案
  19. SDKMAN!使用指南
  20. 男女之间没有真正的友谊

热门文章

  1. 计算机哪种语言处理速度最快,哪种高级编程语言的执行速度最快?
  2. matlab程序FP-tree,FP-Tree算法的实现
  3. LangChain vs Semantic Kernel
  4. Oracle修改内存大小
  5. 依靠云计算推动企业业务模式变革
  6. OpenCV | Mat类的copyT、clone、=赋值的区别
  7. H265 HEVC 协议文档第4章缩写词及其含义翻译
  8. 【AGL】初探AGL之Application framework
  9. python如何安装pil库_Python安装PIL库
  10. 如来昔在然灯是和所时_TGB