في ما يلي التعديلات التي يتم إجراؤها على هذه المواضع الخاصة بالعرض:
- تغيير حجم الأنشطة والشاشات
- أحجام الشاشات ونِسب العرض إلى الارتفاع
- سياسات الشبكة الإعلانية
- إعدادات نافذة العرض
- معرّفات الشبكة الإعلانية الثابتة
- استخدام أكثر من شاشتي عرض
- التركيز لكل عرض
تغيير حجم الأنشطة والشاشات
للإشارة إلى أنّ التطبيق قد لا يتيح وضع النوافذ المتعددة أو تغيير الحجم،
تستخدم سمة resizeableActivity=false
. الإعدادات الشائعة
تشمل المشاكل التي تواجهها التطبيقات عند تغيير حجم الأنشطة ما يلي:
- يمكن أن يختلف إعداد التطبيق عن إعدادات التطبيق أو إعدادات أخرى. مكون غير مرئي. من الأخطاء الشائعة قراءة مقاييس العرض من التطبيق السياق. ولن يتم تعديل القيم المعروضة حسب مقاييس المنطقة المرئية في يتم عرض النشاط فيه.
- وقد لا يتعامل النشاط مع تغيير الحجم والأعطال أو عرض واجهة مستخدم مشوهة، أو فقدان حالة المثيل بسبب إعادة التشغيل بدون حفظ حالة المثيل.
- قد يحاول أحد التطبيقات استخدام الإحداثيات المطلقة للإدخال (بدلاً من تلك بالنسبة إلى موضع النافذة)، وهو ما قد يقسم المدخل إلى نوافذ متعددة.
في نظام التشغيل Android 7 (والإصدارات الأحدث)، يمكن ضبط تطبيق.
تشغيل resizeableActivity=false
في وضع ملء الشاشة دائمًا. ضِمن
في هذه الحالة، تمنع المنصة تقسيم الأنشطة التي لا يمكن تغيير حجمها
الشاشة. إذا حاول المستخدم استدعاء نشاط لا يمكن تغيير حجمه من مشغّل التطبيقات
في وضع تقسيم الشاشة، يخرج النظام الأساسي من وضع تقسيم الشاشة
تبدأ النشاط الذي لا يمكن تغيير حجمه في وضع ملء الشاشة.
التطبيقات التي تضبط هذه السمة صراحةً على false
في
يجب ألا يتم تشغيل البيان في وضع النوافذ المتعددة، ما لم يكن التوافق
تطبيق الوضع التالي:
- يتم تطبيق الإعدادات نفسها على العملية، التي تحتوي على جميع الأنشطة والمكونات غير النشطة.
- تلبي الإعدادات المطبَّقة متطلبات بروتوكول CDD في ما يتعلق بالتوافق مع التطبيق. ما يعرضه.
في Android 10، لا يزال النظام الأساسي يمنع الأنشطة التي لا يمكن تغيير حجمها من الانتقال إلى وضع تقسيم الشاشة، ولكن يمكن يتم تغيير حجمها مؤقتًا إذا كان النشاط يتضمن اتجاهًا أو جانبًا ثابتًا النسبة المئوية. وإذا لم يكن كذلك، يتم تغيير حجم النشاط لملء الشاشة بأكملها كما هو الحال في Android 9 والإصدارات الأقدم.
تطبّق عملية التنفيذ التلقائية السياسة التالية:
عندما يتبيّن أنّ أحد الأنشطة غير متوافق مع ميزة النوافذ المتعددة من خلال
استخدام السمة android:resizeableActivity
ومتى
نشاط يستوفي أحد الشروط الموضحة أدناه، ثم عندما تنطبق
من تهيئة الشاشة، ويتم حفظ النشاط والعملية مع
بالتهيئة الأصلية وأن يُتاح للمستخدم إمكانية إعادة تشغيل
عملية التطبيق لاستخدام إعدادات الشاشة المعدّلة
- هو الاتجاه الثابت عبر تطبيق
android:screenOrientation
- يحتوي التطبيق على الحد الأقصى أو الحد الأدنى التلقائي لنسبة العرض إلى الارتفاع عن طريق استهداف مستوى واجهة برمجة التطبيقات. أو يفصح عن نسبة العرض إلى الارتفاع بشكل صريح
يعرِض هذا الشكل نشاطًا لا يمكن تغيير حجمه بنسبة عرض إلى ارتفاع مُعرَّفة. عند طي الجهاز، يتم تصغير حجم النافذة لتناسب المنطقة أثناء الحفاظ على نسبة العرض إلى الارتفاع باستخدام المحتوى المُعدّ للعرض على شاشة عريضة أفقيًا. بالإضافة إلى ذلك، يتوفر خيار نشاط إعادة التشغيل للمستخدم في كل مرة تكون فيها منطقة عرض تغيير النشاط.
عند فتح الجهاز، يتم ضبط الإعدادات والحجم ونسبة العرض إلى الارتفاع لا يتغير النشاط، ولكن يظهر خيار إعادة بدء النشاط.
عند عدم ضبط السمة resizeableActivity
(أو ضبطها على
true
)، يتيح التطبيق تغيير الحجم بالكامل.
التنفيذ
يسمى النشاط الذي لا يمكن تغيير حجمه ذي الاتجاه الثابت أو نسبة العرض إلى الارتفاع الثابتة
وضع توافق الحجم (SCM) في الرمز البرمجي يتم تحديد الشرط في
ActivityRecord#shouldUseSizeCompatMode()
متى يكون أحد أنشطة SCM
تم إطلاقه، يتم إصلاح التهيئة المتعلقة بالشاشة (مثل الحجم أو الكثافة)
في إعدادات الإلغاء المطلوبة، بحيث لا يعتمد النشاط بعد الآن
على إعدادات العرض الحالية.
إذا لم يتمكن نشاط SCM من ملء الشاشة بأكملها، فسيتم المحاذاة إلى أعلى
في منتصف أفقي. يتم احتساب حدود النشاط حسب
AppWindowToken#calculateCompatBoundsTransformation()
عندما يستخدم أحد أنشطة SCM إعدادات شاشة مختلفة عن
الحاوية (على سبيل المثال، يتم تغيير حجم شاشة العرض أو يتم نقل النشاط إلى حاوية أخرى
العرض)، تكون قيمة ActivityRecord#inSizeCompatMode()
صحيحة
يتلقّى SizeCompatModeActivityController
(في واجهة مستخدم النظام)
لعرض زر إعادة تشغيل العملية.
أحجام شاشة العرض ونِسب العرض إلى الارتفاع فيها
يتوافق Android 10 مع نِسب عرض إلى ارتفاع جديدة.
من النسب العالية للشاشات الطويلة والرقيقة إلى النسب 1:1. يمكن للتطبيقات تحديد
ApplicationInfo#maxAspectRatio
وApplicationInfo#minAspectRatio
من الشاشة التي
قادرًا على التعامل معها.
الشكل 1. أمثلة على نِسب التطبيقات المتوافقة مع نظام التشغيل Android 10
يمكن أن تتضمن عمليات تنفيذ الأجهزة شاشات ثانوية ذات أحجام
بدرجات دقة أصغر من تلك المطلوبة في Android 9 وأقل (2.5 كحد أدنى
بوصة العرض أو الارتفاع، 320 وحدة بكسل مستقلة الكثافة لـ smallestScreenWidth
)
ولكن لا يمكن وضع سوى الأنشطة التي تدعم هذه الشاشات الصغيرة
هناك.
يمكن للتطبيقات الموافقة من خلال الإعلان عن حد أدنى متوافق للحجم أصغر من
أو مساويًا لحجم العرض المستهدَف يمكنك استخدام android:minHeight
و
android:minWidth
سمات تنسيق النشاط في
وبيان AndroidManifest لإجراء ذلك.
سياسات الشبكة الإعلانية
يعمل Android 10 على فصل شاشة معيّنة ونقلها
من تنفيذ WindowManagerPolicy
التلقائي في
من PhoneWindowManager
إلى الصفوف المعروضة لكل عرض، مثل:
- حالة العرض والتدوير
- بعض المفاتيح وتتبُّع أحداث الحركة
- واجهة مستخدم النظام ونوافذ الديكور
في الإصدار 9 من نظام Android (الإصدارات الأقدم)، تمت معالجة فئة PhoneWindowManager
.
سياسات العرض، والحالة والإعدادات، والتدوير، وإطار نافذة الزينة
والتتبع والمزيد. ينقل Android 10 معظم هذه المهمة إلى
الفئة DisplayPolicy
، باستثناء تتبع عرض التناوب، الذي
تم نقل إلى DisplayRotation
.
إعدادات النوافذ المعروضة
في Android 10، تشمل الأجهزة القابلة للتهيئة لكل شاشة تم توسيع إعدادات النافذة لتشمل ما يلي:
- الوضع التلقائي لنافذة العرض
- تجاوز القيم
- وضع تدوير المستخدم وتدويره
- الحجم الإجباري والكثافة ووضع القياس
- وضع إزالة المحتوى (عند إزالة الشاشة)
- دعم زخارف النظام وIME
تحتوي الفئة DisplayWindowSettings
على إعدادات لهذه الحسابات
الخيارات. يتم الاحتفاظ بها على قرص في قسم /data
في
display_settings.xml
في كل مرة يتم فيها تغيير إعداد. بالنسبة
التفاصيل، يُرجى الاطّلاع على DisplayWindowSettings.AtomicFileStorage
و
DisplayWindowSettings#writeSettings()
يمكن للشركات المصنّعة للأجهزة
تقديم القيم التلقائية في display_settings.xml
للأجهزة
التكوين. ومع ذلك، بما أن الملف مخزَّن في /data
،
قد يلزم اتخاذ إجراء إضافي لاستعادة الملف إذا تم محوه من خلال مسح.
يستخدم Android 10 تلقائيًا
DisplayInfo#uniqueId
كمعرّف للعرض عند الاستمرار
الإعدادات. يجب ملء uniqueId
لجميع الشاشات. ضِمن
بالإضافة إلى ذلك، فهو ثابت عند استخدام الشاشات المادية والشبكة. من الممكن أيضًا
استخدام منفذ العرض الفعلي كمعرّف، والذي يمكن ضبطه في
DisplayWindowSettings#mIdentifier
عند كل عملية كتابة، سيتم عرض جميع الإعدادات
بحيث يمكن تحديث المفتاح المستخدم لإدخال العرض في
مساحة التخزين. للحصول على التفاصيل، يمكنك مراجعة
معرّفات الشبكة الإعلانية الثابتة:
يتم الاحتفاظ بالإعدادات في دليل /data
للسجلّ
الأسباب. في الأصل، كانت تُستخدم للحفاظ على الإعدادات التي حددها المستخدم، مثل
تدوير الشاشة.
معرّفات الشبكة الإعلانية الثابتة
لم يوفِّر الإصدار Android 9 (والإصدارات الأقدم) معرّفات ثابتة لشاشات العرض في
إطار العمل. عند إضافة شاشة إلى النظام،
القيمة السابقة للعمود "Display#mDisplayId
" أو "DisplayInfo#displayId
"
التي تم إنشاؤها لهذه الشاشة عن طريق زيادة عدّاد ثابت. إذا أكمل النظام
تمت إضافة الشاشة نفسها وإزالتها، نتج عن معرّف مختلف.
إذا كان الجهاز يتضمن عدة شاشات متاحة عند بدء التشغيل، يمكن أن تكون الشاشات
محددات مختلفة حسب التوقيت. بينما يعمل Android 9 (
سابقًا) تتضمن DisplayInfo#uniqueId
، لم تكن تحتوي على ما يكفي
للتمييز بين الشاشات نظرًا لأن العروض المادية كانت
المحددة إما local:0
أو local:1
، لتمثيل
الشاشة المدمجة والخارجية.
التغييرات في Android 10 DisplayInfo#uniqueId
لإضافة معرّف ثابت والتمييز بين الشبكات المحلية
الشاشات الافتراضية.
نوع العرض | التنسيق |
---|---|
بالتوقيت المحلي | local:<stable-id> |
الشبكة | network:<mac-address> |
"Virtual" (افتراضي) | virtual:<package-name-and-name> |
بالإضافة إلى التحديثات التي أُجريت على "uniqueId
"،
DisplayInfo.address
يحتوي على DisplayAddress
،
معرّف عرض ثابت في عمليات إعادة التشغيل. في Android
10، DisplayAddress
يدعم الاتصال المادي
والشبكة. يحتوي الحقل DisplayAddress.Physical
على قيمة ثابتة
المعرّف المعروض (كما هو الحال في uniqueId
) ويمكن إنشاؤه باستخدام
DisplayAddress#fromPhysicalDisplayId()
يوفّر Android 10 أيضًا طريقة ملائمة
معلومات المنفذ (Physical#getPort()
) يمكن استخدام هذه الطريقة في
إطار العمل لتحديد الشاشات بشكل ثابت. على سبيل المثال، تستخدم في
DisplayWindowSettings
). DisplayAddress.Network
على عنوان MAC ويمكن إنشاؤها باستخدام
DisplayAddress#fromMacAddress()
تسمح هذه الإضافات للشركات المصنّعة للأجهزة بالتعرّف على الشاشات في
إعدادات الشاشات المتعددة، وضبط إعدادات وميزات النظام المختلفة
باستخدام معرّفات الشاشة الثابتة، مثل منافذ الشاشات المادية هذه
هذه الطرق مخفية وهي مخصّصة فقط للاستخدام ضمن
system_server
وفقًا لمعرّف عرض HWC (الذي قد يكون مبهمًا ولا يكون ثابتًا دائمًا)، هذا
لإرجاع رقم منفذ 8 بت (خاص بالنظام الأساسي) يحدد
موصل فعلي لإخراج الشاشة، بالإضافة إلى كائن EDID الإضافي على الشاشة.
يستخلص SurfaceFlinger معلومات الشركة المصنّعة أو النموذج من EDID إلى
إنشاء معرفات عرض مستقرة 64 بت المعروضة لإطار العمل. إذا كانت هذه الطريقة
غير متوافق أو حدثت أخطاء، يعود SurfaceFlinger إلى وضع MD القديم.
حيث يكون DisplayInfo#address
قيمة خالية
DisplayInfo#uniqueId
غير قابل للتغيير، كما هو موضح أعلاه.
للتأكّد من توفّر هذه الميزة، شغِّل:
$ dumpsys SurfaceFlinger --display-id # Example output. Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32" Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i" Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"
استخدام أكثر من شاشتي عرض
في Android 9 (الإصدارات الأقدم)، SurfaceFlinger وDisplayManagerService
افتراض وجود شاشتي عرض ماديتين على الأكثر بمعرّفات البيانات غير القابلة للتغيير في البرنامج
و1.
بدءًا من نظام Android 10، يمكن لـ SurfaceFlinger الاستفادة من واجهة برمجة تطبيقات Device Composer (HWC) لإنشاء معرّفات عرض ثابتة، ما يتيح لها إدارة هذه المعرّفات. عدد عشوائي من العروض المادية لمزيد من المعلومات، يُرجى مراجعة معرّفات الشبكة الإعلانية الثابتة:
يمكن لإطار العمل البحث عن الرمز المميّز IBinder
للحصول على
العرض من خلال SurfaceControl#getPhysicalDisplayToken
بعد الحصول على
رقم تعريف العرض 64 بت من SurfaceControl#getPhysicalDisplayIds
أو
من حدث مقبس كهربائي في DisplayEventReceiver
.
في نظام التشغيل Android 10 (والإصدارات الأقدم)، الشاشة الداخلية الأساسية هي
تم وضع علامة "TYPE_EXTERNAL
" على "TYPE_INTERNAL
" وجميع الشاشات الثانوية.
بغض النظر عن نوع الاتصال. ولذلك، يتم التعامل مع شاشات العرض الداخلية الإضافية على أنها شاشات خارجية.
وكحل بديل، يمكن للرمز البرمجي الخاص بالجهاز وضع افتراضات حول
DisplayAddress.Physical#getPort
إذا كان HWC معروفًا وتخصيص المنفذ
المنطق يمكن التنبؤ به.
تمت إزالة هذا القيد في نظام التشغيل Android 11 (والإصدارات الأحدث).
- في نظام Android 11، أول شاشة يتم الإبلاغ عنها أثناء التشغيل هي الشاشة الأساسية. نوع الاتصال (الداخلي مقابل الخارجي) غير مناسب. ومع ذلك، يظل من الصحيح عدم إمكانية فصل الشاشة الأساسية ومتابعة ما يلي: ينبغي أن يكون شاشة داخلية في الواقع. يُرجى ملاحظة أنّ بعض الهواتف القابلة للطيّ الشاشات الداخلية.
- تم تصنيف شاشات العرض الثانوية بشكلٍ صحيح على أنّها
Display.TYPE_INTERNAL
. أوDisplay.TYPE_EXTERNAL
(المعروف سابقًا باسمDisplay.TYPE_BUILT_IN
) وDisplay.TYPE_HDMI
على التوالي) حسب نوع الاتصال
التنفيذ
في الإصدار Android 9 والإصدارات الأقدم، يتم التعرّف على الشاشات من خلال أرقام تعريف 32 بت،
حيث يشير الرقم 0 إلى الشاشة الداخلية، والرقم 1 هو الشاشة الخارجية، و[2, INT32_MAX]
هي شاشات HWC الافتراضية، ويمثّل الرقم -1 شاشة عرض غير صالحة أو شاشة افتراضية غير تابعة لـ HWC.
بدءًا من نظام التشغيل Android 10، يتم توفير الشاشات بشكل ثابت.
وأرقام التعريف الدائمة، ما يسمح باستخدام SurfaceFlinger وDisplayManagerService
لتتبع أكثر من شاشتي عرض والتعرف على الشاشات المعروضة من قبل. إذا كان HWC
يتوافق مع IComposerClient.getDisplayIdentificationData
ويوفّر إمكانية العرض
بيانات التعريف، يحلّل SurfaceFlinger بنية EDID ويخصص قيمًا ثابتة
معرّفات شاشات 64 بت لشاشات العرض المادية وHWC يتم التعبير عن المعرّفات باستخدام
أحد أنواع الخيارات، حيث تمثل القيمة الفارغة عرضًا غير صالح أو نموذجًا افتراضيًا غير تابع لـ HWC
العرض. بدون دعم HWC، يعود SurfaceFlinger إلى السلوك القديم مع
معظم شاشتي عرض.
التركيز لكل عرض
لإتاحة العديد من مصادر الإدخال التي تستهدف شاشات فردية الوقت، يمكن ضبط Android 10 للتوافق مع العديد نافذة واحدة كحد أقصى لكل عرض. هذه المجموعة مخصَّصة فقط أنواع الأجهزة عندما يتفاعل عدة مستخدمين مع نفس الجهاز الوقت واستخدام أساليب أو أجهزة إدخال مختلفة، مثل Android السيارات.
ننصحك بشدة بعدم تفعيل هذه الميزة الأجهزة العادية، بما في ذلك الأجهزة متعددة الشاشات أو تلك المستخدمة لأجهزة كمبيوتر سطح المكتب وخبراتهم. ويرجع ذلك في المقام الأول إلى وجود مشكلة أمنية قد تتسبب في حدوث للتساؤل عن النافذة التي تركز على الإدخال.
تخيل أن المستخدم الذي يُدخل معلومات آمنة في حقل إدخال نص، مثل تسجيل الدخول إلى تطبيق مصرفي أو إدخال نص يحتوي على بيانات حساسة المعلومات. يمكن لأحد التطبيقات الضارة إنشاء شاشة افتراضية خارج الشاشة باستخدام لتنفيذ نشاط، وأيضًا باستخدام حقل إدخال نص. المشروع تركيز الأنشطة الضارة وعرض كليهما مؤشر إدخال نشط (مؤشر وامض).
ومع ذلك، بما أن الإدخال من لوحة المفاتيح (الأجهزة أو البرامج) يتم إدخاله في النشاط الأعلى فقط (التطبيق الذي تم إطلاقه مؤخرًا)، من خلال عبر إنشاء شاشة افتراضية مخفية، يمكن لتطبيق ضار أن يجلب مدخلات المستخدم، حتى عند استخدام لوحة مفاتيح برمجية على شاشة الجهاز الأساسية.
استخدام "com.android.internal.R.bool.config_perDisplayFocusEnabled
"
لضبط التركيز لكل شاشة.
التوافق
المشكلة: في الإصدار 9 من نظام Android والإصدارات الأقدم، تظهر نافذة واحدة كحد أقصى في النظام في كل مرة.
الحل:في هذه الحالة النادرة، عندما تبدأ نافذتان من سيتم التركيز على العملية نفسها، سيركّز النظام على النافذة فقط أعلى في ترتيب Z. وقد تمت إزالة هذا الشرط من التطبيقات التي تستهدف Android 10، فمن المتوقع عندها أن يتمكنوا من دعم نوافذ متعددة يتم التركيز عليها في وقت واحد.
التنفيذ
يتحكّم WindowManagerService#mPerDisplayFocusEnabled
في
مدى توفر هذه الميزة. بعد ActivityManager
،
يتم استخدام ActivityDisplay#getFocusedStack()
الآن بدلاً من العالمية
التتبع في متغير. ActivityDisplay#getFocusedStack()
التركيز بناءً على الترتيب Z بدلاً من التخزين المؤقت للقيمة. هذا حتى
يحتاج مصدر واحد فقط، وهو WindowManager، إلى تتبع الترتيب Z للأنشطة.
يحصل ActivityStackSupervisor#getTopDisplayFocusedStack()
على
نهجًا مشابهًا لتلك الحالات عندما تكون الحزمة الأكثر تركيزًا في النظام
. يتم اجتياز المكدسات من أعلى إلى أسفل، بحثًا عن
أول حزمة مؤهلة.
يمكن أن يحتوي InputDispatcher
الآن على نوافذ متعددة يتم التركيز عليها
(واحدة لكل شاشة). إذا كان حدث الإدخال متعلّقًا بالعرض، سيتم نقله
إلى النافذة محل التركيز في الشاشة المقابلة. وبخلاف ذلك، يتم إرساله
إلى النافذة محل التركيز في الشاشة محل التركيز، وهي الشاشة التي يمكن للمستخدم
الذين تفاعلوا معهم مؤخرًا.
يمكنك الاطّلاع على InputDispatcher::mFocusedWindowHandlesByDisplay
و
InputDispatcher::setFocusedDisplay()
يتم أيضًا تحديث التطبيقات المركَّزة
بشكل منفصل في ContentManagerService من خلال
NativeInputManager::setFocusedApplication()
في WindowManager
، يتم أيضًا تتبُّع النوافذ التي يتم التركيز عليها بشكل منفصل.
يمكنك الاطّلاع على DisplayContent#mCurrentFocus
و
DisplayContent#mFocusedApp
والاستخدامات ذات الصلة. تركيز ذو صلة
حيث تم نقل طرق التتبع والتحديث من
WindowManagerService
إلى DisplayContent