كما هو الحال في الإصدارات السابقة، يشمل نظام التشغيل Android 15 تغييرات في السلوك قد تؤثر في تطبيقك. تنطبق التغييرات التالية في السلوك حصريًا على التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث. إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android أو إصدارًا أحدث، يجب تعديل تطبيقك ليتوافق مع هذه السلوكيات بشكل صحيح، حيثما ينطبق ذلك.
احرص أيضًا على مراجعة قائمة تغييرات السلوك التي تسري على جميع التطبيقات
التي تعمل بنظام التشغيل Android 15 بغض النظر عن targetSdkVersion
في تطبيقك.
الوظيفة الأساسية
يعمل Android 15 على تعديل الإمكانات الأساسية المتنوعة لنظام Android أو توسيعها.
التغييرات على الخدمات التي تعمل في المقدّمة
سنُجري التغييرات التالية على الخدمات التي تعمل في المقدّمة ضمن الإصدار 15 من نظام التشغيل Android.
- نوع الخدمة التي تعمل في المقدّمة لمعالجة الوسائط الجديدة
- القيود المفروضة على
BOOT_COMPLETED
جهاز استقبال البث الذي يستخدم الخدمات التي تعمل في المقدّمة
سلوك مهلة مزامنة البيانات التي تعمل في المقدّمة
يوفِّر Android 15 سلوكًا جديدًا للمهلة في dataSync
بشأن استهداف التطبيقات.
الإصدار 15 من نظام التشغيل Android أو إصدار أحدث ينطبق هذا السلوك أيضًا على 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]"
لتجنُّب حدوث مشاكل في هذا التغيير في السلوك، يمكنك إجراء واحد أو أكثر من الإجراءات التالي:
- يجب أن تنفِّذ خدمتك طريقة
Service.onTimeout(int, int)
الجديدة. عندما يتلقّى تطبيقك معاودة الاتصال، احرص على الاتصال بـstopSelf()
خلال بضع ثوانٍ. (إذا لم توقف التطبيق على الفور، فسينشئ النظام إخفاقًا). - عليك التأكّد من عدم تشغيل خدمات
dataSync
في تطبيقك لأكثر من إجمالي 6 ساعات في أي فترة 24 ساعة (ما لم يتفاعل المستخدم مع التطبيق، إعادة تعيين المؤقت). - بدء
dataSync
خدمة تعمل في المقدّمة نتيجة طلب مستخدم مباشر التفاعل لأنّ تطبيقك يعمل في المقدّمة عند بدء تشغيل الخدمة ستستغرق الخدمة ست ساعات كاملة بعد انتقال التطبيق إلى الخلفية. - بدلاً من استخدام خدمة تعمل في المقدّمة من "
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
نوع خدمة تعمل في المقدّمة لمعالجة الوسائط الجديدة
يقدّم 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]"
ولتجنّب الحصول على استثناء، يمكنك تنفيذ أحد الإجراءات التالية:
- يجب أن تنفِّذ خدمتك طريقة
Service.onTimeout(int, int)
الجديدة. عندما يتلقّى تطبيقك معاودة الاتصال، احرص على الاتصال بـstopSelf()
في غضون بضع ثوانٍ. (إذا لم توقف التطبيق على الفور، سيفشل النظام.) - عليك التأكّد من عدم تشغيل خدمات
mediaProcessing
في تطبيقك لأكثر من 6 ساعات إجمالاً خلال 24 ساعة (ما لم يتفاعل المستخدم مع التطبيق يُعيد ضبط الموقّت). - يجب عدم بدء تشغيل خدمات "
mediaProcessing
" التي تعمل في المقدّمة إلا نتيجة تفاعل مباشر من المستخدم. وبما أنّ تطبيقك يعمل في المقدّمة عند بدء الخدمة، تبقى الخدمة متاحة خلال الساعات الست الكاملة بعد انتقال التطبيق إلى الخلفية. - بدلاً من استخدام خدمة تعمل في المقدّمة من
mediaProcessing
، يمكنك استخدام واجهة برمجة تطبيقات بديلة، مثل WorkManager.
إذا تم تشغيل خدمات "mediaProcessing
" التي تعمل في المقدّمة داخل تطبيقك لمدة 6 ساعات خلال آخر 24، لن تتمكّن من بدء خدمة "mediaProcessing
" أخرى تعمل في المقدّمة ما لم يجلب المستخدم تطبيقك إلى المقدّمة (ما يؤدي إلى إعادة ضبط الموقّت). إذا حاولت بدء خدمة "mediaProcessing
" أخرى تعمل في المقدّمة، سيعرض النظام
ForegroundServiceStartNotAllowedException
رسالة خطأ مثل "تم استنفاد المهلة الزمنية لنوع الخدمة التي تعمل في المقدّمة
mediaProcessing".
لمزيد من المعلومات حول نوع خدمة mediaProcessing
، يمكنك الاطّلاع على التغييرات على أنواع الخدمات التي تعمل في المقدّمة لنظام Android 15: معالجة الوسائط.
الاختبار
لاختبار سلوك تطبيقك، يمكنك تفعيل مهلات معالجة الوسائط حتى إذا
كان تطبيقك لا يستهدف الإصدار 15 من نظام التشغيل Android (ما دام التطبيق يعمل على
جهاز 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
(تم فرض هذا القيد علىmicrophone
منذ الإصدار 14 من نظام التشغيل Android)
إذا حاول مستلِم BOOT_COMPLETED
تشغيل أي من هذه الأنواع من المقدّمة
متعددة، سيطرح النظام ForegroundServiceStartNotAllowedException
.
الاختبار
لاختبار سلوك تطبيقك، يمكنك تفعيل هذه القيود الجديدة حتى إذا كان
لا يستهدف التطبيق نظام التشغيل Android 15 (ما دام التطبيق يعمل على الإصدار 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
القيود المفروضة على بدء الخدمات التي تعمل في المقدّمة إذا كان أحد التطبيقات يحمل إذن "SYSTEM_ALERT_WINDOW
"
في السابق، إذا كان أحد التطبيقات حاصل على إذن SYSTEM_ALERT_WINDOW
، كان بإمكانه تشغيل
خدمة تعمل في المقدّمة حتى إذا كان التطبيق قيد التشغيل حاليًا في الخلفية (كما هو موضّح في
الاستثناءات من قيود التشغيل في الخلفية).
إذا كان أحد التطبيقات يستهدف الإصدار 15 من نظام التشغيل Android، سيتم الآن الحدّ من هذا الاستثناء. يحتاج التطبيق الآن
إلى إذن SYSTEM_ALERT_WINDOW
وأن يكون أيضًا به نافذة
مرئية على سطح الفيديو. وهذا يعني أنّه على التطبيق أولاً تشغيل نافذة TYPE_APPLICATION_OVERLAY
ويجب أن تكون النافذة مرئية قبل بدء خدمة تعمل في المقدّمة.
إذا حاول تطبيقك بدء خدمة تعمل في المقدّمة من الخلفية بدون استيفاء هذه المتطلبات الجديدة (ولم يكن له استثناء آخر)، سيطرح النظام ForegroundServiceStartNotAllowedException
.
إذا أعلن تطبيقك عن إذن SYSTEM_ALERT_WINDOW
وأطلق الخدمات التي تعمل في المقدّمة من الخلفية، قد يتأثّر بهذا التغيير. إذا حصل تطبيقك على ForegroundServiceStartNotAllowedException
، تحقّق من ترتيب عمليات التطبيق وتأكَّد من أنّ تطبيقك يتضمّن نافذة نشطة على سطح الفيديو قبل أن يحاول بدء خدمة تعمل في المقدّمة من
الخلفية. يمكنك التحقّق ممّا إذا كانت نافذة التراكب مرئية حاليًا
من خلال طلب View.getWindowVisibility()
، أو يمكنك
إلغاء View.onWindowVisibilityChanged()
لتلقّي إشعارات كلما تغيّرت مستوى الرؤية.
تغييرات على الوقت الذي يمكن للتطبيقات فيه تعديل الحالة العامة لوضع "عدم الإزعاج"
لم يعُد بإمكان التطبيقات التي تستهدف الإصدار 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()
:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
على سبيل المثال، يتم طرح الاستثناء التالي عندما يكون فهرس الوسيطة 0 يتم استخدام (
%0
في سلسلة التنسيق):IllegalFormatArgumentIndexException: Illegal format argument index = 0
في هذه الحالة، يمكن إصلاح المشكلة باستخدام فهرس الوسيطات بالقيمة 1 (
%1
). في سلسلة التنسيق).تغييرات على نوع المكوِّن
Arrays.asList(...).toArray()
: عند استخدامArrays.asList(...).toArray()
، نوع المكون للصفيف الناتج هو الآنObject
—وليس نوع عناصر الصفيفة الأساسية. لذا فإن المحور الرأسي هو في الواقع يؤدي الرمز التالي إلى عرضClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
في هذه الحالة، للحفاظ على
String
كنوع المكوِّن في نتيجة مصفوفة، يمكنك استخدامCollection.toArray(Object[])
بدلاً من ذلك:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
تغييرات على معالجة رموز اللغة: عند استخدام واجهة برمجة التطبيقات
Locale
، لم يعُد يتم تحويل رموز اللغات للعبرية واليديشية والإندونيسية إلى الأشكال القديمة (العبرية: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" >
وتكون إجراءات الأمان الجديدة نشطة في حال استيفاء جميع الشروط التالية:
- يستهدف التطبيق القائم بإطلاق الإصدار Android 15.
- يستهدف التطبيق في أعلى حزمة المهام نظام التشغيل Android 15.
- تم تفعيل إجراءات الحماية الجديدة لأي نشاط مرئي.
في حال تفعيل إجراءات الأمان، قد تعود التطبيقات إلى الشاشة الرئيسية بدلاً من آخر تطبيق مرئي إذا أنهوا مهمتهم.
تغييرات أخرى
بالإضافة إلى القيود المفروضة على مطابقة المعرّف الفريد، يتم أيضًا تضمين هذه التغييرات الأخرى:
- تغيير إعدادات
PendingIntent
الخاصة بصنّاع المحتوى إلى حظر عمليات إطلاق الأنشطة في الخلفية تلقائيًا: يساعد ذلك في منع التطبيقات من إنشاءPendingIntent
عن طريق الخطأ، ما قد تسيء إليه الجهات الضارّة. - لا تجلب تطبيقًا إلى المقدمة إلا إذا كان المُرسِل
PendingIntent
يسمح بذلك. يهدف هذا التغيير إلى منع التطبيقات الضارّة من إساءة استخدام إمكانية بدء الأنشطة في الخلفية. بشكل تلقائي، لا يُسمح للتطبيقات بعرض حزمة المهام في المقدّمة ما لم يسمح المنشئ بامتيازات تشغيل النشاط في الخلفية أو يملك المُرسِل امتيازات تشغيل النشاط في الخلفية. - التحكّم في الطريقة التي يتّبعها النشاط الأعلى ضمن مجموعة مهام لإنجاز مهمتها إذا أنهى النشاط الرئيسي مهمة، سيعود Android إلى أي مهمة كانت آخر نشاط لها. علاوة على ذلك، إذا أنهى نشاط غير أساسي مهمته، سيعود Android إلى الشاشة الرئيسية؛ ولن يحجب نهاية هذا النشاط غير الأعلى.
- منع بدء أنشطة عشوائية من تطبيقات أخرى في مهامك الخاصة: يمنع هذا التغيير التطبيقات الضارة من التصيّد الاحتيالي للمستخدمين من خلال إنشاء أنشطة تبدو وكأنها من تطبيقات أخرى.
- حظر النوافذ غير المرئية من وضعها في الاعتبار عند إطلاق الأنشطة في الخلفية: يساعد ذلك في منع التطبيقات الضارة من إساءة استخدام الأنشطة التي يتم إطلاقها في الخلفية لعرض محتوى غير مرغوب فيه أو ضار للمستخدمين.
نوايا أكثر أمانًا
يوفّر Android 15 إجراءات أمان جديدة لجعل الأهداف أكثر أمانًا وقوة. وتهدف هذه التغييرات إلى منع الثغرات المحتملة وإساءة استخدام الأهداف التي يمكن أن تستغلها التطبيقات الضارة. هناك تحسينان رئيسيان على أمان الأهداف في Android 15:
- مطابقة فلاتر الأهداف المستهدفة: يجب أن تتطابق الأهداف التي تستهدف مكوّنات محدّدة بدقة مع مواصفات فلتر الأهداف في الاستهداف. إذا أرسلت نية لإطلاق نشاط تطبيق آخر، يجب أن يتوافق عنصر intent المستهدف مع فلاتر الأهداف المُعلَن عنها لنشاط التلقي.
- يجب أن تتضمّن الأهداف إجراءات: إنّ الأهداف التي لا تتضمّن إجراءً لن تتطابق مع أي فلاتر أهداف. هذا يعني أن الأغراض المستخدمة لبدء الأنشطة أو الخدمات يجب أن يكون لها إجراء محدد بوضوح.
- نوايا في انتظار المراجعة: يتم التعامل مع منشئ الغرض الذي في انتظار المراجعة كمُرسِل الغرض المرفَق، وليس كمُرسِل الغرض في انتظار المراجعة.
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 لواجهة برمجة التطبيقات).
وهذا تغيير قد يؤدي إلى عطل قد يؤثر سلبًا في واجهة مستخدم تطبيقك. تشير رسالة الأشكال البيانية تؤثر التغييرات في مناطق واجهة المستخدم التالية:
- شريط التنقّل باستخدام مقبض الإيماءات
- شفاف تلقائيًا.
- تم إيقاف الإزاحة السفلية بحيث يظهر المحتوى خلف التنقل في النظام ما لم يتم تطبيق مجموعات داخلية.
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) وقبل تطبيق المساحات الداخلية وبعدها
الجوانب التي يجب التأكّد منها ممّا إذا كان تطبيقك شاملاً
إذا كان تطبيقك شاملاً ويطبّق فئات داخلية، يعني ذلك أنّك: غير متأثرة في الغالب، إلا في السيناريوهات التالية. ومع ذلك، حتى إذا كنت تعتقد غير متأثّرين بهذا التغيير، ننصحك باختبار تطبيقك
- لديك نافذة غير عائمة، مثل
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
.
موارد إضافية شاملة
يمكنك الاطّلاع على طرق عرض الحافة إلى الحافة والكتابة من الحافة إلى الحافة. أدلة للاعتبارات الإضافية حول تطبيق المجموعات الداخلية.
واجهات برمجة التطبيقات التي تم إيقافها نهائيًا
تم إيقاف واجهات برمجة التطبيقات التالية نهائيًا:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#isStatusBarContrastEnforced
Window#setDecorFitsSystemWindows
Window#setNavigationBarColor
Window#setNavigationBarDividerColor
Window#setStatusBarColor
Window#setStatusBarContrastEnforced
الإعدادات الثابتة
إذا كان تطبيقك يستهدف نظام التشغيل Android 15 (المستوى 35 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، Configuration
لا
أطول يستبعد أشرطة النظام. إذا كنت تستخدم حجم الشاشة في
فئة Configuration
لحساب التصميم، يجب استبدالها بفئة أفضل
بدائل مثل ViewGroup
أو WindowInsets
أو
WindowMetricsCalculator
حسب حاجتك.
أصبح Configuration
متاحًا منذ واجهة برمجة التطبيقات 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
تم إيقاف هذا الإعداد نهائيًا بدءًا من المستوى 30 لواجهة برمجة التطبيقات. - سبَق أن عملت الإضافة
Display.getMetrics()
على هذا النحو منذ الوصول إلى المستوى 33 من واجهة برمجة التطبيقات.
السمة الإعدادات التلقائية لسمة smartTextHeight على true
في التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android، تصبح السمة elegantTextHeight
TextView
true
تلقائيًا، لتستبدل
الخط المكثّف المُستخدَم تلقائيًا ببعض النصوص البرمجية ذات المقاييس العمودية الكبيرة
بنص أكثر قابلية للقراءة. وقد تم تصميم الخط المكثّف لمنع تعطّل التنسيقات، ويمنع Android 13 (المستوى 33 لواجهة برمجة التطبيقات) العديد من هذه الأعطال من خلال السماح لتنسيق النص بزيادة الارتفاع العمودي باستخدام السمة fallbackLineSpacing
.
في نظام التشغيل Android 15، يظل الخط المضغوط موجودًا في النظام، لذلك يمكن لتطبيقك ضبط
elegantTextHeight
على false
للحصول على السلوك نفسه كما في السابق، ولكن من غير المحتمل
أن يكون متوافقًا في الإصدارات القادمة. مثلاً، إذا كان تطبيقك متوافقًا مع النصوص التالية: العربية واللاوية وميانمار والتاميلية والغوجاراتية والكنادية والماليالامية
أو الأودية أو التيلوغوية أو التايلاندية، يمكنك اختبار تطبيقك من خلال ضبط elegantTextHeight
على true
.
يتغير عرض TextView لأشكال الأحرف المعقدة
في الإصدارات السابقة من Android، قد ترسم بعض الخطوط أو اللغات ذات التشكيل المعقدة الأحرف في منطقة الحرف السابق أو التالي.
وفي بعض الحالات، يتم اقتطاع هذه الأحرف في موضع البداية أو النهاية.
بدءًا من نظام التشغيل Android 15، تخصّص السمة TextView
عرضًا لرسم مساحة كافية لهذه الأحرف، كما تسمح للتطبيقات بطلب مساحات متروكة إضافية إلى اليسار
لمنع الاقتصاص.
بما أنّ هذا التغيير يؤثر في طريقة تحديد TextView
للعرض، يخصِّص TextView
عرضًا أكبر تلقائيًا إذا كان التطبيق يستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث. يمكنك تفعيل هذا الإجراء أو إيقافه من خلال طلب البيانات من واجهة setUseBoundsForWidth
API على TextView
.
لا تتم إضافة المساحة المتروكة تلقائيًا حتى في التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث لأنّ إضافة مساحة متروكة لليسار قد تتسبب في عدم اتساق في التنسيقات الحالية.
مع ذلك، يمكنك إضافة مساحة متروكة إضافية لمنع الاقتصاص من خلال طلب الرمز
setShiftDrawingOffsetForStartOverhang
.
توضح الأمثلة التالية كيف يمكن لهذه التغييرات أن تحسن تخطيط النص لبعض الخطوط واللغات.
ارتفاع السطر التلقائي حسب اللغة لـ EditText
في الإصدارات السابقة من نظام التشغيل Android، كان تنسيق النص يوسِّع ارتفاع النص
ليتناسب ارتفاع سطر الخط الذي يطابق اللغة الحالية. على سبيل المثال، إذا كان المحتوى باللغة اليابانية، لأن ارتفاع سطر الخط الياباني أكبر بقليل من الخط اللاتيني، فسيصبح ارتفاع النص أكبر قليلاً. مع ذلك، على الرغم من هذه الاختلافات في ارتفاعات الأسطر، تم ضبط حجم عنصر EditText
بشكل موحد، بغض النظر عن اللغة المستخدَمة، كما هو موضّح في الصورة التالية:
في التطبيقات التي تستهدف الإصدار 15 من Android، يتم الآن تخصيص حد أدنى لارتفاع السطر لـ 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.