واجهات برمجة تطبيقات Android 4.3

مستوى واجهة برمجة التطبيقات: 18

الإصدار 4.3 من نظام التشغيل Android (JELLY_BEAN_MR2) هو تحديث لإصدار Jelly Bean يوفّر ميزات جديدة للمستخدمين ومطوّري التطبيقات. يوفر هذا المستند مقدمة لأهم واجهات برمجة التطبيقات الجديدة.

بصفتك مطور تطبيقات، ينبغي لك تنزيل نسخة نظام Android 4.3 ومنصة SDK من SDK Manager في أقرب وقت ممكن. إذا لم يكن لديك جهاز يعمل بالإصدار 4.3 من نظام التشغيل Android لاختبار تطبيقك، استخدِم صورة نظام الإصدار 4.3 من نظام التشغيل Android لاختبار تطبيقك على محاكي Android. ثم أنشئ تطبيقاتك بناءً على نظام Android 4.3 الأساسي لبدء استخدام أحدث واجهات برمجة التطبيقات.

تعديل مستوى واجهة برمجة التطبيقات المستهدَف

لتحسين أداء تطبيقك على الأجهزة التي تعمل بالإصدار 4.3 من نظام التشغيل Android بشكل أفضل، يجب ضبط targetSdkVersion على "18"، وتثبيته على صورة نظام Android 4.3، واختباره، ثم نشر تحديث يتضمّن هذا التغيير.

يمكنك استخدام واجهات برمجة التطبيقات في نظام التشغيل Android 4.3 مع دعم الإصدارات الأقدم أيضًا من خلال إضافة شروط إلى الرمز الخاص بك للتحقق من مستوى واجهة برمجة تطبيقات النظام قبل تنفيذ واجهات برمجة التطبيقات غير المتوافقة مع minSdkVersion. لمعرفة المزيد من المعلومات حول الحفاظ على التوافق مع الأنظمة القديمة، يُرجى الاطّلاع على دعم إصدارات الأنظمة الأساسية المختلفة.

تتوفر أيضًا العديد من واجهات برمجة التطبيقات في مكتبة دعم Android والتي تتيح لك تنفيذ ميزات جديدة على الإصدارات القديمة من النظام الأساسي.

لمزيد من المعلومات حول آلية عمل مستويات واجهة برمجة التطبيقات، يُرجى الاطّلاع على المقالة ما هو مستوى واجهة برمجة التطبيقات؟

تغييرات مهمة في السلوك

إذا نشرت سابقًا تطبيقًا لنظام التشغيل Android، يُرجى العلم بأن تطبيقك قد يتأثر بالتغييرات التي طرأت على نظام التشغيل Android 4.3.

إذا كان تطبيقك يستخدم أهدافًا ضمنية...

قد لا يعمل تطبيقك بشكل صحيح في بيئة ملف شخصي تم فرض قيود عليها.

