التغييرات في السلوك: التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث

كما هو الحال في الإصدارات السابقة، يتضمّن Android 15 تغييرات في السلوك قد تؤثّر في السلوك تطبيقك. تنطبق التغييرات التالية في السلوك حصريًا على التطبيقات التي يستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث، عليك تعديل تطبيقك للتوافق مع هذه السلوكيات بشكل صحيح، السارية.

تأكد أيضًا من مراجعة قائمة تغييرات السلوك التي تؤثر في جميع التطبيقات يعمل بنظام التشغيل Android 15 بصرف النظر عن targetSdkVersion في تطبيقك.

الوظيفة الأساسية

يعمل Android 15 على تعديل الإمكانات الأساسية المتنوعة لنظام Android أو توسيعها.

التغييرات على الخدمات التي تعمل في المقدّمة

We are making the following changes to foreground services with Android 15.

Data sync foreground service timeout behavior

يوفِّر Android 15 سلوكًا جديدًا للمهلة في dataSync بشأن استهداف التطبيقات. نظام التشغيل Android 15 (المستوى 35) أو الإصدارات الأحدث وينطبق هذا السلوك أيضًا على mediaProcessing نوع الخدمة التي تعمل في المقدّمة:

يسمح النظام بتشغيل خدمات dataSync للتطبيق لمدة 6 ساعات إجمالاً. خلال 24 ساعة، وبعدها يستدعي النظام طريقة 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]"

لتجنُّب حدوث مشاكل في هذا التغيير في السلوك، يمكنك إجراء واحد أو أكثر من الإجراءات التالي:

  1. يجب أن تنفِّذ خدمتك طريقة Service.onTimeout(int, int) الجديدة. عندما يتلقّى تطبيقك معاودة الاتصال، احرص على الاتصال بـ stopSelf() خلال بضع ثوانٍ. (إذا لم توقف التطبيق على الفور، فسينشئ النظام إخفاقًا).
  2. عليك التأكّد من عدم تشغيل خدمات dataSync في تطبيقك لأكثر من إجمالي 6 ساعات في أي فترة 24 ساعة (ما لم يتفاعل المستخدم مع التطبيق، إعادة تعيين المؤقت).
  3. بدء dataSync خدمة تعمل في المقدّمة نتيجة طلب مستخدم مباشر التفاعل لأنّ تطبيقك يعمل في المقدّمة عند بدء تشغيل الخدمة ستستغرق الخدمة ست ساعات كاملة بعد انتقال التطبيق إلى الخلفية.
  4. بدلاً من استخدام خدمة تعمل في المقدّمة من "dataSync"، يمكنك استخدام واجهة برمجة تطبيقات بديلة.

إذا تم تشغيل خدمات dataSync التي تعمل في المقدّمة في تطبيقك لمدة 6 ساعات خلال آخر 24، لا يمكنك بدء خدمة "dataSync" أخرى تعمل في المقدّمة ما لم. وضع تطبيقك في المقدّمة (ما يؤدي إلى إعادة ضبط الموقّت). إذا حاولت بدء خدمة dataSync أخرى تعمل في المقدّمة، سيطرح النظام ForegroundServiceStartNotAllowedException مع رسالة خطأ، مثل "تم استنفاد الحدّ الزمني للخدمة التي تعمل في المقدّمة اكتب dataSync".

الاختبار

لاختبار سلوك تطبيقك، يمكنك تفعيل مهلات مزامنة البيانات حتى إذا كان تطبيقك. لا يستهدف نظام التشغيل Android 15 (ما دام التطبيق يعمل على الإصدار 15 من نظام التشغيل Android) الجهاز). لتفعيل المهلات، شغِّل الأمر 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

New media processing foreground service type

يقدّم Android 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 في تطبيقك لأكثر من إِجْمَالِي 6 ساعات في أي فترة 24 ساعة (ما لم يتفاعل المستخدم مع التطبيق، إعادة تعيين المؤقت).
  3. بدء mediaProcessing خدمة تعمل في المقدّمة نتيجة طلب مستخدم مباشر التفاعل لأنّ تطبيقك يعمل في المقدّمة عند بدء تشغيل الخدمة ستستغرق الخدمة ست ساعات كاملة بعد انتقال التطبيق إلى الخلفية.
  4. بدلاً من استخدام خدمة تعمل في المقدّمة mediaProcessing، يمكنك استخدام خدمة بديلة واجهة برمجة التطبيقات، مثل WorkManager.

