مانند نسخههای قبلی، Android 15 شامل تغییرات رفتاری است که ممکن است بر برنامه شما تأثیر بگذارد. تغییرات رفتاری زیر منحصراً برای برنامههایی اعمال میشود که Android 15 یا بالاتر را هدف قرار میدهند. اگر برنامه شما Android 15 یا بالاتر را هدف قرار میدهد، باید برنامه خود را اصلاح کنید تا از این رفتارها بهدرستی پشتیبانی کند، درصورت قابل اجرا بودن.
حتماً فهرست تغییرات رفتاری را که بر همه برنامههای
اجراشده در Android 15 تأثیر میگذارد، صرفنظر از targetSdkVersion برنامهتان، مرور کنید.
عملکرد اصلی
Android 15 قابلیتهای اصلی مختلف سیستم Android را اصلاح یا گسترش میدهد.
تغییرات در سرویسهای پیشزمینهای
ما در حال انجام تغییرات زیر در سرویس های پیش زمینه با اندروید 15 هستیم.
- رفتار درنگ سرویس پیش زمینه همگام سازی داده ها
- نوع سرویس پیش زمینه پردازش رسانه جدید
- محدودیت در گیرنده های پخش
BOOT_COMPLETEDکه خدمات پیش زمینه را راه اندازی می کنند - محدودیتهایی برای شروع سرویسهای پیشزمینه در زمانی که برنامه دارای مجوز
SYSTEM_ALERT_WINDOWاست
رفتار درنگ سرویس پیش زمینه همگام سازی داده ها
Android 15 برای برنامههایی که Android 15 (سطح API 35) یا بالاتر را هدف قرار میدهند، رفتار مهلت زمانی جدیدی را برای dataSync معرفی میکند. این رفتار همچنین برای نوع جدید سرویس پیشزمینه mediaProcessing اعمال میشود.
این سیستم به سرویسهای dataSync یک برنامه اجازه میدهد در یک دوره 24 ساعته در مجموع 6 ساعت اجرا شوند، پس از آن سیستم سرویس سرویس در حال اجرا را متد Service.onTimeout(int, int) (معرفی شده در اندروید 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فقط در نتیجه تعامل مستقیم کاربر شروع کنید. از آنجایی که برنامه شما هنگام شروع سرویس در پیش زمینه است، سرویس شما شش ساعت کامل پس از رفتن برنامه به پسزمینه است. - به جای استفاده از سرویس پیش زمینه
dataSync، از یک API جایگزین استفاده کنید.
اگر سرویسهای پیشزمینه 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
نوع سرویس پیش زمینه پردازش رسانه جدید
اندروید 15 یک نوع سرویس پیش زمینه جدید، mediaProcessing را معرفی می کند. این نوع سرویس برای عملیاتی مانند رمزگذاری فایل های رسانه ای مناسب است. به عنوان مثال، یک برنامه رسانه ممکن است یک فایل صوتی را دانلود کند و قبل از پخش آن را به فرمت دیگری تبدیل کند. میتوانید از سرویس پیشزمینه mediaProcessing استفاده کنید تا مطمئن شوید که تبدیل حتی زمانی که برنامه در پسزمینه است ادامه مییابد.
این سیستم به سرویسهای mediaProcessing یک برنامه اجازه میدهد در مجموع 6 ساعت در یک دوره 24 ساعته اجرا شوند، پس از آن سیستم سرویس سرویس در حال اجرا را متد 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برنامه شما در هر دوره ۲۴ ساعته در مجموع بیش از ۶ ساعت اجرا نمیشوند (مگر اینکه کاربر با برنامه تعامل داشته باشد و تایمر را بازنشانی کند). - خدمات پیش زمینه
mediaProcessingرا فقط در نتیجه تعامل مستقیم کاربر شروع کنید. از آنجایی که هنگام شروع سرویس، برنامه شما در پیش زمینه است، سرویس شما شش ساعت کامل پس از رفتن برنامه به پسزمینه است. - به جای استفاده از سرویس پیش زمینه
mediaProcessing، از یک API جایگزین مانند WorkManager استفاده کنید.
اگر سرویسهای پیشزمینه 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(این محدودیت از اندروید 14 برایmicrophoneاعمال شده است)
اگر یک گیرنده BOOT_COMPLETED سعی کند هر یک از آن نوع خدمات پیش زمینه را راه اندازی کند، سیستم ForegroundServiceStartNotAllowedException پرتاب می کند.
تست کردن
برای آزمایش رفتار برنامهتان، میتوانید این محدودیتهای جدید را فعال کنید، حتی اگر برنامه شما اندروید 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
تغییرات مربوط به زمانهایی که برنامهها میتوانند وضعیت کلی حالت «مزاحم نشوید» را اصلاح کنند
Apps that target Android 15 (API level 35) and higher can no longer change the
global state or policy of Do Not Disturb (DND) on a device (either by modifying
user settings, or turning off DND mode). Instead, apps must contribute an
AutomaticZenRule, which the system combines into a global policy with the
existing most-restrictive-policy-wins scheme. Calls to existing APIs that
previously affected global state (setInterruptionFilter,
setNotificationPolicy) result in the creation or update of an implicit
AutomaticZenRule, which is toggled on and off depending on the call-cycle of
those API calls.
Note that this change only affects observable behavior if the app is calling
setInterruptionFilter(INTERRUPTION_FILTER_ALL) and expects that call to
deactivate an AutomaticZenRule that was previously activated by their owners.
تغییرات OpenJDK API
Android 15 به کار بازآوری کتابخانههای اصلی Android ادامه میدهد تا با ویژگیهای جدیدترین نسخههای OpenJDK LTS همسو شود.
برخیاز این تغییرات میتواند بر سازگاری برنامه برای برنامههایی که Android 15 (سطح میانای برنامهسازی کاربردی ۳۵) را هدف قرار میدهند تأثیر بگذارد:
تغییرات در میاناهای برنامهسازی کاربردی قالببندی رشته: درستیسنجی نمایه شناسه، پرچمها، عرض، و دقت اکنون هنگام استفاده از میاناهای برنامهسازی کاربردی
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در رشته قالب) برطرف کرد.تغییرات در نوع مؤلفه
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]);تغییرات در مدیریت کد زبان: هنگام استفاده از
LocaleAPI، کدهای زبان عبری، ییدیش، و اندونزیایی دیگر به شکلهای منسوخشده خود تبدیل نمیشوند (عبری:iw، ییدیش:ji، و اندونزیایی:in). هنگام مشخص کردن کد زبان برای یکی از این زبانها، بهجای آن از کدهای ISO 639-1 استفاده کنید (عبری:he، ییدیش:yi، و اندونزیایی:id).تغییرات در توالیهای عدد صحیح تصادفی: بهدنبال تغییرات ایجادشده در https://bugs.openjdk.org/browse/JDK-8301574، روشهای
Random.ints()زیر اکنون توالی متفاوتی از اعداد را نسبت به روشهایRandom.nextInt()برمیگردانند:بهطور کلی، این تغییر نباید منجر به رفتار مخرب برنامه شود، اما کد شما نباید انتظار داشته باشد که توالی تولیدشده از روشهای
Random.ints()باRandom.nextInt()مطابقت داشته باشد.
میانای برنامهسازی کاربردی جدید SequencedCollection میتواند بر سازگاری برنامهتان
پساز بهروزرسانی compileSdk در پیکربندی ساخت برنامهتان برای استفاده از
Android 15 (سطح میانای برنامهسازی کاربردی ۳۵) تأثیر بگذارد:
تداخل با توابع افزونه
MutableList.removeFirst()وMutableList.removeLast()درkotlin-stdlibنوع
Listدر جاوا به نوعMutableListدر Kotlin نگاشت میشود. چون میاناهای برنامهسازی کاربردیList.removeFirst()وList.removeLast()در Android 15 (سطح API ۳۵) معرفی شدهاند، کامپایلر Kotlin فراخوانیهای تابع، مثلاًlist.removeFirst()، را بهصورت ایستا بهجای توابع افزونه درkotlin-stdlibبه میاناهای برنامهسازی کاربردی جدیدListتبدیل میکند.اگر برنامهای با
compileSdkتنظیمشده روی35وminSdkتنظیمشده روی34یا پایینتر دوباره ترجمه شود و سپس برنامه در Android 14 و پایینتر اجرا شود، خطای زمان اجرا رخ میدهد:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;گزینه موجود
NewApilint در «افزایه Android Gradle» میتواند این موارد استفاده جدید از میانای برنامهسازی کاربردی را شناسایی کند../gradlew lintMainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()برای رفع خطاهای lint و استثنای زمان اجرا، فراخوانیهای تابع
removeFirst()وremoveLast()را میتوان بهترتیب باremoveAt(0)وremoveAt(list.lastIndex)در Kotlin جایگزین کرد. اگر از Android Studio Ladybug | 2024.1.3 یا بالاتر استفاده میکنید، این نسخه همچنین گزینه رفع سریع برای این خطاها ارائه میدهد.اگر گزینه lint غیرفعال شده است،
@SuppressLint("NewApi")وlintOptions { disable 'NewApi' }را بردارید.تداخل با روشهای دیگر در Java
روشهای جدیدی به انواع موجود اضافه شده است، برای مثال،
ListوDeque. این روشهای جدید ممکن است با روشهایی که نام و نوع متغیر مستقل یکسانی در دیگر میاناها و کلاسها دارند سازگار نباشد. درصورت تداخل امضای روش با ناسازگاری، کامپایلرjavacخطای زمان ساخت را خروجی میدهد. برای مثال:نمونه خطای ۱:
javac MyList.javaMyList.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نمونه خطا ۲:
javac MyList.javaMyList.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خطای نمونه ۳:
javac MyList.javaMyList.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(); }
امنیت
Android 15 شامل تغییراتی است که امنیت سیستم را ارتقا میدهد تا به محافظت از برنامهها و کاربران دربرابر برنامههای مخرب کمک کند.
نسخههای محدودشده «امنیت لایه انتقال»
Android 15 استفاده از نسخههای ۱.۰ و ۱.۱ «امنیت لایه انتقال» (TLS) را محدود میکند. این نسخهها قبلاً در Android منسوخ شده بودند، اما اکنون برای برنامههایی که Android 15 را هدف قرار میدهند غیرمجاز هستند.
راهاندازیهای فعالیت پسزمینه ایمنشده
Android 15 protects users from malicious apps and gives them more control over their devices by adding changes that prevent malicious background apps from bringing other apps to the foreground, elevating their privileges, and abusing user interaction. Background activity launches have been restricted since Android 10 (API level 29).
Other changes
- Change
PendingIntentcreators to block background activity launches by default. This helps prevent apps from accidentally creating aPendingIntentthat could be abused by malicious actors. - Don't bring an app to the foreground unless the
PendingIntentsender allows it. This change aims to prevent malicious apps from abusing the ability to start activities in the background. By default, apps are not allowed to bring the task stack to the foreground unless the creator allows background activity launch privileges or the sender has background activity launch privileges. - Control how the top activity of a task stack can finish its task. If the top activity finishes a task, Android will go back to whichever task was last active. Moreover, if a non-top activity finishes its task, Android will go back to the home screen; it won't block the finish of this non-top activity.
- Prevent launching arbitrary activities from other apps into your own task. This change prevents malicious apps from phishing users by creating activities that appear to be from other apps.
- Block non-visible windows from being considered for background activity launches. This helps prevent malicious apps from abusing background activity launches to display unwanted or malicious content to users.
مقصودهای ایمنتر
Android 15 StrictMode را برای
قصدها معرفی میکند.
برای دیدن گزارشهای دقیق درباره نقضهای استفاده از Intent، از روش زیر استفاده کنید:
کاتلین
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
جاوا
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
تجربه کاربری و واسط کاربر سیستم
Android 15 شامل برخی تغییرات است که هدف آنها ایجاد تجربه کاربری منسجمتر و شهودیتر است.
تغییرات درج پنجره
در اندروید 15 دو تغییر مربوط به ورودیهای پنجره وجود دارد: لبه به لبه بهطور پیشفرض اعمال میشود و همچنین تغییراتی در پیکربندی وجود دارد، مانند پیکربندی پیشفرض نوارهای سیستم.
اجرای لبه به لبه
Apps are edge-to-edge by default on devices running Android 15 if the app is targeting Android 15 (API level 35).
This is a breaking change that might negatively impact your app's UI. The changes affect the following UI areas:
- Gesture handle navigation bar
- Transparent by default.
- Bottom offset is disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColorandR.attr#navigationBarColorare deprecated and don't affect gesture navigation.setNavigationBarContrastEnforcedandR.attr#navigationBarContrastEnforcedcontinue to have no effect on gesture navigation.
- 3-button navigation
- Opacity set to 80% by default, with color possibly matching the window background.
- Bottom offset disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColorandR.attr#navigationBarColorare set to match the window background by default. The window background must be a color drawable for this default to apply. This API is deprecated but continues to affect 3-button navigation.setNavigationBarContrastEnforcedandR.attr#navigationBarContrastEnforcedis true by default, which adds an 80% opaque background across 3-button navigation.
- Status bar
- Transparent by default.
- The top offset is disabled so content draws behind the status bar unless insets are applied.
setStatusBarColorandR.attr#statusBarColorare deprecated and have no effect on Android 15.setStatusBarContrastEnforcedandR.attr#statusBarContrastEnforcedare deprecated but still have an effect on Android 15.
- Display cutout
layoutInDisplayCutoutModeof non-floating windows must beLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS.SHORT_EDGES,NEVER, andDEFAULTare interpreted asALWAYSso that users don't see a black bar caused by the display cutout and appear edge-to-edge.
The following example shows an app before and after targeting Android 15 (API level 35), and before and after applying insets. This example is not comprehensive, this might appear differently on Android Auto.
What to check if your app is already edge-to-edge
If your app is already edge-to-edge and applies insets, you are mostly unimpacted, except in the following scenarios. However, even if you think you aren't impacted, we recommend you test your app.
- You have a non-floating window, such as an
Activitythat usesSHORT_EDGES,NEVERorDEFAULTinstead ofLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. If your app crashes on launch, this might be due to your splashscreen. You can either upgrade the core splashscreen dependency to 1.2.0-alpha01 or later or setwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always. - There might be lower-traffic screens with occluded UI. Verify these
less-visited screens don't have occluded UI. Lower-traffic screens include:
- Onboarding or sign-in screens
- Settings pages
What to check if your app is not already edge-to-edge
If your app is not already edge-to-edge, you are most likely impacted. In addition to the scenarios for apps that are already edge-to-edge, you should consider the following:
- If your app uses Material 3 Components (
androidx.compose.material3) in compose, such asTopAppBar,BottomAppBar, andNavigationBar, these components are likely not impacted because they automatically handle insets. - If your app is using Material 2 Components (
androidx.compose.material) in Compose, these components don't automatically handle insets. However, you can get access to the insets and apply them manually. In androidx.compose.material 1.6.0 and later, use thewindowInsetsparameter to apply the insets manually forBottomAppBar,TopAppBar,BottomNavigation, andNavigationRail. Likewise, use thecontentWindowInsetsparameter forScaffold. - If your app uses views and Material Components
(
com.google.android.material), most views-based Material Components such asBottomNavigationView,BottomAppBar,NavigationRailView, orNavigationView, handle insets and require no additional work. However, you need to addandroid:fitsSystemWindows="true"if usingAppBarLayout. - For custom composables, apply the insets manually as padding. If your
content is within a
Scaffold, you can consume insets using theScaffoldpadding values. Otherwise, apply padding using one of theWindowInsets. - If your app is using views and
BottomSheet,SideSheetor custom containers, apply padding usingViewCompat.setOnApplyWindowInsetsListener. ForRecyclerView, apply padding using this listener and also addclipToPadding="false".
What to check if your app must offer custom background protection
If your app must offer custom background protection to 3-button navigation or
the status bar, your app should place a composable or view behind the system bar
using WindowInsets.Type#tappableElement() to get the 3-button
navigation bar height or WindowInsets.Type#statusBars.
Additional edge-to-edge resources
See the Edge to Edge Views and Edge to Edge Compose guides for additional considerations on applying insets.
Deprecated APIs
The following APIs are deprecated but not disabled:
R.attr#enforceStatusBarContrastR.attr#navigationBarColor(for 3 button navigation, with 80% alpha)Window#isStatusBarContrastEnforcedWindow#setNavigationBarColor(for 3 button navigation, with 80% alpha)Window#setStatusBarContrastEnforced
The following APIs are deprecated and disabled:
R.attr#navigationBarColor(for gesture navigation)R.attr#navigationBarDividerColorR.attr#statusBarColorWindow#setDecorFitsSystemWindowsWindow#getNavigationBarColorWindow#getNavigationBarDividerColorWindow#getStatusBarColorWindow#setNavigationBarColor(for gesture navigation)Window#setNavigationBarDividerColorWindow#setStatusBarColor
پیکربندی پایدار
If your app targets Android 15 (API level 35) or higher, Configuration no
longer excludes the system bars. If you use the screen size in the
Configuration class for layout calculation, you should replace it with better
alternatives like an appropriate ViewGroup, WindowInsets, or
WindowMetricsCalculator depending on your need.
Configuration has been available since API 1. It is typically obtained from
Activity.onConfigurationChanged. It provides information like window density,
orientation, and sizes. One important characteristic about the window sizes
returned from Configuration is that it previously excluded the system bars.
The configuration size is typically used for resource selection, such as
/res/layout-h500dp, and this is still a valid use case. However, using it for
layout calculation has always been discouraged. If you do so, you should move
away from it now. You should replace the use of Configuration with something
more suitable depending on your use case.
If you use it to calculate the layout, use an appropriate ViewGroup, such as
CoordinatorLayout or ConstraintLayout. If you use it to determine the height
of the system navbar, use WindowInsets. If you want to know the current size
of your app window, use computeCurrentWindowMetrics.
The following list describes the fields affected by this change:
Configuration.screenWidthDpandscreenHeightDpsizes no longer exclude the system bars.Configuration.smallestScreenWidthDpis indirectly affected by changes toscreenWidthDpandscreenHeightDp.Configuration.orientationis indirectly affected by changes toscreenWidthDpandscreenHeightDpon close-to-square devices.Display.getSize(Point)is indirectly affected by the changes inConfiguration. This was deprecated beginning in API level 30.Display.getMetrics()has already worked like this since API level 33.
مشخصه elegantTextHeight بهطور پیشفرض روی true تنظیم شده است
برای برنامههایی که Android 15 (سطح API 35) را هدف قرار میدهند، ویژگی elegantTextHeight TextView بهطور پیشفرض true میشود و فونت فشردهای را که بهطور پیشفرض استفاده میشود با برخی از اسکریپتهایی که معیارهای عمودی بزرگی دارند با فونتی که بسیار خواناتر است جایگزین میکند. فونت فشرده برای جلوگیری از شکستن طرحبندیها معرفی شد. Android 13 (سطح API 33) از بسیاری از این شکستگیها جلوگیری میکند و به طرح متن اجازه میدهد تا ارتفاع عمودی را با استفاده از ویژگی fallbackLineSpacing کشیده شود.
در اندروید 15، فونت فشرده همچنان در سیستم باقی میماند، بنابراین برنامه شما میتواند elegantTextHeight را روی false تنظیم کند تا رفتار قبلی را داشته باشد، اما بعید است که در نسخههای آینده پشتیبانی شود. بنابراین، اگر برنامه شما از اسکریپت های زیر پشتیبانی می کند: عربی، لائوس، میانمار، تامیل، گجراتی، کانادا، مالایالام، اودیا، تلوگو یا تایلندی، برنامه خود را با تنظیم elegantTextHeight روی true تست کنید.