قد لا تتوفر جميع تطبيقات 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" للارتفاع أو العرض قد يكون قد قدّم تنسيق الفيديو الذي تريده من قبل، قد يؤدي ذلك إلى عرض فيديو أصغر بكثير على نظام التشغيل Android 4.3 والإصدارات الأحدث. لحلّ هذه المشكلة، يجب استبدال "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>:

    <application ...
        android:requiredAccountType="com.example.account.type" >
    

    على سبيل المثال، يستخدم تطبيق Gmail هذه السمة لإيقاف نفسه للملفات الشخصية المحظورة، لأنه يجب ألا يكون البريد الإلكتروني الشخصي للمالك متاحًا للملفات الشخصية المحظورة.

  • اللاسلكي وإمكانية الاتصال

    بلوتوث منخفض الطاقة (جاهز للاستخدام الذكي)

    يوفّر Android الآن تقنية Bluetooth Low Energy (LE) مع واجهات برمجة التطبيقات الجديدة في android.bluetooth. باستخدام واجهات برمجة التطبيقات الجديدة، يمكنك إنشاء تطبيقات Android التي تتصل بالأجهزة الملحقة التي تعمل بالبلوتوث منخفض الطاقة مثل أجهزة مراقبة معدل ضربات القلب وعدادات الخطوات.

    بما أنّ Bluetooth LE هي ميزة من ميزات الأجهزة ولا تتوفّر على جميع الأجهزة التي تعمل بنظام التشغيل Android، عليك الإشارة في ملف البيان إلى عنصر <uses-feature> في "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
    

    إذا كنت على دراية بواجهات برمجة تطبيقات Bluetooth الكلاسيكية في Android، يُرجى العلم أنّ استخدام Bluetooth LE APIs له بعض الاختلافات. والأهم من ذلك أنّ هناك فئة 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. عندما يرصد محوِّل البلوتوث جهازًا ملحقًا بتقنية Bluetooth LE، يتلقّى تطبيق BluetoothAdapter.LeScanCallback طلبًا إلى طريقة onLeScan(). توفّر لك هذه الطريقة كائن BluetoothDevice يمثّل الجهاز الذي تم رصده، وقيمة RSSI للجهاز، ومصفوفة بايت تحتوي على سجلّ الإعلانات الخاص بالجهاز.

    إذا كنت تريد البحث عن أنواع معيّنة فقط من الأجهزة الملحقة، يمكنك بدلاً من ذلك استدعاء startLeScan() وتضمين مصفوفة من عناصر UUID التي تحدّد خدمات GATT المتوافقة مع تطبيقك.

    ملاحظة: يمكنك البحث عن أجهزة Bluetooth LE فقط أو البحث عن أجهزة بلوتوث الكلاسيكية باستخدام واجهات برمجة التطبيقات السابقة. ولا يمكنك البحث عن أجهزة بلوتوث 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) مع محتوى الوسائط من خلال فصل مخاوف إدارة الحقوق الرقمية عن تشغيل الوسائط. على سبيل المثال، يتيح لك فصل واجهة برمجة التطبيقات هذا تشغيل المحتوى المشفَّر على نطاق Waze بدون الحاجة إلى استخدام تنسيق الوسائط Waze. يتيح حل إدارة الحقوق الرقمية هذا أيضًا استخدام نظام التشفير DASH المشترك (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.

    Mipmapping للعناصر القابلة للرسم

    إنّ استخدام صورة mipmap كمصدر للصورة النقطية أو القابلة للرسم هو طريقة بسيطة لتوفير صورة عالية الجودة ومقاييس مختلفة للصور، وهو ما يمكن أن يكون مفيدًا بشكل خاص إذا كنت تتوقع أن يتم تحجيم الصورة أثناء الرسوم المتحركة.

    أتاح نظام Android 4.2 (المستوى 17 من واجهة برمجة التطبيقات) استخدام خرائط mipmap في الفئة Bitmap. ويستبدل Android صور mip في Bitmap عندما يتم توفير مصدر mipmap وتفعيل setHasMipMap(). في الإصدار Android 4.3، يمكنك أيضًا تفعيل خرائط mip لكائن 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. لكل طريقة عرض، تشير الخطوط الحمراء إلى الحدود البصرية، والخطوط الزرقاء إلى حدود المقطع، بينما يشير اللون الوردي إلى الهوامش.

    الشكل 1. تنسيق يستخدم حدود المقطع (تلقائي).

    الشكل 2. تخطيط باستخدام الحدود البصرية.

    لمحاذاة طرق العرض استنادًا إلى حدودها البصرية، اضبط السمة android:layoutMode على "opticalBounds" في أحد التنسيقات الرئيسية. مثلاً:

    <LinearLayout android:layoutMode="opticalBounds" ... >
    

    الشكل 3. عرض مكبر لزر Holo من تسعة رقعة مع حدود بصرية.

    لكي ينجح ذلك، يجب أن تحدد الصور ذات اللاصقات التسع المطبقة على خلفية طرق العرض الحدود البصرية باستخدام خطوط حمراء على طول الجزء السفلي والجانب الأيمن من ملف اللاصقات التسعة (كما هو موضح في الشكل 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.

    أحداث النظام للتطبيقات

    يضيف نظام التشغيل Android 4.3 الفئة Trace بطريقتين ثابتتين، beginSection() وendSection()، وهما تتيحان لك تحديد كتل من الرموز لتضمينها في تقرير 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، يمكنك الاطّلاع على تقرير الاختلافات في واجهة برمجة التطبيقات.