إذا تم تشغيل خدمات "mediaProcessing" التي تعمل في المقدّمة في تطبيقك لمدة 6 ساعات في آخر 24 يومًا، لا يمكنك بدء خدمة "mediaProcessing" أخرى تعمل في المقدّمة ما لم. عرض المستخدِم تطبيقك في المقدّمة (ما يؤدي إلى إعادة ضبط الموقّت) إذا كنت محاولة بدء خدمة mediaProcessing أخرى تعمل في المقدّمة، سيطرح النظام ForegroundServiceStartNotAllowedException مع رسالة خطأ، مثل "تم استنفاد الحدّ الزمني للخدمة التي تعمل في المقدّمة type 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

Restrictions on BOOT_COMPLETED broadcast receivers launching foreground services

هناك قيود جديدة على إطلاق أجهزة استقبال بث BOOT_COMPLETED. والخدمات التي تعمل في المقدّمة. لا يُسمح لأجهزة استقبال BOOT_COMPLETED بتشغيل الأنواع التالية من الخدمات التي تعمل في المقدّمة:

إذا حاول مستقبل BOOT_COMPLETED بدء أيّ من هذه الأنواع من الخدمات التي تعمل في المقدّمة، يُرسِل النظام الخطأ ForegroundServiceStartNotAllowedException.

الاختبار

لاختبار سلوك تطبيقك، يمكنك تفعيل هذه القيود الجديدة حتى إذا كان تطبيقك لا يستهدف الإصدار 15 من Android (ما دام التطبيق يعمل على جهاز يعمل بالإصدار 15 من Android). شغِّل الأمر 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

Restrictions on starting foreground services while an app holds the SYSTEM_ALERT_WINDOW permission

في السابق، إذا كان لدى أحد التطبيقات إذن SYSTEM_ALERT_WINDOW، يمكن تشغيله. خدمة تعمل في المقدّمة حتى لو كان التطبيق في الخلفية حاليًا (كما المذكورة في الاستثناءات من قيود البدء في الخلفية).

إذا كان التطبيق يستهدف الإصدار 15 من نظام التشغيل Android، سيصبح هذا الإعفاء أقل الآن. يحتاج التطبيق الآن إلى أن يكون لديك إذن SYSTEM_ALERT_WINDOW وأن يكون لديك أيضًا تراكب مرئي نافذة. أي أنّ التطبيق يحتاج أولاً إلى تشغيل نافذة TYPE_APPLICATION_OVERLAY والنافذة أن يكون مرئيًا قبل بدء خدمة تعمل في المقدّمة.

إذا كان تطبيقك يحاول بدء خدمة تعمل في المقدّمة من الخلفية بدون استيفاء هذه المتطلبات الجديدة (وليس لديها بعض الإعفاءات الأخرى)، عمليات طرح النظام ForegroundServiceStartNotAllowedException.

إذا استخدم تطبيقك إذن SYSTEM_ALERT_WINDOW ويشغِّل الخدمات التي تعمل في المقدّمة من الخلفية، فقد يتأثر بذلك التغيير. إذا حصل تطبيقك على ForegroundServiceStartNotAllowedException، تحقَّق من ترتيب عمليات التطبيق والتأكّد من أنّ التطبيق نشط قبل محاولة بدء خدمة تعمل في المقدّمة من الخلفية. يمكنك التحقق مما إذا كانت نافذة التراكب مرئية حاليًا من خلال الاتصال بـ View.getWindowVisibility() أو يمكن أن تلغي View.onWindowVisibilityChanged() إلى تلقّي إشعارات كلما تغيّر مستوى الرؤية.

الاختبار

لاختبار سلوك تطبيقك، يمكنك تفعيل هذه القيود الجديدة حتى إذا كان لا يستهدف التطبيق نظام التشغيل Android 15 (ما دام التطبيق يعمل على الإصدار 15 من نظام التشغيل Android) الجهاز). لتفعيل هذه القيود الجديدة عند بدء الخدمات التي تعمل في المقدّمة في الخلفية، شغِّل الأمر adb التالي:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

تغييرات على الوقت الذي يمكن للتطبيقات فيه تعديل الحالة العامة لوضع "عدم الإزعاج"

