Android 14已经发布,因此我整理了文档、专家评论和其他可用资源,总结了对大多数应用程序开发者影响最大的重要变化。让我们来看看后台模式的新限制、前台服务的变化以及Intent和BroadcastReceiver的新限制。在这个版本中,我们有很多限制,但也有新功能。
在Android 13中,我们已经被告知在下一个Android版本中,我们应该期待_Back Gesture_和_Predictive Back Gesture_的更新,其中包括一个预览屏幕的动画,我们将在其中移动。该预览的动画仍然无法正常工作。如果您希望它正常工作,您应该在开发者设置中激活它。
演示使用返回导航的动画
此外,还添加了在应用程序内创建个人过渡动画的功能。为此,在OnBackPressedCallback中添加了一个名为handleOnBackProgressed()的方法。该方法会根据_Back Gesture_的进度调用,以及在_Back Gesture_的动画结束和取消时调用的handleOnBackPressed()和handleOnBackCancelled()方法。在屏幕上,您可以看到使用Jetpack AppCompat 1.8.0库实现自定义动画的示例。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
val box = findViewById<View>(R.id.box)
val screenWidth =
Resources.getSystem().displayMetrics.widthPixels
val maxXShift = (screenWidth / 20)
val callback = object : OnBackPressedCallback(
enabled = true
) {
override fun handleOnBackProgressed(
backEvent: BackEvent
) {
when (backEvent.swipeEdge) {
BackEvent.EDGE_LEFT ->
box.translationX = backEvent.progress *
maxXShift
BackEvent.EDGE_RIGHT ->
box.translationX = -(backEvent.progress *
maxXShift)
}
box.scaleX = 1F - (0.1F * backEvent.progress)
box.scaleY = 1F - (0.1F * backEvent.progress)
}
override fun handleOnBackPressed() {
// Back Gesture competed
}
override fun handleOnBackCancelled() {
// Back Gesture cancelled
// Reset animation objects to initial state
}
}
this.onBackPressedDispatcher.addCallback(callback)
}
}
此外,现在应该调用新的overrideActivityTransition()方法,而不是被标记为已弃用的overidePendingTransition()方法。现有的方法在执行过渡动画时与_Predictive Back_存在较高的优先级,因此无法正常工作。
// 新的API
override ActivityTransition(
enterAnim = R.anim.open_trans,
exitAnim = R.anim.exit_trans,
backgroundColor = R.color.bgr_color
)
// 已弃用
override PendingTransition(R.anim.open_trans, R.anim.exit_trans)
Android 14中宣布的第一个变化之一是无法安装_targetSdk_ <= 23(Android 6.0)的应用程序。请不要将其与minSdk混淆。
此更改旨在阻止不更新到新版本_targetSdk_并在Google Play之外分发的应用程序利用旧版Android的漏洞。通过这种方式,应用程序可以在安装过程中绕过运行时权限机制获取所有权限。
当用户尝试安装此类应用程序时,他们将看到一个错误,并且_Logcat_中将显示详细信息。
INSTALL_FAILED_DEPRECATED_SDK_VERSION:应用程序包必须至少针对SDK版本23,但找到了7
通过adb以忽略限制的特殊标志,可以安装任何targetSdk的应用程序。
adb install --bypass-low-target-sdk-block FILENAME.apk
在我看来,这是对抗旧软件的正确限制,并且对于那些想要这样做的爱好者,他们通过_adb_留下了机会。我敢打赌,随着每个新的Android版本发布,允许的最低_targetSdkVersion_将会提高。将来,这个策略甚至可能与新版本无关,而是扩展到所有Android版本。
现在用户可以更改区域设置,而不管系统语言环境的选择:温度单位、一周的第一天和计算系统。开发者在显示应用程序中的信息时应考虑这些信息。
对于存在性别概念的语言(如俄语、意大利语、法语等),Android的新版本引入了语法变化API。现在,您可以通过_GrammaticalInflectionManager_指定用户在应用程序中的性别,这将导致Activity作为配置的一部分重新创建。
// 为语法指定用户的性别
val gIM: GrammaticalInflectionManager = сontext.getSystemService()
gIM.setRequestedApplicationGrammaticalGender(
Configuration.GRAMMATICAL_GENDER_FEMININE
)
现在,您可以为不同性别创建单独的字符串资源。
在Android中,建议使用sp设置文本大小,这是一种特殊的单位,它考虑了用户在系统设置中指定的文本缩放比例。缺点是整个文本都会放大,如果小文本变得可读,那么较大的标题由于裁剪而变得不可读。
Android 14引入了根据Web内容可访问性指南(WCAG)进行文本缩放的新系统。现在将应用非线性字体缩放。这意味着较大的文本不会像较小的文本那样增加。此外,最大文本大小也增加了。在搭载Android 13的Pixel 7 Pro上,最大值为130%;在Android 14上为200%。
为了正确地将像素转换为sp和反向转换,您需要使用TypedValue.applyDimension()和TypedValue.deriveDimension()。与仅仅将SP中的文本大小乘以可以在Configuration.fontScale和DisplayMetrics.scaledDensity中获取的缩放因子相比,这些API将考虑非线性文本缩放特性。
// 将10 SP转换为PX
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10F, displayMetrics)
// 将50 PX转换为SP
TypedValue.deriveDimension(TypedValue.COMPLEX_UNIT_SP, 50F, displayMetrics)
Android 14更新了共享菜单的设计和功能,这是一个系统对话框,当您分享文本、图片或其他内容时会出现。
在Pixel 7 Pro上,在直接共享部分,与Android 13中的4个元素相比,新版本的操作系统中放置了5个元素。他们还改变了此部分中所见内容的排名系统。当您向用户发送消息时,请使用ShortcutManagerCompat.pushDynamicShortcut(),并在创建ShortcutInfo时使用值为actions.intent.SEND_MESSAGE的addCapabilityBinding()。在我看来,他们没有为这个解决方案添加常量非常奇怪。```kotlin ShortcutManagerCompat.pushDynamicShortcut(context, ShortcutInfoCompat.Builder(context, id) // 配置快捷方式 .addCapabilityBinding("actions.intent.SEND_MESSAGE") .build() )
![Android 14中的更新的共享菜单。[来源](https://developer.android.com/about/versions/14/features#sharesheet-improvements)](https://miro.medium.com/0*izyXS9cdph-aGL1S)
现在在标准系统UI中,可以添加额外的操作作为[ChooserAction](https://developer.android.com/reference/android/service/chooser/ChooserAction)对象,其中包含图标、标题和PendingIntent,当您选择操作时将发送该PendingIntent。您的个人操作数量没有限制。
还有另一种特殊操作,用于编辑发送的内容。要创建它,您还需要使用ChooserActions。
所有创建的额外操作都必须通过特殊的新EXTRA添加到Intent中。您可以在下面看到如何做到这一点。
```kotlin
val intent: Intent = // 创建Intent并放入要共享的内容
val modifyAction: ChooserAction =
ChooserAction.Builder(modifyIcon, "修改共享", modifyActionIntent).build()
// 指定编辑内容的操作
intent.putExtra(EXTRA_CHOOSER_MODIFY_SHARE_ACTION, modifyAction)
// 可以对内容执行的其他操作
val customActions: Array<ChooserAction> = arrayOf(
ChooserAсtion.Builder(copyIcon, "复制", copyIntent).build(),
ChooserAсtion.Builder(albumIcon, "创建相册", createAlbumIntent).build(),
ChooserAсtion.Builder(createLinkIcon, "创建链接", createLinkIntent).build()
)
// 添加可以对内容执行的其他操作
inent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
// 创建共享菜单的Intent
val chooserIntent = Intent.createChooser(customActions, "共享1张图片")
// 启动共享菜单
context.startActivity(chooserIntent)
如果他们能够在Android 14中默认添加一些标准操作,就像在Android 13中一样,那将是很好的,但是在撰写本文时,我找不到任何此类操作。
适用于目标SDK 33+的应用程序
在Android 12中,引入了一个新的[SCHEDULE_EXACT_ALARM](https://developer.android.com/reference/android/Manifest.permission#SCHEDULE_EXACT_ALARM)权限,用于使用与闹钟准确时间相关的AlarmManager API。在Android 13中出现了新的USE_EXACT_ALARMS权限。在Android 14中没有添加新的权限,但是他们改变了SCHEDULE_EXACT_ALARM的工作方式。现在,它将不会授予目标SDK为33及更高的应用程序。权限将在设备更新或备份恢复的情况下授予,但不适用于新安装的应用程序。例外情况包括使用系统证书签名的应用程序和具有特殊权限的应用程序,以及禁用了电池优化的应用程序。
在Android 10中,为所有的前台服务提供了一种可能性,即宣布服务类型,以指定其启动的目的。在Android 14中,对于所有可以作为前台启动的服务,必须指定类型,而在现代Android中,几乎所有情况都是如此。为了涵盖所有使用前台服务的选项,他们添加了新的服务类型,每个类型都有特殊的权限。
<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 启动前台服务的权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 启动前台服务的数据同步类型的权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<application>
<service
android:name=".SyncService"
android:foregroundServiceType="dataSync"
/>
</application>
</manifest>
这个新功能将清楚地表明服务中执行的操作是否属于允许的类别。系统将能够更好地了解应用程序的功能以及是否存在可疑行为。Google强烈建议使用_WorkManager_和其他特殊API,并在这些API不适用的情况下实现前台服务。
Google Play在构建上传阶段也会检查前台服务。任何支持Android 14(targetSdk >= 34)的应用程序必须确认所宣布的任务类型的服务是运行应用程序所必需的。否则,您将无法在商店中发布应用程序。
要启动前台服务,除了添加启动前台服务的权限外,还需要添加启动特定类型服务的权限。所有这些权限都是_normal_类型的,即在安装应用程序时会自动授予这些权限,您不需要单独请求它们。除了权限之外,还有其他要求,例如,对于与相机一起工作的服务,需要_AndroidManifest_中也有一个相机权限。有关类型和相关权限的更多信息,请参阅官方文档。
除了以下情况外,所有类型都与特定用例相关:
-
systemExempted - 特殊类型,用于系统应用程序和闹钟,其确定方式是通过是否具有SCHEDULE_EXACT_ALARM和USE_EXACT_ALARM权限。
-
specialUse类型用于当其他类型的前台服务不适用时。除了类型和权限之外,其声明还需要在_AndroidManifest_中的特殊属性中指定使用此类型的原因。在评论中写下您如何使用这些新类型的想法。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application>
<service
android:name=".SpecialService"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="使用特殊服务类型的原因" />
</service>
</application>
</manifest>
- shortService类型用于执行无法中断或延迟的操作。此类型不需要额外的权限,但有几个特殊限制:有限的生命周期(最多3分钟),无法启动其他前台服务,当应用程序的进程被系统停止时无法重新启动等。
服务的生命周期从调用startForeground()的时刻开始计算。服务应通过调用stopSelf()或stopForeground()来结束。当运行时间到期时,将在服务中调用一个新的回调方法 - onTimeout()。此回调会警告您,您有最后一次机会停止服务。否则,即使应用程序在前台服务中执行其他操作,也会发生ANR。禁用电池优化不会影响服务生命周期的限制。
可以延长短前台服务的生命周期。如果应用程序可以启动前台服务,则可以重新启动短前台服务。短服务的重新启动将使服务的生命周期增加3分钟。
Android 14继续推动最佳实践,以防止恶意软件利用内部应用程序组件。现在,隐式Intent_只会传递给_exported_应用程序组件;对于未导出的组件,应使用_显式Intent。
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="dev.androidbroadcast.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
// 如果目标SDK为34+,则不会抛出异常
context.startActivity(Intent("dev.androidbroadcast.action.APP_ACTION"))
// 通过指定应用程序包名来明确Intent
val explicitIntent =
Intent("dev.androidbroadcast.action.APP_ACTION")
// 指定组件所在的应用程序包名
// 对于您的应用程序,是您的应用程序的包名
.setPackage(context.packageName)
context.startActivity(explicitIntent)
Intent机制的第二个变化是,任何使用隐式Intent的可变PendingIntent现在都会导致抛出异常。
BroadcastReceiver的更改此外,对于所有应用程序,无论目标SDK如何,传递给上下文注册(在代码中注册)的BroadcastReceiver的Intent的行为都发生了变化。当应用程序处于缓存状态(即最小化且用户一段时间内未使用)时,它们可能接收到的所有Intent都不会被传递。当应用程序再次变为活动状态时,Intent将会被传递。此外,当发送多个相同的Intent时,只有其中一个可以被传递。在AndroidManifest中注册的BroadcastReceiver将继续像以前一样工作。
此外,代码中的BroadcastReceiver注册变得更加严格。现在需要类似地指定它们是否被导出,就像AndroidManifest中的所有组件一样。在注册时,您需要指定RECEIVER_EXPORTED或RECEIVER_NOT_EXPORTED标志。此更改仅适用于支持Android 14的应用程序。
class DataReceiver: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// 处理数据
}
}
val intentFilter = IntentFilter() // 配置IntentFilter
context.registerReceiver(DataReceiver(), intentFilter, Context.RECEIVER_NOT_EXPORTED)
JobScheduler获得了在设备和服务器之间进行数据传输的长时间任务启动能力。这种类型的任务称为“用户发起的数据传输任务”。只有当应用程序对用户可见或应用程序可以从后台启动Activity时,才能启动此类型的Job。
要启动用户发起的数据传输任务,您必须在AndroidManifest中指定RUN_USER_INITIATED_JOBS权限,并添加一个扩展_JobService_类的Service。在创建_JobInfo_时,您需要调用setUserInitiated()方法,并将_true_作为参数。启动_JobInfo_的先决条件是显示系统通知。在调用onStartJob()时,您应该这样做。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RUN_USER_INITIATED_JOBS" />
<application>
<service
android:name="dev.androidbroadcast.CustomTransferService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
// 其他网络请求要求
.build()
val jobInfo = JobInfo.Builder(1, ComponentName(context, CustomTransferService::class.java))
.setUserInitiated(true)
.setRequiredNetwork(networkRequest)
.setEstimatedNetworkBytes(ONE_GIGABYTE, ZERO_BYTES)
// ...
.build()
val jobScheduler: JobScheduler = checkNotNull(context.getSystemService())
jobScheduler.schedule(jobInfo)
class CustomTransferService : JobService() {
override fun onStartJob(job: JobParameters): Boolean {
if (job.jobId == JOB_ID) {
// 显示通知
setNotification(job, NOTIF_ID, newNotification(), JobService.JOB_END_NOTIFICATION_POLICY_REMOVE)
val success = doDataTransfer()
jobFinished(job, wantsReschedule = !success)
return false
}
error("未处理的Job")
}
}
为了成功启动,需要满足所有启动条件。此外,系统需要具备执行所需的资源。用户发起的数据传输任务的一个重要区别是它不受启动Job的App Standby Buckets配额的限制。在某些条件下,系统仍然可以停止任务,如果系统认为有必要的话。在此之前,将调用onStopJob()方法,在其中建议保存网络操作的当前进度,以便在重新启动后不必从头开始工作,而只需完成必要的部分。
class CustomTransferService : JobService() {
override fun onStopJob(job: JobParameters): Boolean {
if (job.jobId == JOB_ID) {
// 保存数据传输进度
return true
}
}
}
从API来看,User Initiated标记似乎可以用于任何类型的Job,但该方法的文档表示,在Android 14中,它只能与setRequiredNetwork()或setRequiredNetworkType()结合使用。也许在未来的Android版本中,我们会看到更多类型的明确标记任务,可以由用户发起。
在Android 14发布时,Jetpack WorkManager,Google推荐的JobScheduler替代方案,尚未在其API中明确添加此功能。这可能会在未来的版本中发生,或者该更改将在现有WorkManager API的内部使用。
与iOS类似,Android 14提供了对照片和视频的部分访问权限。现在,当您请求媒体时,用户将看到一个对话框,询问是否提供对所有媒体的访问权限,还是仅提供对单个照片/视频的访问权限。无论目标SDK如何,这个新功能都将适用于所有应用程序。
Android 13已经引入了单独的照片访问权限和视频访问权限。现在,将添加另一个附加权限READ_MEDIA_VISUAL_USER_SELECTED,允许您重复请求选择单个照片/视频。新权限应与现有的READ_MEDIA_IMAGES和READ_MEDIA_VIDEO一起使用,以支持新的行为。声明它意味着您的应用程序支持此重新选择。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
<!-- 运行Android 13(API级别33)或更高版本的设备 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 在Android 14上处理应用程序内的重新选择 -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
</manifest>
对单个媒体的访问权限将被临时授予,但文档没有描述持续多长时间。如果未声明新权限,当应用程序进入后台或用户终止应用程序时,部分访问权限将立即被撤销。类似于临时一次性权限的工作方式。因此,您不能存储获取READ_MEDIA_VISUAL_USER_SELECTED权限的状态,您需要每次都进行检查。
当您将设备更新到Android 14时,如果应用程序通过获取适当的权限来完全访问用户的照片/视频,它将保持对这些数据的相同访问级别。
文档表示,添加新权限和机制不会影响应用程序的工作。但是在将来,应该进行修改,以考虑用户可能希望添加新的照片到选择中。一些应用程序甚至专门用于处理整个媒体库,肯定需要进行改进。作为用户,我认为这是一个很大的改进,因为各种各样的即时通讯应用和社交网络将不再能够访问我在相册中的所有内容。
如果您的应用程序需要在后台运行时访问照片/视频,强烈建议支持新权限,以确保进一步的正确操作;否则,您的权限可能会在Android 14中被定期撤销。
Android 14通过向PackageInstaller添加新的API,使第三方商店的生活变得更加轻松。让我们从安装应用程序的限制开始。现在,可以通过调用相应的API随时进行安装。Android U添加了“安装约束API”,允许您指定可以执行安装的条件。
PackageInstaller.InstallConstraints.Builder()
// 应用程序对用户不可见
.setAppNotForegroundRequired()
// 与应用程序无交互
.setAppNotInteractingRequired()
// 应用程序可见但不在前台
.setAppNotTopVisibleRequired()
// 设备未使用
.setDeviceIdleRequired()
// 没有当前电话通话
.setNotInCallRequired()
.build()
```然后,您可以使用[checkInstallConstraints()](https://developer.android.com/reference/android/content/pm/PackageInstaller)方法来检查指定的应用程序是否满足要求。
```kotlin
val packageInstaller: PackageInstaller = //...
packageInstaller.checkInstallConstraints(
packageNames = listOf("dev.androidbroadcast"),
constraints,
Executors.newSingleThreadExecutor()
) { result: PackageInstaller.InstallConstraintsResult ->
if (result.areAllConstraintsSatisfied()) {
// 安装APK文件
}
}
您还可以调用阻塞的waitForInstallConstraints()方法,它将等待满足指定应用程序的条件。
packageInstaller.waitForInstallConstraints(
listOf("dev.androidbroadcast"),
constraints,
intentSender,
timeout = Duration.ofHours(1).toMillis()
)
您可以使用commitSessionAfterInstallConstraintsAreMet()方法推迟更新,直到满足条件。
packageInstaller.commitSessionAfterInstallConstraintsAreMet(
sessionId,
intentSender,
constraints,
timeout = Duration.ofHours(1).toMillis()
)
现在,在使用PackageSession API安装多个APK之前,您可以获得用户的许可。您需要调用新的requestUserPreapproval()方法。这样,您就可以方便地使用App Bundle,而无需反复获取安装单个APK的权限。因此,对于多个应用程序的商店更新,只需要一个用户批准。
val sessionId: Int = packageInstaller.createSession(
PackageInstaller.SessionParams(SessionParams.MODE_INHERIT_EXISTING)
)
val pendingIntent: PendingIntent = // ...
val session: Session = packageInstaller.openSession(sessionId)
// 调用系统对话框以请求用户权限
// intentSender确定结果将发送到哪里
session.requestUserPreapproval(
PreapprovalDetails.Builder()
.setIcon(iconBitmap)
.setLabel(message)
.setLocale(locale)
.build(),
pendingIntent.intentSender
)
// 等待用户的许可,然后会话开始
session.commit(intentSender)
为了保护用户免受从意外商店更新应用程序的影响,PackageInstaller API中引入了setRequestUpdateOwnership()方法。它要求用户确认他们确实希望更改安装程序应用程序。通常,当您从一个应用程序(例如Google Play)安装应用程序,但尝试从另一个应用商店更新它们时,就会发生这种情况。根据我所了解的情况,此功能适用于关键软件包:Google Play服务、Health Connect、Chrome WebView。
当用户尝试从不同的安装程序更新应用程序时,他们将看到一个对话框,其中显示了一个警告,通常情况下应该从不同的来源更新应用程序。用户需要确认更新。
在Android 14中,为了检测截图,Activity中出现了一个特殊的API。它在截图被拍摄后调用回调函数。该API只能检测到用户使用特殊的组合键在设备上拍摄的截图。如果在测试期间使用特殊命令或通过ADB捕获屏幕截图,则回调函数将不起作用。为了使该API工作,您需要在AndroidManifest中添加DETECT_SCREEN_CAPTURE权限。然后在onStart()中注册回调函数,并在onStop()中记得将其删除。否则,您可以使用Jetpack Lifecycle。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
</manifest>
class MainActivity : Activity() {
private val mainExecutor = MainEcxector()
private val screenshotCallback = ScreenCaptureCallback {
// 截图被拍摄
}
override fun onStart() {
super.onStart()
registerScreenCaptureCallback(mainExecutor, screenshotCallback)
}
override fun onStop() {
super.onStop()
unregisterScreenCaptureCallback(screenshotCallback)
}
}
Android 11引入了全屏通知,这些通知将在锁定屏幕和全屏应用程序运行时可见。这种格式旨在显示诸如来电和闹钟等重要通知。从Android 14开始,只有那些被授权的应用程序才能获得现有的USE_FULL_SCREEN_INTENT权限。Google Play将在审核构建时监控此权限。在更新到Android 14设备后,所有已经使用此权限的应用程序将继续使用,但在将新构建下载到Google Play时,如果不符合政策,将不得不删除该权限。
重要的是要记住,用户始终可以撤销权限,因此在显示全屏通知之前,通过调用NotificationManager.canUseFullScreenIntent()来检查此功能的可用性非常重要。要求用户授予此权限,可以使用一个新的Intent,其中包含ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
,它将打开一个屏幕,用户可以在其中授予权限。
val intent = Intent(Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT)
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
// 无法启动Activity
}
在2023年,Google Play要求填写有关确保应用程序处理的数据安全的信息。现在,这些信息不仅会显示在商店中的应用程序页面上,还会显示在系统中。在Android 14中,当您的应用程序在系统对话框中请求访问用户位置时,用户将能够看到应用程序为何需要访问其位置以及该数据将与谁共享。只有当应用程序与第三方服务共享位置时,才会显示此部分。
如果应用程序更改了与其他服务共享用户位置的方式,用户将每月收到有关这些更改的通知。打开通知后,用户将看到一个“更新位置共享”部分,其中列出了所有已更改相应规则的应用程序。
此更改旨在使用户对数据共享透明。应用程序将无法在用户不知情的情况下更改规则。希望不仅关于位置,而且关于所有其他类型的数据都能收到此类通知。
一个小但重要的变化是,Google已开始积极与厂商合作,以在基于Android的不同制造商的操作系统中标准化应用程序在后台的行为。三星已经表示,基于Android 14的One UI 6.0将保证前台服务按照文档和新政策工作。目前,我们只能希望这不只是空话,情况会变得更好。
Android 14中有很多变化,但其中一些变化很小,只会影响少数人,所以让我们快速浏览一下:
- 在自我提交时,_PendingIntent_应用程序现在必须明确指定其后台Activity可以启动。为此,在创建_PendingIntent_时,您必须传递_Bundle ActivityOptions_并调用setPendingIntentBackgroundActivityStartMode()方法,参数为MODE_BACKGROUND_ACTIVITY_START_ALLOWED
val options = ActivityOptions.makeBasic()
.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
)
val pendingIntent =
PendingIntent.getActivity(context, REQUEST_CODE, intent, options)
pendingIntent.send()
```- 当从一个活动应用程序绑定一个服务时,你需要在调用bindService()方法时显式地指定后台应用程序可以启动一个活动,通过添加[BIND_ALLOW_ACTIVITY_STARTS](https://developer.android.com/reference/android/content/Context#BIND_ALLOW_ACTIVITY_STARTS)标志。
```kotlin
context.bindService(intent, serviceConnection, Context.BIND_ALLOW_ACTIVITY_STARTS)
- 对于Path API,现在可以获取迭代器并遍历其段。
// 创建路径
val path = Path().apply {
moveTo(1.0f, 1.0f)
lineTo(2.0f, 2.0f)
close()
}
val pathIterator: PathIterator = path.pathIterator
for (segment in pathIterator) {
println("segment: ${segment.verb}, ${segment.points}")
}
- 现在还可以使用路径插值。这对于在两个路径之间进行动画处理很有用。
val interpolatedResult = Path()
if (path.isInterpolatable(otherPath)) {
path.interpolate(otherPath, t = .5f, interpolatedResult)
}
-
与前台服务或持续标签相关联的Android通知现在无法删除。这些更改是在任务管理器出现后发生的。在Android 14中,几乎所有通知都可以被删除。例外情况是持续通知、呼叫通知和一些来自Android企业的通知。这些通知无法从锁屏界面上删除,也无法通过点击“全部删除”按钮删除。
-
后台任务运行的规则变得更加严格。应用程序进入缓存状态后的几秒钟内,除了用于此目的的API(如WorkManager、JobScheduler或前台服务)之外,任何后台工作都是禁止的。应用程序的后台工作变得比在Android 13中更快不可用。
-
Android 14继续添加来自最新OpenJDK的功能。这次更新包括来自Java 17语言的库和特性:多行文字、instanceof的模式匹配、密封类等。这些功能将通过模块化更新系统移植到Android 12和13。如果你们中有人一直在等待这些功能,请在评论中写下来。我认识的每个人似乎都对JDK 8和Kotlin很满意。
-
修复了Zip文件的漏洞利用。
-
所有在Android 14上启用的使用动态代码加载的应用程序只能使用只读文件进行加载。
val jar = File("DYNAMICALLY_LOADED_FILE.jar")
// 将文件设置为只读
jar.setReadOnly()
// 加载代码
val cl = PathClassLoader(jar, parentClassLoader)
-
在Android 14上,所有应用程序只能停止同一应用程序中的后台进程。如果尝试停止另一个应用程序的进程,将不会发生任何事情,只会在LogCat中显示一条消息。
-
CredentialManager和HealthConnect已成为Android的系统服务,但仍建议通过适当的Jetpack库使用这些API。
-
现在可以将视图标记为仅对辅助功能服务可见,以帮助残障用户。
view.setAccessibilityDataSensitive(View.ACCESSIBILITY_DATA_SENSITIVE_YES)
-
对于发布Android 14或更高版本的设备,将需要支持AV1编解码器和身份凭证。这将允许将驾驶执照存储在设备上。
-
添加了一个新的应用程序角色 - NOTES。该角色用于用于记笔记的应用程序。具有此角色的应用程序在发送具有CREATE_NOTE操作的Intent时,默认情况下会启动。
-
注解@CriticalNative和@FastNative已成为Android SDK的公共部分。它们用于标记本地方法,以加速ART中的JNI工作。
-
Android SDK中完全删除了Android Beam支持。
-
现在支持通过USB进行无损音频传输。音频发烧友会很高兴。Google正在与合作伙伴合作,使这一功能在设备上可用。
-
Canvas中添加了渲染缓冲区的硬件加速。
-
新发布的支持Android 14或更高版本的芯片组不得支持32位NDK ABI。
-
跨设备SDK已成为Android SDK的一部分。
-
添加了对10位HDR图像的支持,允许保存更多关于颜色和对比度的信息。该格式称为Ultra HDR。Google相机和Google相册将支持它。
-
添加了新的主线模块:Health Connect、管理标志功能的模块、Cronet、设备锁控制器、远程密钥提供者和根证书。
-
改进了对手写的支持。这个功能将在平板电脑上使用。
-
支持卫星通话。
-
发布了
VirtualDeviceManager
系统服务。它将用于创建和管理虚拟设备。不要将其与Android Studio中的模拟器混淆。
每年,Android添加的新功能越来越少,更多地致力于改进Android SDK并加强与Android系统标准组件的工作规则。许多新的API已经在Jetpack中开发了很长时间。它们不与Android版本绑定,可以独立更新。Android SDK本身已成为操作系统和Jetpack之间的桥梁,开发人员越来越多地使用后者、Kotlin库和其他第三方解决方案。
在评论中分享你对新版本Android的看法。你喜欢什么,不喜欢什么。也许你还可以告诉我我漏掉了什么。