مانند نسخه های قبلی، Android 15 شامل تغییرات رفتاری است که ممکن است بر برنامه شما تأثیر بگذارد. تغییرات رفتاری زیر منحصراً برای برنامههایی اعمال میشود که Android 15 یا بالاتر را هدف قرار میدهند. اگر برنامه شما اندروید 15 یا بالاتر را هدف قرار می دهد، باید برنامه خود را تغییر دهید تا در صورت لزوم از این رفتارها به درستی پشتیبانی کند.
حتماً فهرستی از تغییرات رفتاری را نیز مرور کنید که بر همه برنامههای در حال اجرا در Android 15 بدون توجه به targetSdkVersion
برنامه شما تأثیر میگذارد.
عملکرد اصلی
اندروید 15 قابلیت های اصلی مختلف سیستم اندروید را اصلاح یا گسترش می دهد.
تغییرات در خدمات پیش زمینه
我们将对 Android 15 中的前台服务进行以下更改。
数据同步前台服务超时行为
对于以 Android 15(API 级别 35)或更高版本为目标平台的应用,Android 15 为 dataSync
引入了新的超时行为。此行为也适用于新的 mediaProcessing
前台服务类型。
系统允许应用的 dataSync
服务在 24 小时内总共运行 6 小时,之后系统会调用正在运行的服务的 Service.onTimeout(int, int)
方法(在 Android 15 中引入)。此时,该服务有几秒钟时间来调用 Service.stopSelf()
。调用 Service.onTimeout()
后,该服务将不再被视为前台服务。如果服务未调用 Service.stopSelf()
,系统会抛出内部异常。系统会在 Logcat 中记录此异常,并显示以下消息:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
为避免因行为变更而导致问题,您可以执行以下一项或多项操作:
- 让您的服务实现新的
Service.onTimeout(int, int)
方法。当您的应用收到回调时,请务必在几秒钟内调用stopSelf()
。(如果您不立即停止应用,系统会生成故障。) - 确保应用的
dataSync
服务在任何 24 小时内总运行时间不超过 6 小时(除非用户与应用互动,重置计时器)。 - 仅通过直接的用户互动来启动
dataSync
前台服务;由于您的应用在服务启动时位于前台,因此服务会在应用进入后台后的 6 小时内完整运行。 - 请改用替代 API,而不是使用
dataSync
前台服务。
如果您的应用的 dataSync
前台服务在过去 24 小时内运行了 6 小时,则您无法启动其他 dataSync
前台服务,除非用户已将您的应用切换到前台(这会重置计时器)。如果您尝试启动其他 dataSync
前台服务,系统会抛出 ForegroundServiceStartNotAllowedException
,并显示类似“前台服务类型 dataSync 的时间限制已用尽”的错误消息。
测试
如需测试应用的行为,您可以启用数据同步超时功能,即使应用未以 Android 15 为目标平台也是如此(前提是应用在 Android 15 设备上运行)。如需启用超时,请运行以下 adb
命令:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
您还可以调整超时期限,更轻松地测试应用在达到此限制时的行为。如需设置新的超时期限,请运行以下 adb
命令:
adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds
新的媒体处理前台服务类型
Android 15 引入了一种新的前台服务类型 mediaProcessing
。此服务类型适用于转码媒体文件等操作。例如,媒体应用可能会下载音频文件,并需要先将其转换为其他格式,然后才能播放。您可以使用 mediaProcessing
前台服务,确保即使应用在后台运行时转换也会继续。
系统允许应用的 mediaProcessing
服务在 24 小时内总共运行 6 小时,之后系统会调用正在运行的服务的 Service.onTimeout(int, int)
方法(在 Android 15 中引入)。此时,服务有几秒钟的时间来调用 Service.stopSelf()
。如果服务未调用 Service.stopSelf()
,系统会抛出内部异常。系统会在 Logcat 中记录此异常,并显示以下消息:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"
为避免出现此异常,您可以执行以下任一操作:
- 让您的服务实现新的
Service.onTimeout(int, int)
方法。当您的应用收到回调时,请务必在几秒钟内调用stopSelf()
。(如果您未立即停止应用,系统会生成失败情况。) - 确保应用的
mediaProcessing
服务在任何 24 小时内总运行时间不超过 6 小时(除非用户与应用互动,重置计时器)。 - 仅在有直接用户互动时启动
mediaProcessing
前台服务;由于服务启动时应用位于前台,因此您的服务在应用进入后台后有完整的 6 小时时间。 - 请改用 替代 API(例如 WorkManager),而不是使用
mediaProcessing
前台服务。
如果您的应用的 mediaProcessing
前台服务在过去 24 小时内运行了 6 小时,则您无法启动其他 mediaProcessing
前台服务,除非用户将您的应用切换到前台(这会重置计时器)。如果您尝试启动另一个 mediaProcessing
前台服务,系统会抛出 ForegroundServiceStartNotAllowedException
,并显示类似于“前台服务类型 mediaProcessing 的时间限制已用尽”的错误消息。
如需详细了解 mediaProcessing
服务类型,请参阅 Android 15 前台服务类型变更:媒体处理。
测试
如需测试应用的行为,您可以启用媒体处理超时,即使您的应用并非以 Android 15 为目标平台也是如此(前提是应用在 Android 15 设备上运行)。如需启用超时,请运行以下 adb
命令:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
您还可以调整超时期限,以便更轻松地测试应用在达到上限时的行为方式。如需设置新的超时期限,请运行以下 adb
命令:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
对启动前台服务的 BOOT_COMPLETED
广播接收器的限制
在启动 BOOT_COMPLETED
广播接收器方面存在新限制
前台服务。BOOT_COMPLETED
接收器不能启动
以下类型的前台服务:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(自 Android 14 起,microphone
就受到此限制)
如果 BOOT_COMPLETED
接收器尝试启动任何上述类型的前台
服务,系统会抛出 ForegroundServiceStartNotAllowedException
。
测试
如需测试应用的行为,您可以启用这些新限制,即使您的应用并未以 Android 15 为目标平台(只要应用在 Android 15 设备上运行)也是如此。运行以下 adb
命令:
adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name
如需在不重启设备的情况下发送 BOOT_COMPLETED
广播,请运行以下 adb
命令:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name
在应用拥有 SYSTEM_ALERT_WINDOW
权限时启动前台服务的限制
قبلاً، اگر برنامهای مجوز SYSTEM_ALERT_WINDOW
را داشت، میتوانست یک سرویس پیشزمینه راهاندازی کند، حتی اگر برنامه در حال حاضر در پسزمینه باشد (همانطور که در معافیتها از محدودیتهای شروع پسزمینه بحث شد).
اگر برنامه ای اندروید 15 را هدف قرار دهد، این معافیت اکنون محدودتر شده است. اکنون برنامه باید مجوز SYSTEM_ALERT_WINDOW
را داشته باشد و همچنین یک پنجره همپوشانی قابل مشاهده داشته باشد. یعنی برنامه باید ابتدا یک پنجره TYPE_APPLICATION_OVERLAY
راه اندازی کند و قبل از شروع سرویس پیش زمینه باید پنجره قابل مشاهده باشد.
اگر برنامه شما سعی کند یک سرویس پیشزمینه را از پسزمینه راهاندازی کند، بدون اینکه این الزامات جدید را برآورده کند (و معافیت دیگری ندارد)، سیستم ForegroundServiceStartNotAllowedException
را پرتاب میکند.
اگر برنامه شما مجوز SYSTEM_ALERT_WINDOW
را اعلام کند و خدمات پیشزمینه را از پسزمینه راهاندازی کند، ممکن است تحت تأثیر این تغییر قرار گیرد. اگر برنامه شما یک ForegroundServiceStartNotAllowedException
دریافت می کند، ترتیب عملکرد برنامه خود را بررسی کنید و مطمئن شوید که برنامه شما قبلاً یک پنجره همپوشانی فعال دارد قبل از اینکه بخواهد یک سرویس پیش زمینه را از پس زمینه راه اندازی کند. میتوانید با فراخوانی View.getWindowVisibility()
بررسی کنید که آیا پنجره همپوشانی شما قابل مشاهده است یا خیر، یا میتوانید View.onWindowVisibilityChanged()
را لغو کنید تا هر زمان که قابلیت مشاهده تغییر کرد مطلع شوید.
تست کردن
برای آزمایش رفتار برنامهتان، میتوانید این محدودیتهای جدید را فعال کنید، حتی اگر برنامه شما اندروید 15 را هدف قرار ندهد (تا زمانی که برنامه روی دستگاه Android 15 اجرا شود). برای فعال کردن این محدودیتهای جدید برای شروع خدمات پیشزمینه از پسزمینه، دستور adb
زیر را اجرا کنید:
adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name
زمانی که برنامهها میتوانند وضعیت جهانی حالت مزاحم نشوید را تغییر دهند
برنامههایی که Android 15 (سطح API 35) و بالاتر را هدف قرار میدهند، دیگر نمیتوانند وضعیت کلی یا خطمشی «مزاحم نشوید» (DND) را در دستگاه تغییر دهند (چه با تغییر تنظیمات کاربر یا خاموش کردن حالت DND). در عوض، برنامهها باید یک AutomaticZenRule
ارائه دهند، که سیستم آن را در یک خطمشی جهانی با طرح موجود بیشترین محدودیتکننده-سیاست-برنده ترکیب میکند. تماسهای APIهای موجود که قبلاً بر وضعیت جهانی تأثیر میگذاشتند ( setInterruptionFilter
، setNotificationPolicy
) منجر به ایجاد یا بهروزرسانی یک AutomaticZenRule
ضمنی میشود که بسته به چرخه تماس آن فراخوانهای API، روشن و خاموش میشود.
توجه داشته باشید که این تغییر تنها در صورتی بر رفتار قابل مشاهده تأثیر میگذارد که برنامه setInterruptionFilter(INTERRUPTION_FILTER_ALL)
را فراخوانی کند و انتظار دارد که این تماس AutomaticZenRule
را که قبلاً توسط صاحبان آن فعال شده است غیرفعال کند.
OpenJDK API تغییر می کند
اندروید 15 به کار تازه سازی کتابخانه های اصلی اندروید برای هماهنگی با ویژگی های آخرین نسخه OpenJDK LTS ادامه می دهد.
برخی از این تغییرات میتواند بر سازگاری برنامهها برای برنامههایی که Android 15 را هدف قرار میدهند (سطح API 35) تأثیر بگذارد:
تغییرات در APIهای قالببندی رشتهای : اعتبارسنجی شاخص آرگومان، پرچمها، عرض و دقت اکنون هنگام استفاده از APIهای
String.format()
وFormatter.format()
سختتر است:-
String.format(String, Object[])
-
String.format(Locale, String, Object[])
-
Formatter.format(String, Object[])
-
Formatter.format(Locale, String, Object[])
به عنوان مثال، زمانی که از شاخص آرگومان 0 استفاده می شود، استثنای زیر ایجاد می شود (
%0
در رشته قالب):IllegalFormatArgumentIndexException: Illegal format argument index = 0
در این مورد، مشکل را می توان با استفاده از شاخص آرگومان 1 (
%1
در رشته قالب) برطرف کرد.-
تغییرات در نوع مؤلفه
Arrays.asList(...).toArray()
: هنگام استفاده ازArrays.asList(...).toArray()
، نوع مؤلفه آرایه حاصل اکنون یکObject
است — نه نوع عناصر آرایه زیرین. بنابراین کد زیر یکClassCastException
می اندازد:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
برای این مورد، برای حفظ
String
به عنوان نوع مؤلفه در آرایه حاصل، میتوانید به جای آن ازCollection.toArray(Object[])
استفاده کنید:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
تغییرات در مدیریت کد زبان : هنگام استفاده از
Locale
API، کدهای زبان عبری، ییدیش و اندونزیایی دیگر به شکلهای منسوخ خود تبدیل نمیشوند (عبری:iw
، ییدیش:ji
، و اندونزیایی:in
). هنگام تعیین کد زبان برای یکی از این مناطق، به جای آن از کدهای ISO 639-1 استفاده کنید (عبری:he
، ییدیش:yi
، و اندونزیایی:id
).تغییرات در دنبالههای تصادفی int : به دنبال تغییرات ایجاد شده در https://bugs.openjdk.org/browse/JDK-8301574 ، متدهای
Random.ints()
زیر ترتیب متفاوتی از اعداد را نسبت به متدهایRandom.nextInt()
برمیگردانند:به طور کلی، این تغییر نباید منجر به رفتار شکستن برنامه شود، اما کد شما نباید انتظار داشته باشد که دنباله تولید شده از متدهای
Random.ints()
مطابق باRandom.nextInt()
باشد.
بعد از اینکه compileSdk
در پیکربندی ساخت برنامه خود برای استفاده از Android 15 (سطح API 35) بهروزرسانی کردید، API جدید SequencedCollection
میتواند بر سازگاری برنامه شما تأثیر بگذارد:
برخورد با توابع پسوند
MutableList.removeFirst()
وMutableList.removeLast()
درkotlin-stdlib
نوع
List
در جاوا به نوعMutableList
در Kotlin نگاشت می شود. از آنجایی که API هایList.removeFirst()
وList.removeLast()
در اندروید 15 معرفی شده اند (سطح API 35)، کامپایلر Kotlin فراخوانی های تابع، به عنوان مثالlist.removeFirst()
را به جای توابع پسوند درkotlin-stdlib
به صورت ایستا به API هایList
جدید حل می کند.اگر برنامهای دوباره با
compileSdk
روی35
وminSdk
روی34
یا پایینتر کامپایل شود، و سپس برنامه روی اندروید 14 و پایینتر اجرا شود، یک خطای زمان اجرا ایجاد میشود:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
گزینه
NewApi
lint موجود در پلاگین Android Gradle می تواند این موارد استفاده جدید API را دریافت کند../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()برای رفع خطاهای Exception و lint در زمان اجرا، فراخوانی تابع
removeFirst()
وremoveLast()
می توان به ترتیب باremoveAt(0)
وremoveAt(list.lastIndex)
در Kotlin جایگزین کرد. اگر از Android Studio Ladybug | 2024.1.3 یا بالاتر، همچنین گزینه ای برای رفع سریع این خطاها ارائه می دهد.اگر گزینه lint غیرفعال شده است
@SuppressLint("NewApi")
وlintOptions { disable 'NewApi' }
حذف کنید.برخورد با روش های دیگر در جاوا
روش های جدیدی به انواع موجود اضافه شده است، به عنوان مثال،
List
وDeque
. این متدهای جدید ممکن است با متدهایی با همان نام و انواع آرگومان در سایر رابطها و کلاسها سازگار نباشند. در مورد تصادم امضای روش با ناسازگاری، کامپایلرjavac
یک خطای زمان ساخت را خروجی میکند. به عنوان مثال:خطای مثال 1:
javac MyList.java
MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List public void removeLast() { ^ return type void is not compatible with Object where E is a type-variable: E extends Object declared in interface Listمثال خطای 2:
javac MyList.java
MyList.java:7: error: types Deque<Object> and List<Object> are incompatible; public class MyList implements List<Object>, Deque<Object> { both define reversed(), but with unrelated return types 1 errorمثال خطای 3:
javac MyList.java
MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible; public static class MyList implements List<Object>, MyInterface<Object> { class MyList inherits unrelated defaults for getFirst() from types List and MyInterface where E#1,E#2 are type-variables: E#1 extends Object declared in interface List E#2 extends Object declared in interface MyInterface 1 errorبرای رفع این خطاهای ساخت، کلاسی که این رابطها را پیادهسازی میکند، باید متد را با نوع بازگشتی سازگار لغو کند. به عنوان مثال:
@Override public Object getFirst() { return List.super.getFirst(); }
امنیت
اندروید 15 شامل تغییراتی است که امنیت سیستم را ارتقا میدهد تا از برنامهها و کاربران در برابر برنامههای مخرب محافظت کند.
نسخه های محدود TLS
اندروید 15 استفاده از TLS نسخه 1.0 و 1.1 را محدود می کند. این نسخهها قبلاً در اندروید منسوخ شده بودند، اما اکنون برای برنامههایی که اندروید 15 را هدف قرار میدهند غیرمجاز هستند.
فعالیت پس زمینه ایمن راه اندازی می شود
اندروید 15 از کاربران در برابر برنامههای مخرب محافظت میکند و با افزودن تغییراتی که مانع از نمایش برنامههای مخرب در پسزمینه، افزایش امتیازات و سوء استفاده از تعامل با کاربر میشود، کنترل بیشتری بر دستگاههایشان میدهد. راه اندازی فعالیت های پس زمینه از Android 10 (سطح API 29) محدود شده است.
تغییرات دیگر
علاوه بر محدودیت برای تطبیق UID، این تغییرات دیگر نیز شامل می شود:
- سازندگان
PendingIntent
تغییر دهید تا به طور پیشفرض راهاندازیهای فعالیت پسزمینه را مسدود کنند . این به جلوگیری از ایجاد تصادفی یکPendingIntent
توسط برنامهها کمک میکند که ممکن است توسط عوامل مخرب مورد سوء استفاده قرار گیرد. - یک برنامه را در پیش زمینه نیاورید مگر اینکه فرستنده
PendingIntent
اجازه دهد . هدف این تغییر جلوگیری از سوء استفاده برنامه های مخرب از توانایی شروع فعالیت در پس زمینه است. بهطور پیشفرض، برنامهها اجازه ندارند پشته کار را به پیشزمینه بیاورند، مگر اینکه سازنده امتیازات راهاندازی فعالیت پسزمینه را اجازه دهد یا فرستنده دارای امتیازات راهاندازی فعالیت در پسزمینه باشد. - کنترل کنید که فعالیت برتر یک پشته وظیفه چگونه می تواند کار خود را به پایان برساند . اگر فعالیت برتر یک کار را تمام کند، Android به هر کاری که آخرین بار فعال بوده است برمی گردد. علاوه بر این، اگر یک فعالیت غیر برتر وظیفه خود را به پایان برساند، Android به صفحه اصلی باز خواهد گشت. پایان این فعالیت غیر برتر را مسدود نخواهد کرد.
- از راهاندازی فعالیتهای خودسرانه از برنامههای دیگر در وظیفه خود جلوگیری کنید . این تغییر با ایجاد فعالیت هایی که به نظر می رسد از سایر برنامه ها باشد، از فیشینگ کاربران توسط برنامه های مخرب جلوگیری می کند.
- از در نظر گرفتن پنجرههای غیرقابل مشاهده برای راهاندازی فعالیت پسزمینه جلوگیری کنید . این به جلوگیری از سوء استفاده برنامه های مخرب از راه اندازی فعالیت های پس زمینه برای نمایش محتوای ناخواسته یا مخرب به کاربران کمک می کند.
اندروید 15 از کاربران در برابر برنامههای مخرب محافظت میکند و با افزودن تغییراتی که مانع از نمایش برنامههای مخرب در پسزمینه، افزایش امتیازات و سوء استفاده از تعامل با کاربر میشود، کنترل بیشتری بر دستگاههایشان میدهد. راه اندازی فعالیت های پس زمینه از Android 10 (سطح API 29) محدود شده است.
تغییرات دیگر
علاوه بر محدودیت برای تطبیق UID، این تغییرات دیگر نیز شامل می شود:
- سازندگان
PendingIntent
تغییر دهید تا به طور پیشفرض راهاندازیهای فعالیت پسزمینه را مسدود کنند . این به جلوگیری از ایجاد تصادفی یکPendingIntent
توسط برنامهها کمک میکند که ممکن است توسط عوامل مخرب مورد سوء استفاده قرار گیرد. - یک برنامه را در پیش زمینه نیاورید مگر اینکه فرستنده
PendingIntent
اجازه دهد . هدف این تغییر جلوگیری از سوء استفاده برنامه های مخرب از توانایی شروع فعالیت در پس زمینه است. بهطور پیشفرض، برنامهها اجازه ندارند پشته کار را به پیشزمینه بیاورند، مگر اینکه سازنده امتیازات راهاندازی فعالیت پسزمینه را اجازه دهد یا فرستنده دارای امتیازات راهاندازی فعالیت در پسزمینه باشد. - کنترل کنید که فعالیت برتر یک پشته وظیفه چگونه می تواند کار خود را به پایان برساند . اگر فعالیت برتر یک کار را تمام کند، Android به هر کاری که آخرین بار فعال بوده است برمی گردد. علاوه بر این، اگر یک فعالیت غیر برتر وظیفه خود را به پایان برساند، Android به صفحه اصلی باز خواهد گشت. پایان این فعالیت غیر برتر را مسدود نخواهد کرد.
- از راهاندازی فعالیتهای خودسرانه از برنامههای دیگر در وظیفه خود جلوگیری کنید . این تغییر با ایجاد فعالیت هایی که به نظر می رسد از سایر برنامه ها باشد، از فیشینگ کاربران توسط برنامه های مخرب جلوگیری می کند.
- از در نظر گرفتن پنجرههای غیرقابل مشاهده برای راهاندازی فعالیت پسزمینه جلوگیری کنید . این به جلوگیری از سوء استفاده برنامه های مخرب از راه اندازی فعالیت های پس زمینه برای نمایش محتوای ناخواسته یا مخرب به کاربران کمک می کند.
مقاصد امن تر
Android 15 引入了新的可选安全措施,以提高 intent 的安全性 和更强大的模型。这些变更旨在防范潜在的漏洞, 可能会被恶意应用利用的 intent 滥用。Android 15 对 intent 的安全性进行了两项主要改进:
- 匹配目标 intent 过滤器:针对特定组件的 intent 准确匹配目标的 intent 过滤器规范。如果您发送 intent 来启动另一个应用的 activity,则目标 intent 组件需要 与接收 activity 声明的 intent 过滤器保持一致。
- intent 必须包含操作:不含操作的 intent 将不再与任何 intent 过滤器匹配。也就是说,用于启动 activity 或 服务都必须有明确定义的操作。
要检查应用如何响应这些更改,请使用
StrictMode
。要查看详细的
关于 Intent
使用违规行为的日志,请添加以下方法:
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
تجربه کاربری و رابط کاربری سیستم
اندروید 15 شامل تغییراتی است که برای ایجاد یک تجربه کاربری سازگارتر و بصری در نظر گرفته شده است.
ورودی پنجره تغییر می کند
Android 15 中与窗口内边距相关的两项变更:默认强制执行边到边,此外还有配置变更,例如系统栏的默认配置。
全面实施政策
اگر برنامه اندروید 15 (سطح API 35) را هدف قرار دهد، برنامهها بهطور پیشفرض در دستگاههای دارای Android 15 لبه به لبه هستند.

این یک تغییر اساسی است که ممکن است بر رابط کاربری برنامه شما تأثیر منفی بگذارد. تغییرات بر حوزه های UI زیر تأثیر می گذارد:
- نوار پیمایش دسته اشاره
- به طور پیش فرض شفاف است.
- افست پایین غیرفعال است، بنابراین محتوا در پشت نوار پیمایش سیستم کشیده میشود، مگر اینکه ورودیها اعمال شوند.
-
setNavigationBarColor
وR.attr#navigationBarColor
منسوخ شدهاند و بر ناوبری اشارهای تأثیری ندارند. -
setNavigationBarContrastEnforced
وR.attr#navigationBarContrastEnforced
همچنان هیچ تاثیری بر ناوبری اشاره ای ندارند.
- ناوبری 3 دکمه ای
- Opacity به طور پیشفرض روی 80% تنظیم شده است و رنگ احتمالاً با پسزمینه پنجره مطابقت دارد.
- افست پایین غیرفعال است، بنابراین محتوا در پشت نوار پیمایش سیستم کشیده میشود مگر اینکه درجهای داخلی اعمال شوند.
-
setNavigationBarColor
وR.attr#navigationBarColor
به طور پیشفرض با پسزمینه پنجره مطابقت دارند. پس زمینه پنجره باید یک رنگ قابل ترسیم باشد تا این پیش فرض اعمال شود. این API منسوخ شده است اما همچنان بر ناوبری 3 دکمه ای تأثیر می گذارد. -
setNavigationBarContrastEnforced
وR.attr#navigationBarContrastEnforced
به طور پیشفرض درست است، که 80% پسزمینه مات را در مسیریابی 3 دکمه اضافه میکند.
- نوار وضعیت
- به طور پیش فرض شفاف است.
- افست بالا غیرفعال است، بنابراین محتوا در پشت نوار وضعیت ترسیم می شود، مگر اینکه درج ها اعمال شوند.
-
setStatusBarColor
وR.attr#statusBarColor
منسوخ شده اند و روی اندروید 15 تاثیری ندارند. -
setStatusBarContrastEnforced
وR.attr#statusBarContrastEnforced
منسوخ شدهاند اما همچنان روی اندروید 15 اثر دارند.
- برش نمایشگر
-
layoutInDisplayCutoutMode
پنجرههای غیر شناور بایدLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
باشد.SHORT_EDGES
،NEVER
وDEFAULT
بهعنوانALWAYS
تفسیر میشوند تا کاربران نوار سیاه ناشی از بریدگی نمایشگر را نبینند و لبه به لبه ظاهر شوند.
-
مثال زیر یک برنامه را قبل و بعد از هدف قرار دادن Android 15 (سطح API 35) و قبل و بعد از اعمال insets نشان می دهد. این مثال جامع نیست، ممکن است در Android Auto متفاوت ظاهر شود.



چه باید بررسی کرد که آیا برنامه شما از قبل لبه به لبه است
اگر برنامه شما از قبل لبه به لبه است و از inset ها استفاده می کند، به جز در سناریوهای زیر، اکثراً بی تأثیر هستید. با این حال، حتی اگر فکر می کنید تحت تأثیر قرار نگرفته اید، توصیه می کنیم برنامه خود را آزمایش کنید.
- شما یک پنجره غیر شناور دارید، مانند
Activity
که به جایLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
ازSHORT_EDGES
،NEVER
یاDEFAULT
استفاده می کند. اگر برنامه شما در هنگام راهاندازی از کار میافتد، ممکن است به خاطر صفحه نمایش شما باشد. میتوانید وابستگی اصلی صفحه نمایش اسپلش را به 1.2.0-alpha01 یا بالاتر ارتقا دهید یاwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
را تنظیم کنید. - ممکن است صفحه نمایش هایی با ترافیک کمتر با رابط کاربری مسدود شده وجود داشته باشد. بررسی کنید این صفحهنمایشهایی که کمتر بازدید شدهاند، رابط کاربری مسدود شده ندارند. صفحه نمایش های کم تردد عبارتند از:
- صفحات ورود یا ورود به سیستم
- صفحات تنظیمات
اگر برنامه شما از قبل لبه به لبه نیست، چه باید بررسی کنید
اگر برنامه شما در حال حاضر لبه به لبه نیست، به احتمال زیاد تحت تأثیر قرار خواهید گرفت. علاوه بر سناریوهای برنامههایی که از قبل لبه به لبه هستند، باید موارد زیر را در نظر بگیرید:
- اگر برنامه شما از Material 3 Components (
androidx.compose.material3
) در نوشتن استفاده میکند، مانندTopAppBar
،BottomAppBar
، وNavigationBar
، این مؤلفهها احتمالاً تحت تأثیر قرار نمیگیرند زیرا بهطور خودکار ورودیها را مدیریت میکنند. - اگر برنامه شما از Material 2 Components (
androidx.compose.material
) در Compose استفاده میکند، این مؤلفهها بهطور خودکار ورودیها را مدیریت نمیکنند. با این حال، می توانید به inset ها دسترسی داشته باشید و آنها را به صورت دستی اعمال کنید. در androidx.compose.material 1.6.0 و جدیدتر، از پارامترwindowInsets
برای اعمال دستی Insets برایBottomAppBar
،TopAppBar
،BottomNavigation
وNavigationRail
استفاده کنید. به همین ترتیب، از پارامترcontentWindowInsets
برایScaffold
استفاده کنید. - اگر برنامه شما از نماها و مؤلفههای مواد (
com.google.android.material
) استفاده میکند، بیشتر مؤلفههای مواد مبتنی بر نما مانندBottomNavigationView
،BottomAppBar
،NavigationRailView
یاNavigationView
، ورودیها را مدیریت میکنند و نیازی به کار اضافی ندارند. با این حال، اگر ازAppBarLayout
استفاده می کنید، بایدandroid:fitsSystemWindows="true"
را اضافه کنید. - برای ترکیبهای سفارشی، اینستها را بهصورت دستی بهعنوان بالشتک اعمال کنید. اگر محتوای شما در داخل یک
Scaffold
است، میتوانید با استفاده از مقادیرScaffold
padding از انست استفاده کنید. در غیر این صورت، با استفاده از یکی ازWindowInsets
، padding را اعمال کنید. - اگر برنامه شما از نماها و
BottomSheet
،SideSheet
یا ظروف سفارشی استفاده می کند، با استفاده ازViewCompat.setOnApplyWindowInsetsListener
، padding را اعمال کنید. برایRecyclerView
، با استفاده از این شنونده، padding را اعمال کنید وclipToPadding="false"
را نیز اضافه کنید.
چه باید بررسی کرد که آیا برنامه شما باید محافظت پسزمینه سفارشی ارائه دهد
اگر برنامه شما باید محافظت پسزمینه سفارشی برای پیمایش 3 دکمه یا نوار وضعیت ارائه دهد، برنامه شما باید با استفاده از WindowInsets.Type#tappableElement()
یک تصویر قابل ترکیب یا نمایش را در پشت نوار سیستم قرار دهد تا ارتفاع نوار ناوبری 3 دکمه یا WindowInsets.Type#statusBars
دریافت کند.
منابع لبه به لبه اضافی
برای ملاحظات بیشتر در مورد اعمال inset ها، راهنمای Edge to Edge Views و Edge to Edge Compose را ببینید.
API های منسوخ شده
API های زیر منسوخ شده اند اما غیرفعال نشده اند:
-
R.attr#enforceStatusBarContrast
-
R.attr#navigationBarColor
(برای پیمایش با 3 دکمه، با 80% آلفا) -
Window#isStatusBarContrastEnforced
-
Window#setNavigationBarColor
(برای پیمایش 3 دکمه، با 80% آلفا) -
Window#setStatusBarContrastEnforced
API های زیر منسوخ و غیرفعال شده اند:
-
R.attr#navigationBarColor
(برای پیمایش با اشاره) -
R.attr#navigationBarDividerColor
-
R.attr#statusBarColor
-
Window#setDecorFitsSystemWindows
-
Window#getNavigationBarColor
-
Window#getNavigationBarDividerColor
-
Window#getStatusBarColor
-
Window#setNavigationBarColor
(برای پیمایش با اشاره) -
Window#setNavigationBarDividerColor
-
Window#setStatusBarColor
稳定配置
اگر برنامه شما Android 15 (سطح API 35) یا بالاتر را هدف قرار می دهد، Configuration
دیگر نوارهای سیستم را حذف نمی کند. اگر از اندازه صفحه در کلاس Configuration
برای محاسبه چیدمان استفاده می کنید، باید بسته به نیاز خود، آن را با گزینه های بهتری مانند ViewGroup
مناسب، WindowInsets
یا WindowMetricsCalculator
جایگزین کنید.
Configuration
از API 1 در دسترس بوده است. معمولاً از Activity.onConfigurationChanged
دریافت میشود. اطلاعاتی مانند تراکم، جهت و اندازه پنجره را ارائه می دهد. یکی از ویژگیهای مهم در مورد اندازههای پنجره بازگشتی از Configuration
این است که قبلاً نوارهای سیستم را حذف میکرد.
اندازه پیکربندی معمولاً برای انتخاب منبع استفاده میشود، مانند /res/layout-h500dp
، و این هنوز یک مورد استفاده معتبر است. با این حال، استفاده از آن برای محاسبه چیدمان همیشه دلسرد شده است. اگر این کار را انجام دهید، اکنون باید از آن دور شوید. شما باید بسته به مورد استفاده خود، استفاده از Configuration
را با چیزی مناسب تر جایگزین کنید.
اگر از آن برای محاسبه طرح بندی استفاده می کنید، از یک ViewGroup
مناسب مانند CoordinatorLayout
یا ConstraintLayout
استفاده کنید. اگر از آن برای تعیین ارتفاع نوار ناوبری سیستم استفاده می کنید، از WindowInsets
استفاده کنید. اگر می خواهید اندازه فعلی پنجره برنامه خود را بدانید، از computeCurrentWindowMetrics
استفاده کنید.
لیست زیر فیلدهای تحت تأثیر این تغییر را شرح می دهد:
- اندازههای
Configuration.screenWidthDp
وscreenHeightDp
دیگر نوارهای سیستم را حذف نمیکنند. -
Configuration.smallestScreenWidthDp
به طور غیر مستقیم تحت تأثیر تغییراتscreenWidthDp
وscreenHeightDp
قرار می گیرد. -
Configuration.orientation
به طور غیرمستقیم تحت تأثیر تغییراتscreenWidthDp
وscreenHeightDp
در دستگاه های نزدیک به مربع است. -
Display.getSize(Point)
به طور غیر مستقیم تحت تأثیر تغییراتConfiguration
قرار می گیرد. این در ابتدا در سطح API 30 منسوخ شد. -
Display.getMetrics()
قبلاً از سطح API 33 به این شکل کار کرده است.
صفت elegantTextHeight به طور پیش فرض درست است
对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight
TextView
属性默认会变为 true
,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing
属性拉伸垂直高度,从而防止许多此类中断。
在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight
设置为 false
以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight
设置为 true
以测试您的应用。

elegantTextHeight
行为。
elegantTextHeight
行为。عرض TextView برای اشکال حروف پیچیده تغییر می کند
در نسخههای قبلی اندروید، برخی از فونتهای شکسته یا زبانهایی که شکل پیچیدهای دارند، ممکن است حروف را در ناحیه شخصیت قبلی یا بعدی بکشند. در برخی موارد، چنین حروفی در موقعیت آغاز یا پایان بریده می شدند. با شروع اندروید 15، یک TextView
عرض را برای ترسیم فضای کافی برای چنین حروفی اختصاص میدهد و به برنامهها اجازه میدهد تا برای جلوگیری از برش، بالشتکهای اضافی را در سمت چپ درخواست کنند.
از آنجایی که این تغییر بر نحوه تعیین عرض یک TextView
تأثیر میگذارد، اگر برنامه Android 15 (سطح API 35) یا بالاتر را هدف قرار دهد، TextView
به طور پیشفرض عرض بیشتری را اختصاص میدهد. می توانید این رفتار را با فراخوانی API setUseBoundsForWidth
در TextView
فعال یا غیرفعال کنید.
از آنجایی که افزودن پد سمت چپ ممکن است باعث ایجاد ناهماهنگی در طرحبندیهای موجود شود، این پد بهطور پیشفرض حتی برای برنامههایی که Android 15 یا بالاتر را هدف قرار میدهند، اضافه نمیشود. با این حال، میتوانید با فراخوانی setShiftDrawingOffsetForStartOverhang
، بالشتک اضافی برای جلوگیری از بریدن اضافه کنید.
مثالهای زیر نشان میدهند که چگونه این تغییرات میتوانند طرحبندی متن را برای برخی از فونتها و زبانها بهبود بخشند.

<TextView android:fontFamily="cursive" android:text="java" />

<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />

<TextView android:text="คอมพิวเตอร์" />

<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
ارتفاع خط پیشفرض آگاه از محلی برای EditText
در نسخههای قبلی اندروید، طرحبندی متن، ارتفاع متن را به اندازه ارتفاع خط فونتی که با منطقه فعلی مطابقت دارد، افزایش میداد. به عنوان مثال، اگر محتوا به زبان ژاپنی بود، چون ارتفاع خط فونت ژاپنی کمی بزرگتر از فونت لاتین است، ارتفاع متن کمی بزرگتر می شد. با این حال، علیرغم این تفاوتها در ارتفاع خط، عنصر EditText
بدون توجه به منطقه مورد استفاده، همانطور که در تصویر زیر نشان داده شده است، اندازه یکسانی داشت:

EditText
که می تواند حاوی متنی از انگلیسی (en)، ژاپنی (ja) و برمه ای (my) باشد. ارتفاع EditText
یکسان است، حتی اگر این زبان ها دارای ارتفاع خطوط متفاوت از یکدیگر باشند. برای برنامههایی که Android 15 (سطح API 35) را هدف قرار میدهند، اکنون یک حداقل ارتفاع خط برای EditText
محفوظ است تا با فونت مرجع برای Locale مشخصشده مطابقت داشته باشد، همانطور که در تصویر زیر نشان داده شده است:

EditText
که می تواند حاوی متنی از انگلیسی (en)، ژاپنی (ja) و برمه ای (my) باشد. ارتفاع EditText
اکنون شامل فضایی برای قرار دادن ارتفاع خط پیشفرض برای فونتهای این زبانها میشود. در صورت نیاز، برنامه شما میتواند رفتار قبلی را با تعیین ویژگی useLocalePreferredLineHeightForMinimum
به false
بازیابی کند، و برنامه شما میتواند حداقل معیارهای عمودی سفارشی را با استفاده از setMinimumFontMetrics
API در Kotlin و Java تنظیم کند.
دوربین و رسانه
Android 15 تغییرات زیر را در رفتار دوربین و رسانه برای برنامه هایی که اندروید 15 یا بالاتر را هدف قرار می دهند، اعمال می کند.
محدودیت در درخواست فوکوس صوتی
以 Android 15(API 级别 35)为目标平台的应用必须是顶部应用或正在运行前台服务,才能请求音频焦点。如果应用在未满足上述任一要求的情况下尝试请求焦点,调用将返回 AUDIOFOCUS_REQUEST_FAILED
。
如需详细了解音频焦点,请参阅管理音频焦点。
محدودیتهای غیر SDK بهروزرسانی شد
Android 15 شامل لیست های به روز شده از رابط های غیر SDK محدود شده بر اساس همکاری با توسعه دهندگان اندروید و آخرین آزمایش داخلی است. در صورت امکان، قبل از اینکه رابطهای غیر SDK را محدود کنیم، مطمئن میشویم که جایگزینهای عمومی در دسترس هستند.
اگر برنامه شما اندروید 15 را هدف قرار نمی دهد، برخی از این تغییرات ممکن است فوراً روی شما تأثیر نگذارند. با این حال، در حالی که بسته به سطح API هدف برنامه شما ، ممکن است برنامه شما به برخی از رابطهای غیر SDK دسترسی داشته باشد، استفاده از هر روش یا فیلد غیر SDK همیشه خطر شکستن برنامه شما را بالا میبرد.
اگر مطمئن نیستید که برنامه شما از رابط های غیر SDK استفاده می کند، می توانید برنامه خود را آزمایش کنید تا متوجه شوید. اگر برنامه شما به رابطهای غیر SDK متکی است، باید برنامهریزی برای انتقال به جایگزینهای SDK را شروع کنید. با این وجود، میدانیم که برخی از برنامهها دارای موارد استفاده معتبر برای استفاده از رابطهای غیر SDK هستند. اگر نمی توانید جایگزینی برای استفاده از یک رابط غیر SDK برای یک ویژگی در برنامه خود پیدا کنید، باید یک API عمومی جدید درخواست کنید .
برای اطلاعات بیشتر در مورد تغییرات این نسخه از اندروید، بهروزرسانیهای محدودیتهای رابط غیر SDK در Android 15 را ببینید. برای کسب اطلاعات بیشتر در مورد رابط های غیر SDK به طور کلی، به محدودیت ها در رابط های غیر SDK مراجعه کنید.