مانند نسخه های قبلی، Android 14 شامل تغییرات رفتاری است که ممکن است بر برنامه شما تأثیر بگذارد. تغییرات رفتاری زیر منحصراً برای برنامههایی اعمال میشود که Android 14 (سطح API 34) یا بالاتر را هدف قرار میدهند. اگر برنامه شما اندروید 14 یا بالاتر را هدف قرار می دهد، باید برنامه خود را تغییر دهید تا در صورت لزوم از این رفتارها به درستی پشتیبانی کند.
حتماً فهرستی از تغییرات رفتاری را نیز مرور کنید که بر همه برنامههای در حال اجرا در Android 14 بدون توجه به targetSdkVersion
برنامه تأثیر میگذارد.
عملکرد اصلی
انواع خدمات پیش زمینه مورد نیاز است
If your app targets Android 14 (API level 34) or higher, it must specify at least one foreground service type for each foreground service within your app. You should choose a foreground service type that represents your app's use case. The system expects foreground services that have a particular type to satisfy a particular use case.
If a use case in your app isn't associated with any of these types, it's strongly recommended that you migrate your logic to use WorkManager or user-initiated data transfer jobs.
اجرای مجوز BLUETOOTH_CONNECT در آداپتور بلوتوث
Android 14 enforces the BLUETOOTH_CONNECT
permission when calling the
BluetoothAdapter
getProfileConnectionState()
method for apps targeting
Android 14 (API level 34) or higher.
This method already required the BLUETOOTH_CONNECT
permission, but it was not
enforced. Make sure your app declares BLUETOOTH_CONNECT
in your app's
AndroidManifest.xml
file as shown in the following snippet and check that
a user has granted the permission before calling
getProfileConnectionState
.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
به روز رسانی OpenJDK 17
Android 14 به کار تازه کردن کتابخانههای اصلی Android ادامه میدهد تا با ویژگیهای جدیدترین نسخه OpenJDK LTS، از جمله بهروزرسانیهای کتابخانه و پشتیبانی از زبان جاوا 17 برای توسعهدهندگان برنامهها و پلتفرمها، هماهنگ شود.
تعدادی از این تغییرات می تواند بر سازگاری برنامه تأثیر بگذارد:
- تغییرات در عبارات منظم : ارجاعات گروه نامعتبر اکنون مجاز نیستند تا معنایی OpenJDK را با دقت بیشتری دنبال کنند. ممکن است موارد جدیدی را مشاهده کنید که در آن یک
IllegalArgumentException
توسط کلاسjava.util.regex.Matcher
پرتاب می شود، بنابراین مطمئن شوید که برنامه خود را برای مناطقی که از عبارات منظم استفاده می کنند آزمایش کنید. برای فعال یا غیرفعال کردن این تغییر در حین آزمایش، پرچمDISALLOW_INVALID_GROUP_REFERENCE
را با استفاده از ابزارهای چارچوب سازگاری تغییر دهید. - مدیریت UUID : متد
java.util.UUID.fromString()
اکنون بررسی های دقیق تری را هنگام تأیید آرگومان ورودی انجام می دهد، بنابراین ممکن است در حین deserialization یکIllegalArgumentException
را مشاهده کنید. برای فعال یا غیرفعال کردن این تغییر در حین آزمایش، پرچمENABLE_STRICT_VALIDATION
را با استفاده از ابزارهای چارچوب سازگاری تغییر دهید. - مشکلات ProGuard : در برخی موارد، افزودن کلاس
java.lang.ClassValue
باعث ایجاد مشکل می شود اگر بخواهید برنامه خود را با استفاده از ProGuard کوچک کنید، مبهم کنید و بهینه کنید. مشکل از یک کتابخانه Kotlin سرچشمه می گیرد که رفتار زمان اجرا را بر اساس اینکهClass.forName("java.lang.ClassValue")
یک کلاس را برمی گرداند یا نه، تغییر می دهد. اگر برنامه شما بر اساس نسخه قدیمیتری از زمان اجرا بدون کلاسjava.lang.ClassValue
در دسترس است، این بهینهسازیها ممکن است متدcomputeValue
را از کلاسهای مشتقشده ازjava.lang.ClassValue
حذف کنند.
JobScheduler رفتار برگشت به تماس و شبکه را تقویت می کند
Since its introduction, JobScheduler expects your app to return from
onStartJob
or onStopJob
within a few seconds. Prior to Android 14,
if a job runs too long, the job is stopped and fails silently.
If your app targets Android 14 (API level 34) or higher and
exceeds the granted time on the main thread, the app triggers an ANR
with the error message "No response to onStartJob
" or
"No response to onStopJob
".
This ANR may be a result of 2 scenarios:
1. There is work blocking the main thread, preventing the callbacks onStartJob
or onStopJob
from executing and completing within the expected time limit.
2. The developer is running blocking work within the JobScheduler
callback onStartJob
or onStopJob
, preventing the callback from
completing within the expected time limit.
To address #1, you will need to further debug what is blocking the main thread
when the ANR occurs, you can do this using
ApplicationExitInfo#getTraceInputStream()
to get the tombstone
trace when the ANR occurs. If you're able to manually reproduce the ANR,
you can record a system trace and inspect the trace using either
Android Studio or Perfetto to better understand what is running on
the main thread when the ANR occurs.
Note that this can happen when using JobScheduler API directly
or using the androidx library WorkManager.
To address #2, consider migrating to WorkManager, which provides
support for wrapping any processing in onStartJob
or onStopJob
in an asynchronous thread.
JobScheduler
also introduces a requirement to declare the
ACCESS_NETWORK_STATE
permission if using setRequiredNetworkType
or
setRequiredNetwork
constraint. If your app does not declare the
ACCESS_NETWORK_STATE
permission when scheduling the job and is targeting
Android 14 or higher, it will result in a SecurityException
.
کاشیها API را راهاندازی میکنند
For apps targeting 14 and higher,
TileService#startActivityAndCollapse(Intent)
is deprecated and now throws
an exception when called. If your app launches activities from tiles, use
TileService#startActivityAndCollapse(PendingIntent)
instead.
حریم خصوصی
دسترسی جزئی به عکس ها و فیلم ها
Android 14 دسترسی به عکسهای انتخاب شده را معرفی میکند، که به کاربران اجازه میدهد به برنامهها اجازه دسترسی به تصاویر و ویدیوهای خاص موجود در کتابخانه خود را بدهند، نه اینکه به همه رسانههای یک نوع خاص دسترسی داشته باشند.
این تغییر تنها در صورتی فعال میشود که برنامه شما Android 14 (سطح API 34) یا بالاتر را هدف قرار دهد. اگر هنوز از انتخابگر عکس استفاده نکردهاید، توصیه میکنیم آن را در برنامه خود پیادهسازی کنید تا تجربهای ثابت برای انتخاب تصاویر و ویدیوها ارائه دهید که همچنین حریم خصوصی کاربر را بدون نیاز به درخواست مجوز ذخیرهسازی افزایش میدهد.
اگر انتخابگر گالری خود را با استفاده از مجوزهای ذخیره سازی حفظ می کنید و نیاز دارید که کنترل کامل بر پیاده سازی خود داشته باشید، پیاده سازی خود را با استفاده از مجوز جدید READ_MEDIA_VISUAL_USER_SELECTED
تطبیق دهید. اگر برنامه شما از مجوز جدید استفاده نمی کند، سیستم برنامه شما را در حالت سازگاری اجرا می کند.
تجربه کاربری
اعلانهای Intent تمام صفحه را ایمن کنید
With Android 11 (API level 30), it was possible for any app to use
Notification.Builder.setFullScreenIntent
to send full-screen
intents while the phone is locked. You could auto-grant this on app install by
declaring USE_FULL_SCREEN_INTENT
permission in the
AndroidManifest.
Full-screen intent notifications are designed for extremely high-priority
notifications demanding the user's immediate attention, such as an incoming
phone call or alarm clock settings configured by the user. For apps targeting
Android 14 (API level 34) or higher, apps that are allowed to use this
permission are limited to those that provide calling and alarms only. The Google
Play Store revokes default USE_FULL_SCREEN_INTENT
permissions for any apps
that don't fit this profile. The deadline for these policy changes is May 31,
2024.
This permission remains enabled for apps installed on the phone before the user updates to Android 14. Users can turn this permission on and off.
You can use the new API
NotificationManager.canUseFullScreenIntent
to check if your app
has the permission; if not, your app can use the new intent
ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
to launch the settings
page where users can grant the permission.
امنیت
محدودیت برای مقاصد ضمنی و معلق
برای برنامههایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار میدهند، Android برنامهها را از ارسال مقاصد ضمنی به اجزای داخلی برنامه به روشهای زیر محدود میکند:
- مقاصد ضمنی فقط به اجزای صادر شده تحویل داده می شوند. برنامهها یا باید از یک قصد صریح برای تحویل به اجزای صادر نشده استفاده کنند یا مؤلفه را بهعنوان صادرشده علامتگذاری کنند.
- اگر یک برنامه یک هدف معلق قابل تغییر ایجاد کند که یک جزء یا بسته را مشخص نمی کند، سیستم یک استثنا ایجاد می کند.
این تغییرات مانع از رهگیری برنامه های مخرب در مقاصد ضمنی می شود که برای استفاده توسط اجزای داخلی برنامه در نظر گرفته شده است.
به عنوان مثال، در اینجا یک فیلتر قصد وجود دارد که می تواند در فایل مانیفست برنامه شما اعلام شود:
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
اگر برنامه شما سعی کند این فعالیت را با استفاده از یک هدف ضمنی راه اندازی کند، یک استثنا ActivityNotFoundException
ایجاد می شود:
کاتلین
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
جاوا
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(new Intent("com.example.action.APP_ACTION"));
برای راه اندازی فعالیت غیرصادراتی، برنامه شما باید به جای آن از یک هدف صریح استفاده کند:
کاتلین
// This makes the intent explicit. val explicitIntent = Intent("com.example.action.APP_ACTION") explicitIntent.apply { package = context.packageName } context.startActivity(explicitIntent)
جاوا
// This makes the intent explicit. Intent explicitIntent = new Intent("com.example.action.APP_ACTION") explicitIntent.setPackage(context.getPackageName()); context.startActivity(explicitIntent);
گیرنده های پخش ثبت شده در زمان اجرا باید رفتار صادراتی را مشخص کنند
برنامهها و سرویسهایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار میدهند و از گیرندههای ثبت شده در زمینه استفاده میکنند، باید پرچمی را مشخص کنند تا نشان دهد گیرنده باید به همه برنامههای دیگر دستگاه صادر شود یا نه: به ترتیب RECEIVER_EXPORTED
یا RECEIVER_NOT_EXPORTED
. . این نیاز به محافظت از برنامهها در برابر آسیبپذیریهای امنیتی با استفاده از ویژگیهای این گیرندههای معرفیشده در Android 13 کمک میکند.
استثنا برای گیرنده هایی که فقط پخش سیستم را دریافت می کنند
اگر برنامه شما فقط برای پخشهای سیستمی از طریق روشهای Context#registerReceiver
، مانند Context#registerReceiver()
یک گیرنده را ثبت میکند، پس نباید هنگام ثبت گیرنده پرچمی را مشخص کند.
بارگیری کد پویا ایمن تر
اگر برنامه شما Android 14 (سطح API 34) یا بالاتر را هدف قرار میدهد و از بارگذاری کد پویا (DCL) استفاده میکند، همه فایلهای بارگذاری شده پویا باید بهعنوان فقط خواندنی علامتگذاری شوند. در غیر این صورت، سیستم یک استثنا ایجاد می کند. توصیه میکنیم برنامهها تا حد امکان از بارگذاری پویا کد خودداری کنند ، زیرا انجام این کار خطر آسیبدیدگی یک برنامه با تزریق کد یا دستکاری کد را به شدت افزایش میدهد.
اگر باید کد را به صورت پویا بارگیری کنید، از روش زیر استفاده کنید تا فایل بارگذاری شده پویا (مانند فایل DEX، JAR، یا APK) را بهمحض باز شدن فایل و قبل از نوشتن هر محتوایی فقط خواندنی تنظیم کنید:
کاتلین
val jar = File("DYNAMICALLY_LOADED_FILE.jar") val os = FileOutputStream(jar) os.use { // Set the file to read-only first to prevent race conditions jar.setReadOnly() // Then write the actual file content } val cl = PathClassLoader(jar, parentClassLoader)
جاوا
File jar = new File("DYNAMICALLY_LOADED_FILE.jar"); try (FileOutputStream os = new FileOutputStream(jar)) { // Set the file to read-only first to prevent race conditions jar.setReadOnly(); // Then write the actual file content } catch (IOException e) { ... } PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);
مدیریت فایلهای بارگذاری شده پویا که از قبل وجود دارند
برای جلوگیری از ایجاد استثنا برای فایلهای موجود که به صورت پویا بارگذاری شدهاند، توصیه میکنیم قبل از بارگیری مجدد آنها به صورت پویا در برنامه خود، فایلها را حذف و دوباره ایجاد کنید. همانطور که فایل ها را دوباره ایجاد می کنید، دستورالعمل های قبلی را برای علامت گذاری فایل ها به صورت فقط خواندنی در زمان نوشتن دنبال کنید. همچنین، میتوانید فایلهای موجود را دوباره بهعنوان فقط خواندنی برچسبگذاری کنید، اما در این مورد، اکیداً توصیه میکنیم که ابتدا یکپارچگی فایلها را تأیید کنید (مثلاً با بررسی امضای فایل در برابر یک مقدار قابل اعتماد)، برای کمک به محافظت برنامه شما از اقدامات مخرب
محدودیت های اضافی برای شروع فعالیت ها از پس زمینه
For apps targeting Android 14 (API level 34) or higher, the system further restricts when apps are allowed to start activities from the background:
- When an app sends a
PendingIntent
usingPendingIntent#send()
or similar methods, the app must opt in if it wants to grant its own background activity launch privileges to start the pending intent. To opt in, the app should pass anActivityOptions
bundle withsetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
. - When a visible app binds a service of another app that's in the background
using the
bindService()
method, the visible app must now opt in if it wants to grant its own background activity launch privileges to the bound service. To opt in, the app should include theBIND_ALLOW_ACTIVITY_STARTS
flag when calling thebindService()
method.
These changes expand the existing set of restrictions to protect users by preventing malicious apps from abusing APIs to start disruptive activities from the background.
پیمایش مسیر زیپ
For apps targeting Android 14 (API level 34) or higher, Android prevents the Zip
Path Traversal Vulnerability in the following way:
ZipFile(String)
and
ZipInputStream.getNextEntry()
throws a
ZipException
if zip file entry names contain ".." or start
with "/".
Apps can opt-out from this validation by calling
dalvik.system.ZipPathValidator.clearCallback()
.
رضایت کاربر برای هر جلسه ضبط MediaProjection لازم است
For apps targeting Android 14 (API level 34) or higher, a SecurityException
is
thrown by MediaProjection#createVirtualDisplay
in either of the following
scenarios:
- Your app caches the
Intent
that is returned fromMediaProjectionManager#createScreenCaptureIntent
, and passes it multiple times toMediaProjectionManager#getMediaProjection
. - Your app invokes
MediaProjection#createVirtualDisplay
multiple times on the sameMediaProjection
instance.
Your app must ask the user to give consent before each capture session. A single
capture session is a single invocation on
MediaProjection#createVirtualDisplay
, and each MediaProjection
instance must
be used only once.
Handle configuration changes
If your app needs to invoke MediaProjection#createVirtualDisplay
to handle
configuration changes (such as the screen orientation or screen size changing),
you can follow these steps to update the VirtualDisplay
for the existing
MediaProjection
instance:
- Invoke
VirtualDisplay#resize
with the new width and height. - Provide a new
Surface
with the new width and height toVirtualDisplay#setSurface
.
Register a callback
Your app should register a callback to handle cases where the user doesn't grant
consent to continue a capture session. To do this, implement
Callback#onStop
and have your app release any related resources (such as
the VirtualDisplay
and Surface
).
If your app doesn't register this callback,
MediaProjection#createVirtualDisplay
throws an IllegalStateException
when your app invokes it.
محدودیتهای غیر SDK بهروزرسانی شد
Android 14 includes updated lists of restricted non-SDK interfaces based on collaboration with Android developers and the latest internal testing. Whenever possible, we make sure that public alternatives are available before we restrict non-SDK interfaces.
If your app does not target Android 14, some of these changes might not immediately affect you. However, while you can currently use some non-SDK interfaces (depending on your app's target API level), using any non-SDK method or field always carries a high risk of breaking your app.
If you are unsure if your app uses non-SDK interfaces, you can test your app to find out. If your app relies on non-SDK interfaces, you should begin planning a migration to SDK alternatives. Nevertheless, we understand that some apps have valid use cases for using non-SDK interfaces. If you cannot find an alternative to using a non-SDK interface for a feature in your app, you should request a new public API.
برای کسب اطلاعات بیشتر در مورد تغییرات این نسخه از اندروید، بهروزرسانیهای محدودیتهای رابط غیر SDK در Android 14 را ببینید. برای کسب اطلاعات بیشتر در مورد رابط های غیر SDK به طور کلی، به محدودیت ها در رابط های غیر SDK مراجعه کنید.