لم يعُد بإمكان التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android تغيير الحالة أو السياسة العامة لميزة عدم الإزعاج (DND) على جهاز (إما من خلال تعديل إعدادات المستخدم أو إيقاف وضع DND). بدلاً من ذلك، يجب أن تساهم التطبيقات في السمة AutomaticZenRule، التي يدمجها النظام في سياسة عالمية مع المخطط الحالي الأكثر تقييدًا-policy-wins. إنّ الطلبات الموجّهة إلى واجهات برمجة التطبيقات الحالية والتي كانت تأثرت سابقًا بالحالة العامة (setInterruptionFilter, setNotificationPolicy) تؤدي إلى إنشاء أو تعديل AutomaticZenRuleضمنية، يتم إيقافها وإيقافها بناءً على دورة طلب البيانات من واجهة برمجة التطبيقات هذه.

يُرجى العلم بأنّ هذا التغيير لا يؤثّر إلا في السلوك الملحوظ فقط إذا كان التطبيق يطلب setInterruptionFilter(INTERRUPTION_FILTER_ALL) ويتوقّع أن تؤدي هذه المكالمة إلى إيقاف AutomaticZenRule الذي سبق أن فعَّله مالكو التطبيق.

التغييرات في واجهة برمجة التطبيقات OpenJDK

يواصل Android 15 العمل على إعادة تحميل مكتبات Android الأساسية للتوافق مع المتطلبات الأخرى. مع الميزات المتوفّرة في أحدث إصدارات OpenJDK LTS.

قد تؤثّر بعض هذه التغييرات في توافق التطبيقات المستهدَفة. Android 15 (المستوى 35):

  • التغييرات في واجهات برمجة التطبيقات لتنسيق السلسلة: التحقق من صحة فهرس الوسيطات والعلامات وأصبحت الدقة أكثر صرامة الآن عند استخدام ما يلي واجهات برمجة التطبيقات 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، لم تعُد رموز اللغات للعبرية واليديشية والإندونيسية محوَّلة إلى الأشكال القديمة (العبرية: iw، واليديشية: ji، والإندونيسية: in). عند تحديد رمز اللغة لإحدى هذه اللغات، استخدم الرموز من ISO 639-1 بدلاً من ذلك (العبرية: he، واليديشية: yi، والإندونيسية: id).

  • التغييرات في تسلسلات Intent العشوائية: وفقًا للتغييرات التي تم إجراؤها في https://bugs.openjdk.org/Browse/JDK-8301574، ما يلي تُرجع Random.ints() طريقة الآن تسلسل أرقام مختلفًا عن تُجري طرق Random.nextInt() ما يلي:

    بشكل عام، لا ينبغي أن يؤدي هذا التغيير إلى تعطيل سلوك، ولكن تطبيقك في الرمز البرمجي، لن يتوقع التسلسل الذي تم إنشاؤه من Random.ints() طريقة تطابق Random.nextInt().

يمكن أن تؤثر واجهة برمجة التطبيقات SequencedCollection الجديدة في توافق تطبيقك بعد تحديث compileSdk في إعدادات إصدار تطبيقك لاستخدام نظام التشغيل Android 15 (المستوى 35):

  • التلازمة مع MutableList.removeFirst() وظائف إضافة MutableList.removeLast() في kotlin-stdlib

    يتم ربط النوع List في Java بالنوع MutableList في Kotlin. وذلك لأنّ واجهتَي برمجة التطبيقات List.removeFirst() وList.removeLast() تم تقديمها في نظام التشغيل Android 15 (المستوى 35)، وهو المحول البرمجي لـ Kotlin لحل استدعاءات الدوال، على سبيل المثال list.removeFirst()، بشكل ثابت إلى واجهات برمجة تطبيقات List جديدة بدلاً من دوال الإضافة في kotlin-stdlib.

    في حال إعادة تجميع التطبيق مع ضبط compileSdk على 35 وminSdk على 34 أو أقل، وبعد ذلك يكون التطبيق يعمل على الإصدار 14 من نظام التشغيل Android والإصدارات الأقدم، وهو وقت تشغيل حدث خطأ:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    يمكن لخيار وحدة Lint NewApi الحالي في المكوّن الإضافي لنظام Gradle المتوافق مع Android اكتشاف هذه الأخطاء الاستخدامات الجديدة لواجهة برمجة التطبيقات.

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    لإصلاح استثناء وقت التشغيل وأخطاء الوبر، يمكن لـ removeFirst() يمكن استبدال استدعاءات الدوال removeLast() بـ removeAt(0) removeAt(list.lastIndex) على التوالي بلغة Kotlin. إذا كنت تستخدم الدعسوقة في "استوديو Android" | 2024.1.3 أو إصدار أحدث، يوفّر أيضًا حلّاً سريعًا. الخاص بهذه الأخطاء.

    ننصحك بإزالة @SuppressLint("NewApi") وlintOptions { disable 'NewApi' } إذا تم إيقاف خيار Lint.

  • التصادم مع الطرق الأخرى في Java

    تمّت إضافة طرق جديدة إلى الأنواع الحالية، مثل 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.getLast();
    }
    