elegantTextHeight برای برنامههایی که Android 14 (سطح API 34) و پایینتر را هدف قرار میدهند. 
elegantTextHeight برای برنامه هایی که اندروید 15 را هدف قرار می دهند.تغییرات عرض TextView برای شکلهای پیچیده حروف
In previous versions of Android, some cursive fonts or languages that have
complex shaping might draw the letters in the previous or next character's area.
In some cases, such letters were clipped at the beginning or ending position.
Starting in Android 15, a TextView allocates width for drawing enough space
for such letters and allows apps to request extra paddings to the left to
prevent clipping.
Because this change affects how a TextView decides the width, TextView
allocates more width by default if the app targets Android 15 (API level 35) or
higher. You can enable or disable this behavior by calling the
setUseBoundsForWidth API on TextView.
Because adding left padding might cause a misalignment for existing layouts, the
padding is not added by default even for apps that target Android 15 or higher.
However, you can add extra padding to preventing clipping by calling
setShiftDrawingOffsetForStartOverhang.
The following examples show how these changes can improve text layout for some fonts and languages.
<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 تغییرات زیر را در رفتار دوربین و رسانه برای برنامههایی که Android 15 یا بالاتر را هدف قرار میدهند ایجاد میکند.
محدودیتهای درخواست تمرکز صوتی
Apps that target Android 15 (API level 35) must be the top app or running a
foreground service in order to request audio focus. If an app
attempts to request focus when it does not meet one of these requirements, the
call returns AUDIOFOCUS_REQUEST_FAILED.
You can learn more about audio focus at Manage audio focus.
محدودیتهای غیرکیت توسعه نرمافزار بهروز شد
Android 15 شامل فهرستهای بهروزشدهای از میاناهای غیرکیت توسعه نرمافزار محدودشده است که براساس همکاری با توسعهدهندگان Android و جدیدترین آزمایشهای داخلی تهیه شدهاند. هرزمان ممکن باشد، پیشاز محدود کردن میاناهای غیرکیت توسعه نرمافزار، مطمئن میشویم که جایگزینهای عمومی دردسترس باشند.
اگر برنامه شما Android 15 را هدف قرار نمیدهد، برخیاز این تغییرات ممکن است فوراً بر شما تأثیر نگذارد. بااینحال، اگرچه ممکن است برنامهتان بتواند به برخیاز میاناهای غیر کیت توسعه نرمافزار دسترسی پیدا کند بسته به سطح میانای برنامهسازی کاربردی هدف برنامهتان، استفاده از هرگونه روش یا فیلد غیر کیت توسعه نرمافزار همیشه خطر بالایی برای خراب کردن برنامهتان دارد.
اگر مطمئن نیستید که برنامهتان از میاناهای غیرکیت توسعه نرمافزار استفاده میکند یا نه، میتوانید برنامهتان را آزمایش کنید تا متوجه شوید. اگر برنامهتان به میاناهای غیر SDK متکی است، باید برنامهریزی برای انتقال به جایگزینهای SDK را شروع کنید. بااینحال، میدانیم که برخیاز برنامهها موارد استفاده معتبری برای استفاده از میاناهای غیرکیت توسعه نرمافزار دارند. اگر نمیتوانید جایگزینی برای استفاده از میانای غیرکیت توسعه نرمافزار برای ویژگیای در برنامهتان پیدا کنید، باید درخواست میانای برنامهسازی کاربردی عمومی جدیدی بدهید.
برای اطلاعات بیشتر در مورد تغییرات این نسخه از اندروید، بهروزرسانیهای محدودیتهای رابط غیر SDK در Android 15 را ببینید. برای کسب اطلاعات بیشتر در مورد رابط های غیر SDK به طور کلی، به محدودیت ها در رابط های غیر SDK مراجعه کنید.