مثل الإصدارات السابقة، يتضمّن Android 15 تغييرات في السلوك قد تؤثر في تطبيقك. تنطبق تغييرات السلوك التالية حصريًا على التطبيقات التي تستهدف الإصدار 15 من Android أو الإصدارات الأحدث. إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android أو إصدارًا أحدث، عليك تعديل تطبيقك لتفعيل هذه السلوكيات بشكلٍ سليم، حيث ينطبق ذلك.
احرص أيضًا على مراجعة قائمة التغييرات في السلوك التي تؤثر في جميع التطبيقات
التي تعمل بنظام التشغيل Android 15 بغض النظر عن targetSdkVersion
تطبيقك.
الوظيفة الأساسية
يعدّل نظام Android 15 أو يوسّع إمكانات نظام Android الأساسية المختلفة.
تغييرات على الخدمات التي تعمل في المقدّمة
نحن بصدد إجراء التغييرات التالية على الخدمات التي تعمل في المقدّمة في Android 15.
- سلوك مهلة الخدمة التي تعمل في المقدّمة لمزامنة البيانات
- نوع الخدمة الجديدة التي تعمل في المقدّمة لمعالجة الوسائط
- القيود المفروضة على
BOOT_COMPLETED
مستقبلات البث التي تبدأ الخدمات التي تعمل في المقدّمة - قيود على بدء الخدمات التي تعمل في المقدّمة عندما يكون لدى التطبيق إذن
SYSTEM_ALERT_WINDOW
سلوك مهلة الخدمة التي تعمل في المقدّمة لمزامنة البيانات
يقدّم 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]"
لتجنُّب المشاكل المتعلّقة بهذا التغيير في السلوك، يمكنك اتّخاذ إجراء أو أكثر من الإجراءات التالية:
- يجب أن تنفِّذ خدمتك طريقة
Service.onTimeout(int, int)
الجديدة. عندما يتلقّى تطبيقك المكالمة المُعاد توجيهها، احرص على الاتصال بالرقمstopSelf()
في غضون بضع ثوانٍ. (إذا لم توقف التطبيق على الفور، سيُنشئ النظام حالة تعطُّل.) - تأكَّد من أنّ خدمات
dataSync
في تطبيقك لا تعمل لأكثر من إجمالي 6 ساعات في أي فترة 24 ساعة (ما لم يتفاعل المستخدم مع التطبيق، يؤدي ذلك إلى إعادة ضبط الموقّت). - يجب عدم بدء تشغيل خدمات "
dataSync
" التي تعمل في المقدّمة إلا نتيجة تفاعل مباشر من المستخدم. وبما أنّ تطبيقك يعمل في المقدّمة عند بدء الخدمة، تبقى الخدمة متاحة خلال الساعات الست الكاملة بعد انتقال التطبيق إلى الخلفية. - بدلاً من استخدام خدمة تعمل في المقدّمة
dataSync
، يمكنك استخدام واجهة برمجة تطبيقات بديلة.
إذا استمر تشغيل خدمات dataSync
التي تعمل في المقدّمة في تطبيقك لمدة 6 ساعات في آخر
24 ساعة، لا يمكنك بدء خدمة أخرى تعمل في المقدّمة dataSync
ما لم ينقل المستخدم
تطبيقك إلى المقدّمة (ما يؤدي إلى إعادة ضبط الموقّت). إذا حاولت بدء خدمة "dataSync
" أخرى تعمل في المقدّمة، سيعرض النظام
ForegroundServiceStartNotAllowedException
رسالة خطأ مثل "سبق أن نفد الحدّ الزمني لنوع الخدمة التي تعمل في المقدّمة
"dataSync".
الاختبار
لاختبار سلوك تطبيقك، يمكنك تفعيل مهلات مزامنة البيانات حتى إذا كان تطبيقك
لا يستهدف الإصدار 15 من نظام التشغيل Android (ما دام التطبيق يعمل على جهاز يعمل بالإصدار 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 (ما دام التطبيق يعمل على
جهاز يعمل بالإصدار 15 من نظام التشغيل Android). لتفعيل مهلات الانتظار، شغِّل الأمر 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
.
الاختبار
لاختبار سلوك تطبيقك، يمكنك تفعيل هذه القيود الجديدة حتى إذا كان
تطبيقك لا يستهدف الإصدار 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
القيود المفروضة على بدء الخدمات التي تعمل في المقدّمة عندما يكون لدى التطبيق إذن 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 (ما دام التطبيق يعمل على جهاز
Android 15). لتفعيل هذه القيود الجديدة على بدء الخدمات التي تعمل في المقدّمة
من الخلفية، شغِّل الأمر adb
التالي:
adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name
تغييرات على الحالات التي يمكن للتطبيقات فيها تعديل الحالة العامة لوضع "عدم الإزعاج"
لم تعُد التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android (المستوى 35 لواجهة برمجة التطبيقات) والإصدارات الأحدث قادرة على تغيير الحالة أو السياسة الشاملة لوضع "عدم الإزعاج" على الجهاز (إما عن طريق تعديل إعدادات المستخدم أو إيقاف وضع "عدم الإزعاج"). بدلاً من ذلك، يجب أن توفّر التطبيقات ملفًا بعنوان
AutomaticZenRule
، والذي يجمعه النظام في سياسة عامة وفقًا لأسلوب
السياسة الأكثر تقييدًا هي السائدة. تؤدي طلبات البيانات من واجهات برمجة التطبيقات الحالية التي أثرت في السابق في الحالة العامة (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
).تغييرات على تسلسلات الأعداد الصحيحة العشوائية: بعد التغييرات التي تم إجراؤها في 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
أو إصدار أقدم، ثم تشغيل التطبيق على Android 14 والإصدارات الأقدم، يتم طرح خطأ أثناء التشغيل:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
يمكن أن يرصد خيار
NewApi
lint الحالي في "المكوّن الإضافي لنظام Gradle المتوافق مع Android" هذه الاستخدامات الجديدة لواجهات برمجة التطبيقات../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()لحلّ استثناء وقت التشغيل وأخطاء Lint، يمكن استبدال استدعاءات الدالتَين
removeFirst()
وremoveLast()
بدالتَيremoveAt(0)
وremoveAt(list.lastIndex)
على التوالي في Kotlin. إذا كنت تستخدم IDE IDE Android Studio Ladybug | 2024.1.3 أو إصدارًا أحدث، يتيح لك أيضًا خيارًا لإصلاح هذه الأخطاء بشكل سريع.ننصحك بإزالة
@SuppressLint("NewApi")
وlintOptions { disable 'NewApi' }
إذا تم إيقاف خيار "التنقيح".تداخل مع طرق أخرى في 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.getFirst(); }
الأمان
يتضمّن 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 تدابير أمان اختيارية جديدة لجعل النوايا أكثر أمانًا وفعالية. تهدف هذه التغييرات إلى منع الثغرات الأمنية المحتملة وإساءة استخدام النوايا التي يمكن للتطبيقات الضارة استغلالها. هناك نوعان من التحسينات الرئيسية على أمان النوايا في Android 15:
- مطابقة فلاتر الأهداف المستهدَفة: يجب أن تتطابق الأهداف التي تستهدف مكوّنات معيّنة بدقة مع مواصفات فلاتر الأهداف المستهدَفة. إذا أرسلت نية لإطلاق نشاط تطبيق آخر، يجب أن يتوافق عنصر intent المستهدف مع فلاتر الأهداف المُعلَن عنها لنشاط التلقي.
- يجب أن تتضمّن الأهداف إجراءات: لن تتطابق الأهداف التي لا تتضمّن إجراءً مع أي فلاتر أهداف. وهذا يعني أنّ النِيّات المستخدَمة لبدء الأنشطة أو الخدمات يجب أن تتضمّن إجراءً محدّدًا بوضوح.
للتحقّق من استجابة تطبيقك لهذه التغييرات، استخدِم StrictMode
في تطبيقك. للاطّلاع على سجلّات detailed
حول انتهاكات استخدام 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: يتم تطبيق التمويه من الحافة إلى الحافة تلقائيًا، وهناك أيضًا تغييرات في الإعدادات، مثل الإعدادات التلقائية لأشرطة النظام.
التنفيذ الشامل
يتم عرض التطبيقات بشكل تلقائي على الأجهزة التي تعمل بالإصدار 15 من Android إذا كان التطبيق يستهدف الإصدار 15 من Android (المستوى 35 لواجهة برمجة التطبيقات).
هذا تغيير جذري قد يؤثر سلبًا في واجهة مستخدم تطبيقك. تؤثر التغييرات في مجالات واجهة المستخدم التالية:
- شريط التنقّل في عناصر التحكّم بالإيماءات
- شفافة تلقائيًا
- يتم إيقاف الإزاحة السفلية حتى يتم رسم المحتوى خلف شريط التنقّل في النظام ما لم يتم تطبيق المكوّنات المضمّنة.
- تمّت
إيقاف
setNavigationBarColor
وR.attr#navigationBarColor
نهائيًا ولا يؤثّران في التنقّل بالإيماءات. - لا يزال
setNavigationBarContrastEnforced
وR.attr#navigationBarContrastEnforced
بدون تأثير على التنقّل باستخدام الإيماءات.
- التنقّل باستخدام 3 أزرار
- يتم ضبط مستوى التعتيم على% 80 تلقائيًا، مع احتمال أن يتطابق اللون مع خلفية النافذة.
- تم إيقاف الإزاحة السفلية حتى يتم رسم المحتوى خلف شريط التنقّل في النظام ما لم يتم تطبيق المكوّنات المضمّنة.
- يتم تلقائيًا ضبط
setNavigationBarColor
وR.attr#navigationBarColor
لتطابق خلفية النافذة. يجب أن تكون خلفية النافذة قابلة للرسم بالألوان لكي يتم تطبيق هذا الخيار التلقائي. تمّت إيقاف واجهة برمجة التطبيقات هذه نهائيًا، ولكنها لا تزال تؤثر في التنقّل باستخدام 3 أزرار. - يكون الخياران
setNavigationBarContrastEnforced
وR.attr#navigationBarContrastEnforced
صحيحَين تلقائيًا، ما يضيف خلفية غير شفافة بنسبة% 80 على ميزة التنقّل باستخدام 3 أزرار.
- شريط الحالة
- شفافة تلقائيًا
- يكون الإزاحة العلوية غير مفعّلة حتى يتم رسم المحتوى خلف شريط الحالة ما لم يتم تطبيق العناصر المضمّنة.
- تمّت
إلغاء استخدام
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
إذا تعطّل تطبيقك عند تشغيله، قد يكون السبب في ذلك شاشة البداية. يمكنك ترقية الاعتماد على core splashscreen إلى 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
. - إذا كان تطبيقك يستخدم عناصر العرض ومكونات Material Design
(
com.google.android.material
)، تتعامل معظم مكونات Material Design المستندة إلى عناصر العرض، مثل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
(للتنقّل باستخدام 3 أزرار، مع 80% من الإصدار التجريبي)Window#isStatusBarContrastEnforced
Window#setNavigationBarColor
(للتنقّل باستخدام 3 أزرار، مع شفافية بنسبة% 80)Window#setStatusBarContrastEnforced
تم إيقاف واجهات برمجة التطبيقات التالية نهائيًا:
R.attr#navigationBarColor
(للتنقّل بالإيماءات)R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#setDecorFitsSystemWindows
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#setNavigationBarColor
(للتنقّل بالإيماءات)Window#setNavigationBarDividerColor
Window#setStatusBarColor
الإعدادات الثابتة
إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android (المستوى 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 لواجهة برمجة التطبيقات.
القيمة التلقائية لسمة elegantTextHeight هي true
بالنسبة إلى التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android (المستوى 35 لواجهة برمجة التطبيقات)، تصبح سمة
elegantTextHeight
TextView
true
تلقائيًا، ما يؤدي إلى استبدال الخط المكثّف المستخدَم تلقائيًا ببعض
النصوص البرمجية التي تحتوي على مقاييس عمودية كبيرة بخط يسهل قراءته.
تم طرح الخط المكثّف لمنع حدوث مشاكل في التنسيقات. يمنع نظام التشغيل Android 13 (المستوى 33 من واجهة برمجة التطبيقات) حدوث العديد من هذه المشاكل من خلال السماح لتنسيق النص بشدّ الارتفاع العمودي باستخدام السمة fallbackLineSpacing
.
في Android 15، سيظل الخط المكثّف متوفّرًا في النظام، لذا يمكن لتطبيقك ضبط
elegantTextHeight
على false
للحصول على السلوك نفسه كما في السابق، ولكن من المرجّح عدم توفّره في الإصدارات القادمة. لذلك، إذا كان تطبيقك متوافقًا مع
النصوص البرمجية التالية: العربية أو البورمية أو التايلاندية أو التاميل أو الغوجاراتية أو الكجراتية أو الماليالامية أو
الأوديا أو التيلوغوية أو اللاوية، يمكنك اختبار تطبيقك من خلال ضبط القيمة elegantTextHeight
على true
.
تغييرات في عرض TextView لأشكال الأحرف المعقّدة
في الإصدارات السابقة من Android، قد ترسم بعض الخطوط المكتوبة بخط اليد أو اللغات التي تتضمن
أشكالًا معقّدةً الأحرف في منطقة الحرف السابق أو التالي.
في بعض الحالات، تم اقتطاع هذه الأحرف في موضع البداية أو النهاية.
بدءًا من Android 15، يخصّص TextView
عرضًا لرسم مساحة كافية
لهذه الأحرف ويسمح للتطبيقات بطلب مساحات إضافية على يمين الحرف لمنع اقتصاصه.
وبما أنّ هذا التغيير يؤثر في كيفية تحديد TextView
للعرض، TextView
يحدّد عرضًا أكبر تلقائيًا إذا كان التطبيق يستهدف الإصدار 15 من نظام التشغيل Android (المستوى 35 لواجهة برمجة التطبيقات) أو
الإصدارات الأحدث. يمكنك تفعيل هذا السلوك أو إيقافه من خلال طلب بيانات من واجهة برمجة التطبيقات
setUseBoundsForWidth
على TextView
.
بما أنّ إضافة مساحة متروكة على يمين العنصر قد تؤدي إلى عدم محاذاة التنسيقات الحالية، لا تتم إضافة
المساحة المتروكة تلقائيًا حتى للتطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث.
ومع ذلك، يمكنك إضافة مساحة متروكة إضافية لمنع الاقتصاص من خلال استدعاء
setShiftDrawingOffsetForStartOverhang
.
توضح الأمثلة التالية كيف يمكن لهذه التغييرات تحسين تخطيط النص لبعض الخطوط واللغات.
ارتفاع السطر التلقائي المراعي للّغة في EditText
في الإصدارات السابقة من Android، كان تنسيق النص يمدّد ارتفاع
النص ليتناسب مع ارتفاع سطر الخط الذي يتطابق مع اللغة الحالية. على سبيل المثال، إذا كان المحتوى باللغة اليابانية، يصبح ارتفاع النص أكبر قليلاً لأنّ ارتفاع السطر للخط الياباني
أكبر قليلاً من ارتفاع السطر للخط اللاتيني. ومع ذلك، على الرغم من هذه الاختلافات في ارتفاعات السطور، تم ضبط حجم العنصر
EditText
بشكلٍ موحّد، بغض النظر عن
اللغة المستخدَمة، كما هو موضّح في الصورة التالية:
بالنسبة إلى التطبيقات التي تستهدف الإصدار 15 من Android (المستوى 35 لواجهة برمجة التطبيقات)، تم الآن تخصيص الحد الأدنى لارتفاع السطر
لـ EditText
لمطابقة الخط المرجعي للّغة المحدّدة، كما هو موضح
في الصورة التالية:
يمكن لتطبيقك استعادة السلوك السابق إذا لزم الأمر من خلال تحديد سمة
useLocalePreferredLineHeightForMinimum
على false
، ويمكن لتطبيقك ضبط الحد الأدنى المخصّص للمقاييس العمودية باستخدام واجهة برمجة التطبيقات
setMinimumFontMetrics
في Kotlin وJava.
الكاميرا والوسائط
يُجري نظام Android 15 التغييرات التالية على سلوك الكاميرا والوسائط للتطبيقات التي تستهدف الإصدار 15 من نظام Android أو الإصدارات الأحدث.
القيود المفروضة على طلب تركيز الصوت
يجب أن تكون التطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android (المستوى 35 لواجهة برمجة التطبيقات) هي التطبيق الأهم أو أن تعمل
بخدمة في المقدّمة من أجل طلب تركيز الصوت. إذا حاول أحد التطبيقات طلب التركيز عندما لا يستوفي أحد هذه المتطلبات، يعرض الإجراء AUDIOFOCUS_REQUEST_FAILED
.
يمكنك الاطّلاع على مزيد من المعلومات حول ميزة "تركيز الصوت" في مقالة إدارة ميزة "تركيز الصوت".
قيود غير متعلّقة بحِزم SDK تم تعديلها
يتضمّن الإصدار 15 من Android قوائم معدَّلة للواجهات غير المتوافقة مع حزمة تطوير البرامج (SDK) والتي تم حظرها استنادًا إلى التعاون مع مطوّري تطبيقات Android وأحدث الاختبار الداخلي. نحرص على توفّر بدائل عامة كلما أمكن ذلك قبل حظر الواجهات غير المتوفّرة في حزمة SDK.
إذا كان تطبيقك لا يستهدف الإصدار 15 من نظام التشغيل Android، قد لا تسري بعض هذه التغييرات عليك على الفور. ومع أنّه من الممكن أن يتمكّن تطبيقك من الوصول إلى بعض الواجهات غير التابعة لحِزم SDK استنادًا إلى مستوى واجهة برمجة التطبيقات المستهدَف في تطبيقك، فإنّ استخدام أي أسلوب أو حقل غير تابع لحِزم SDK يشكّل دائمًا خطرًا كبيرًا على تطبيقك.
إذا لم تكن متأكّدًا مما إذا كان تطبيقك يستخدم واجهات غير متوفرة في حزمة SDK، يمكنك اختبار تطبيقك لمعرفة ذلك. إذا كان تطبيقك يعتمد على واجهات ليست حِزم تطوير برامج (SDK)، عليك بدء التخطيط لنقل البيانات إلى حِزم تطوير برامج (SDK) بديلة. ومع ذلك، ندرك أنّ بعض التطبيقات لها حالات استخدام صالحة لاستخدام واجهات غير متوفرة في حِزم تطوير البرامج (SDK). إذا لم تتمكّن من العثور على بديل لاستخدام واجهة برمجة تطبيقات غير تابعة لحزمة SDK لإحدى الميزات في تطبيقك، عليك طلب واجهة برمجة تطبيقات عامة جديدة.
لمزيد من المعلومات عن التغييرات في هذا الإصدار من Android، اطّلِع على التعديلات على قيود واجهات غير حزمة SDK في Android 15. للاطّلاع على مزيد من المعلومات حول الواجهات غير المتوفّرة في حزمة SDK بشكل عام، اطّلِع على مقالة القيود المفروضة على الواجهات غير المتوفّرة في حزمة SDK.