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

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

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

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

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

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

يمكنك استخدام واجهات برمجة التطبيقات في 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.

تطبيق "VideoView" المصغّر بشكلٍ غير صحيح في الإصدارات السابقة من Android تم حساب القيمة "wrap_content" لـ layout_height وlayout_width لتكون القيمة نفسها لـ "match_parent". وبالتالي، على الرغم من أنّ استخدام "wrap_content" للارتفاع أو العرض قد يقدّم لك تنسيق الفيديو المطلوب، قد يؤدي ذلك إلى ظهور فيديو أصغر حجمًا على الإصدار 4.3 من نظام التشغيل Android والإصدارات الأحدث. لحلّ هذه المشكلة، استبدِل "wrap_content" بـ "match_parent" وتأكَّد من ظهور الفيديو على النحو المتوقّع على Android 4.3 والإصدارات الأقدم.

الملفات الشخصية المحظورة

على أجهزة 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" >

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

  • إيقاف وظائف معيّنة عند عدم التمكّن من تعديل الحسابات

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

  • الاتصال اللاسلكي

    بلوتوث منخفض الطاقة (Smart Ready)

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

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

    ملاحظة: يمكنك البحث فقط عن أجهزة Bluetooth LE أو للبحث عن أجهزة بلوتوث الكلاسيكية باستخدام واجهات برمجة التطبيقات السابقة. لا يمكنك إجراء بحث عن كل من LE والإصدار الكلاسيكي. أجهزة البلوتوث في آنٍ واحد.

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

    للحصول على هذا الغرض، يجب تقديم بيان عن إذن "SEND_RESPOND_VIA_MESSAGE".

    وسائط متعددة

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

    يمكنك استخدام MediaDrm للحصول على رسائل طلب مفتاح غير مفهومة ومعالجتها من الخادم للحصول على التراخيص وتوفيرها تطبيقك المسئولة عن التعامل مع اتصال الشبكة بالخوادم؛ أمّا الفئة MediaDrm، فتتيح إنشاء الرسائل ومعالجتها فقط.

    تم تصميم واجهات برمجة تطبيقات MediaDrm لاستخدامها مع واجهات برمجة تطبيقات MediaCodec التي تم طرحها في Android 4.1 (المستوى 16 من واجهة برمجة التطبيقات)، بما في ذلك MediaCodec لتشفير المحتوى وفك تشفيره، وMediaCrypto لمعالجة المحتوى المشفَّر، وMediaExtractor لاستخراج المحتوى وإزالة الترميز منه.

    يجب أولاً إنشاء كائنَي MediaExtractor و MediaCodec. يمكنك بعد ذلك الوصول إلى واجهة برمجة التطبيقات DRM-scheme-identizing UUID، عادةً من البيانات الوصفية في المحتوى، ويمكنك استخدامها لإنشاء مثال لكائن MediaDrm مع الدالة الإنشائية له.

    ترميز الفيديو من جهاز Surface

    أضاف نظام التشغيل Android 4.1 (المستوى 16 من واجهة برمجة التطبيقات) فئة MediaCodec لتشفير محتوى الوسائط وفك تشفيره على مستوى منخفض. عند ترميز الفيديو، يتطلب Android 4.1 توفيره الوسائط مع مصفوفة ByteBuffer، لكنّ الإصدار Android 4.3 يتيح لك الآن استخدام Surface كمدخل لبرنامج الترميز. على سبيل المثال، يتيح لك ذلك ترميز الإدخال من ملف فيديو حالي أو باستخدام إطارات تم إنشاؤها باستخدام OpenGL ES.

    لاستخدام Surface كمدخل لبرنامج الترميز، يُرجى أولاً الاتصال بالرقم configure() للحصول على MediaCodec. بعد ذلك، اتّصِل بـ createInputSurface() لتلقّي Surface الذي يمكنك من خلاله بث الوسائط.

    على سبيل المثال، يمكنك استخدام Surface المحدَّد كنافذة لسياق OpenGL من خلال تمريرها إلى eglCreateWindowSurface(). وأثناء عرض السطح، اطلب eglSwapBuffers() لتمرير الإطار إلى MediaCodec.

    لبدء عملية الترميز، يُرجى الاتصال برقم start() على MediaCodec. عند الانتهاء، اتصل برقم signalEndOfInputStream() لإنهاء عملية التشفير، ثم اتصل برقم release() على الرقم Surface.

    ربط الوسائط

    تتيح فئة MediaMuxer الجديدة إمكانية تعدد الإشارات بين مجموعة بث صوتي واحدة ومجموعة بث فيديو واحدة. تعمل واجهات برمجة التطبيقات هذه كنظير لـ MediaExtractor تمت إضافة الفئة في الإصدار 4.2 من نظام التشغيل Android لإزالة تعدد الإرسال (إزالة تعدد الإرسال).

    يتم تحديد تنسيقات الإخراج المتوافقة في MediaMuxer.OutputFormat. في الوقت الحالي، يعدّ تنسيق MP4 هو تنسيق الإخراج الوحيد المتوافق، ولا يتيح تطبيق MediaMuxer حاليًا سوى بث صوتي واحد و/أو بث فيديو واحد في المرة الواحدة.

    تم تصميم تطبيق "MediaMuxer" في الغالب للعمل مع "MediaCodec". لتتمكن من معالجة الفيديو حتى MediaCodec ثم احفظ إلى ملف MP4 من خلال MediaMuxer. يمكنك أيضًا استخدام MediaMuxer مع MediaExtractor لتنفيذ تعديل الوسائط بدون الحاجة إلى ترميزها أو فك ترميزها

    مستوى تقدُّم التشغيل والالتمرير على واجهة برمجة التطبيقات RemoteControlClient

    في الإصدار 4.0 من نظام التشغيل Android (المستوى 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، يمكنك الآن تفعيل خرائط MIP لعنصر BitmapDrawable أيضًا، من خلال تقديم مادة عرض خريطة MIP و ضبط السمة 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: صورة مصغَّرة لزر هولو بتسع حزم الحدود البصرية.

    لكي يعمل هذا الإجراء، يجب أن تحدِّد صور "التقسيم إلى تسعة أقسام" التي يتم تطبيقها على خلفية طرق العرض الحدّ الأقصى للعرض باستخدام خطوط حمراء على طول الجزء السفلي والجانب الأيمن من ملف "التقسيم إلى تسعة أقسام" (كما هو موضح في الشكل 3). تشير الخطوط الحمراء إلى المنطقة التي يجب طرحها من حدود المقطع، مع ترك الحدود البصرية للصورة.

    عند تفعيل الحدود البصرية لعنصر ViewGroup في التنسيق، تكتسِب جميع الاطِّلاعات الفرعية وضع تنسيق الحدود البصرية ما لم تلغي ذلك لمجموعة من خلال ضبط android:layoutMode على "clipBounds". تلتزم أيضًا جميع عناصر التنسيق بحدود الرؤية البصرية للعناصر الفرعية، مع تعديل حدودها استنادًا إلى حدود الرؤية البصرية للعناصر المضمّنة فيها. ولكن عناصر التنسيق (الفئات الفرعية من ViewGroup) لا تتيح في الوقت الحالي استخدام الحدود البصرية للصور المكوَّنة من تسع أجزاء يتم تطبيقها على الخلفية الخاصة بها.

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

    ملاحظة: تم تحديث جميع التطبيقات المصغّرة المتوافقة مع مظهر Holo. بحدود بصرية، بما في ذلك Button وSpinner EditText وآخرون لذا يمكنك الاستفادة على الفور من خلال تعيين السمة android:layoutMode إلى "opticalBounds" إذا كان تطبيقك يطبّق مظهرًا شاملاً (Theme.Holo أو Theme.Holo.Light أو غير ذلك).

    لتحديد الحدود البصرية لصورك المكوّنة من تسعة أقسام باستخدام أداة رسم صورة مكوّنة من تسعة أقسام، اضغط مع الاستمرار على مفتاح Ctrl عند النقر على وحدات البكسل في الحدود.

    الصور المتحركة لقيم Rect

    يمكنك الآن إنشاء تأثيرات متحركة بين قيمتَي 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

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

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

    الإفصاح عن ميزات تسهيل الاستخدام

    بدءًا من Android 4.3، يجب أن توضّح خدمة تسهيل الاستخدام إمكانات إمكانية الوصول في ملف بياناتها الوصفية من أجل استخدام بعض ميزات إمكانية الوصول. إذا لم يتم طلب الميزة في ملف البيانات الوصفية، لن تعمل. ولإعلان ميزات تسهيل الاستخدام في خدمتك، يجب استخدام سمات XML التي تتوافق مع ثوابت "capability" المختلفة في فئة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، يُرجى الاطّلاع على تحليل العرض والأداء من خلال النظام الأساسي.

    الأمان

    ملف تخزين مفاتيح Android للمفاتيح الخاصة للتطبيقات

    يوفّر Android الآن "مزوّد أمان Java مخصّص" في KeyStore. يُعرف باسم "متجر مفاتيح Android"، ويتيح لك إنشاء وحفظ مفاتيح خاصة يمكن الاطّلاع عليها واستخدامها من خلال تطبيقك فقط. لتحميل ملف تخزين مفاتيح Android، عليك اجتياز من "AndroidKeyStore" إلى KeyStore.getInstance().

    لإدارة بيانات الاعتماد الخاصة لتطبيقك في Android Key Store، يمكنك إنشاء مفتاح جديد باستخدام "KeyPairGenerator" مع "KeyPairGeneratorSpec" أولاً، احصل على مثيل من KeyPairGenerator من خلال استدعاء getInstance(). بعد ذلك، يمكنك استدعاء initialize() مع تمرير مثيل KeyPairGeneratorSpec إليه، والذي يمكنك الحصول عليه باستخدام KeyPairGeneratorSpec.Builder. وأخيرًا، احصل على KeyPair من خلال الاتصال بالرقم generateKeyPair().

    وحدة تخزين بيانات الاعتماد على الجهاز

    يتيح نظام التشغيل Android الآن أيضًا مساحة تخزين مستندة إلى الأجهزة لبيانات اعتمادك على KeyChain ، ما يوفر المزيد من الأمان من خلال جعل المفاتيح غير متاحة للاستخراج. أي مرة واحدة في مخزن مفاتيح يدعم الأجهزة (Secure Element أو 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 وأنّه يجب تثبيته على الأجهزة فقط التي يمكنها التواصل مع الأجهزة الأخرى عبر 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، يمكن الاطّلاع على تقرير اختلافات واجهة برمجة التطبيقات