تحذير: تم إيقاف OpenSL ES نهائيًا. على المطوّرين استخدام مكتبة Oboe المفتوحة المصدر المتوفّرة على GitHub. Oboe هو برنامج تضمين لـ C++ يقدّم واجهة برمجة تطبيقات تشبه إلى حد كبير AAudio. يُطلِق Oboe مكتبة AAudio عندما تكون متاحة، ويستخدم OpenSL ES كحل احتياطي إذا لم تكن AAudio متاحة.
تكمل الملاحظات الواردة في هذا القسم مواصفات OpenSL ES 1.0.1.
الكائنات وتهيئة الواجهة
هناك جانبان من نموذج البرمجة OpenSL ES قد لا يكونان معروفَين للمطوّرين الجدد، وهما التمييز بين العناصر الواجهات وتسلسل الإعداد.
باختصار، يشبه كائن OpenSL ES مفهوم الكائن في لغات البرمجة مثل Java وC++ ، باستثناء كائن OpenSL ES الذي لا يظهر إلا من خلال الواجهات المرتبطة به.
ويتضمّن ذلك الواجهة الأولية لجميع الكائنات المسماة SLObjectItf
.
لا يتوفَّر مقبض للكائن نفسه، بل هو مجرّد مقبض لواجهة SLObjectItf
الخاصة بالكائن.
يتم أولاً إنشاء عنصر OpenSL ES، ما يؤدي إلى عرض SLObjectItf
، ثم تتم إدراكه. يشبه ذلك نمط البرمجة الشائع المتمثل في إنشاء
عنصر أولاً (الذي لا يجب أن يتعطّل أبدًا إلا بسبب نقص الذاكرة أو المَعلمات غير الصالحة)، ثم
إكمال عملية الإعداد (التي قد تتعذّر بسبب نقص الموارد). تمنح خطوة التنفيذ
التنفيذ مكانًا منطقيًا لتخصيص موارد إضافية إذا لزم الأمر.
يحدد التطبيق مصفوفة من الواجهات المطلوبة التي يخطط للحصول عليها لاحقًا كجزء من واجهة برمجة التطبيقات لإنشاء عنصر. يُرجى العلم أنّ هذه الصفيف لا تُكتسَب تلقائيًا الواجهات، بل تشير فقط إلى نية مستقبلية للحصول عليها. يتم تمييز الواجهات على أنّها ضمنية أو واضحة. يجب إدراج واجهة صريحة في الصفيف إذا كانت ستتمّ اكتسابها لاحقًا. لا يلزم إدراج واجهة ضمنية في صفيف إنشاء الكائن، ولكن لا ضرر في إدراجها هناك. يحتوي OpenSL ES على نوع آخر من الواجهات يُسمى ديناميكي، ولا يلزم تحديده في صفيف إنشاء الكائن، ويمكن إضافته لاحقًا بعد إنشاء الكائن. يقدّم تطبيق Android ميزة سهولة الاستخدام لتجنّب هذا التعقيد، كما هو موضّح في الواجهات الديناميكية عند إنشاء العناصر.
بعد إنشاء الكائن وتنفيذه، يجب أن يحصل التطبيق على واجهات لكل
ميزة يحتاج إليها، وذلك باستخدام GetInterface
في SLObjectItf
الأوّلي.
أخيرًا، يتوفّر الكائن للاستخدام من خلال واجهاته، مع العلم أنّه تتطلّب بعض الكائنات إعدادًا إضافيًا. على وجه الخصوص، يحتاج مشغّل الصوت الذي يستخدم مصدر بيانات URI إلى مزيد من الإعدادات لرصد أخطاء الاتصال. راجِع القسم التحميل المُسبَق لمشغّل الصوت للحصول على التفاصيل.
بعد الانتهاء من التطبيق باستخدام الكائن، يجب عليك إتلافه بشكل صريح، ويمكنك الاطّلاع على القسم التدمير أدناه.
ميزة "التحميل المُسبَق" لمشغّل الصوت
بالنسبة إلى مشغّل الصوت الذي يتضمّن مصدر بيانات معرّف الموارد المنتظم (URI)، يخصّص Object::Realize
الموارد ولكنّه لا
يربط بمصدر البيانات (الإعداد) أو يبدأ جلب البيانات مسبقًا. وتحدث هذه المشاكل عند ضبط
حالة المشغّل على SL_PLAYSTATE_PAUSED
أو SL_PLAYSTATE_PLAYING
.
قد تظل بعض المعلومات غير معروفة حتى وقت متأخر نسبيًا في هذا التسلسل. على وجه الخصوص، تعرض الدالة Player::GetDuration
في البداية SL_TIME_UNKNOWN
وإما MuteSolo::GetChannelCount
بنجاح مع عدد القنوات صفر أو نتيجة الخطأ SL_RESULT_PRECONDITIONS_VIOLATED
. تعرض واجهات برمجة التطبيقات هذه القيم المناسبة
بعد أن تصبح معروفة.
تشمل السمات الأخرى غير المعروفة في البداية معدّل أخذ العينات و نوع محتوى الوسائط الفعلي استنادًا إلى فحص عنوان المحتوى (بدلاً من نوع MIME و نوع الحاوية المحدّدَين من التطبيق). ويتم تحديد هذه العناصر أيضًا لاحقًا أثناء مرحلة التحضير/التحميل المُسبَق، ولكن لا تتوفّر واجهات برمجة تطبيقات لاستردادها.
تُعد واجهة حالة الجلب المُسبَق مفيدة لرصد جميع المعلومات أو توفُّرها في تطبيقك بشكل دوري. يُرجى العلم أنّ بعض المعلومات، مثل مدة بث محتوى MP3، قد غير معروفة.
تكون واجهة حالة الجلب المُسبَق مفيدة أيضًا لرصد الأخطاء. تسجيل معاودة الاتصال وتفعيل حدثَي SL_PREFETCHEVENT_FILLLEVELCHANGE
وSL_PREFETCHEVENT_STATUSCHANGE
على الأقل إذا تم إرسال كلا الحدثَين في الوقت نفسه، وتسجيل
PrefetchStatus::GetFillLevel
لمستوى صفري، وتسجيل
PrefetchStatus::GetPrefetchStatus
لقيمة SL_PREFETCHSTATUS_UNDERFLOW
،
يعني ذلك أنّه
حدث خطأ لا يمكن تصحيحه في مصدر البيانات. ويشمل ذلك عدم التمكّن من
الاتصال بأحد
مصادر البيانات لأنّ اسم الملف المحلي غير متوفّر أو لأنّ معرّف الموارد الموحّد للشبكة غير صالح.
من المتوقّع أن يضيف الإصدار التالي من OpenSL ES مزيدًا من الدعم الواضح لمعالجة الأخطاء في مصدر البيانات. مع ذلك، بالنسبة إلى التوافق الثنائي في المستقبل، سنواصل إتاحة الطريقة الحالية للإبلاغ عن خطأ غير قابل للإصلاح.
باختصار، تسلسل الرموز المقترَح هو:
Engine::CreateAudioPlayer
Object:Realize
Object::GetInterface
لـSL_IID_PREFETCHSTATUS
PrefetchStatus::SetCallbackEventsMask
PrefetchStatus::SetFillUpdatePeriod
PrefetchStatus::RegisterCallback
Object::GetInterface
لـSL_IID_PLAY
- من
Play::SetPlayState
إلىSL_PLAYSTATE_PAUSED
، أوSL_PLAYSTATE_PLAYING
ملاحظة: يتمّ إجراء الإعداد والتحميل المُسبَق هنا، وخلال هذه الفترة يتمّ استدعاء دالة الاستدعاء مع تلقي رسائل تنقُّل منتظمة بشأن الحالة.
تدمير
احرص على تدمير جميع العناصر عند الخروج من تطبيقك. يجب تدمير العناصر في الترتيب العكسي لإنشاءها، لأنّه ليس من الآمن تدمير عنصر يحتوي على أي عناصر تابعة. على سبيل المثال، يمكنك الحذف بالترتيب التالي: مشغّلات ومسجلات الصوت، ومزيج الإخراج، ثم أخيرًا المحرّك.
لا توفّر مكتبة OpenSL ES ميزة جمع المهملات التلقائي أو
احتساب مراجع الواجهات. بعد استدعاء Object::Destroy
، تصبح جميع الواجهات المتبقية المستمدة من الكائن المرتبط غير محددة.
لم يرصد تطبيق Android OpenSL ES الاستخدام غير الصحيح لهذه الواجهات. يمكن أن يؤدي مواصلة استخدام هذه الواجهات بعد إتلاف العنصر إلى تعطُّل تطبيقك أو بدء سلوكه بطرق غير متوقَّعة.
ننصحك بضبط واجهة الكائن الأساسية وجميع الواجهات المرتبطة
عليها صراحةً على NULL
كجزء من تسلسل تدمير الكائن، ما يمنع
إساءة استخدام معرّف واجهة قديم عن طريق الخطأ.
التقديم والترجيع الصوتي الاستيريو
عند استخدام السمة Volume::EnableStereoPosition
لتفعيل تصوير استيريو لمصدر أحادي، يتم خفض إجمالي
مستوى طاقة الصوت بمقدار 3 ديسيبل. ويُعدّ ذلك ضروريًا للسماح ببقاء إجمالي مستوى طاقة الصوت ثابتًا عند نقل مصدره من قناة إلى أخرى. لذلك، يجب تفعيل ميزة تحديد الموقع الاستيريو فقط إذا كنت بحاجة إليها. لمزيد من المعلومات، يمكنك الاطّلاع على مقالة ويكيبيديا حول
إزاحة الصوت.
عمليات الاستدعاء وسلاسل المحادثات
يتم استدعاء معالجات طلب الاستدعاء بشكل عام بشكل متزامن عندما يرصد التنفيذ أحد الأحداث. هذه النقطة غير متزامنة مع التطبيق، لذا عليك استخدام آلية معالجة ملف شخصي غير حظر للتحكم في الوصول إلى أي متغيّرات تتم مشاركتها بين التطبيق ومعالج الاستدعاء. في نموذج الرمز البرمجي، مثل قوائم انتظار المخزن المؤقت، إما أننا أغفلنا عملية المزامنة هذه أو استخدمنا حظر المزامنة حرصًا على البساطة. ومع ذلك، فإنّ المزامنة المناسبة غير المانعة للوصول إلى البيانات هي أمر بالغ الأهمية لأي رمز برمجي مخصّص للإصدار العلني.
يتم طلب معالِجات معاودة الاتصال من سلاسل محادثات داخلية غير مخصَّصة للتطبيقات وغير مرتبطة ببيئة تشغيل Android، وبالتالي تكون هذه المعالِجات غير مؤهَّلة لاستخدام خوارزمية JNI. ولأنّ هذه المواضيع الداخلية مهمة لسلامة تنفيذ OpenSL ES، يجب ألّا تحظر معالجات الاستدعاء أيضًا تنفيذ مهمة زائدة أو تؤدي إلى ذلك.
إذا كان معالج معاودة الاتصال يحتاج إلى استخدام JNI أو تنفيذ عمل لا يتناسب مع معاودة الاتصال، يجب أن ينشر المعالج حدثًا بدلاً من ذلك حتى تتم معالجة سلسلة محادثات أخرى. تشمل أمثلة عبء العمل المقبول لوظائف ردّ الاتصال عرض وإضافة العنصر التالي إلى قائمة الانتظار في وحدة تخزين الإخراج (لتطبيق AudioPlayer)، أو معالجة وحدة تخزين الإدخال التي تم ملؤها للتو وإضافة العنصر التالي إلى قائمة الانتظار في وحدة تخزين فارغة (لتطبيق AudioRecorder)، أو واجهات برمجة تطبيقات بسيطة مثل معظم عائلة Get. اطّلِع على القسم الأداء أدناه لمعرفة المزيد من المعلومات عن حجم العمل.
يُرجى العلم أنّ العكس آمن: يُسمح لسلسلة مهام تطبيق Android التي دخلت JNI باستدعاء واجهة برمجة التطبيقات OpenSL ES مباشرةً، بما في ذلك تلك التي تحظر. ومع ذلك، لا يُنصح بإجراء عمليات حظر من سلسلة التعليمات الرئيسية، لأنّها قد تؤدي إلى خطأ "التطبيق لا يستجيب" (ANR).
يعود القرار إلى حد كبير بشأن سلسلة المحادثات التي تستدعي معالج معاودة الاتصال. وسبب هذه المرونة هو السماح بإجراء تحسينات مستقبلية، لا سيما على الأجهزة المتعددة النواة.
لا يمكن ضمان أن يكون للسلسلة المُهمّة التي يتم فيها تنفيذ معالِج الاستدعاء الهوية نفسها في
عمليات الاستدعاء المختلفة. لذلك، لا تعتمد على pthread_t
التي يعرضها pthread_self()
أو pid_t
التي تعرضها gettid()
لتكون متسقة في جميع المكالمات. وللسبب نفسه، لا تستخدِم واجهات برمجة تطبيقات مساحة التخزين المحلية للسلسلة (TLS) مثل
pthread_setspecific()
وpthread_getspecific()
من دالة استدعاء.
يضمن التنفيذ عدم حدوث طلبات استدعاء متوازية من النوع نفسه للعنصر نفسه. ومع ذلك، من الممكن أن تكون هناك عمليات استدعاء متوازية من أنواع مختلفة للكائن نفسه على سلاسل محادثات مختلفة.
الأداء
بما أنّ OpenSL ES هي واجهة برمجة تطبيقات أصلية لـ C، لا تُعرّض سلاسل مهام التطبيقات غير المخصّصة لوقت التشغيل التي تستدعي OpenSL ES أيّ تكلفة إضافية مرتبطة بوقت التشغيل، مثل فترات التوقف في جمع المهملات. باستثناء واحد موضّح أدناه، لا تتوفّر ميزة أداء إضافية لاستخدام OpenSL ES غير ذلك. على وجه التحديد، لا يضمن استخدام OpenSL ES تحسينات، مثل تقليل وقت استجابة الصوت ومنح الأولوية لجدولة المهام بشكلٍ أكبر مما يوفّره النظام الأساسي بشكلٍ عام. من ناحية أخرى، مع استمرار تطوير نظام Android وعمليات التنفيذ على أجهزة معيّنة، يمكن أن يستفيد تطبيق OpenSL ES من أي تحسينات مستقبلية في أداء النظام.
ومن بين هذه التطورات، إتاحة ميزة تقليل
وقت استجابة إخراج الصوت.
تم تضمين الاعتبارات الأساسية لتقليل وقت استجابة معدلات التشغيل أولاً في Android 4.1 (المستوى 16 لواجهة برمجة التطبيقات)، ثم تم مواصلة التقدم في Android 4.2 (المستوى 17 لواجهة برمجة التطبيقات). تتوفّر هذه التحسينات من خلال
OpenSL ES لعمليات تنفيذ الأجهزة التي
تدّعي توفّر الميزة android.hardware.audio.low_latency
.
إذا لم يكن الجهاز يقدّم هذه الميزة ولكنه متوافق مع Android 2.3 (المستوى 9 من واجهة برمجة التطبيقات)
أو الإصدارات الأحدث، سيظل بإمكانك استخدام واجهات برمجة التطبيقات OpenSL ES ولكن قد يكون وقت استجابة الإخراج أعلى.
لا يتم استخدام مسار زمن الاستجابة المنخفض للعُجلة إلا إذا طلب التطبيق حجم ذاكرة تخزين مؤقت ومعدّل أخذ العينات
اللذين يتوافقان مع إعدادات الإخراج الأصلية للجهاز. وهذه المعلَمات خاصة بكل جهاز ويجب الحصول عليها على النحو الموضّح أدناه.
بدءًا من الإصدار 4.2 من Android (المستوى 17 لواجهة برمجة التطبيقات)، يمكن للتطبيق الاستعلام عن معدل تقاطر الإخراج الأمثل أو التلقائي للنظام الأساسي وحجم المخزن المؤقت لمصدر الإخراج الأساسي للجهاز. عند دمج اختبار الميزات الذي ذكرناه للتو، يمكن للتطبيق الآن ضبط نفسه بشكل مناسب لعرض وقت استجابة أقل على الأجهزة التي تدعي توفُّر الميزة.
بالنسبة إلى نظام التشغيل Android 4.2 (المستوى 17 من واجهة برمجة التطبيقات) والإصدارات الأقدم، يجب أن يكون عدد المخزونات المؤقتة اثنين أو أكثر لخفض وقت الاستجابة. بدءًا من الإصدار 4.3 من نظام التشغيل Android (المستوى 18 لواجهة برمجة التطبيقات)، يكفي استخدام ملف مؤقت واحد لخفض وقت الاستجابة.
تمنع جميع واجهات OpenSL ES لتأثيرات الإخراج مسار وقت الاستجابة الأقل.
التسلسل المقترَح هو على النحو التالي:
- تحقَّق من توفُّر المستوى 9 من واجهة برمجة التطبيقات أو مستوى أعلى لتأكيد استخدام OpenSL ES.
- تحقق من الميزة
android.hardware.audio.low_latency
باستخدام رمز مثل هذا:Kotlin
import android.content.pm.PackageManager ... val pm: PackageManager = context.packageManager val claimsFeature: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
Java
import android.content.pm.PackageManager; ... PackageManager pm = getContext().getPackageManager(); boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
- تحقَّق من توفّر المستوى 17 من واجهة برمجة التطبيقات أو مستوى أعلى لتأكيد استخدام
android.media.AudioManager.getProperty()
. - يمكنك الحصول على معدل أخذ العينات الأصلي أو الأمثل للإخراج وحجم المخزن المؤقت لمصدر الإخراج
الأساسي
لهذا الجهاز باستخدام رمز مثل هذا:
Kotlin
import android.media.AudioManager ... val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager val sampleRate: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE) val framesPerBuffer: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
Java
import android.media.AudioManager; ... AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
sampleRate
وframesPerBuffer
سلسلتان. تحقَّق أولاً من القيمة "null" (فارغ) ثم التحويل إلى عدد صحيح باستخدامInteger.parseInt()
. - استخدِم الآن OpenSL ES لإنشاء AudioPlayer مع أداة تحديد بيانات قائمة انتظار مخزن مؤقت PCM.
ملاحظة: يمكنك استخدام تطبيق اختبار حجم مخزن الصوت لتحديد حجم المخزن الأصلي ومعدّل أخذ العينات لتطبيقات معالجة الصوت OpenSL ES على جهاز الصوت. يمكنك أيضًا الانتقال إلى GitHub للاطّلاع على عينات من حجم المخزن المؤقت للصوت.
إنّ عدد مشغّلات الصوت ذات وقت الاستجابة المنخفض محدود. إذا كان تطبيقك يتطلب أكثر من بضعة مصادر صوت، ننصحك بمزج الصوت على مستوى التطبيق. احرص على إتلاف المشغّلات الصوتية عند إيقاف نشاطك مؤقتًا، فهي مورد عام تتم مشاركته مع تطبيقات أخرى.
لتجنّب حدوث مشاكل صوتية، يجب تنفيذ معالِج طلب الاستدعاء في قائمة الانتظار المؤقتة خلال فترة زمنية صغيرة و قابلة للتوقّع. ويعني ذلك عادةً عدم حظر عمليات قفل المهام المتعدّدة أو الشروط أو عمليات الإدخال/الإخراج بشكل غير محدود. بدلاً من ذلك، ننصحك باستخدام محاولات القفل والقفل والانتظار مع مهلات، و الخوارزميات غير المحظورة.
يجب أن يستغرق الحساب المطلوب لعرض المخزن المؤقت التالي (لتطبيق AudioPlayer) أو استخدام المخزن المؤقت السابق (لتطبيق AudioRecord) المدة نفسها تقريبًا لكل وظيفة استدعاء. تجنَّب الخوارزميات التي يتم تنفيذها في فترة زمنية غير محدّدة أو مكثفة في عمليات الحساب. يكون احتساب طلب الاستدعاء متقطّعًا إذا كان وقت وحدة المعالجة المركزية المستغرَق في أي طلب استدعاء معيّن أكبر بكثير من المتوسط. باختصار، يكمن الخيار المثالي في أن يكون وقت تنفيذ وحدة المعالجة المركزية (CPU) للمعالج مرتفعًا بشكل قريب من الصفر، وألا يحظر المعالِج الأوقات غير المحدودة.
يمكن خفض وقت استجابة الصوت في مصادر الإخراج التالية فقط:
- مكبّرات الصوت على الجهاز
- سماعات رأس سلكية
- سماعات الرأس السلكية
- انسحب من المحادثة.
- مكبّر صوت رقمي عبر USB
في بعض الأجهزة، يكون وقت استجابة مكبّر الصوت أعلى من المسارات الأخرى بسبب معالجة الإشارات الرقمية لتعديل ملف صوت المكبّر وحمايته.
بدءًا من الإصدار Android 5.0 (مستوى واجهة برمجة التطبيقات 21)، أصبح الإدخال الصوتي
بوقت استجابة بطيء متاحًا على أجهزة محدّدة. للاستفادة من هذه الميزة، تأكَّد أولاً من توفُّر إخراج بوقت استجابة أقل كما هو موضّح أعلاه. إنّ إمكانية عرض المحتوى بوقت استجابة منخفض
هي شرط أساسي لميزة إدخال المحتوى بوقت استجابة منخفض. بعد ذلك، أنشئ AudioRecorder باستخدام معدل الصعق الكهربي
وحجم المخزن المؤقت نفسهما اللذَين سيتم استخدامهما في الإخراج. واجهات OpenSL ES لتأثيرات الإدخال
تمنع استخدام مسار وقت الاستجابة المنخفض. يجب استخدام الإعداد المُسبَق لتسجيل المحتوى
SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
لتقليل وقت الاستجابة، إذ يؤدي هذا الإعداد المُسبَق إلى إيقاف معالجة الإشارات الرقمية الخاصة بالجهاز والتي قد تضيف وقت استجابة إلى مسار الإدخال.
لمزيد من المعلومات عن الإعدادات المُسبَقة للتسجيل، يُرجى الاطّلاع على القسم
واجهة إعدادات Android أعلاه.
للإدخال والإخراج المتزامنين، يتم استخدام عناصر معالجة منفصلة لإكمال صفوف انتظار المخزن المؤقت لكل جانب. لا يمكن ضمان الترتيب النسبي لهذه طلبات إعادة الاتصال أو مزامنة ساعات الصوت، حتى عندما يستخدم كلا الجانبَين معدّل أخذ العينات نفسه. يجب أن يخزِّن تطبيقك البيانات في ذاكرة التخزين المؤقت مع مزامنة ذاكرة التخزين المؤقت المناسبة.
تتمثل إحدى نتائج الساعات الصوتية التي يُحتمل أن تكون مستقلة في الحاجة إلى تحويل معدّل العيّنة غير المتزامن. إنّ إحدى الطرق البسيطة (ولكنها ليست مثالية لجودة الصوت) لإجراء عملية تحويل معدل أخذ العينات غير المتزامن هي تكرار العيّنات أو إسقاطها حسب الحاجة بالقرب من نقطة عبور الصفر. فمن الممكن إجراء إحالات ناجحة أكثر تعقيدًا.
أوضاع الأداء
بدءًا من الإصدار 7.1 من Android (المستوى 25 لواجهة برمجة التطبيقات)، وفّرت مكتبة OpenSL ES طريقة لتحديد وضع الأداء لمسار الصوت. الخيارات هي:
SL_ANDROID_PERFORMANCE_NONE
: ما مِن متطلبات محدَّدة للأداء. يسمح بتأثيرات الأجهزة والبرامج.SL_ANDROID_PERFORMANCE_LATENCY
: يتم منح الأولوية لوقت الاستجابة. ليس هناك تأثيرات للأجهزة أو البرامج. وهذا هو الوضع التلقائي.SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS
: يتم منح الأولوية لوقت الاستجابة مع السماح بتأثيرات الأجهزة والبرامج.SL_ANDROID_PERFORMANCE_POWER_SAVING
: الأولوية الممنوحة للحفاظ على الطاقة يسمح بتأثيرات الأجهزة والبرامج.
ملاحظة: إذا لم تكن بحاجة إلى مسار يتميز بوقت استجابة منخفض وأردت الاستفادة
من المؤثرات الصوتية المدمجة في الجهاز (على سبيل المثال، لتحسين الجودة الصوتية
لتشغيل الفيديو)، عليك ضبط وضع الأداء على
SL_ANDROID_PERFORMANCE_NONE
بشكل صريح.
لضبط وضع الأداء، عليك استدعاء SetConfiguration
باستخدام واجهة إعدادات Android
، كما هو موضّح أدناه:
// Obtain the Android configuration interface using a previously configured SLObjectItf. SLAndroidConfigurationItf configItf = nullptr; (*objItf)->GetInterface(objItf, SL_IID_ANDROIDCONFIGURATION, &configItf); // Set the performance mode. SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE; result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(performanceMode));
الأمان والأذونات
بقدر ما يمكن للمستخدمين تنفيذ هذا الإجراء، يتم تعزيز الأمان في Android على مستوى العمليات. لا يمكن لشفرة لغة البرمجة Java تنفيذ أي شيء بخلاف الرمز الأصلي، ولا يمكن للبرمجة الأصلية أن تفعل أي شيء أكثر من رمز لغة البرمجة Java. والاختلافات الوحيدة بينهما هي واجهات برمجة التطبيقات المتاحة.
على التطبيقات التي تستخدم OpenSL ES طلب الأذونات التي تحتاجها لواجهات برمجة التطبيقات المشابهة
غير الأصلية. على سبيل المثال، إذا كان تطبيقك يسجّل الصوت، سيحتاج إلى
إذن android.permission.RECORD_AUDIO
. تحتاج التطبيقات التي تستخدم التأثيرات الصوتية إلى
android.permission.MODIFY_AUDIO_SETTINGS
. تحتاج التطبيقات التي تشغِّل موارد معرّف الموارد المنتظم (URI) للشبكة
إلى android.permission.NETWORK
. لمزيد من المعلومات، يُرجى الاطّلاع على استخدام أذونات النظام.
استنادًا إلى إصدار النظام الأساسي وطريقة التنفيذ، قد يتم تنفيذ برامج فك ترميز البرامج ومعالجات محتوى الوسائط في سياق تطبيق Android الذي يستدعي OpenSL ES (يتم تجميع برامج فك ترميز الأجهزة بشكل مجرد ولكنها تعتمد على الجهاز). إنّ المحتوى الذي يتضمّن تنسيقًا غير صحيح ومصمّم لاستغلال ثغرات في برامج الترميز وتحليل المحتوى هو أحد أدوات الهجوم المعروفة. ننصحك بتشغيل الوسائط من مصادر موثوق بها فقط أو تقسيم تطبيقك بحيث يتم تشغيل الرمز البرمجي الذي يعالج الوسائط من مصادر غير موثوق بها في بيئة وضع الحماية نسبيًا. على سبيل المثال، يمكنك معالجة الوسائط من مصادر غير جديرة بالثقة في عملية منفصلة. على الرغم من أن كلتا العمليتين ستستمران في العمل تحت المعرف الفريد نفسه، إلا أن هذا الفصل يزيد من صعوبة الهجوم.