الأمان

يتضمّن Android 15 تغييرات تعزّز أمان النظام للمساعدة في حماية التطبيقات. والمستخدمين من التطبيقات الضارة.

عمليات تشغيل الأنشطة الآمنة في الخلفية

يحمي Android 15 المستخدمين من التطبيقات الضارة ويمنحهم إمكانية تحكُّم أكبر في أجهزته عن طريق إضافة تغييرات تمنع تطبيقات الخلفية الضارة من عرض تطبيقات أخرى في المقدّمة، ورفع امتيازاتها وإساءة استخدامها تفاعل المستخدم. تم حظر عمليات إطلاق الأنشطة في الخلفية منذ Android 10 (المستوى 29)

منع التطبيقات التي لا تتطابق مع المعرّف الفريد الأعلى في الحزمة من تشغيل الأنشطة

يمكن للتطبيقات الضارة تشغيل نشاط تطبيق آخر ضمن المهمة نفسها، ثم تداخلها فوقه، ما يخلق الوهم بأنّها هذا التطبيق. ويتجاوز هجوم "اختراق المهام" الحالي القيود المفروضة على التشغيل في الخلفية لأنّه يتم تنفيذ كل ذلك ضمن المهمة المرئية نفسها. وللتخفيف من هذه المخاطر، يضيف Android 15 علامة تمنع تشغيل التطبيقات التي لا تتطابق مع المعرّف الفريد الأعلى في الحزمة والأنشطة السابقة. للموافقة على جميع أنشطة تطبيقك، عدِّل السمة allowCrossUidActivitySwitchFromBelow في ملف AndroidManifest.xml الخاص بتطبيقك:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

تكون إجراءات الأمان الجديدة نشطة في حال استيفاء جميع الشروط التالية:

  • يستهدف التطبيق مرحلة الإطلاق الإصدار 15 من نظام التشغيل Android.
  • يستهدف التطبيق أعلى حزمة المهام نظام التشغيل Android 15.
  • أي نشاط مرئي تم تفعيل عناصر الحماية الجديدة له

في حال تفعيل تدابير الأمان، قد تعود التطبيقات إلى الشاشة الرئيسية بدلاً من التطبيق الأخير المرئي، إذا أنهت مهمتها.

تغييرات أخرى

بالإضافة إلى القيود المفروضة على مطابقة المعرّف الفريد، تم أيضًا تضمين التغييرات التالية:

  • تغيير PendingIntent صانع محتوى إلى حظر عمليات إطلاق الأنشطة في الخلفية من خلال التلقائية. ويساعد هذا في منع التطبيقات من إنشاء PendingIntent الذي يمكن أن تسيء إليه الجهات المسيئة.
  • لا تعرض تطبيقًا في المقدّمة ما لم يسمح PendingIntent المُرسِل بذلك. يهدف هذا التغيير إلى منع التطبيقات الضارة من إساءة استخدام والقدرة على بدء الأنشطة في الخلفية. بشكلٍ افتراضي، لا تكون التطبيقات يُسمح له بعرض حزمة المهام في المقدّمة ما لم يسمح صانع المحتوى امتيازات تشغيل النشاط في الخلفية أو لدى المُرسِل نشاط في الخلفية امتيازات الإطلاق.
  • التحكّم في كيفية إنهاء النشاط الرئيسي في حزمة المهام لمهمته إذا كانت عند الانتهاء من تحديد "أهم نشاط"، سيعود Android إلى أي مهمة آخر نشاط. علاوة على ذلك، إذا أنهى نشاط غير بارز مهمته، فسيجري Android والعودة إلى الشاشة الرئيسية؛ لن يحجب انتهاء هذا العنصر الأخرى.
  • منع إطلاق أنشطة عشوائية من تطبيقات أخرى على تطبيقك المهمة. ويمنع هذا التغيير التطبيقات الضارة من التصيُّد الاحتيالي للمستخدمين من خلال إنشاء أنشطة تبدو وكأنها من تطبيقات أخرى.
  • حظر النوافذ غير المرئية من النظر في النشاط في الخلفية عمليات الإطلاق. يساعد ذلك على منع التطبيقات الضارة من إساءة استخدام الخلفية. نشاط عرض محتوى غير مرغوب فيه أو ضار للمستخدمين.

