Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
较低版本的构建系统会报告一个不同的错误,但指示的是同一问题:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
这两种错误情况都会显示一个共同的数字:65536。此数字是单个 Dalvik Executable (DEX) 字节码文件内的代码可调用的引用总数。本页介绍如何通过启用称为“多 dex 文件”的应用配置(该配置使您的应用能够构建和读取多个 DEX 文件)来越过这一限制。
Android 5.0 之前版本的多 dex 文件支持
Android 5.0(API 级别 21)之前的平台版本使用 Dalvik 运行时来执行应用代码。默认情况下,Dalvik 将应用限制为每个 APK 只能使用一个 classes.dex
字节码文件。要绕过这一限制,您可以在您的项目中添加多 dex 文件支持库:
dependencies {
def multidex_version = “2.0.1”
implementation ‘androidx.multidex:multidex:$multidex_version’
}
如果您不使用 AndroidX,请改为添加以下支持库依赖项:
dependencies {
implementation ‘com.android.support:multidex:1.0.3’
}
此库会成为应用的主要 DEX 文件的一部分,然后管理对其他 DEX 文件及其所包含代码的访问
Android 5.0 及更高版本的多 dex 文件支持
Android 5.0(API 级别 21)及更高版本使用名为 ART 的运行时,它本身支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,扫描 classesN.dex 文件,并将它们编译成单个 .oat 文件,以供 Android 设备执行。因此,如果您的 minSdkVersion 为 21 或更高的值,则默认情况下启用多 dex 文件,并且您不需要多 dex 文件支持库。
针对多 dex 文件配置您的应用
如果您的 minSdkVersion
设为 21 或更高的值,则默认情况下启用多 dex 文件,并且您不需要多 dex 文件支持库。
不过,如果您的 minSdkVersion
设为 20 或更低的值,则必须使用多 dex 文件支持库并对应用项目进行以下修改:
- 修改模块级
build.gradle
文件以启用多 dex 文件,并将多 dex 文件库添加为依赖项,如下所示:
android {
defaultConfig {
…
minSdkVersion 15
targetSdkVersion 28
multiDexEnabled true
}
…
}
dependencies {
implementation ‘com.android.support:multidex:1.0.3’
}
2.对Application的配置
方法一:不替换Application
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android=“http://schemas.android.com/apk/res/android”
package=“com.example.myapp”>
<application
android:name=“android.support.multidex.MultiDexApplication” >
…
方法二:替换Application
public class MyApplication extends MultiDexApplication { … }
方法三(推荐):替换 Application类,不改基类
则可以改为替换 attachBaseContext()方法并调用 MultiDex.install(this)来启用多 dex 文件:
class MyApplication : SomeOtherApplication() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
作为 Android Jetpack的一部分,Security 库提供了与读取和写入静态数据以及密钥创建和验证相关的安全最佳做法实现方法。
该库使用构建器模式为以下安全等级提供安全的默认设置:
-
**在可靠加密和良好性能之间取得平衡的强安全性。**这种安全等级适用于银行和聊天应用等消费者应用,以及执行证书吊销检查的企业应用。
-
**最高安全性。**这种安全等级适用于需要由硬件支持的密钥库和用户上线以提供密钥访问权限的应用。
介绍了如何使用 Security 库的建议安全配置,以及如何轻松且安全地读取和写入存储在文件和共享偏好设置中的加密数据。
密钥管理
Security 库使用一个由两部分组成的密钥管理系统:
-
包含一个或多个密钥的密钥集,用于加密文件或共享偏好设置数据。密钥集本身存储在 SharedPreferences 中。
-
用于加密所有密钥集的主密钥。此密钥使用 Android 密钥库系统进行存储。
库中包含的类
Security 库包含以下类,以提供更安全的静态数据:
EncryptedFile
提供 FileInputStream 和 FileOutputStream 的自定义实现,为您的应用赋予更安全的流式读写操作。
EncryptedSharedPreferences
封装 SharedPreferences 类,并使用双重方案方法自动加密密钥和值:
-
密钥使用确定性加密算法进行加密,这样便可以正确查找和加密密钥。
-
值使用 AES-256 GCM 加密,并且具有不确定性。
使用 EncryptedFile 以更安全的方式读取文件内容:
// Although you can define your own key generation parameter specification, it’s
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
val fileToRead = “my_sensitive_data.txt”
val encryptedFile = EncryptedFile.Builder(
File(directory, fileToRead),
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
val contents = encryptedFile.bufferedReader().useLines { lines ->
lines.fold(“”) { working, line ->
“KaTeX parse error: Undefined control sequence: \n at position 8: working\̲n̲line”
}
}
使用 EncryptedFile 以更安全的方式写入文件内容:
// Although you can define your own key generation parameter specification, it’s
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val fileToWrite = “my_sensitive_data.txt”
val encryptedFile = EncryptedFile.Builder(
File(directory, fileToWrite),
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
encryptedFile.openFileOutput().bufferedWriter().use {
it.write(“MY SUPER-SECRET INFORMATION”)
}
对于需要额外安全性的用例,请完成以下步骤:
-
创建一个
KeyGenParameterSpec.Builder
对象,将true
传递到setUserAuthenticationRequired()
,并将一个大于 0 的值传递到setUserAuthenticationValidityDurationSeconds()
。 -
使用
createConfirmDeviceCredentialIntent()
提示用户输入凭据。详细了解如何要求用户验证身份才能使用密钥。
注意:Security 库在加密操作级别不支持 BiometricPrompt
。
- 替换
onActivityResult()
以获取经确认的凭据回调。
如需了解详情,请参阅要求用户验证身份才能使用密钥。
修改共享偏好设置
使用 EncryptedSharedPreferences 以更安全的方式修改用户的一组共享偏好设置:
val sharedPreferences = EncryptedSharedPreferences
.create(
fileName,
masterKeyAlias,
context,
Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
r还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
[外链图片转存中…(img-MZdY95UP-1714281959990)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!