تغییرات رفتار: برنامه هایی که اندروید 15 یا بالاتر را هدف قرار می دهند

مانند نسخه های قبلی، Android 15 شامل تغییرات رفتاری است که ممکن است بر برنامه شما تأثیر بگذارد. تغییرات رفتاری زیر منحصراً برای برنامه‌هایی اعمال می‌شود که Android 15 یا بالاتر را هدف قرار می‌دهند. اگر برنامه شما اندروید 15 یا بالاتر را هدف قرار می دهد، باید برنامه خود را تغییر دهید تا در صورت لزوم از این رفتارها به درستی پشتیبانی کند.

حتماً فهرستی از تغییرات رفتاری را نیز مرور کنید که بر همه برنامه‌های در حال اجرا در Android 15 بدون توجه به targetSdkVersion برنامه شما تأثیر می‌گذارد.

عملکرد اصلی

اندروید 15 قابلیت های اصلی مختلف سیستم اندروید را اصلاح یا گسترش می دهد.

تغییرات در خدمات پیش زمینه

ما در حال انجام تغییرات زیر در سرویس های پیش زمینه با اندروید 15 هستیم.

رفتار درنگ سرویس پیش زمینه همگام سازی داده ها

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]"

برای جلوگیری از مشکلات ناشی از این تغییر رفتار، می توانید یک یا چند مورد از موارد زیر را انجام دهید:

  1. از سرویس خود بخواهید روش جدید Service.onTimeout(int, int) را پیاده سازی کند. وقتی برنامه شما پاسخ تماس را دریافت کرد، مطمئن شوید که در عرض چند ثانیه stopSelf() تماس بگیرید. (اگر برنامه را فورا متوقف نکنید، سیستم خراب می شود.)
  2. مطمئن شوید که سرویس‌های dataSync برنامه شما در هر دوره 24 ساعته در مجموع بیش از 6 ساعت اجرا نمی‌شوند (مگر اینکه کاربر با برنامه تعامل داشته باشد و تایمر را بازنشانی کند).
  3. خدمات پیش زمینه dataSync فقط در نتیجه تعامل مستقیم کاربر شروع کنید. از آنجایی که برنامه شما هنگام شروع سرویس در پیش زمینه است، سرویس شما شش ساعت کامل پس از رفتن برنامه به پس‌زمینه است.
  4. به جای استفاده از سرویس پیش زمینه 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]"

برای جلوگیری از استثناء، می توانید یکی از موارد زیر را انجام دهید:

  1. از سرویس خود بخواهید روش جدید Service.onTimeout(int, int) را پیاده سازی کند. هنگامی که برنامه شما پاسخ تماس را دریافت کرد، مطمئن شوید که در عرض چند ثانیه stopSelf() تماس بگیرید. (اگر برنامه را فوراً متوقف نکنید، سیستم یک خرابی ایجاد می کند.)
  2. مطمئن شوید که سرویس‌های mediaProcessing برنامه شما در هر دوره ۲۴ ساعته در مجموع بیش از ۶ ساعت اجرا نمی‌شوند (مگر اینکه کاربر با برنامه تعامل داشته باشد و تایمر را بازنشانی کند).
  3. خدمات پیش زمینه mediaProcessing را فقط در نتیجه تعامل مستقیم کاربر شروع کنید. از آنجایی که هنگام شروع سرویس، برنامه شما در پیش زمینه است، سرویس شما شش ساعت کامل پس از رفتن برنامه به پس‌زمینه است.
  4. به جای استفاده از سرویس پیش زمینه 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 مجاز به راه اندازی انواع خدمات پیش زمینه زیر نیستند :

اگر یک گیرنده 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 权限,即使应用当前在后台运行,也可以启动前台服务(如免于后台启动限制中所述)。

如果应用以 Android 15 为目标平台,则此豁免范围现在更窄。现在,应用需要具有 SYSTEM_ALERT_WINDOW 权限,并且需要有一个可见的叠加窗口。也就是说,应用需要先启动 TYPE_APPLICATION_OVERLAY 窗口,并且该窗口需要处于可见状态,然后您才能启动前台服务。

如果您的应用尝试从后台启动前台服务,但不符合这些新要求(并且没有其他豁免情况),系统会抛出 ForegroundServiceStartNotAllowedException