نوايا أكثر أمانًا

Android 15 introduces new optional security measures to make intents safer and more robust. These changes are aimed at preventing potential vulnerabilities and misuse of intents that can be exploited by malicious apps. There are two main improvements to the security of intents in Android 15:

  • Match target intent-filters: Intents that target specific components must accurately match the target's intent-filter specifications. If you send an intent to launch another app's activity, the target intent component needs to align with the receiving activity's declared intent-filters.
  • Intents must have actions: Intents without an action will no longer match any intent-filters. This means that intents used to start activities or services must have a clearly defined action.

In order to check how your app responds to these changes, use StrictMode in your app. To see detailed logs about Intent usage violations, add the following method:

Kotlin


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

Java


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

تجربة المستخدم وواجهة مستخدم النظام

يتضمن Android 15 بعض التغييرات التي تهدف إلى إنشاء صورة تجربة المستخدم السهلة.

التغييرات على المساحة الداخلية للنافذة

هناك تغييران متعلّقان بمساحات النوافذ الداخلية في Android 15: يتم فرض استخدام جميع النوافذ بشكلٍ تلقائي، كما أنّ هناك تغييرات في الإعدادات، مثل الإعدادات التلقائية لأشرطة النظام.

التنفيذ الشامل

تظهر التطبيقات بشكل تلقائي على نطاق واسع على الأجهزة التي تعمل بنظام التشغيل Android 15 إذا كان التطبيق: يستهدف Android 15 (المستوى 35 لواجهة برمجة التطبيقات).

تطبيق يستهدف الإصدار 14 من نظام التشغيل Android ولا يراعي مبدأ التشابه بين الأطراف جهاز Android 15


تطبيق يستهدف Android 15 (المستوى 35) لواجهة برمجة التطبيقات الشاملة على جهاز Android 15 يستخدم هذا التطبيق غالبًا مكونات Material 3 Compose التي تطبق الأجزاء الداخلية تلقائيًا. لا تتأثر هذه الشاشة سلبًا التشفير التام بين الأطراف في Android 15

وهذا تغيير قد يؤدي إلى عطل قد يؤثر سلبًا في واجهة مستخدم تطبيقك. تشير رسالة الأشكال البيانية تؤثر التغييرات في مناطق واجهة المستخدم التالية:

  • شريط التنقّل باستخدام مقبض الإيماءات
    • شفاف تلقائيًا.
    • تم إيقاف الإزاحة السفلية بحيث يظهر المحتوى خلف التنقل في النظام ما لم يتم تطبيق مجموعات داخلية.
    • setNavigationBarColor وR.attr#navigationBarColor متوقفة نهائيًا ولا تؤثر على التنقل بالإيماءات.
    • setNavigationBarContrastEnforced و لن يكون للوضع R.attr#navigationBarContrastEnforced أي تأثير في التنقُّل بالإيماءات.
  • التنقّل باستخدام ثلاثة أزرار
    • يتم تعيين التعتيم على 80٪ افتراضيًا، مع احتمال تطابق اللون مع النافذة الخلفية.
    • تم إيقاف الإزاحة السفلية بحيث يظهر المحتوى خلف شريط التنقل في النظام ما لم يتم تطبيق مواد داخلية.
    • setNavigationBarColor وR.attr#navigationBarColor يتم ضبطها ليتناسب مع خلفية النافذة تلقائيًا. خلفية النافذة يجب أن يكون لونًا قابلاً للرسم ليتم تطبيق هذا الإعداد التلقائي. واجهة برمجة التطبيقات هذه ستتوقف عن العمل ولكنها ستستمر في التأثير في التنقل باستخدام ثلاثة أزرار.
    • setNavigationBarContrastEnforced و تكون R.attr#navigationBarContrastEnforced صحيحة بشكل افتراضي، مما يضيف خلفية معتمة بنسبة 80% عبر التنقُّل باستخدام ثلاثة أزرار.
  • شريط الحالة
    • شفاف تلقائيًا.
    • يتم إيقاف الإزاحة العلوية بحيث يظهر المحتوى خلف شريط الحالة ما لم يتم تطبيق مجموعات داخلية.
    • setStatusBarColor وR.attr#statusBarColor متوقفة ولن يكون لها أي تأثير على نظام التشغيل Android 15.
    • setStatusBarContrastEnforced و تم إيقاف R.attr#statusBarContrastEnforced نهائيًا ولكن لا يزال هناك على Android 15.
  • صورة مقطوعة للشاشة
    • يجب أن يكون layoutInDisplayCutoutMode من النوافذ غير العائمة LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS SHORT_EDGES وNEVER و يتم تفسير DEFAULT على أنها ALWAYS بحيث لا يرى المستخدمون علامة "أسود" ناتجة عن الرسم المقطوعة للشاشة وتظهر من حافة إلى أخرى.

