مثل الإصدارات السابقة، يتضمّن الإصدار 15 من Android تغييرات في السلوك قد تؤثر في تطبيقك. تنطبق تغييرات السلوك التالية حصريًا على التطبيقات التي تستهدف الإصدار 15 من Android أو الإصدارات الأحدث. إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android أو إصدارًا أحدث، عليك تعديل تطبيقك لتفعيل هذه السلوكيات بشكلٍ سليم، حيث ينطبق ذلك.
احرص أيضًا على مراجعة قائمة التغييرات في السلوك التي تؤثر في جميع التطبيقات
التي تعمل بنظام التشغيل Android 15 بغض النظر عن targetSdkVersion
تطبيقك.
الوظيفة الأساسية
يعدّل نظام Android 15 أو يوسّع إمكانات نظام Android الأساسية المختلفة.
التغييرات على الخدمات التي تعمل في المقدّمة
我们将对 Android 15 中的前台服务进行以下更改。
数据同步前台服务超时行为
يقدّم 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 تغييرات تعزّز أمان النظام للمساعدة في حماية التطبيقات والمستخدمين من التطبيقات الضارّة.
إصدارات بروتوكول أمان طبقة النقل (TLS) المحظورة
Android 15 限制了对 TLS 版本 1.0 和 1.1 的使用。这些版本之前已在 Android 中被弃用,但现在不允许面向 Android 15 的应用使用。
بدء الأنشطة الآمنة في الخلفية
Android 15 可保护用户免受恶意应用的侵害,并让用户更好地控制 来防止恶意后台应用 将其他应用置于前台、提升其权限以及滥用 用户互动自以下时间以来,后台活动启动一直受到限制 Android 10(API 级别 29)。
禁止与堆栈中的顶部 UID 不匹配的应用启动 activity
恶意应用可以在同一任务中启动另一个应用的 activity,然后
叠加在上面,营造出像该应用一样的错觉。这个“任务”
劫持"攻击绕过了当前的后台启动限制,
会发生在同一个可见任务中。为了降低这种风险,Android 15 新增了
用于阻止与堆栈中的顶层 UID 不匹配的应用启动的标志
活动。如需选择启用应用的所有活动,请更新
allowCrossUidActivitySwitchFromBelow
属性:AndroidManifest.xml
<application android:allowCrossUidActivitySwitchFromBelow="false" >
如果满足以下所有条件,则启用新的安全措施:
- 执行启动的应用以 Android 15 为目标平台。
- 任务堆栈顶部的应用以 Android 15 为目标平台。
- 所有可见活动都已选择启用新保护措施
如果启用了安全措施,应用可能会返回主屏幕,而不是返回 最后一个可见应用(如果他们自行完成任务)。
其他变更
除了限制 UID 匹配之外,这些其他变更也 包括:
- 更改
PendingIntent
创作者,以阻止后台活动启动,具体方法是: 默认。这有助于防止应用意外创建 可能被恶意操作者滥用的PendingIntent
。 - 请勿将应用调到前台,除非
PendingIntent
发送者 允许它。此变更旨在防止恶意应用滥用 在后台启动 activity 的功能。默认情况下,应用 允许将任务堆栈转到前台,除非创建者允许 后台活动启动权限或发送者有后台活动 启动权限 - 控制任务堆栈的顶层 activity 完成其任务的方式。如果 顶层 activity 完成一项任务后,Android 会返回到之前执行的 上次活动时间。此外,如果非顶层 activity 完成其任务,Android 将 返回主屏幕;因此不会阻碍这个非顶层的 活动。
- 防止将其他应用中的任意 activity 启动到您自己的 activity 任务。这项变更旨在防止恶意应用 看起来像是来自其他应用的活动
- 禁止将不可见窗口视为后台活动 发布。这有助于防止恶意应用滥用后台 activity 来向用户显示不需要或恶意的内容。
نوايا أكثر أمانًا
يقدّم نظام التشغيل 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: يتم تطبيق التمويه من الحافة إلى الحافة تلقائيًا، وهناك أيضًا تغييرات في الإعدادات، مثل الإعدادات التلقائية لأشرطة النظام.
全面实施政策
يتم عرض التطبيقات تلقائيًا على الأجهزة التي تعمل بنظام Android 15 إذا كان التطبيق يستهدف Android 15 (المستوى 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
لكي لا يظهر للمستخدمين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"
أيضًا.
الخطوات التي يجب اتّباعها لمعرفة ما إذا كان يجب أن يقدّم تطبيقك حماية مخصّصة للعمل في الخلفية
إذا كان تطبيقك يجب أن يقدّم حماية مخصّصة في الخلفية للتنقّل باستخدام 3 أزرار أو
شريط الحالة، يجب أن يضع تطبيقك عنصرًا قابلاً للتجميع أو عرضًا خلف شريط النظام
باستخدام WindowInsets.Type#tappableElement()
للحصول على ارتفاع
شريط التنقّل باستخدام 3 أزرار أو 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
对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight
TextView
属性默认会变为 true
,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing
属性拉伸垂直高度,从而防止许多此类中断。
在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight
设置为 false
以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight
设置为 true
以测试您的应用。

elegantTextHeight
行为。
elegantTextHeight
行为。تغييرات في عرض TextView لأشكال الأحرف المعقّدة
في الإصدارات السابقة من Android، قد ترسم بعض الخطوط المكتوبة بخط اليد أو اللغات التي تتضمن
أشكالًا معقّدةً الأحرف في منطقة الحرف السابق أو التالي.
في بعض الحالات، تم اقتطاع هذه الأحرف في موضع البداية أو النهاية.
بدءًا من Android 15، يخصّص TextView
عرضًا لرسم مساحة كافية
لهذه الأحرف ويسمح للتطبيقات بطلب مساحات إضافية على يمين الحرف لمنع اقتصاصه.
وبما أنّ هذا التغيير يؤثر في كيفية تحديد TextView
للعرض، TextView
يحدّد عرضًا أكبر تلقائيًا إذا كان التطبيق يستهدف الإصدار 15 من نظام التشغيل Android (المستوى 35 لواجهة برمجة التطبيقات) أو
الإصدارات الأحدث. يمكنك تفعيل هذا السلوك أو إيقافه من خلال طلب بيانات من واجهة برمجة التطبيقات
setUseBoundsForWidth
على TextView
.
بما أنّ إضافة مساحة متروكة على يمين العنصر قد تؤدي إلى عدم محاذاة التنسيقات الحالية، لا تتم إضافة
المساحة المتروكة تلقائيًا حتى للتطبيقات التي تستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث.
ومع ذلك، يمكنك إضافة مساحة متروكة إضافية لمنع الاقتصاص من خلال استدعاء
setShiftDrawingOffsetForStartOverhang
.
توضح الأمثلة التالية كيف يمكن لهذه التغييرات تحسين تخطيط النص لبعض الخطوط واللغات.

<TextView android:fontFamily="cursive" android:text="java" />

<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />

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

<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
ارتفاع السطر التلقائي المراعي للّغة في EditText
在较低版本的 Android 中,文本布局会拉伸文本的高度,以满足与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高略高于拉丁字体,因此文本的高度会略高。不过,尽管行高存在这些差异,但无论使用的是哪种语言区域,EditText
元素的大小都是统一的,如下图所示:

EditText
元素。EditText
的高度相同,即使这些语言的行高各不相同。对于以 Android 15(API 级别 35)为目标平台的应用,现在为 EditText
预留了最小行高,以匹配指定语言区域的参考字体,如下图所示:

EditText
元素。EditText
的高度现在包含足够的空间来容纳这些语言字体的默认行高。如有需要,您的应用可以将 useLocalePreferredLineHeightForMinimum
属性指定为 false
,以恢复之前的行为;您的应用还可以在 Kotlin 和 Java 中使用 setMinimumFontMetrics
API 设置自定义最小垂直指标。
الكاميرا والوسائط
يُجري الإصدار 15 من Android التغييرات التالية على سلوك الكاميرا والوسائط للتطبيقات التي تستهدف الإصدار 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.