如果您的应用声明了 SYSTEM_ALERT_WINDOW 权限并从后台启动前台服务,则可能会受到此变更的影响。如果您的应用获得了 ForegroundServiceStartNotAllowedException,请检查应用的操作顺序,并确保应用在尝试从后台启动前台服务之前已具有有效的叠加层窗口。您可以通过调用 View.getWindowVisibility() 检查叠加层窗口当前是否可见,也可以替换 View.onWindowVisibilityChanged(),以便在可见性发生变化时收到通知。

测试

如需测试应用的行为,您可以启用这些新限制,即使您的应用并未以 Android 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() سخت‌تر است:

    به عنوان مثال، زمانی که از شاخص آرگومان 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() به صورت ایستا به List API های جدید حل می کند. توابع پسوند در kotlin-stdlib .

    اگر برنامه‌ای دوباره با 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 شامل تغییراتی است که امنیت سیستم را ارتقا می‌دهد تا از برنامه‌ها و کاربران در برابر برنامه‌های مخرب محافظت کند.

فعالیت پس زمینه ایمن راه اندازی می شود

اندروید 15 از کاربران در برابر برنامه‌های مخرب محافظت می‌کند و با افزودن تغییراتی که مانع از نمایش برنامه‌های مخرب در پس‌زمینه، افزایش امتیازات و سوء استفاده از تعامل با کاربر می‌شود، کنترل بیشتری بر دستگاه‌هایشان می‌دهد. راه اندازی فعالیت های پس زمینه از Android 10 (سطح API 29) محدود شده است.

تغییرات دیگر

علاوه بر محدودیت برای تطبیق UID، این تغییرات دیگر نیز شامل می شود:

  • سازندگان PendingIntent تغییر دهید تا به طور پیش‌فرض راه‌اندازی‌های فعالیت پس‌زمینه را مسدود کنند . این به جلوگیری از ایجاد تصادفی یک PendingIntent توسط برنامه‌ها کمک می‌کند که ممکن است توسط عوامل مخرب مورد سوء استفاده قرار گیرد.
  • یک برنامه را در پیش زمینه نیاورید مگر اینکه فرستنده PendingIntent اجازه دهد . هدف این تغییر جلوگیری از سوء استفاده برنامه های مخرب از توانایی شروع فعالیت در پس زمینه است. به‌طور پیش‌فرض، برنامه‌ها اجازه ندارند پشته کار را به پیش‌زمینه بیاورند، مگر اینکه سازنده امتیازات راه‌اندازی فعالیت پس‌زمینه را اجازه دهد یا فرستنده دارای امتیازات راه‌اندازی فعالیت در پس‌زمینه باشد.
  • کنترل کنید که فعالیت برتر یک پشته وظیفه چگونه می تواند کار خود را به پایان برساند . اگر فعالیت برتر یک کار را تمام کند، Android به هر کاری که آخرین بار فعال بوده است برمی گردد. علاوه بر این، اگر یک فعالیت غیر برتر وظیفه خود را به پایان برساند، Android به صفحه اصلی باز خواهد گشت. پایان این فعالیت غیر برتر را مسدود نخواهد کرد.
  • از راه‌اندازی فعالیت‌های خودسرانه از برنامه‌های دیگر در وظیفه خود جلوگیری کنید . این تغییر با ایجاد فعالیت هایی که به نظر می رسد از سایر برنامه ها باشد، از فیشینگ کاربران توسط برنامه های مخرب جلوگیری می کند.
  • از در نظر گرفتن پنجره‌های غیرقابل مشاهده برای راه‌اندازی فعالیت پس‌زمینه جلوگیری کنید . این به جلوگیری از سوء استفاده برنامه های مخرب از راه اندازی فعالیت های پس زمینه برای نمایش محتوای ناخواسته یا مخرب به کاربران کمک می کند.
،

اندروید 15 از کاربران در برابر برنامه‌های مخرب محافظت می‌کند و با افزودن تغییراتی که مانع از نمایش برنامه‌های مخرب در پس‌زمینه، افزایش امتیازات و سوء استفاده از تعامل با کاربر می‌شود، کنترل بیشتری بر دستگاه‌هایشان می‌دهد. راه اندازی فعالیت های پس زمینه از Android 10 (سطح API 29) محدود شده است.

تغییرات دیگر