يوضح المثال التالي تطبيقًا قبل الاستهداف وبعده. Android 15 (المستوى 35) وقبل تطبيق المساحات الداخلية وبعدها

تطبيق يستهدف الإصدار 14 من نظام التشغيل Android ولا يراعي مبدأ التشابه بين الأطراف جهاز Android 15
تطبيق يستهدف Android 15 (المستوى 35) لواجهة برمجة التطبيقات الشاملة على جهاز Android 15 ومع ذلك، يتم الآن إخفاء العديد من العناصر حسب الحالة أو شريط تنقل مكوّن من ثلاثة أزرار أو صورة مقطوعة للشاشة بسبب الإصدار 15 من Android إجراءات التنفيذ الشاملة. واجهة المستخدم المخفية تتضمن المادة 2 وشريط التطبيق العلوي وأزرار الإجراءات العائمة وعناصر القوائم
التطبيقات التي تستهدف Android 15 (المستوى 35 لواجهة برمجة التطبيقات) جهاز Android 15 ويطبق مجموعات داخلية حتى لا تكون واجهة المستخدم مخفي.
الجوانب التي يجب التأكّد منها ممّا إذا كان تطبيقك شاملاً

إذا كان تطبيقك شاملاً ويطبّق فئات داخلية، يعني ذلك أنّك: غير متأثرة في الغالب، إلا في السيناريوهات التالية. ومع ذلك، حتى إذا كنت تعتقد غير متأثّرين بهذا التغيير، ننصحك باختبار تطبيقك

  • لديك نافذة غير عائمة، مثل Activity التي تستخدم SHORT_EDGES أو NEVER أو DEFAULT بدلاً من LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS إذا تعطّل تطبيقك عند تشغيله، سيؤدي ذلك إلى بسبب شاشة البداية يمكنك إما ترقية الخوارزمية التبعية لشاشة البداية إلى 1.2.0-alpha01 أو لاحقًا أو ضبط window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • قد تكون هناك شاشات ذات عدد زيارات منخفض مع واجهة مستخدم مغطاة. إثبات صحة هذه المعلومات الشاشات الأقل زيارة لا تحتوي على واجهة مستخدم مغطاة. تشمل الشاشات ذات الزيارات المنخفضة ما يلي:
    • شاشات الإعداد أو تسجيل الدخول
    • صفحات الإعدادات
الجوانب التي يجب التأكّد منها ممّا إذا كان تطبيقك لا يغطّي الحواف

