تحديد المشاكل وحلّها


إصلاح أخطاء "لا يُسمح بزيارات HTTP بنص واضح"

سيظهر هذا الخطأ إذا طلب تطبيقك زيارات HTTP بنص غير مرمّز (أي http:// بدلاً من https://) عندما لا يسمح بذلك إعداد أمان الشبكة. إذا كان تطبيقك يستهدف الإصدار 9 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 28) أو إصدارًا أحدث، يتم إيقاف زيارات HTTP بنص واضح من خلال الإعدادات التلقائية.

إذا كان تطبيقك بحاجة إلى العمل مع زيارات HTTP بنص واضح، عليك استخدام إعداد أمان شبكة يسمح بذلك. راجِع مستندات أمان الشبكة في Android للحصول على التفاصيل. لتفعيل جميع زيارات HTTP بنص غير مرمّز، يمكنك ببساطة إضافة android:usesCleartextTraffic="true" إلى العنصر application في ملف AndroidManifest.xml الخاص بتطبيقك.

يستخدم التطبيق التجريبي ExoPlayer إعداد أمان الشبكة التلقائي، لذا لا يسمح بزيارات HTTP بنص واضح. يمكنك تفعيلها باستخدام التعليمات أعلاه.

إصلاح أخطاء "SSLHandshakeException" و"CertPathValidatorException" و"ERR_CERT_AUTHORITY_INVALID"

تشير الأخطاء SSLHandshakeException وCertPathValidatorException وERR_CERT_AUTHORITY_INVALID إلى مشكلة في شهادة SSL الخاصة بالخادم. ولا تقتصر هذه الأخطاء على ExoPlayer. راجِع مستندات SSL في Android لمزيد من التفاصيل.

لماذا لا يمكن البحث في بعض ملفات الوسائط؟

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

إذا كنت بحاجة إلى البحث ولكن لديك وسائط غير قابلة للبحث، ننصحك بتحويل المحتوى لاستخدام تنسيق حاوية أكثر ملاءمةً. بالنسبة إلى ملفات MP3 وADTS وAMR، يمكنك أيضًا تفعيل البحث بافتراض أنّ الملفات لها معدّل نقل بيانات ثابت، كما هو موضّح هنا.

لماذا يكون البحث غير دقيق في بعض ملفات MP3؟

إنّ ملفات MP3 ذات معدّل نقل البيانات المتغيّر (VBR) غير مناسبة بشكل أساسي لحالات الاستخدام التي تتطلّب بحثًا دقيقًا. ويرجع ذلك إلى سببَين:

  1. لإجراء بحث دقيق، من الأفضل أن يوفّر تنسيق الحاوية عملية ربط دقيقة من الوقت إلى البايت في رأس الملف. يسمح هذا الربط للمشغّل بربط وقت البحث المطلوب بإزاحة البايت المقابلة، وبدء طلب الوسائط وتحليلها وتشغيلها من تلك الإزاحة. إنّ رؤوس الملفات المتاحة لتحديد هذا الربط في MP3 (مثل رؤوس ملفات XING) غالبًا ما تكون غير دقيقة، للأسف.
  2. بالنسبة إلى تنسيقات الحاويات التي لا توفّر عملية ربط دقيقة من الوقت إلى البايت (أو أي عملية ربط من الوقت إلى البايت على الإطلاق)، لا يزال من الممكن إجراء بحث دقيق إذا كانت الحاوية تتضمّن طوابع زمنية مطلقة للعيّنات في البث. في هذه الحالة، يمكن للمشغّل ربط وقت البحث بأفضل تخمين لإزاحة البايت المقابلة، وبدء طلب الوسائط من تلك الإزاحة، وتحليل أول طابع زمني مطلق للعيّنة، وإجراء بحث ثنائي موجَّه بشكل فعّال في الوسائط إلى أن يعثر على العيّنة الصحيحة. لا يتضمّن MP3 طوابع زمنية مطلقة للعيّنات في البث، لذا لا يمكن استخدام هذا النهج.

لهذه الأسباب، فإنّ الطريقة الوحيدة لإجراء بحث دقيق في ملف MP3 ذي معدّل نقل بيانات متغيّر هي فحص الملف بأكمله وإنشاء عملية ربط من الوقت إلى البايت يدويًا في المشغّل. يمكن تفعيل هذه الاستراتيجية باستخدام FLAG_ENABLE_INDEX_SEEKING, التي يمكن ضبطها على DefaultExtractorsFactory باستخدام setMp3ExtractorFlags. يُرجى العِلم أنّ هذه الاستراتيجية لا تتناسب مع ملفات MP3 الكبيرة، خاصةً إذا حاول المستخدِم البحث بالقرب من نهاية البث بعد فترة قصيرة من بدء التشغيل، ما يتطلّب من المشغّل الانتظار إلى أن يتم تنزيل البث بأكمله وفهرسته قبل إجراء البحث. في ExoPlayer، قرّرنا تحسين السرعة بدلاً من الدقة في هذه الحالة، لذا يتم إيقاف FLAG_ENABLE_INDEX_SEEKING تلقائيًا.

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

لماذا يكون البحث في الفيديو بطيئًا؟

عندما يبحث المشغّل عن موضع تشغيل جديد في فيديو، عليه إجراء ما يلي:

  1. تحميل البيانات المقابلة لموضع التشغيل الجديد في المخزن المؤقت (قد لا يكون ذلك ضروريًا إذا كانت هذه البيانات مخزّنة مؤقتًا من قبل)
  2. إفراغ برنامج فك ترميز الفيديو وبدء فك الترميز من الإطار I (الإطار الرئيسي) قبل موضع التشغيل الجديد، بسبب الترميز داخل الإطار الذي تستخدمه معظم تنسيقات ضغط الفيديو. لضمان أن يكون البحث دقيقًا (أي يبدأ التشغيل بالضبط في موضع البحث)، يجب فك ترميز جميع الإطارات بين الإطار I السابق وموضع البحث ثم تجاهلها على الفور (بدون عرضها على الشاشة).

يمكن تقليل وقت الاستجابة الناتج عن الخطوة (1) إما عن طريق زيادة مقدار البيانات التي يخزّنها المشغّل مؤقتًا في الذاكرة، أو عن طريق التخزين المؤقت المسبق للبيانات على القرص.

يمكن تقليل وقت الاستجابة الناتج عن الخطوة (2) إما عن طريق تقليل دقة البحث باستخدام ExoPlayer.setSeekParameters، أو عن طريق إعادة ترميز الفيديو ليتضمّن إطارات I أكثر تكرارًا (ما سيؤدي إلى ملف إخراج أكبر).

لماذا يتعذّر تشغيل بعض ملفات MPEG-TS؟

لا تحتوي بعض ملفات MPEG-TS على فواصل وحدات الوصول (AUD). تلقائيًا، يعتمد ExoPlayer على فواصل وحدات الوصول لرصد حدود الإطارات بتكلفة منخفضة. وبالمثل، لا تحتوي بعض ملفات MPEG-TS على إطارات رئيسية IDR. تلقائيًا، هذا هو النوع الوحيد من الإطارات الرئيسية التي يأخذها ExoPlayer في الاعتبار.

سيبدو أنّ ExoPlayer عالق في حالة التخزين المؤقت عند الطلب منه تشغيل ملف MPEG-TS لا يحتوي على فواصل وحدات الوصول أو إطارات رئيسية IDR. إذا كنت بحاجة إلى تشغيل هذه الملفات، يمكنك فعل ذلك باستخدام FLAG_DETECT_ACCESS_UNITS و FLAG_ALLOW_NON_IDR_KEYFRAMES على التوالي. يمكن ضبط هذه العلامات على set on a DefaultExtractorsFactory باستخدام setTsExtractorFlags أو على DefaultHlsExtractorFactory باستخدام الـ طريقة وضع التصميم. لا يؤدي استخدام FLAG_DETECT_ACCESS_UNITS إلى أي آثار جانبية بخلاف أنّه مكلف من الناحية الحسابية مقارنةً برصد حدود الإطارات استنادًا إلى فواصل وحدات الوصول. قد يؤدي استخدام FLAG_ALLOW_NON_IDR_KEYFRAMES إلى تلف مرئي مؤقت في بداية التشغيل وبعد عمليات البحث مباشرةً عند تشغيل بعض ملفات MPEG-TS.

لماذا لا يتم العثور على الترجمة في بعض ملفات MPEG-TS؟

تتضمّن بعض ملفات MPEG-TS مسارات CEA-608 ولكن لا يتم الإعلان عنها في البيانات الوصفية للحاوية، لذا لا يتمكّن ExoPlayer من رصدها. يمكنك تحديد أي مسارات ترجمة يدويًا من خلال تقديم قائمة بتنسيقات الترجمة المتوقّعة إلى DefaultExtractorsFactory، بما في ذلك قنوات تسهيل الاستخدام التي يمكن استخدامها لتحديدها في بث MPEG-TS:

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory()
    .setTsSubtitleFormats(
      listOf(
        Format.Builder()
          .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
          .setAccessibilityChannel(accessibilityChannel)
          // Set other subtitle format info, such as language.
          .build()
      )
    )
val player: Player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory()
        .setTsSubtitleFormats(
            ImmutableList.of(
                new Format.Builder()
                    .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
                    .setAccessibilityChannel(accessibilityChannel)
                    // Set other subtitle format info, such as language.
                    .build()));
Player player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

لماذا يتم تشغيل بعض ملفات MP4/FMP4 بشكل غير صحيح؟

تحتوي بعض ملفات MP4/FMP4 على قوائم تعديل تعيد كتابة المخطط الزمني للوسائط عن طريق تخطّي قوائم العيّنات أو نقلها أو تكرارها. يتيح ExoPlayer دعمًا جزئيًا لتطبيق قوائم التعديل. على سبيل المثال، يمكنه تأخير مجموعات العيّنات أو تكرارها بدءًا من عيّنة المزامنة، ولكنّه لا يقتطع عيّنات الصوت أو وسائط التشغيل المسبق للتعديلات التي لا تبدأ بعيّنة مزامنة.

إذا لاحظت أنّ جزءًا من الوسائط مفقود أو مكرّر بشكل غير متوقّع، حاوِل ضبط Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS أو FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS، ما سيؤدي إلى أن يتجاهل برنامج الاستخراج قوائم التعديل بالكامل. يمكن ضبط هذه العلامات على set on a DefaultExtractorsFactory باستخدام setMp4ExtractorFlags أو setFragmentedMp4ExtractorFlags.

لماذا تفشل بعض عمليات البث بسبب رمز استجابة HTTP 301 أو 302؟

يشير كل من رمزي استجابة HTTP 301 و302 إلى إعادة التوجيه. يمكنك الاطّلاع على أوصاف موجزة على ويكيبيديا. عندما يقدّم ExoPlayer طلبًا ويتلقّى استجابة برمز الحالة 301 أو 302، سيتبع عادةً عملية إعادة التوجيه ويبدأ التشغيل كالمعتاد. الحالة الوحيدة التي لا يحدث فيها ذلك تلقائيًا هي عمليات إعادة التوجيه بين البروتوكولات. عملية إعادة التوجيه بين البروتوكولات هي عملية إعادة توجيه من HTTPS إلى HTTP أو العكس (أو بشكل أقل شيوعًا، بين زوج آخر من البروتوكولات). يمكنك اختبار ما إذا كان عنوان URL يؤدي إلى عملية إعادة توجيه بين البروتوكولات باستخدام أداة سطر الأوامر wget على النحو التالي:

wget "https://yourserver.example.com/test.mp3" 2>&1  | grep Location

يجب أن يبدو الناتج على النحو التالي:

Location: https://secondserver.example.net/test.mp3 [following]
Location: http://thirdserver.example.org/test.mp3 [following]

في هذا المثال، هناك عمليتان لإعادة التوجيه. عملية إعادة التوجيه الأولى هي من https://yourserver.example.com/test.mp3 إلى https://secondserver.example.net/test.mp3. كلاهما HTTPS، لذا ليست هذه عملية إعادة توجيه بين البروتوكولات. عملية إعادة التوجيه الثانية هي من https://secondserver.example.net/test.mp3 إلى http://thirdserver.example.org/test.mp3. تعيد هذه العملية التوجيه من HTTPS إلى HTTP، لذا فهي عملية إعادة توجيه بين البروتوكولات. لن يتبع ExoPlayer عملية إعادة التوجيه هذه في إعداداته التلقائية، ما يعني أنّ التشغيل سيفشل.

إذا لزم الأمر، يمكنك ضبط ExoPlayer على اتّباع عمليات إعادة التوجيه بين البروتوكولات عند إنشاء DefaultHttpDataSource.Factory المستخدَمة في تطبيقك. يمكنك التعرّف على اختيار حزمة الشبكة وضبطها هنا.

لماذا تفشل بعض عمليات البث بسبب UnrecognizedInputFormatException؟

يتعلّق هذا السؤال بفشل التشغيل الذي يكون على النحو التالي:

UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.

هناك سببان محتملان لهذا الفشل. السبب الأكثر شيوعًا هو أنّك تحاول تشغيل محتوى DASH (mpd) أو HLS (m3u8) أو SmoothStreaming (ism وisml)، ولكن يحاول المشغّل تشغيله كبث تدريجي. لتشغيل عمليات البث هذه، يجب أن تعتمد على وحدة ExoPlayer المعنيّة. في الحالات التي لا ينتهي فيها معرّف URI للبث بامتداد الملف العادي، يمكنك أيضًا تمرير MimeTypes.APPLICATION_MPD أو MimeTypes.APPLICATION_M3U8 أو MimeTypes.APPLICATION_SS إلى setMimeType في MediaItem.Builder لتحديد نوع البث بشكل صريح.

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

لماذا لا تعمل طريقة setPlaybackParameters بشكل صحيح على بعض الأجهزة؟

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

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

ما هو معنى أخطاء "تم الوصول إلى المشغّل على سلسلة محادثات غير صحيحة"؟

راجِع ملاحظة حول سلاسل المحادثات في صفحة البدء.

كيف يمكنني إصلاح الخطأ "Unexpected status line: ICY 200 OK"؟

يمكن أن تحدث هذه المشكلة إذا تضمّنت استجابة الخادم سطر حالة ICY، بدلاً من سطر متوافق مع HTTP. تم إيقاف أسطر حالة ICY نهائيًا ويجب عدم استخدامها، لذا إذا كنت تتحكّم في الخادم، عليك تعديله لتقديم استجابة متوافقة مع HTTP. إذا لم تتمكّن من إجراء ذلك، سيؤدي استخدام الـ ExoPlayer OkHttp library إلى حلّ المشكلة، لأنّها قادرة على التعامل مع أسطر حالة ICY بشكل صحيح.

كيف يمكنني الاستعلام عما إذا كانت عملية البث التي يتم تشغيلها هي بث مباشر؟

يمكنك الاستعلام عن طريقة isCurrentWindowLive في المشغّل. بالإضافة إلى ذلك، يمكنك التحقّق من isCurrentWindowDynamic لمعرفة ما إذا كانت النافذة ديناميكية (أي لا تزال يتم تعديلها بمرور الوقت).

كيف يمكنني مواصلة تشغيل الصوت عندما يكون تطبيقي في الخلفية؟

يُرجى اتّباع الخطوات التالية لضمان استمرار تشغيل الصوت عندما يكون تطبيقك في الخلفية:

  1. عليك أن يكون لديك خدمة تعمل في المقدّمة. يمنع ذلك النظام من إيقاف العملية لتحرير الموارد.
  2. عليك الاحتفاظ بـ WifiLock وWakeLock. تضمن هذه الأقفال أنّ النظام يحافظ على تشغيل جهاز استقبال WiFi ووحدة المعالجة المركزية. يمكن إجراء ذلك بسهولة إذا كنت تستخدم ExoPlayer من خلال استدعاء setWakeMode، ما سيؤدي تلقائيًا إلى الحصول على الأقفال المطلوبة وإطلاقها في الأوقات الصحيحة.

من المهم إطلاق الأقفال (إذا لم تكن تستخدم setWakeMode) وإيقاف الخدمة بمجرد عدم تشغيل الصوت.

لماذا يتوافق ExoPlayer مع المحتوى الخاص بي، ولكن لا تتوافق مكتبة ExoPlayer Cast معه؟

من المحتمل أنّ المحتوى الذي تحاول تشغيله غير مفعّل لـ CORS. يتطلّب إطار عمل Cast تفعيل CORS للمحتوى لتشغيله.

لماذا يتعذّر تشغيل المحتوى، ولكن لا يظهر أي خطأ؟

من المحتمل أنّ الجهاز الذي تشغّل عليه المحتوى لا يتيح تنسيق عيّنة وسائط معيّنًا. يمكن تأكيد ذلك بسهولة عن طريق إضافة EventLogger كمتتبِّع إلى المشغّل، والبحث عن سطر مشابه لهذا السطر في أداة Logcat:

[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE

NO_UNSUPPORTED_TYPE يعني أنّ الجهاز غير قادر على فك ترميز تنسيق عيّنة الوسائط المحدّد بواسطة mimeType. راجِع مستندات تنسيقات الوسائط في Android للحصول على معلومات حول تنسيقات العيّنات المتوافقة. قد يكون أيضًا السؤال كيف يمكنني تحميل مكتبة فك ترميز واستخدامها للتشغيل؟ مفيدًا.

كيف يمكنني تحميل مكتبة فك ترميز واستخدامها للتشغيل؟

  • تتضمّن معظم مكتبات فك الترميز خطوات يدوية لتنزيل التبعيات وإنشائها، لذا تأكَّد من اتّباع الخطوات الواردة في ملف README للمكتبة المعنيّة. على سبيل المثال، بالنسبة إلى مكتبة ExoPlayer FFmpeg، من الضروري اتّباع الـ تعليمات الواردة في libraries/decoder_ffmpeg/README.md، بما في ذلك تمرير علامات الإعداد لـ تفعيل برامج فك الترميز لأي تنسيقات تريد تشغيلها.
  • بالنسبة إلى المكتبات التي تحتوي على رموز برمجية أصلية، تأكَّد من استخدام الإصدار الصحيح من Android NDK كما هو محدّد في ملف README، وابحث عن أي أخطاء تظهر أثناء الإعداد والإنشاء. يجب أن تظهر ملفات .so في الدليل الفرعي libs لمسار المكتبة لكل بنية متوافقة بعد اتّباع الخطوات الواردة في ملف README.
  • لتجربة التشغيل باستخدام المكتبة في التطبيق التجريبي التطبيقي، راجِع تفعيل برامج فك الترميز المجمّعة. راجِع ملف README الخاص بالمكتبة للحصول على تعليمات حول استخدام المكتبة من تطبيقك.
  • إذا كنت تستخدم DefaultRenderersFactory، يجب أن يظهر سطر سجلّ على مستوى المعلومات مثل "تم تحميل FfmpegAudioRenderer" في Logcat عند تحميل برنامج فك الترميز. إذا لم يظهر ذلك، تأكَّد من أنّ التطبيق يعتمد على مكتبة فك الترميز.
  • إذا ظهرت لك سجلّات على مستوى التحذير من LibraryLoader في Logcat، يشير ذلك إلى أنّه تعذّر تحميل المكوّن الأصلي للمكتبة. إذا حدث ذلك، تأكَّد من اتّباع الخطوات الواردة في ملف README الخاص بالمكتبة بشكل صحيح وأنّه لم يتم عرض أي أخطاء أثناء اتّباع التعليمات.

إذا كنت لا تزال تواجه مشاكل في استخدام مكتبات فك الترميز، يُرجى الاطّلاع على أداة تتبُّع المشاكل في Media3 بحثًا عن أي مشاكل حديثة ذات صلة. إذا كنت بحاجة إلى تسجيل مشكلة جديدة وكانت مرتبطة بإنشاء الجزء الأصلي من المكتبة، يُرجى تضمين ناتج سطر الأوامر الكامل من تشغيل تعليمات ملف README لمساعدتنا في تشخيص المشكلة.

هل يمكنني تشغيل فيديوهات YouTube مباشرةً باستخدام ExoPlayer؟

لا، لا يمكن لـ ExoPlayer تشغيل فيديوهات من YouTube، مثل عناوين URL التي تكون على النحو https://www.youtube.com/watch?v=.... بدلاً من ذلك، عليك استخدام YouTube IFrame Player API، وهي الطريقة الرسمية لتشغيل فيديوهات YouTube على Android.

تشغيل الفيديو متقطع

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

إذا كنت تواجه تقطُّع الفيديو على جهاز يعمل بإصدار من Android من Android 6.0 (مستوى واجهة برمجة التطبيقات 23) حتى Android 11 (مستوى واجهة برمجة التطبيقات 30) ضِمنًا، خاصةً عند تشغيل محتوى محمي بموجب إدارة الحقوق الرقمية أو محتوى بمعدّل إطارات مرتفع، يمكنك محاولة تفعيل وضع قائمة انتظار المخزن المؤقت غير المتزامن.

أخطاء أداة lint في واجهة برمجة التطبيقات غير الثابتة

تضمن Media3 التوافق الثنائي لمجموعة فرعية من واجهة برمجة التطبيقات. الأجزاء التي لا تضمن التوافق الثنائي يتم وضع علامة عليها@UnstableApi. لتوضيح هذا التمييز، تؤدي استخدامات رموز واجهة برمجة التطبيقات غير الثابتة إلى ظهور خطأ في أداة lint ما لم يتم وضع العلامة @OptIn عليها.

لا تشير العلامة @UnstableApi إلى أي شيء بشأن جودة واجهة برمجة التطبيقات أو أدائها، بل تشير فقط إلى أنّها ليست "واجهة برمجة تطبيقات ثابتة".

أمامك خياران للتعامل مع أخطاء أداة lint في واجهة برمجة التطبيقات غير الثابتة:

  • التبديل إلى استخدام واجهة برمجة تطبيقات ثابتة تحقق النتيجة نفسها
  • مواصلة استخدام واجهة برمجة التطبيقات غير الثابتة ووضع العلامة @OptIn على الاستخدام، كما هو موضّح لاحقًا
إضافة العلامة @OptIn

يمكن أن يساعدك "استوديو Android" في إضافة العلامة:

لقطة شاشة: كيفية إضافة التعليق التوضيحي Optin
الشكل 2: إضافة العلامة @androidx.annotations.OptIn باستخدام "استوديو Android".

يمكنك أيضًا وضع العلامة يدويًا على مواقع استخدام معيّنة:

Kotlin

import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi

@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }

Java

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }

يمكن الموافقة على استخدام حزم كاملة عن طريق إضافة ملف package-info:

Kotlin

// In your package-info.kt
@OptIn(UnstableApi::class)
package name.of.your.package

import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi

Java

// In your package-info.java
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

يمكن الموافقة على استخدام مشاريع كاملة عن طريق إيقاف خطأ أداة lint المحدّد في ملفها lint.xml:

 <?xml version="1.0" encoding="utf-8"?>
 <lint>
   <issue id="UnsafeOptInUsageError">
     <option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
   </issue>
 </lint>

هناك أيضًا العلامة kotlin.OptIn التي يجب عدم استخدامها. من المهم استخدام العلامة androidx.annotation.OptIn.