مستوى واجهة برمجة التطبيقات: 18
الإصدار Android 4.3 (JELLY_BEAN_MR2
)
هو تحديث لإصدار Jelly Bean يقدم ميزات جديدة للمستخدمين ومطوّري التطبيقات. يقدم هذا المستند مقدمة لأهم واجهات برمجة التطبيقات
الجديدة.
بصفتك مطور تطبيقات، يجب عليك تنزيل النسخة الأساسية لنظام Android 4.3 والنظام الأساسي لحزمة تطوير البرامج (SDK) من مدير SDK في أقرب وقت ممكن. إذا لم يكن لديك جهاز يعمل بالإصدار 4.3 من نظام التشغيل Android لاختبار تطبيقك، فاستخدِم صورة النظام Android 4.3 لاختبار تطبيقك على محاكي Android. ثم أنشئ تطبيقاتك وفق نظام Android 4.3 الأساسي لبدء استخدام أحدث واجهات برمجة التطبيقات.
تعديل مستوى واجهة برمجة التطبيقات المستهدَف
لتحسين أداء تطبيقك على الأجهزة التي تعمل بالإصدار 4.3 من نظام التشغيل Android،
عليك ضبط السمة targetSdkVersion
على
"18"
، وتثبيتها على إحدى صور النظام التي تعمل بالإصدار 4.3 من نظام التشغيل Android،
واختبارها، ثم نشر تحديث يتضمّن هذا التغيير.
يمكنك استخدام واجهات برمجة التطبيقات في Android 4.3 مع إتاحة الإصدارات الأقدم أيضًا من خلال إضافة شروط إلى الرمز البرمجي للتحقّق من مستوى واجهة برمجة تطبيقات النظام قبل تنفيذ واجهات برمجة التطبيقات غير المتوافقة مع minSdkVersion
.
لمعرفة المزيد حول الحفاظ على التوافق مع الأنظمة القديمة، اقرأ دعم إصدارات الأنظمة الأساسية المختلفة.
تتوفر أيضًا واجهات برمجة تطبيقات متعددة في مكتبة دعم Android تسمح لك بتنفيذ ميزات جديدة على الإصدارات القديمة من النظام الأساسي.
لمزيد من المعلومات حول طريقة عمل مستويات واجهة برمجة التطبيقات، يمكنك الاطّلاع على المقالة ما هو مستوى واجهة برمجة التطبيقات؟
تغييرات مهمة في السلوك
إذا سبق لك نشر تطبيق لنظام التشغيل Android، يُرجى العلم بأنّ تطبيقك قد يتأثر بالتغييرات في الإصدار 4.3 من نظام التشغيل Android.
في حال كان تطبيقك يستخدم أهدافًا ضمنية...
قد لا يعمل تطبيقك في بيئة ملف شخصي مقيدة.
وقد لا تتوفّر جميع تطبيقات Android العادية للمستخدمين في بيئة ملف شخصي محدود. على سبيل المثال، قد يتم إيقاف متصفح الويب وتطبيق الكاميرا
في ملف شخصي مقيَّد. لذلك، يجب ألا يضع تطبيقك افتراضات حول التطبيقات المتاحة، لأنّه في حال طلب startActivity()
بدون
التحقّق مما إذا كان التطبيق متاحًا للتعامل مع Intent
، قد يتعطّل تطبيقك في ملف شخصي مقيَّد.
عند استخدام هدف ضمني، يجب التأكد دائمًا من أنّ التطبيق متاح للتعامل مع الغرض من خلال الاتصال بالرقم resolveActivity()
أو queryIntentActivities()
. مثلاً:
Kotlin
val intent = Intent(Intent.ACTION_SEND) ... if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show() }
Java
Intent intent = new Intent(Intent.ACTION_SEND); ... if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show(); }
إذا كان تطبيقك يعتمد على الحسابات...
قد لا يعمل تطبيقك في بيئة ملف شخصي مقيدة.
لا يمكن للمستخدمين في بيئة ملفات شخصية مشروطة الوصول إلى حسابات المستخدمين بشكل تلقائي.
وإذا كان تطبيقك يعتمد على Account
، قد يتعطّل تطبيقك أو يتصرف بشكل غير متوقّع عند استخدامه في ملف شخصي محدود.
إذا أردت منع الملفات الشخصية المحظورة من استخدام تطبيقك بالكامل لأنّ
تطبيقك يعتمد على معلومات الحساب الحسّاسة، حدِّد السمة android:requiredAccountType
في عنصر <application>
البيان.
إذا أردت السماح للملفات الشخصية المحظورة بمواصلة استخدام تطبيقك حتى لو لم يكن بإمكانها إنشاء حساباتها الخاصة، يمكنك إمّا إيقاف ميزات التطبيق التي تتطلّب حسابًا أو السماح للملفات الشخصية المحظورة بالوصول إلى الحسابات التي أنشأها المستخدم الأساسي. لمزيد من المعلومات، يُرجى الاطّلاع على القسم أدناه حول دعم الحسابات في ملف شخصي مقيَّد.
إذا كان تطبيقك يستخدم VideoView...
قد يظهر الفيديو بحجم أصغر على Android 4.3.
في الإصدارات السابقة من نظام التشغيل Android، احتسبت أداة VideoView
بشكل غير صحيح قيمة "wrap_content"
للسمة layout_height
وlayout_width
لتكون القيمة نفسها للسمة "match_parent"
. ولذلك قد يكون استخدام "wrap_content"
للارتفاع أو العرض قد يوفّر تنسيق الفيديو الذي تريده سابقًا، إلا أنّ ذلك قد يؤدي إلى عرض فيديو أصغر بكثير على الإصدار 4.3 من نظام التشغيل Android والإصدارات الأحدث. لحلّ المشكلة، يجب استبدال "wrap_content"
بـ "match_parent"
والتأكّد من ظهور الفيديو كما هو متوقّع على الإصدار 4.3 من Android والإصدارات الأقدم.
الملفات الشخصية المحظورة
على أجهزة Android اللوحية، يمكن للمستخدمين الآن إنشاء ملفات شخصية مقيّدة استنادًا إلى المستخدم الأساسي. وعندما ينشئ المستخدمون ملفًا شخصيًا محدودًا، يمكنهم تفعيل القيود مثل التطبيقات المتاحة للملف الشخصي. كما تتيح لك مجموعة جديدة من واجهات برمجة التطبيقات في نظام التشغيل Android 4.3 إنشاء إعدادات للقيود الدقيقة للتطبيقات التي تطورها. على سبيل المثال، يمكنك باستخدام واجهات برمجة التطبيقات الجديدة السماح للمستخدمين بالتحكم في نوع المحتوى المتاح داخل تطبيقك عند تشغيله في بيئة ملف شخصي محدودة.
تتم إدارة واجهة المستخدم للمستخدمين للتحكُّم في القيود التي أنشأتها من خلال تطبيق الإعدادات
الخاص بالنظام. لإظهار إعدادات القيود في تطبيقك للمستخدم،
عليك توضيح القيود التي يوفّرها تطبيقك من خلال إنشاء BroadcastReceiver
يحصل على هدف ACTION_GET_RESTRICTION_ENTRIES
. ويستدعي النظام هذه الغرض للاستعلام عن جميع التطبيقات لمعرفة القيود المتاحة، ثم ينشئ واجهة المستخدم للسماح للمستخدم الأساسي بإدارة القيود لكل ملف شخصي محدود.
وفي طريقة onReceive()
من BroadcastReceiver
، عليك إنشاء RestrictionEntry
لكل قيد يوفّره تطبيقك. يحدّد كل RestrictionEntry
عنوانًا ووصفًا للحظر وأحد أنواع البيانات التالية:
TYPE_BOOLEAN
للقيود التي تكون "صحيح" أو "خطأ".TYPE_CHOICE
للقيود التي تتضمّن خيارات متعددة لا يمكن استخدامها بشكل متبادل (خيارات أزرار الاختيار).TYPE_MULTI_SELECT
لقيود تتضمّن خيارات متعددة ولا لا يمكن استخدامها بشكل متبادل (اختيارات في مربّعات الاختيار).
يمكنك بعد ذلك وضع جميع عناصر RestrictionEntry
في ArrayList
ووضعها في نتيجة مستقبِل البث كقيمة
EXTRA_RESTRICTIONS_LIST
الإضافية.
ينشئ النظام واجهة المستخدم للقيود المفروضة على تطبيقك في تطبيق "الإعدادات"، ويحفظ كل
قيد باستخدام المفتاح الفريد الذي قدّمته لكل
كائن RestrictionEntry
. عندما يفتح المستخدم تطبيقك، يمكنك طلب الاطّلاع على أي قيود حالية من خلال الاتصال على getApplicationRestrictions()
.
يؤدي ذلك إلى عرض Bundle
يحتوي على أزواج المفتاح/القيمة لكل قيد
حددته باستخدام كائنات RestrictionEntry
.
إذا كنت تريد وضع قيود أكثر تحديدًا لا يمكن التعامل معها باستخدام القيم المنطقية، وقيم الاختيار الفردي، والقيم المتعددة الخيارات، يمكنك عندئذٍ إنشاء نشاط يمكن للمستخدم فيه تحديد القيود والسماح للمستخدمين بفتح هذا النشاط من إعدادات القيود. في
جهاز استقبال البث، ضمِّن EXTRA_RESTRICTIONS_INTENT
الإضافي
في النتيجة Bundle
. يجب أن تحدد هذه السمة الإضافية Intent
تشير إلى بدء الفئة Activity
(استخدِم
طريقة
putParcelable()
لتمرير EXTRA_RESTRICTIONS_INTENT
باستخدام الغرض).
عندما يُدخل المستخدم الأساسي نشاطك لضبط قيود مخصّصة، يجب أن يعرض نشاطك نتيجة تحتوي على قيم القيود في عنصر إضافي باستخدام المفتاح EXTRA_RESTRICTIONS_LIST
أو EXTRA_RESTRICTIONS_BUNDLE
، وذلك بناءً على ما إذا كنت تحدّد كائنات RestrictionEntry
أو أزواج المفتاح/القيمة، على التوالي.
دعم الحسابات في ملف شخصي مقيَّد
وتكون أي حسابات مُضافة إلى المستخدم الأساسي متاحة في ملف شخصي محدود، ولكن لا يمكن الوصول إلى الحسابات من خلال واجهات برمجة تطبيقات AccountManager
تلقائيًا.
إذا حاولت إضافة حساب باستخدام AccountManager
في ملف شخصي مقيَّد، ستظهر لك نتيجة تعذُّر تنفيذ العملية. نتيجةً لهذه القيود، تتوفّر لك الخيارات الثلاثة التالية:
للوصول إلى حساب من ملف شخصي محدود، عليك إضافة السمة android:restrictedAccountType
إلى العلامة <Application>:
<application ... android:restrictedAccountType="com.example.account.type" >
تنبيه: يؤدي تفعيل هذه السمة إلى توفير إمكانية وصول تطبيقك إلى حسابات المستخدم الأساسي من الملفات الشخصية المحظورة. لذا يجب عدم السماح بذلك إلا إذا كانت المعلومات التي يعرضها تطبيقك لا تكشف عن معلومات تحديد الهوية الشخصية (PII) التي تعتبر حسّاسة. ستُعلِم إعدادات النظام المستخدم الأساسي بأنّ تطبيقك يمنح ملفات شخصية مقيَّدة لحساباته، لذا يجب أن يكون واضحًا للمستخدم أنّ الوصول إلى الحساب مهم لوظائف التطبيق. عليك أيضًا توفير عناصر تحكّم كافية في القيود للمستخدِم الأساسي تحدِّد مقدار الوصول المسموح به إلى الحساب في تطبيقك، إن أمكن ذلك.
إذا كنت تريد استخدام الحسابات بدون أن تطلبها لاستخدام الوظائف الأساسية لتطبيقك، يمكنك التحقّق من توفّر الحساب وإيقاف الميزات في حال عدم توفّرها.
يجب أولاً التحقق مما إذا كان هناك حساب حالي متاح أم لا. إذا لم يكن الأمر كذلك، استفسر عما إذا كان
من الممكن إنشاء حساب جديد من خلال طلب getUserRestrictions()
والتحقق من وجود DISALLOW_MODIFY_ACCOUNTS
الإضافي في النتيجة. إذا كان true
، عليك إذًا إيقاف أي وظيفة في تطبيقك تتطلب الوصول إلى الحسابات.
مثلاً:
Kotlin
val um = context.getSystemService(Context.USER_SERVICE) as UserManager val restrictions: Bundle = um.userRestrictions if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Java
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
ملاحظة: في هذا السيناريو، يجب عدم الإفصاح عن أي سمات جديدة في ملف البيان.
إذا كان من المهم بدلاً من ذلك ألا يكون تطبيقك متاحًا للملفات الشخصية المحظورة لأنّ
تطبيقك يعتمد على معلومات شخصية حسّاسة في الحساب (ولأن الملفات الشخصية المحظورة
لا يمكنها حاليًا إضافة حسابات جديدة)، أضِف
السمة android:requiredAccountType
إلى علامة <تطبيق>:
<application ... android:requiredAccountType="com.example.account.type" >
على سبيل المثال، يستخدم تطبيق Gmail هذه السمة لإيقاف نفسه للملفات الشخصية المحظورة، لأن البريد الإلكتروني الشخصي للمالك يجب ألا يكون متاحًا للملفات الشخصية المحظورة.
اللاسلكي وإمكانية الاتصال
بلوتوث منخفض الطاقة (إعداد ذكي)
يتيح نظام Android الآن استخدام البلوتوث المنخفض الطاقة (LE) من خلال واجهات برمجة التطبيقات الجديدة في android.bluetooth
.
باستخدام واجهات برمجة التطبيقات الجديدة، يمكنك إنشاء تطبيقات Android تتصل بالأجهزة الطرفية التي تعمل بالبلوتوث منخفض الطاقة مثل أجهزة مراقبة معدل ضربات القلب وأجهزة قياس الخطوات.
بما أنّ ميزة Bluetooth LE هي ميزة في الجهاز ولكنّها غير متوفّرة على جميع الأجهزة التي تعمل بنظام التشغيل Android، يجب الإشارة في ملف البيان إلى أنّه يتضمّن العنصر <uses-feature>
في "android.hardware.bluetooth_le"
:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
إذا كنت على دراية بواجهات برمجة تطبيقات البلوتوث الكلاسيكية في نظام التشغيل Android، يمكنك ملاحظة أنّ استخدام واجهات برمجة تطبيقات Bluetooth LE API له بعض الاختلافات. والأهم من ذلك أنّه يتوفّر الآن فئة BluetoothManager
يجب استخدامها في بعض العمليات العالية المستوى، مثل الحصول على BluetoothAdapter
والحصول على قائمة بالأجهزة المتصلة والتحقق من حالة أحد الأجهزة. على سبيل المثال، إليك خطوات الحصول على
BluetoothAdapter
:
Kotlin
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothAdapter = bluetoothManager.adapter
Java
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter();
لاكتشاف الأجهزة الملحقة التي تعمل بتكنولوجيا Bluetooth LE، يمكنك الاتصال بالرقم startLeScan()
على BluetoothAdapter
، وسيتم تمريرها من خلال تنفيذ
واجهة BluetoothAdapter.LeScanCallback
. عندما يرصد محوّل البلوتوث
جهازًا ملحقًا يتضمّن تقنية البلوتوث منخفض الطاقة، يتلقّى جهاز تنفيذ BluetoothAdapter.LeScanCallback
اتصالاً بطريقة
onLeScan()
. وتزوِّدك هذه الطريقة بكائن BluetoothDevice
يمثّل الجهاز الذي تم رصده، وقيمة RSSI للجهاز، ومصفوفة بايت تتضمّن سجلّ إعلانات الجهاز.
إذا كنت تريد البحث عن أنواع محدّدة فقط من الأجهزة الملحقة، يمكنك بدلاً من ذلك استدعاء startLeScan()
وتضمين مصفوفة من عناصر UUID
التي تحدِّد خدمات GATT التي يتوافق معها تطبيقك.
ملاحظة: يمكنك البحث عن أجهزة Bluetooth LE فقط أو البحث عن أجهزة Bluetooth الكلاسيكية باستخدام واجهات برمجة التطبيقات السابقة. لا يمكنك البحث عن أجهزة Bluetooth LE وكلاسيكية في وقت واحد.
للاتصال بعد ذلك بجهاز ملحق مزوّد بتقنية Bluetooth LE، استدعِ connectGatt()
على الكائن BluetoothDevice
المقابل، واضبطه على تنفيذ BluetoothGattCallback
. تتلقّى عمليات تنفيذ BluetoothGattCallback
استدعاءات بشأن حالة الاتصال بالجهاز والأحداث الأخرى. أثناء معاودة الاتصال بـ "onConnectionStateChange()
"، يمكنك بدء الاتصال بالجهاز إذا اجتازت الطريقة STATE_CONNECTED
باعتباره الحالة الجديدة.
للوصول إلى ميزات البلوتوث على أحد الأجهزة، يجب أيضًا أن يطلب تطبيقك أذونات معيّنة لمستخدم البلوتوث. لمزيد من المعلومات، يُرجى الاطّلاع على دليل واجهة برمجة التطبيقات Bluetooth منخفض الطاقة.
وضع البحث عن شبكات Wi-Fi فقط
عند محاولة تحديد الموقع الجغرافي للمستخدم، قد يستخدم Android شبكة Wi-Fi للمساعدة في تحديد الموقع الجغرافي من خلال البحث عن نقاط وصول قريبة. ومع ذلك، غالبًا ما يحافظ المستخدمون على إيقاف تشغيل شبكة Wi-Fi للحفاظ على البطارية، ما يؤدي إلى ظهور بيانات موقع أقل دقة. يشمل Android الآن وضع "المسح الضوئي فقط" الذي يتيح لشبكة Wi-Fi في الجهاز فحص نقاط الوصول من أجل المساعدة في الحصول على الموقع الجغرافي بدون الاتصال بنقطة وصول، ما يؤدي إلى تقليل استخدام البطارية بشكل كبير.
إذا كنت تريد معرفة الموقع الجغرافي للمستخدم ولكن شبكة Wi-Fi غير مفعّلة حاليًا، يمكنك أن تطلب من المستخدم تفعيل وضع البحث عن شبكات Wi-Fi فقط من خلال استدعاء startActivity()
مع الإجراء ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
.
إعدادات Wi-Fi
تسمح واجهات برمجة التطبيقات WifiEnterpriseConfig
الجديدة للخدمات الموجَّهة للمؤسسات
بتفعيل إعدادات Wi-Fi تلقائيًا للأجهزة المُدارة.
الردّ السريع على المكالمات الواردة
منذ Android 4.0، تتيح ميزة "الاستجابة السريعة" للمستخدمين الرد على المكالمات الواردة برسالة نصية فورية بدون الحاجة إلى الرد على المكالمة أو فتح قفل الجهاز.
حتى الآن، كان تطبيق المراسلة التلقائي يتعامل دائمًا مع هذه الرسائل السريعة. والآن يمكن لأي تطبيق الإفصاح عن قدرته على التعامل مع هذه الرسائل من خلال إنشاء Service
باستخدام فلتر أهداف لـ ACTION_RESPOND_VIA_MESSAGE
.
عندما يردّ المستخدم على مكالمة واردة باستخدام ردّ سريع، يرسل تطبيق "الهاتف"
هدف ACTION_RESPOND_VIA_MESSAGE
مع معرّف موارد منتظم (URI)
يصف المستلِم (المتصل) وEXTRA_TEXT
الرقم الإضافي
مع الرسالة التي يريد المستخدم إرسالها. عندما تتلقّى خدمتك الغرض، من المفترض أن توصل الرسالة
وتتوقف فورًا عن نفسها (يجب ألا يعرض التطبيق أي نشاط).
لتحقيق هذا الغرض، يجب تقديم بيان عن إذن SEND_RESPOND_VIA_MESSAGE
.
وسائط متعددة
تحسينات Mediaاستخراجor وMediaCodec
سيسهّل عليك Android الآن كتابة محتوى البث الديناميكي التكيُّفي عبر مشغّلات HTTP (DASH) بما يتوافق مع معيار ISO/IEC 23009-1،
باستخدام واجهات برمجة التطبيقات الحالية في MediaCodec
وMediaExtractor
. تم تعديل إطار العمل الذي يستند إلى واجهات برمجة التطبيقات هذه لإتاحة تحليل ملفات MP4 المجزأة، ولكن لا يزال تطبيقك مسؤولاً عن تحليل بيانات MPD الوصفية وتمرير عمليات البث الفردية إلى MediaExtractor
.
إذا أردت استخدام DASH مع المحتوى المشفّر، يُرجى العِلم أنّ الطريقة getSampleCryptoInfo()
تعرض البيانات الوصفية MediaCodec.CryptoInfo
التي تصف بنية كل عيّنة من الوسائط المشفّرة. أُضيفت أيضًا الطريقة getPsshInfo()
إلى MediaExtractor
لتتمكّن من الوصول إلى بيانات PSSH الوصفية لوسائط DASH.
تعرض هذه الطريقة خريطة من كائنات UUID
إلى وحدات بايت، حيث يحدّد
UUID
مخطط عملات التشفير، وأن تكون وحدات البايت هي البيانات الخاصة
بهذا المخطط.
إدارة الحقوق الرقمية للوسائط
توفّر الفئة MediaDrm
الجديدة حلاً معياريًا لإدارة الحقوق الرقمية (DRM) في ما يتعلق بمحتوى الوسائط من خلال فصل مخاوف DRM عن تشغيل الوسائط. على سبيل المثال، يسمح لك فصل واجهة برمجة التطبيقات هذا بتشغيل المحتوى المشفّر بـ Widevine بدون الحاجة إلى استخدام تنسيق الوسائط Widevine. ويتوافق حل إدارة الحقوق الرقمية هذا أيضًا مع نظام التشفير DASH المشترك حتى تتمكّن من استخدام مجموعة متنوعة من مخططات إدارة الحقوق الرقمية مع محتوى البث المباشر.
يمكنك استخدام MediaDrm
للحصول على رسائل مبهمة لطلبات المفتاح ومعالجة رسائل الاستجابة الرئيسية من الخادم للحصول على الترخيص وتوفير المتطلبات اللازمة. ويتحمّل تطبيقك مسؤولية معالجة اتصال الشبكة مع الخوادم، ففئة MediaDrm
لا توفّر سوى إمكانية إنشاء الرسائل ومعالجتها.
تم تصميم واجهات برمجة التطبيقات MediaDrm
للاستخدام بالاقتران مع
واجهات برمجة التطبيقات MediaCodec
التي تم تقديمها في الإصدار Android 4.1 (المستوى 16 من واجهة برمجة التطبيقات)،
بما في ذلك MediaCodec
لترميز المحتوى وفك ترميزه، وMediaCrypto
للتعامل مع المحتوى المشفّر، وMediaExtractor
لاستخراج المحتوى وإزالة تشويشه.
يجب أولاً إنشاء كائنات MediaExtractor
وMediaCodec
. يمكنك بعد ذلك الوصول إلى علامة UUID
المحدِّدة لمخطّط DRM
من خلال البيانات الوصفية في المحتوى عادةً، واستخدامها لإنشاء
مثيل لكائن MediaDrm
باستخدام الدالة الإنشائية له.
ترميز الفيديو من أحد أسطح
أضاف نظام التشغيل Android 4.1 (المستوى 16 من واجهة برمجة التطبيقات) الفئة MediaCodec
لترميز محتوى الوسائط وفك ترميزه المنخفض المستوى. أثناء ترميز الفيديو، كان نظام التشغيل Android 4.1 يتطلب منك تزويد
الوسائط بمصفوفة ByteBuffer
، غير أنّ الإصدار 4.3 من نظام التشغيل Android يتيح لك الآن استخدام Surface
كإدخال لبرنامج ترميز. على سبيل المثال، يتيح لك ذلك ترميز الإدخال من ملف فيديو حالي أو استخدام إطارات تم إنشاؤها من OpenGL ES.
لاستخدام Surface
كإدخال لبرنامج الترميز، يجب أولاً الاتصال بـ configure()
على جهاز MediaCodec
.
يمكنك بعد ذلك الاتصال بـ createInputSurface()
لتلقّي Surface
التي يمكنك من خلالها بث الوسائط.
على سبيل المثال، يمكنك استخدام علامة Surface
المحدّدة كنافذة لسياق OpenGL
من خلال تمريرها إلى eglCreateWindowSurface()
. بعد ذلك، أثناء عرض السطح، عليك طلب الرمز eglSwapBuffers()
لتمرير الإطار إلى MediaCodec
.
لبدء عملية الترميز، يُرجى طلب "start()
" على "MediaCodec
". عند الانتهاء، استدعِ signalEndOfInputStream()
لإنهاء الترميز، واستدعِ release()
على
Surface
.
دمج الوسائط
تتيح الفئة MediaMuxer
الجديدة تعدد الإرسال بين بث صوتي واحد وبث فيديو واحد. وتعمل واجهات برمجة التطبيقات هذه كنظير للفئة MediaExtractor
التي تمّت إضافتها في Android 4.2 لإزالة تعدد الإرسال (إزالة التشويش).
يتم تحديد تنسيقات الإخراج المتوافقة باللغة MediaMuxer.OutputFormat
. في الوقت الحالي،
MP4 هو تنسيق الإخراج الوحيد المتاح، ويتوافق MediaMuxer
حاليًا
مع بث صوتي واحد و/أو بث فيديو واحد فقط في كل مرة.
تم تصميم MediaMuxer
بشكل أساسي للعمل مع MediaCodec
، ما يتيح لك معالجة الفيديو من خلال MediaCodec
ثم حفظ الناتج في ملف MP4 من خلال MediaMuxer
. يمكنك أيضًا استخدام MediaMuxer
مع MediaExtractor
لإجراء تعديل
للوسائط بدون الحاجة إلى ترميز أو فك ترميز.
تقدُّم التشغيل وتنقيح البيانات في RemoteControlClient
في نظام التشغيل Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، تمت إضافة RemoteControlClient
لتفعيل عناصر التحكّم في تشغيل الوسائط من برامج التحكّم عن بُعد مثل عناصر التحكّم المتوفّرة على شاشة القفل. أما الآن، نظام التشغيل Android 4.3 فهو يتيح لوحدات التحكم هذه عرض موضع التشغيل وعناصر التحكم في التقديم والترجيع أثناء التشغيل. إذا فعّلت التحكّم عن بُعد لتطبيق الوسائط الخاص بك
باستخدام واجهات برمجة التطبيقات RemoteControlClient
، يمكنك حينئذٍ السماح بالتمرير السريع
للتشغيل من خلال تطبيق واجهتَين جديدتَين.
أولاً، يجب تفعيل علامة FLAG_KEY_MEDIA_POSITION_UPDATE
من خلال تمريرها إلى setTransportControlsFlags()
.
بعد ذلك، نفِّذ الواجهتين الجديدتين التاليتين:
RemoteControlClient.OnGetPlaybackPositionListener
- يشمل ذلك خيار معاودة الاتصال
onGetPlaybackPosition()
الذي يطلب الموضع الحالي للوسائط عندما تحتاج وحدة التحكّم عن بُعد إلى تعديل مستوى التقدّم في واجهة المستخدم الخاصة بها. RemoteControlClient.OnPlaybackPositionUpdateListener
- يشمل ذلك رمز معاودة الاتصال
onPlaybackPositionUpdate()
الذي يحدّد لتطبيقك الرمز الزمني الجديد للوسائط عندما يفسّر المستخدم التشغيل باستخدام واجهة المستخدم لوحدة التحكّم عن بُعد.بعد تعديل موضع التشغيل الجديد، يمكنك استدعاء
setPlaybackState()
للإشارة إلى حالة التشغيل والموضع والسرعة الجديدة.
بعد تحديد هاتين الواجهتين، يمكنك إعدادهما لـ RemoteControlClient
من خلال استدعاء setOnGetPlaybackPositionListener()
وsetPlaybackPositionUpdateListener()
على التوالي.
الرسومات
التوافق مع OpenGL ES 3.0
يضيف نظام التشغيل Android 4.3 واجهات Java ودعمًا أصليًا لبرنامج OpenGL ES 3.0. تشمل الوظائف الأساسية الجديدة التي يوفّرها OpenGL ES 3.0 ما يلي:
- تسريع التأثيرات المرئية المتقدّمة
- ضغط بنية ETC2/EAC عالي الجودة كميزة عادية
- إصدار جديد من لغة تظليل GLSL ES مع عدد صحيح ونقطة عائمة 32 بت
- عرض محسّن للزخرفة
- توحيد حجم القوام وتنسيقات المخزن المؤقت للعرض على نطاق أوسع
يتم توفير واجهة Java لبرنامج OpenGL ES 3.0 على نظام التشغيل Android مع GLES30
.
عند استخدام OpenGL ES 3.0، احرص على الإعلان عنه في ملف البيان باستخدام العلامة
<uses-feature>
والسمة android:glEsVersion
. مثلاً:
<manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest>
وتذكّر تحديد سياق OpenGL ES من خلال طلب setEGLContextClientVersion()
، مع ضبط 3
كإصدار.
لمزيد من المعلومات حول استخدام OpenGL ES، بما في ذلك طريقة التحقّق من إصدار OpenGL ES المتوافق مع الجهاز في وقت التشغيل، يُرجى الاطّلاع على دليل واجهة برمجة التطبيقات OpenGL ES على الجهاز.
دمج الموسيقى مع العناصر القابلة للرسم
إنّ استخدام صورة mipmap كمصدر للصورة النقطية أو القابلة للرسم لها طريقة بسيطة لتوفير صورة عالية الجودة ومقاييس مختلفة للصور، وهو ما قد يكون مفيدًا بشكل خاص إذا كنت تتوقع أن يتم تغيير حجم الصورة أثناء إنشاء مؤثر حركي.
أتاح نظام Android 4.2 (المستوى 17 من واجهة برمجة التطبيقات) استخدام خرائط mipmaps في الفئة Bitmap
. يعمل Android على تبديل صور mip في Bitmap
عند توفير مصدر mipmap وتفعيل setHasMipMap()
. يمكنك الآن في Android 4.3 تفعيل خرائط mipmaps لكائن BitmapDrawable
أيضًا، من خلال توفير مادة عرض mipmap وتعيين السمة android:mipMap
في ملف مورد صورة نقطية أو من خلال استدعاء hasMipMap()
.
واجهة المستخدم
عرض التراكبات
توفّر الفئة ViewOverlay
الجديدة طبقة شفافة فوق View
يمكنك إضافة محتوى مرئي إليها، ولا تؤثر في التسلسل الهرمي للتخطيط. يمكنك الحصول على ViewOverlay
لأي View
من خلال الاتصال على getOverlay()
. يكون للتراكب دائمًا نفس حجم وموضع عرض المضيف (العرض الذي تم إنشاؤه منه)، مما يتيح لك إضافة محتوى يظهر أمام عرض المضيف ولكن لا يمكنه تمديد حدود عرض المضيف هذا.
يُعدّ استخدام السمة ViewOverlay
مفيدًا على وجه الخصوص عندما تريد إنشاء صور متحركة، مثل تمرير عرض خارج حاويته أو نقل العناصر على الشاشة بدون التأثير على هيكلية العرض. ومع ذلك، نظرًا لأن المنطقة القابلة للاستخدام من تراكب تقتصر على نفس المنطقة مثل عرض المضيف الخاص بها، إذا كنت تريد تحريك طريقة عرض خارج موضعها في التخطيط، فيجب عليك استخدام تراكب من طريقة عرض رئيسية لها حدود
التصميم المطلوبة.
عند إنشاء تراكب لعرض أدوات مثل Button
، يمكنك إضافة كائنات Drawable
إلى التراكب عن طريق طلب
add(Drawable)
. إذا استدعيت getOverlay()
لعرض تنسيق، مثل RelativeLayout
،
يكون الكائن الذي يتم عرضه ViewGroupOverlay
. الفئة ViewGroupOverlay
هي فئة فرعية من ViewOverlay
تسمح لك أيضًا بإضافة كائنات View
عن طريق استدعاء add(View)
.
ملاحظة: جميع العناصر القابلة للرسم وطرق العرض التي تضيفها إلى تراكب مرئية فقط. ولا يمكنهم تلقّي التركيز أو إدخال الأحداث.
على سبيل المثال، تحرّك الكود التالي طريقة عرض انزلاقها إلى اليمين من خلال وضع العرض في تراكب طريقة العرض الرئيسية، ثم تنفيذ رسم متحرك للترجمة في هذا العرض:
Kotlin
val view: View? = findViewById(R.id.view_to_remove) val container: ViewGroup? = view?.parent as ViewGroup container?.apply { overlay.add(view) ObjectAnimator.ofFloat(view, "translationX", right.toFloat()) .start() }
Java
View view = findViewById(R.id.view_to_remove); ViewGroup container = (ViewGroup) view.getParent(); container.getOverlay().add(view); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight()); anim.start();
تخطيط الحدود البصرية
بالنسبة إلى طرق العرض التي تحتوي على صور خلفية من تسع رقعات، يمكنك الآن تحديد ضرورة محاذاتها مع طرق العرض المجاورة بناءً على الحدود "البصرية" لصورة الخلفية بدلاً من حدود "المقطع" للعرض.
على سبيل المثال، يعرض الشكلان 1 و2 نفس التخطيط، لكن الإصدار في الشكل 1 يستخدم حدود المقطع (السلوك الافتراضي)، بينما يستخدم الشكل 2 الحدود البصرية. نظرًا لأن الصور ذات النقوش التسع المستخدمة للزر وإطار الصورة تشتمل على مساحة متروكة حول الحواف، فلا يبدو أنها تتماشى مع بعضها البعض أو مع النص عند استخدام حدود المقطع.
ملاحظة: لقطة الشاشة في الشكلين 1 و2 بها إعداد مطوّر البرامج "إظهار حدود التنسيق" مُفعَّل. لكل طريقة عرض، تشير الخطوط الحمراء إلى الحدود البصرية، وتشير الخطوط الزرقاء إلى حدود المقطع، وتشير الخطوط الوردية إلى الهوامش.
![](https://developer.android.com/static/images/tools/clipbounds_2x.png?authuser=7&hl=ar)
الشكل 1. تنسيق باستخدام حدود المقطع (تلقائي).
![](https://developer.android.com/static/images/tools/opticalbounds_2x.png?authuser=7&hl=ar)
الشكل 2. تخطيط باستخدام الحدود البصرية.
لمحاذاة طرق العرض استنادًا إلى حدودها البصرية، اضبط السمة android:layoutMode
على "opticalBounds"
في أحد التنسيقات الرئيسية. مثلاً:
<LinearLayout android:layoutMode="opticalBounds" ... >
![](https://developer.android.com/static/images/tools/ninepatch_opticalbounds_2x.png?authuser=7&hl=ar)
الشكل 3. عرض مُكبَّر للزر "هولو" من تسعة رقعة مع حدود بصرية.
لكي يحدث ذلك، يجب أن تحدد الصور المكونة من تسعة رقاقات والمطبقة على خلفية طرق العرض الحدود البصرية باستخدام خطوط حمراء على طول الجزء السفلي والجانب الأيمن من الملف المكون من تسعة رقاقات (كما هو موضح في الشكل 3). تشير الخطوط الحمراء إلى المنطقة التي يجب طرحها من حدود المقطع، مما يترك الحدود البصرية للصورة.
عند تفعيل الحدود البصرية لـ ViewGroup
في تنسيقك، تكتسِب جميع طرق العرض التابعة وضع تنسيق الحدود البصرية ما لم تستبدِله لمجموعة من خلال
ضبط android:layoutMode
على "clipBounds"
. تلتزم جميع عناصر التصميم أيضًا بالحدود البصرية لطرق العرض الفرعية الخاصة بها، وتكييف حدودها على أساس الحدود البصرية للعروض المتوفّرة بداخلها. ومع ذلك، لا تتوافق عناصر التنسيق (الفئات الفرعية من ViewGroup
) حاليًا مع الحدود البصرية للصور التي تتضمّن تسعة تصحيحات ويتم تطبيقها على الخلفية الخاصة بها.
في حال إنشاء طريقة عرض مخصّصة من خلال التصنيف الفرعي View
أو ViewGroup
أو أي فئات فرعية منها، سيكتسب الملف الشخصي هذه السلوكيات المرتبطة البصري.
ملاحظة: تم تحديث جميع التطبيقات المصغّرة المتوافقة مع مظهر Holo
باستخدام حدود بصرية، بما في ذلك Button
وSpinner
وEditText
وغير ذلك. لكي تستفيد فورًا من هذه السمة من خلال ضبط
السمة android:layoutMode
على "opticalBounds"
إذا كان تطبيقك يطبّق مظهر Holo
(Theme.Holo
، وTheme.Holo.Light
، وغير ذلك).
لتحديد الحدود البصرية لصورك المكوَّنة من تسعة رقاقات باستخدام أداة الرسم 9-بات، اضغط مع الاستمرار على زر التحكّم عند النقر على وحدات بكسل الحدود.
مؤثرات حركية لقيم المستطيل
يمكنك الآن إضافة تأثير متحرك بين قيمتَي Rect
باستخدام السمة RectEvaluator
الجديدة. هذا الصف الجديد هو تنفيذ لـ TypeEvaluator
يمكنك تمريره إلى ValueAnimator.setEvaluator()
.
تثبيت النافذة والتركيز على أداة المستمع
في السابق، إذا كنت تريد الاستماع إلى الصوت عندما يتم إرفاق/فصل العرض بالنافذة أو عند تغيير التركيز، كان عليك إلغاء الفئة View
لتنفيذ الترميزَين onAttachedToWindow()
وonDetachedFromWindow()
، أو onWindowFocusChanged()
على التوالي.
الآن، لتلقّي إرفاق الأحداث وفصلها، يمكنك بدلاً من ذلك تطبيق ViewTreeObserver.OnWindowAttachListener
وضبطه على ملف شخصي باستخدام addOnWindowAttachListener()
.
ولتلقّي أحداث التركيز، يمكنك تنفيذ علامة ViewTreeObserver.OnWindowFocusChangeListener
وضبطها على طريقة عرض باستخدام
addOnWindowFocusChangeListener()
.
إتاحة الخروج عن إطار الشاشة على التلفزيون
للتأكّد من أنّ تطبيقك يملأ الشاشة بأكملها على كل تلفزيون، يمكنك الآن تفعيل ميزة "الإفراط في المسح الضوئي"
لتطبيقك على تنسيق تطبيقك. يتم تحديد وضع الخروج عن إطار الشاشة من خلال علامة FLAG_LAYOUT_IN_OVERSCAN
التي يمكنك تفعيلها باستخدام مظاهر النظام الأساسي مثل Theme_DeviceDefault_NoActionBar_Overscan
أو من خلال تفعيل النمط windowOverscan
في مظهر مخصّص.
اتجاه الشاشة
توفِّر سمة العلامة <activity>
screenOrientation
الآن قيمًا إضافية لتلبية خيار المستخدم المفضّل للتناوب التلقائي:
"userLandscape"
- يتصرف مثل
"sensorLandscape"
، إلا إذا أوقف المستخدم ميزة التدوير التلقائي، سيتم تثبيت الجهاز في الاتجاه الأفقي العادي ولن يؤدي إلى قلب العدسة. "userPortrait"
- يتصرف مثل
"sensorPortrait"
، إلا إذا أوقف المستخدم التدوير التلقائي، سيتم تثبيت الجهاز في الاتجاه العمودي الطبيعي ولن يتم قلب الجهاز. "fullUser"
- يتصرف مثل
"fullSensor"
ويسمح بالتدوير في جميع الاتجاهات الأربعة، إلا إذا أوقف المستخدم التدوير التلقائي، حينئذٍ يتم قفله في الاتجاه الذي يفضله المستخدم.
بالإضافة إلى ذلك، يمكنك الآن أيضًا تقديم بيان عن "locked"
لقفل اتجاه التطبيق في الاتجاه الحالي للشاشة.
الصور المتحركة التي يتم تدويرها
يسمح لك حقل rotationAnimation
الجديد في
WindowManager
بالاختيار من بين ثلاث صور متحركة
تريد استخدامها عندما يبدّل النظام اتجاهات الشاشة. الرسوم المتحركة الثلاثة هي:
ملاحظة: لا تتوفر هذه الصور المتحركة إلا إذا ضبطت نشاطك على استخدام وضع "ملء الشاشة"، والذي يمكنك تفعيله مع مظاهر مثل Theme.Holo.NoActionBar.Fullscreen
.
على سبيل المثال، في ما يلي كيفية تفعيل الصورة المتحركة "التلاشي المتقاطع":
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val params: WindowManager.LayoutParams = window.attributes params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE window.attributes = params ... }
Java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WindowManager.LayoutParams params = getWindow().getAttributes(); params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; getWindow().setAttributes(params); ... }
إدخال المستخدم
أنواع أدوات الاستشعار الجديدة
تتيح لك أداة الاستشعار الجديدة "TYPE_GAME_ROTATION_VECTOR
" اكتشاف دوران الجهاز بدون القلق بشأن التداخل المغناطيسي. على عكس أداة استشعار TYPE_ROTATION_VECTOR
، لا يعتمد جهاز TYPE_GAME_ROTATION_VECTOR
على الشمال المغناطيسي.
توفِّر أدوات الاستشعار TYPE_GYROSCOPE_UNCALIBRATED
وTYPE_MAGNETIC_FIELD_UNCALIBRATED
الجديدة بيانات أداة الاستشعار الأولية بدون مراعاة تقديرات الانحياز. ويعني ذلك أنّ المستشعرَين TYPE_GYROSCOPE
وTYPE_MAGNETIC_FIELD
الحاليَّين يوفران بيانات أداة الاستشعار التي تأخذ في الاعتبار الانحياز المقدَّر بسبب انحرف الجيروسكوب والحديد الصلب في الجهاز على التوالي. بينما توفر الإصدارات الجديدة "غير المعايرة" من أدوات الاستشعار هذه بيانات أداة الاستشعار الأولية وتعرض قيم الانحياز المقدّرة بشكل منفصل. وتتيح لك أدوات الاستشعار هذه إجراء معايرة مخصّصة خاصة بك لبيانات أداة الاستشعار من خلال زيادة مقدار الانحياز المقدَّر باستخدام البيانات الخارجية.
Notification Listener
يضيف نظام التشغيل Android 4.3 فئة خدمة جديدة، وهي NotificationListenerService
، تسمح لتطبيقك بتلقّي معلومات حول الإشعارات الجديدة فور نشرها من خلال النظام.
إذا كان تطبيقك يستخدم حاليًا واجهات برمجة التطبيقات لخدمة تسهيل الاستخدام للوصول إلى إشعارات النظام، يجب تحديث تطبيقك لاستخدام واجهات برمجة التطبيقات هذه بدلاً من ذلك.
مقدِّم جهات الاتصال
طلب بحث عن "العناصر القابلة للاتصال"
يوفّر طلب البحث الجديد لمقدّمي خدمة جهات الاتصال، Contactables.CONTENT_URI
، طريقة فعّالة للحصول على رقم Cursor
واحد يحتوي على جميع عناوين البريد الإلكتروني وأرقام الهواتف التي تنتمي إلى جميع جهات الاتصال المطابقة لطلب البحث المحدّد.
طلب بحث عن قيم دلتا لجهات الاتصال
تمت إضافة واجهات برمجة تطبيقات جديدة إلى "مقدِّم جهات الاتصال" والتي تتيح لك الاستعلام عن التغييرات الأخيرة التي تم إجراؤها على بيانات جهات الاتصال بكفاءة. في السابق، كان بالإمكان إرسال إشعار إلى تطبيقك عند حدوث تغيير في بيانات جهات الاتصال، ولكنك لن تعرف بالضبط ما تم تغييره وستحتاج إلى استرداد جميع جهات الاتصال ثم تكرارها لمعرفة التغيير.
لتتبُّع التغييرات التي تطرأ على عمليات الإدراج والتحديثات، يمكنك الآن تضمين المَعلمة CONTACT_LAST_UPDATED_TIMESTAMP
مع اختيارك لإجراء طلب بحث فقط عن جهات الاتصال التي تم تغييرها منذ آخر مرة أجريت فيها طلب بحث من مقدّم الخدمة.
لتتبع جهات الاتصال التي تم حذفها، يوفر الجدول الجديد ContactsContract.DeletedContacts
سجلاً لجهات الاتصال التي تم حذفها (ولكن يتم الاحتفاظ بكل جهة اتصال في هذا الجدول لفترة محدودة). على غرار CONTACT_LAST_UPDATED_TIMESTAMP
، يمكنك استخدام مَعلمة الاختيار الجديدة CONTACT_DELETED_TIMESTAMP
للتحقّق من جهات الاتصال التي تم حذفها منذ آخر مرة طلبت فيها من مقدّم الخدمة. يحتوي الجدول أيضًا على القيمة الثابتة DAYS_KEPT_MILLISECONDS
التي تتضمّن عدد الأيام (بالمللي ثانية) التي سيتم الاحتفاظ بالسجلّ فيها.
بالإضافة إلى ذلك، يبث "مقدِّم جهات الاتصال" الآن الإجراء CONTACTS_DATABASE_CREATED
عندما يمحو المستخدم مساحة تخزين جهات الاتصال من خلال قائمة إعدادات النظام، ما يؤدي إلى إعادة إنشاء قاعدة بيانات "مقدِّم جهات الاتصال" بفعالية. الغرض منه هو إرسال إشارة إلى التطبيقات أنها بحاجة إلى إسقاط جميع معلومات الاتصال
التي خزنتها وإعادة تحميلها بطلب بحث جديد.
للحصول على نموذج رمز يستخدم واجهات برمجة التطبيقات هذه للتحقّق من التغييرات التي تطرأ على جهات الاتصال، يمكنك الاطّلاع على نموذج ApiDemos المتوفّر في تنزيل SDK عيّنات.
الأقلمة
دعم مُحسَّن للنص ثنائي الاتجاه
تتوافق الإصدارات السابقة من Android مع التنسيق واللغات التي تُكتب من اليمين إلى اليسار (RTL)،
ولكنها لا تتعامل أحيانًا مع النص المختلط بشكل صحيح. ولذلك، يضيف نظام التشغيل Android 4.3 واجهات برمجة التطبيقات BidiFormatter
التي تساعدك في تنسيق النص بشكلٍ صحيح مع محتوى باتجاه معاكس بدون تشويه أي جزء منه.
على سبيل المثال، عندما تريد إنشاء جملة باستخدام متغير سلسلة، مثل "هل تقصد
15 Bay Street, Laurel, CA?"، فعادةً ما يتم تمرير مورد سلسلة مترجم والمتغيّر إلى
String.format()
:
Kotlin
val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
Java
Resources res = getResources(); String suggestion = String.format(res.getString(R.string.did_you_mean), address);
ومع ذلك، إذا كانت اللغة العبرية، فإن السلسلة المنسقة تظهر على النحو التالي:
فيما يلي كل الصور التي يمكن استخدامها على شبكة 15 Bay Street, Laurel, CA?
هذا خطأ لأنه يجب ترك "15" على يسار "Bay Street". الحل هو استخدام BidiFormatter
وطريقة unicodeWrap()
الخاصة بها. على سبيل المثال، يصبح الرمز الوارد أعلاه:
Kotlin
val bidiFormatter = BidiFormatter.getInstance() val suggestion = String.format( resources.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address) )
Java
Resources res = getResources(); BidiFormatter bidiFormatter = BidiFormatter.getInstance(); String suggestion = String.format(res.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address));
بشكل تلقائي، يستخدم unicodeWrap()
أسلوب توجيهي تقديري قوي أولاً، والذي قد يخطئ إذا كانت الإشارة الأولى لاتجاه النص لا تمثّل الاتجاه المناسب للمحتوى ككل.
إذا لزم الأمر، يمكنك تحديد إرشادي مختلف من خلال تمرير أحد ثوابت TextDirectionHeuristic
من TextDirectionHeuristics
إلى unicodeWrap()
.
ملاحظة: تتوفّر واجهات برمجة التطبيقات الجديدة هذه أيضًا للإصدارات السابقة من Android من خلال مكتبة دعم Android، مع الفئة BidiFormatter
وواجهات برمجة التطبيقات ذات الصلة.
خدمات تسهيل الاستخدام
التعامل مع الأحداث الرئيسية
يمكن الآن لـ AccessibilityService
تلقّي استدعاء لأحداث الإدخال الرئيسية باستخدام طريقة معاودة الاتصال onKeyEvent()
. ويتيح ذلك لخدمة تسهيل الاستخدام معالجة الإدخال لأجهزة الإدخال التي تستند إلى المفاتيح، مثل لوحة المفاتيح، وتحويل هذه الأحداث إلى إجراءات خاصة لم يكن من الممكن تنفيذها في السابق إلا باستخدام الإدخال باللمس أو لوحة توجيه الجهاز.
تحديد النص والنسخ/اللصق
توفّر "AccessibilityNodeInfo
" الآن واجهات برمجة تطبيقات تتيح لـ AccessibilityService
اختيار النص وقصه ونسخه ولصقه في عقدة.
لتحديد النص الذي تريد قصه أو نسخه، يمكن لخدمة تسهيل الاستخدام استخدام الإجراء
الجديد، ACTION_SET_SELECTION
، مع تمرير
معه موضعي البداية والنهاية بالرمزين ACTION_ARGUMENT_SELECTION_START_INT
وACTION_ARGUMENT_SELECTION_END_INT
.
يمكنك بدلاً من ذلك اختيار النص من خلال معالجة موضع المؤشر باستخدام الإجراء الحالي ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(كان سابقًا لتحريك موضع المؤشر فقط) وإضافة الوسيطة ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
.
يمكنك بعد ذلك قصها أو نسخها باستخدام ACTION_CUT
وACTION_COPY
، ثم اللصق لاحقًا باستخدام
ACTION_PASTE
.
ملاحظة: تتوفّر واجهات برمجة التطبيقات الجديدة هذه أيضًا للإصدارات السابقة من Android من خلال مكتبة دعم Android، مع الفئة AccessibilityNodeInfoCompat
.
الإفصاح عن ميزات تسهيل الاستخدام
بدايةً من الإصدار 4.3 من نظام التشغيل Android، يجب أن تذكر الخدمة المخصصة لتسهيل الاستخدام ميزات تسهيل الاستخدام
في ملف البيانات الوصفية من أجل استخدام بعض ميزات تسهيل الاستخدام. وإذا لم تكن هذه الميزة مطلوبة في ملف البيانات الوصفية، ستكون الميزة غير مفعّلة. للإعلان عن إمكانات تسهيل الاستخدام في خدمتك، عليك استخدام سمات XML التي تتوافق مع ثوابت "القدرات" المختلفة في الفئة AccessibilityServiceInfo
.
على سبيل المثال، إذا لم تطلب الخدمة إمكانية "flagRequestFilterKeyEvents
"، لن تتلقّى الأحداث الرئيسية.
الاختبار وتصحيح الأخطاء
اختبار مبرمَج لواجهة المستخدم
توفّر الفئة UiAutomation
الجديدة واجهات برمجة تطبيقات تتيح لك محاكاة
إجراءات المستخدم من أجل التشغيل الآلي للاختبار. باستخدام واجهات برمجة التطبيقات AccessibilityService
الخاصة بالنظام الأساسي، تسمح لك واجهات برمجة التطبيقات UiAutomation
بفحص محتوى الشاشة وإدخال أحداث عشوائية لوحة المفاتيح واللمس.
للحصول على نسخة افتراضية من "UiAutomation
"، يمكنك استدعاء "Instrumentation.getUiAutomation()
". لتنفيذ ذلك، عليك توفير الخيار -w
مع الأمر instrument
عند تشغيل InstrumentationTestCase
من adb shell
.
باستخدام مثيل UiAutomation
، يمكنك تنفيذ أحداث عشوائية لاختبار تطبيقك من خلال استدعاء executeAndWaitForEvent()
، ومنحه Runnable
لتنفيذه، ومهلة
عملية للعملية، وتنفيذ واجهة UiAutomation.AccessibilityEventFilter
. ضمن عملية تنفيذ UiAutomation.AccessibilityEventFilter
، ستتلقّى مكالمة تتيح لك فلترة الأحداث التي تهمّك وتحديد مدى نجاح أو
تعذُّر حالة اختبار معيّنة.
لمراقبة جميع الأحداث أثناء الاختبار، أنشئ عملية تنفيذ لـ UiAutomation.OnAccessibilityEventListener
وتمريرها إلى setOnAccessibilityEventListener()
.
بعد ذلك، تتلقّى واجهة المستمع اتصالاً بالرمز onAccessibilityEvent()
في كلّ مرة يقع فيها الحدث، وتتلقّى فيه عنصر AccessibilityEvent
يصف الحدث.
هناك مجموعة متنوّعة من العمليات الأخرى التي تعرضها واجهات برمجة تطبيقات UiAutomation
على مستوى منخفض جدًا لتشجيع تطوير أدوات اختبار واجهة المستخدم مثل uiautomator. على سبيل المثال، يمكنك أيضًا استخدام
"UiAutomation
" لتنفيذ ما يلي:
- إدخال أحداث الإدخال
- تغيير اتجاه الشاشة
- أخذ لقطات شاشة
والأهم من ذلك أنّه في أدوات اختبار واجهة المستخدم، تعمل واجهات برمجة التطبيقات UiAutomation
على مستوى التطبيقات المختلفة، على عكس Instrumentation
.
أحداث Systrace للتطبيقات
يضيف نظام التشغيل Android 4.3 الفئة Trace
بطريقتين ثابتتين،
beginSection()
وendSection()
،
اللذين يسمحان لك بتحديد كتل الرموز المراد تضمينها في تقرير systrace. ومن خلال إنشاء أقسام من الرموز البرمجية القابلة للتتبُّع في تطبيقك، توفّر لك سجلات systrace تحليلاً أكثر تفصيلاً لمكان حدوث تباطؤ في تطبيقك.
وللحصول على معلومات عن استخدام أداة Systrace، اقرأ تحليل العرض والأداء باستخدام Systrace.
الأمان
ملف تخزين مفاتيح Android للمفاتيح الخاصة بالتطبيقات
يوفّر Android الآن "موفِّر أمان JavaScript مخصّصًا" في منشأة KeyStore
، تُسمى "متجر مفاتيح Android"، وهي تتيح لك إنشاء وحفظ مفاتيح خاصة يمكن
لتطبيقك الاطّلاع عليها واستخدامها فقط. لتحميل متجر مفاتيح Android، مرِّر
"AndroidKeyStore"
إلى KeyStore.getInstance()
.
لإدارة بيانات الاعتماد الخاصة لتطبيقك في متجر مفاتيح Android، عليك إنشاء مفتاح جديد باستخدام
KeyPairGenerator
مع KeyPairGeneratorSpec
. أولاً، احصل على مثيل KeyPairGenerator
من خلال استدعاء getInstance()
. استدعِ بعدها initialize()
، وامنحه مثيلاً من
KeyPairGeneratorSpec
يمكنك الحصول عليه باستخدام
KeyPairGeneratorSpec.Builder
.
أخيرًا، يمكنك الحصول على KeyPair
من خلال الاتصال على generateKeyPair()
.
تخزين بيانات اعتماد الأجهزة
يتيح Android الآن أيضًا استخدام ميزة التخزين المستنِدة إلى الأجهزة لبيانات اعتماد KeyChain
، ما يوفّر المزيد من الأمان من خلال عدم إتاحة إمكانية استخراج المفاتيح. وهذا يعني أنّه بمجرد أن تكون المفاتيح في مخزن مفاتيح مستندة إلى الأجهزة (عنصر آمن أو وحدة النظام الأساسي الموثوق TPM أو TrustZone)، يمكن استخدامها في عمليات التشفير ولكن لا يمكن تصدير مواد المفاتيح الخاصة. حتى نواة نظام التشغيل لا يمكنها
الوصول إلى هذه المواد الأساسية. على الرغم من أنّ بعض الأجهزة التي تعمل بنظام التشغيل Android لا تتيح إمكانية التخزين على الأجهزة،
يمكنك التحقّق في وقت التشغيل ممّا إذا كانت مساحة التخزين المستنِدة إلى الأجهزة متاحة من خلال الاتصال بـ
KeyChain.IsBoundKeyAlgorithm()
.
نماذج البيان
الميزات المطلوبة التي يمكن تعريفها
أصبحت القيم التالية متوافقة الآن في العنصر <uses-feature>
،
حتى تتمكّن من التأكد من أنّ تطبيقك لا يتم تثبيته إلا على الأجهزة التي توفّر الميزات
التي يحتاجها تطبيقك.
FEATURE_APP_WIDGETS
- يجب أن تتم الإشارة إلى أنّ تطبيقك يوفّر تطبيق مصغّر، ويجب تثبيته فقط على الأجهزة التي تتضمّن شاشة رئيسية أو موقعًا مشابهًا حيث يمكن للمستخدمين تضمين التطبيقات المصغّرة.
مثال:
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- يوضح أنّ تطبيقك يعمل كبديل للشاشة الرئيسية، ويجب تثبيته فقط على الأجهزة التي تتوافق مع تطبيقات الشاشة الرئيسية التابعة لجهات خارجية.
مثال:
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- يجب الإقرار بأنّ تطبيقك يوفّر أسلوب إدخال مخصّصًا (لوحة مفاتيح تم تصميمها باستخدام
InputMethodService
) وأنّه يجب تثبيته فقط على الأجهزة التي تتوافق مع أساليب الإدخال التابعة لجهات خارجية. مثال:<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- يوضح أنّ تطبيقك يستخدم واجهات برمجة تطبيقات Bluetooth Low Energy API، ويجب تثبيته فقط على الأجهزة
القادرة على الاتصال بالأجهزة الأخرى عبر Bluetooth Low Energy.
مثال:
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
أذونات المستخدمين
القيم التالية متوافقة الآن في <uses-permission>
لتعريف الأذونات التي يتطلبها تطبيقك للوصول إلى واجهات برمجة تطبيقات معيّنة.
BIND_NOTIFICATION_LISTENER_SERVICE
- مطلوب لاستخدام واجهات برمجة التطبيقات
NotificationListenerService
الجديدة. SEND_RESPOND_VIA_MESSAGE
- مطلوب لتلقّي
هدف
ACTION_RESPOND_VIA_MESSAGE
.
للحصول على عرض تفصيلي لجميع التغييرات في واجهة برمجة التطبيقات في Android 4.3، يمكنك الاطّلاع على تقرير اختلافات واجهة برمجة التطبيقات.