علاوه بر محدودیت برای تطبیق UID، این تغییرات دیگر نیز شامل می شود:

  • سازندگان PendingIntent تغییر دهید تا به طور پیش‌فرض راه‌اندازی‌های فعالیت پس‌زمینه را مسدود کنند . این به جلوگیری از ایجاد تصادفی یک PendingIntent توسط برنامه‌ها کمک می‌کند که ممکن است توسط عوامل مخرب مورد سوء استفاده قرار گیرد.
  • یک برنامه را در پیش زمینه نیاورید مگر اینکه فرستنده PendingIntent اجازه دهد . هدف این تغییر جلوگیری از سوء استفاده برنامه های مخرب از توانایی شروع فعالیت در پس زمینه است. به‌طور پیش‌فرض، برنامه‌ها اجازه ندارند پشته کار را به پیش‌زمینه بیاورند، مگر اینکه سازنده امتیازات راه‌اندازی فعالیت پس‌زمینه را اجازه دهد یا فرستنده دارای امتیازات راه‌اندازی فعالیت در پس‌زمینه باشد.
  • کنترل کنید که فعالیت برتر یک پشته وظیفه چگونه می تواند کار خود را به پایان برساند . اگر فعالیت برتر یک کار را تمام کند، Android به هر کاری که آخرین بار فعال بوده است برمی گردد. علاوه بر این، اگر یک فعالیت غیر برتر وظیفه خود را به پایان برساند، Android به صفحه اصلی باز خواهد گشت. پایان این فعالیت غیر برتر را مسدود نخواهد کرد.
  • از راه‌اندازی فعالیت‌های خودسرانه از برنامه‌های دیگر در وظیفه خود جلوگیری کنید . این تغییر با ایجاد فعالیت هایی که به نظر می رسد از سایر برنامه ها باشد، از فیشینگ کاربران توسط برنامه های مخرب جلوگیری می کند.
  • از در نظر گرفتن پنجره‌های غیرقابل مشاهده برای راه‌اندازی فعالیت پس‌زمینه جلوگیری کنید . این به جلوگیری از سوء استفاده برنامه های مخرب از راه اندازی فعالیت های پس زمینه برای نمایش محتوای ناخواسته یا مخرب به کاربران کمک می کند.

مقاصد امن تر

اندروید 15 اقدامات امنیتی اختیاری جدیدی را برای ایمن تر و قوی تر کردن مقاصد معرفی می کند. این تغییرات با هدف جلوگیری از آسیب پذیری های احتمالی و سوء استفاده از اهدافی است که می تواند توسط برنامه های مخرب مورد سوء استفاده قرار گیرد. دو پیشرفت اصلی برای امنیت intent در اندروید 15 وجود دارد:

  • Match target-intent-filters: مقاصدی که اجزای خاصی را هدف قرار می دهند باید دقیقاً با مشخصات فیلتر هدف هدف مطابقت داشته باشند. اگر قصدی برای راه‌اندازی فعالیت برنامه دیگری ارسال می‌کنید، مؤلفه هدف هدف باید با فیلترهای هدف اعلام‌شده فعالیت دریافت‌کننده هماهنگ شود.
  • Intent ها باید دارای عملکرد باشند: Intent های بدون عمل دیگر با فیلترهای intent مطابقت ندارند. این بدان معناست که مقاصد مورد استفاده برای شروع فعالیت ها یا خدمات باید دارای یک کنش به وضوح تعریف شده باشند.

برای بررسی اینکه برنامه شما چگونه به این تغییرات پاسخ می دهد، از StrictMode در برنامه خود استفاده کنید. برای مشاهده گزارش‌های دقیق درباره نقض استفاده Intent ، روش زیر را اضافه کنید:

کاتلین


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

جاوا


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

تجربه کاربری و رابط کاربری سیستم

اندروید 15 شامل تغییراتی است که برای ایجاد یک تجربه کاربری سازگارتر و بصری در نظر گرفته شده است.

ورودی پنجره تغییر می کند

در اندروید 15 دو تغییر مربوط به ورودی‌های پنجره وجود دارد: لبه به لبه به‌طور پیش‌فرض اعمال می‌شود و همچنین تغییراتی در پیکربندی وجود دارد، مانند پیکربندی پیش‌فرض نوارهای سیستم.

اجرای لبه به لبه

اگر برنامه اندروید 15 (سطح API 35) را هدف قرار دهد، برنامه‌ها به‌طور پیش‌فرض در دستگاه‌های دارای Android 15 لبه به لبه هستند.

برنامه ای که اندروید 14 را هدف قرار می دهد و در دستگاه اندروید 15 لبه به لبه نیست.