إذا لم يكن تطبيقك شاملاً، من المرجّح أنّك تتأثر بهذا التغيير. ضِمن بالإضافة إلى سيناريوهات التطبيقات المتباينة بالفعل، فيجب عليك ضع في اعتبارك ما يلي:

  • إذا كان تطبيقك يستخدم مكونات Material 3 ( androidx.compose.material3) في نافذة الإنشاء، مثل TopAppBar، BottomAppBar وNavigationBar، من المحتمل أن لا لأنهم يتعاملون تلقائيًا مع الأجزاء الداخلية.
  • إذا كان تطبيقك يستخدم مكونات Material 2 ( androidx.compose.material) في Compose، تمثّل هذه العناصر لا تتعامل مع الإدخالات تلقائيًا. ومع ذلك، يمكنك الوصول إلى المساحات الداخلية وتطبيقها يدويًا في androidx.compose.material 1.6.0 ولاحقًا، استخدِم المَعلمة windowInsets لتطبيق المجموعات الداخلية يدويًا BottomAppBar، TopAppBar، BottomNavigation، وNavigationRail. وبالمثل، يمكنك استخدام مَعلمة contentWindowInsets Scaffold
  • إذا كان تطبيقك يستخدم طرق العرض ومكوّنات المواد (com.google.android.material)، المواد الأكثر اعتمادًا على المشاهدات المكونات مثل BottomNavigationView، BottomAppBar، التعامل مع الإدخالات في الإدخال NavigationRailView أو NavigationView ولا تتطلب عمل إضافي. ومع ذلك، عليك إضافة android:fitsSystemWindows="true". في حال استخدام AppBarLayout.
  • بالنسبة إلى العناصر المخصّصة القابلة للإنشاء، طبِّق المساحات الداخلية يدويًا كمساحة متروكة. إذا كان المحتوى ضمن Scaffold، يمكنك استهلاك مجموعات داخلية باستخدام Scaffold قيم المساحة المتروكة. بخلاف ذلك، يمكنك تطبيق المساحة المتروكة باستخدام أحد WindowInsets
  • إذا كان تطبيقك يستخدم طرق العرض وBottomSheet أو SideSheet أو المخصّص ، تطبيق المساحة المتروكة باستخدام ViewCompat.setOnApplyWindowInsetsListener بالنسبة RecyclerView، يمكنك تطبيق مساحة متروكة باستخدام أداة الاستماع هذه وإضافة clipToPadding="false"
كيفية التحقّق مما إذا كان يجب أن يوفّر تطبيقك حماية مخصّصة في الخلفية

إذا كان يجب أن يوفّر تطبيقك حماية مخصّصة في الخلفية للتنقّل باستخدام ثلاثة أزرار أو شريط الحالة، فيجب أن يضع التطبيق عرضًا قابلاً للإنشاء أو عرض خلف شريط النظام استخدام WindowInsets.Type#tappableElement() لعرض الزر الثلاثة ارتفاع شريط التنقل أو WindowInsets.Type#statusBars.

موارد إضافية شاملة

يمكنك الاطّلاع على طرق عرض الحافة إلى الحافة والكتابة من الحافة إلى الحافة. أدلة للاعتبارات الإضافية حول تطبيق المجموعات الداخلية.

واجهات برمجة التطبيقات التي تم إيقافها نهائيًا

تم إيقاف واجهات برمجة التطبيقات التالية نهائيًا:

الإعدادات الثابتة

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:

السمة الإعدادات التلقائية لسمة smartTextHeight على true

في التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android، تصبح السمة elegantTextHeight TextView true تلقائيًا، لتستبدل الخط المكثّف المُستخدَم تلقائيًا ببعض النصوص البرمجية ذات المقاييس العمودية الكبيرة بنص أكثر قابلية للقراءة. وقد تم تصميم الخط المكثّف لمنع تعطّل التنسيقات، ويمنع Android 13 (المستوى 33 لواجهة برمجة التطبيقات) العديد من هذه الأعطال من خلال السماح لتنسيق النص بزيادة الارتفاع العمودي باستخدام السمة fallbackLineSpacing.

في نظام التشغيل Android 15، يظل الخط المضغوط موجودًا في النظام، لذلك يمكن لتطبيقك ضبط elegantTextHeight على false للحصول على السلوك نفسه كما في السابق، ولكن من غير المحتمل أن يكون متوافقًا في الإصدارات القادمة. مثلاً، إذا كان تطبيقك متوافقًا مع النصوص التالية: العربية واللاوية وميانمار والتاميلية والغوجاراتية والكنادية والماليالامية أو الأودية أو التيلوغوية أو التايلاندية، يمكنك اختبار تطبيقك من خلال ضبط elegantTextHeight على true.

سلوك "elegantTextHeight" للتطبيقات التي تستهدف الإصدار 14 من Android (المستوى 34 لواجهة برمجة التطبيقات) والإصدارات الأقدم
elegantTextHeight سلوك التطبيقات التي تستهدف Android 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.

Standard layout for English text in a cursive font. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Layout for the same English text with additional width and padding. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Standard layout for Thai text. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:text="คอมพิวเตอร์" />
Layout for the same Thai text with additional width and padding. Here is the corresponding XML:

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

ارتفاع السطر التلقائي حسب اللغة لـ EditText

في الإصدارات السابقة من نظام التشغيل Android، كان تنسيق النص يوسِّع ارتفاع النص ليتناسب ارتفاع سطر الخط الذي يطابق اللغة الحالية. على سبيل المثال، إذا كان المحتوى باللغة اليابانية، لأن ارتفاع سطر الخط الياباني أكبر بقليل من الخط اللاتيني، فسيصبح ارتفاع النص أكبر قليلاً. مع ذلك، على الرغم من هذه الاختلافات في ارتفاعات الأسطر، تم ضبط حجم عنصر EditText بشكل موحد، بغض النظر عن اللغة المستخدَمة، كما هو موضّح في الصورة التالية:

ثلاثة مربعات تمثّل عناصر EditText يمكن أن تحتوي على نص من الإنجليزية (en) واليابانية (ja) والبورمية (my). ويكون ارتفاع EditText متطابقًا، على الرغم من اختلاف ارتفاع الأسطر عن هاتين اللغتَين.

في التطبيقات التي تستهدف الإصدار 15 من Android، يتم الآن تخصيص حد أدنى لارتفاع السطر لـ EditText لمطابقة الخط المرجعي للغة المحددة، كما هو موضّح في الصورة التالية:

ثلاثة مربعات تمثّل عناصر EditText يمكن أن تحتوي على نص من الإنجليزية (en) واليابانية (ja) والبورمية (my). يتضمّن ارتفاع EditText الآن مساحة لاستيعاب ارتفاع السطر التلقائي لخطوط هذه اللغات.

وإذا لزم الأمر، يمكن لتطبيقك استعادة السلوك السابق من خلال تحديد السمة useLocalePreferredLineHeightForMinimum على false، ويمكن لتطبيقك ضبط حدّ أدنى مخصّص لمقاييس القطاع باستخدام واجهة setMinimumFontMetrics API في لغتَي Kotlin وJava.

الكاميرا والوسائط

يجري Android 15 التغييرات التالية على سلوك الكاميرا والوسائط في التطبيقات. تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث

القيود المفروضة على طلب التركيز الصوتي

لطلب التركيز على الصوت، يجب أن تكون التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android هي أفضل تطبيق أو تشغّل خدمة تعمل في المقدّمة. إذا حاول أحد التطبيقات طلب التركيز في حين لا يستوفي أحد هذه المتطلبات، سيتم عرض الرمز AUDIOFOCUS_REQUEST_FAILED.

يمكنك معرفة المزيد من المعلومات حول التركيز الصوتي في إدارة التركيز الصوتي.

تم تعديل القيود غير المستندة إلى حزمة تطوير البرامج (SDK).

يتضمّن Android 15 قوائم مُعدَّلة بالحِزم المحظورة التي ليست ضِمن حزمة تطوير البرامج (SDK) بناءً على التعاون مع مطوري برامج Android وأحدث للاختبار الداخلي. نحرص على توفّر بدائل عامة كلما أمكن ذلك قبل حظر الواجهات غير المتوفّرة في حزمة SDK.

إذا لم يكُن تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android، إليك بعض هذه التغييرات على الفور. ومع ذلك، على الرغم من إمكانية الوصول إلى بعض الواجهات غير المتوفرة في حزمة SDK اعتمادًا على مستوى واجهة برمجة التطبيقات المستهدَف لتطبيقك، باستخدام أيّ حزمة غير SDK ينطوي على مخاطر عالية دائمًا إلى تعطُّل التطبيق.

إذا لم تكن متأكّدًا ممّا إذا كان تطبيقك يستخدِم واجهات غير متوفرة في حزمة SDK، يمكنك اتّباع الخطوات التالية: اختبار تطبيقك لمعرفة ذلك. إذا كان تطبيقك يعتمد على حزمة غير SDK عليك البدء في التخطيط لنقل البيانات إلى بدائل حِزم SDK. ومع ذلك، ندرك أنّ بعض التطبيقات لها حالات استخدام صالحة والواجهات غير المتوفرة في حزمة SDK في حال لم تتمكن من العثور على بديل لاستخدام حزمة غير SDK الخاصة بميزة في تطبيقك، فيجب طلب واجهة برمجة تطبيقات عامة جديدة.

لمزيد من المعلومات حول التغييرات في هذا الإصدار من نظام التشغيل Android، يمكنك الاطّلاع على تعديلات على القيود المفروضة على الواجهة غير المتوفّرة في حزمة تطوير البرامج (SDK) في نظام التشغيل Android 15. للحصول على مزيد من المعلومات حول الواجهات التي لا تستخدم حزمة SDK بوجه عام، يمكنك الاطّلاع على القيود المفروضة على الواجهات غير المتوفرة في حزمة SDK.