برنامه ای که اندروید 15 (سطح API 35) را هدف قرار می دهد و در دستگاه اندروید 15 لبه به لبه است. این برنامه بیشتر از کامپوننت های Material 3 Compose استفاده می کند که به طور خودکار inset ها را اعمال می کنند. این صفحه نمایش تحت تأثیر اجرای لبه به لبه اندروید 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 نشان می دهد.

برنامه ای که اندروید 14 را هدف قرار می دهد و در دستگاه اندروید 15 لبه به لبه نیست.
برنامه ای که اندروید 15 (سطح API 35) را هدف قرار می دهد و در دستگاه اندروید 15 لبه به لبه است. با این حال، بسیاری از عناصر در حال حاضر توسط نوار وضعیت، نوار ناوبری 3 دکمه یا بریدگی نمایشگر به دلیل اجرای لبه به لبه اندروید 15 پنهان شده اند. رابط کاربری پنهان شامل نوار برنامه بالای Material 2، دکمه‌های عمل شناور و موارد فهرست است.
برنامه‌ای که Android 15 (سطح API 35) را هدف قرار می‌دهد، لبه به لبه در دستگاه Android 15 است و ورودی‌ها را اعمال می‌کند تا رابط کاربری پنهان نشود.
چه باید بررسی کرد که آیا برنامه شما از قبل لبه به لبه است

اگر برنامه شما از قبل لبه به لبه است و از 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 های زیر منسوخ شده اند اما غیرفعال نشده اند:

API های زیر منسوخ و غیرفعال شده اند:

پیکربندی پایدار

اگر برنامه شما 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 کشیده شود.

در اندروید 15، فونت فشرده همچنان در سیستم باقی می‌ماند، بنابراین برنامه شما می‌تواند elegantTextHeight را روی false تنظیم کند تا رفتار قبلی را داشته باشد، اما بعید است که در نسخه‌های آینده پشتیبانی شود. بنابراین، اگر برنامه شما از اسکریپت های زیر پشتیبانی می کند: عربی، لائوس، میانمار، تامیل، گجراتی، کانادا، مالایالام، اودیا، تلوگو یا تایلندی، برنامه خود را با تنظیم elegantTextHeight روی true تست کنید.

رفتار elegantTextHeight برای برنامه‌هایی که Android 14 (سطح API 34) و پایین‌تر را هدف قرار می‌دهند.
رفتار elegantTextHeight برای برنامه هایی که اندروید 15 را هدف قرار می دهند.

عرض TextView برای اشکال حروف پیچیده تغییر می کند

در نسخه‌های قبلی اندروید، برخی از فونت‌های شکسته یا زبان‌هایی که شکل پیچیده‌ای دارند، ممکن است حروف را در ناحیه شخصیت قبلی یا بعدی بکشند. در برخی موارد، چنین حروفی در موقعیت آغاز یا پایان بریده می شدند. با شروع اندروید 15، یک TextView عرض را برای ترسیم فضای کافی برای چنین حروفی اختصاص می‌دهد و به برنامه‌ها اجازه می‌دهد تا برای جلوگیری از برش، بالشتک‌های اضافی را در سمت چپ درخواست کنند.

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

از آنجایی که افزودن پد سمت چپ ممکن است باعث ایجاد ناهماهنگی در طرح‌بندی‌های موجود شود، این پد به‌طور پیش‌فرض حتی برای برنامه‌هایی که Android 15 یا بالاتر را هدف قرار می‌دهند، اضافه نمی‌شود. با این حال، می‌توانید با فراخوانی setShiftDrawingOffsetForStartOverhang ، بالشتک اضافی برای جلوگیری از بریدن اضافه کنید.

مثال‌های زیر نشان می‌دهند که چگونه این تغییرات می‌توانند طرح‌بندی متن را برای برخی از فونت‌ها و زبان‌ها بهبود بخشند.

طرح بندی استاندارد برای متن انگلیسی با فونت شکسته. برخی از حروف بریده شده است. اینجا XML مربوطه است:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
طرح بندی برای همان متن انگلیسی با عرض و بالشتک اضافی. اینجا XML مربوطه است:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
طرح بندی استاندارد برای متن تایلندی. برخی از حروف بریده شده است. اینجا XML مربوطه است:

<TextView
    android:text="คอมพิวเตอร์" />
طرح بندی برای همان متن تایلندی با عرض و بالشتک اضافی. اینجا XML مربوطه است:

<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 مراجعه کنید.