عیب یابی


رفع خطاهای "ترافیک HTTP متن واضح مجاز نیست"

این خطا زمانی رخ می‌دهد که برنامه شما درخواست ترافیک HTTP با فرمت cleartext (یعنی http:// به جای https:// ) را داشته باشد، در حالی که پیکربندی امنیت شبکه آن اجازه آن را نمی‌دهد. اگر برنامه شما اندروید ۹ (سطح API 28) یا بالاتر را هدف قرار می‌دهد، ترافیک HTTP با فرمت cleartext توسط پیکربندی پیش‌فرض غیرفعال است.

اگر برنامه شما نیاز به کار با ترافیک HTTP با متن واضح دارد، باید از پیکربندی امنیت شبکه‌ای استفاده کنید که این امکان را فراهم کند. برای جزئیات بیشتر به مستندات امنیت شبکه اندروید مراجعه کنید. برای فعال کردن تمام ترافیک HTTP با متن واضح، می‌توانید به سادگی android:usesCleartextTraffic="true" به عنصر application در فایل AndroidManifest.xml برنامه خود اضافه کنید.

برنامه آزمایشی ExoPlayer از پیکربندی پیش‌فرض امنیت شبکه استفاده می‌کند و بنابراین اجازه عبور ترافیک HTTP با متن ساده را نمی‌دهد. می‌توانید آن را با استفاده از دستورالعمل‌های بالا فعال کنید.

رفع خطاهای "SSLHandshakeException"، "CertPathValidatorException" و "ERR_CERT_AUTHORITY_INVALID"

SSLHandshakeException ، CertPathValidatorException و ERR_CERT_AUTHORITY_INVALID همگی نشان‌دهنده‌ی مشکلی در گواهی SSL سرور هستند. این خطاها مختص ExoPlayer نیستند. برای جزئیات بیشتر به مستندات SSL اندروید مراجعه کنید.

چرا برخی از فایل‌های رسانه‌ای قابل جستجو نیستند؟

به طور پیش‌فرض، ExoPlayer از جستجو در رسانه‌ای که تنها روش برای انجام عملیات جستجوی دقیق، اسکن و فهرست‌بندی کل فایل توسط پخش‌کننده است، پشتیبانی نمی‌کند. ExoPlayer چنین فایل‌هایی را غیرقابل جستجو می‌داند. اکثر قالب‌های کانتینر رسانه‌ای مدرن شامل فراداده برای جستجو (مانند فهرست نمونه) هستند، الگوریتم جستجوی تعریف‌شده‌ای دارند (به عنوان مثال، جستجوی دوبخشی درون‌یابی شده برای Ogg) یا نشان می‌دهند که محتوای آنها بیت‌ریت ثابتی دارد. عملیات جستجوی کارآمد در این موارد توسط ExoPlayer امکان‌پذیر و پشتیبانی می‌شود.

اگر به جستجو نیاز دارید اما رسانه‌های غیرقابل جستجو دارید، پیشنهاد می‌کنیم محتوای خود را به یک قالب کانتینر مناسب‌تر تبدیل کنید. برای فایل‌های MP3، ADTS و AMR، می‌توانید جستجو را با فرض اینکه فایل‌ها بیت‌ریت ثابتی دارند، همانطور که در اینجا توضیح داده شده است، فعال کنید.

چرا جستجو در برخی از فایل‌های MP3 دقیق نیست؟

فایل‌های MP3 با بیت‌ریت متغیر (VBR) اساساً برای مواردی که نیاز به جستجوی دقیق دارند، نامناسب هستند. دو دلیل برای این امر وجود دارد:

  1. برای جستجوی دقیق، یک قالب کانتینر در حالت ایده‌آل، نگاشت دقیقی از زمان به بایت را در یک هدر ارائه می‌دهد. این نگاشت به پخش‌کننده اجازه می‌دهد تا زمان جستجوی درخواستی را به آفست بایت مربوطه نگاشت کند و درخواست، تجزیه و پخش رسانه را از آن آفست آغاز کند. متأسفانه، هدرهای موجود برای مشخص کردن این نگاشت در MP3 (مانند هدرهای XING) اغلب دقیق نیستند.
  2. برای قالب‌های کانتینری که نگاشت زمان به بایت دقیقی (یا اصلاً هیچ نگاشت زمان به بایت دیگری) ارائه نمی‌دهند، اگر کانتینر شامل مهرهای زمانی نمونه مطلق در جریان باشد، هنوز هم می‌توان جستجوی دقیقی انجام داد. در این حالت، یک پخش‌کننده می‌تواند زمان جستجو را به بهترین حدس از آفست بایت مربوطه نگاشت کند، درخواست رسانه را از آن آفست آغاز کند، اولین مهر زمانی نمونه مطلق را تجزیه کند و به طور مؤثر یک جستجوی دودویی هدایت‌شده را در رسانه انجام دهد تا نمونه مناسب را پیدا کند. متأسفانه MP3 شامل مهرهای زمانی نمونه مطلق در جریان نیست، بنابراین این رویکرد امکان‌پذیر نیست.

به همین دلایل، تنها راه برای انجام جستجوی دقیق در یک فایل VBR MP3، اسکن کل فایل و ایجاد دستی نگاشت زمان به بایت در پخش‌کننده است. این استراتژی را می‌توان با استفاده از FLAG_ENABLE_INDEX_SEEKING فعال کرد که می‌تواند با استفاده از setMp3ExtractorFlags روی DefaultExtractorsFactory تنظیم شود . توجه داشته باشید که این روش برای فایل‌های MP3 بزرگ به خوبی مقیاس‌پذیر نیست، به خصوص اگر کاربر سعی کند کمی پس از شروع پخش، به انتهای جریان نزدیک شود، که مستلزم آن است که پخش‌کننده قبل از انجام جستجو، منتظر بماند تا کل جریان دانلود و فهرست‌بندی شود. در ExoPlayer، ما تصمیم گرفتیم در این مورد سرعت را به دقت ترجیح دهیم و بنابراین FLAG_ENABLE_INDEX_SEEKING به طور پیش‌فرض غیرفعال است.

اگر خودتان روی رسانه‌ای که پخش می‌کنید کنترل دارید، اکیداً توصیه می‌کنیم از یک قالب مناسب‌تر برای کانتینر، مانند MP4، استفاده کنید. هیچ موردی وجود ندارد که ما از آن آگاه باشیم که MP3 بهترین انتخاب برای قالب رسانه باشد.

چرا جستجو در ویدیوی من کند است؟

وقتی پخش‌کننده می‌خواهد موقعیت پخش جدیدی را در یک ویدیو پیدا کند، باید دو کار انجام دهد:

  1. داده‌های مربوط به موقعیت پخش جدید را در بافر بارگذاری کنید (اگر این داده‌ها از قبل بافر شده باشند، ممکن است این کار ضروری نباشد).
  2. با توجه به کدگذاری درون فریمی که توسط اکثر فرمت‌های فشرده‌سازی ویدیو استفاده می‌شود، رمزگشای ویدیو را پاک کنید و رمزگشایی را از فریم I (فریم کلیدی) قبل از موقعیت پخش جدید شروع کنید. برای اطمینان از دقیق بودن جستجو (یعنی شروع پخش دقیقاً در موقعیت جستجو)، تمام فریم‌های بین فریم I قبلی و موقعیت جستجو باید رمزگشایی شده و بلافاصله (بدون نمایش روی صفحه) حذف شوند.

تأخیر ایجاد شده توسط (1) را می‌توان با افزایش مقدار داده‌های بافر شده در حافظه توسط پخش‌کننده یا پیش‌ذخیره‌سازی داده‌ها در دیسک کاهش داد.

تأخیر ایجاد شده توسط (2) را می‌توان با کاهش دقت جستجو با استفاده از ExoPlayer.setSeekParameters یا رمزگذاری مجدد ویدیو برای داشتن فریم‌های I مکرر (که منجر به فایل خروجی بزرگتری می‌شود) کاهش داد.

چرا بعضی از فایل‌های MPEG-TS پخش نمی‌شوند؟

برخی از فایل‌های MPEG-TS حاوی جداکننده‌های واحد دسترسی (AUD) نیستند. به طور پیش‌فرض، ExoPlayer برای تشخیص ارزان مرزهای فریم به AUDها متکی است. به طور مشابه، برخی از فایل‌های MPEG-TS حاوی فریم‌های کلیدی IDR نیستند. به طور پیش‌فرض، اینها تنها نوع فریم‌های کلیدی هستند که توسط ExoPlayer در نظر گرفته می‌شوند.

وقتی از ExoPlayer خواسته می‌شود یک فایل MPEG-TS را که فاقد فریم‌های کلیدی AUD یا IDR است پخش کند، در حالت بافرینگ گیر می‌کند. اگر نیاز به پخش چنین فایل‌هایی دارید، می‌توانید به ترتیب با استفاده از FLAG_DETECT_ACCESS_UNITS و FLAG_ALLOW_NON_IDR_KEYFRAMES این کار را انجام دهید. این پرچم‌ها را می‌توان با استفاده از setTsExtractorFlags روی DefaultExtractorsFactory یا با استفاده از سازنده روی DefaultHlsExtractorFactory تنظیم کرد. استفاده از FLAG_DETECT_ACCESS_UNITS هیچ عارضه جانبی ندارد، جز اینکه از نظر محاسباتی نسبت به تشخیص مرز فریم مبتنی بر AUD گران است. استفاده از FLAG_ALLOW_NON_IDR_KEYFRAMES ممکن است منجر به خرابی موقت بصری در شروع پخش و بلافاصله پس از جستجو هنگام پخش برخی از فایل‌های MPEG-TS شود.

چرا زیرنویس‌ها در برخی از فایل‌های MPEG-TS یافت نمی‌شوند؟

برخی از فایل‌های MPEG-TS شامل آهنگ‌های CEA-608 هستند اما آنها را در فراداده‌های کانتینر اعلام نمی‌کنند، بنابراین ExoPlayer قادر به تشخیص آنها نیست. شما می‌توانید با ارائه لیستی از فرمت‌های زیرنویس مورد انتظار به DefaultExtractorsFactory ، از جمله کانال‌های دسترسی که می‌توانند برای شناسایی آنها در جریان MPEG-TS استفاده شوند، آهنگ‌های زیرنویس را به صورت دستی مشخص کنید:

کاتلین

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()

جاوا

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 را تنظیم کنید، که باعث می‌شود استخراج‌کننده لیست‌های ویرایش را به طور کامل نادیده بگیرد. این موارد را می‌توان با استفاده از setMp4ExtractorFlags یا setFragmentedMp4ExtractorFlags روی DefaultExtractorsFactory تنظیم کرد .

چرا برخی از جریان‌ها با کد پاسخ HTTP 301 یا 302 شکست می‌خورند؟

کدهای پاسخ HTTP 301 و 302 هر دو نشان دهنده تغییر مسیر هستند. توضیحات مختصر را می‌توانید در ویکی‌پدیا بیابید. وقتی ExoPlayer درخواستی ارسال می‌کند و پاسخی با کد وضعیت 301 یا 302 دریافت می‌کند، معمولاً تغییر مسیر را دنبال کرده و پخش را به صورت عادی شروع می‌کند. تنها موردی که این اتفاق به طور پیش‌فرض نمی‌افتد، تغییر مسیرهای بین پروتکلی است. تغییر مسیر بین پروتکلی، تغییر مسیری است که از HTTPS به HTTP یا برعکس (یا کمتر رایج، بین دو پروتکل دیگر) تغییر مسیر می‌دهد. می‌توانید با استفاده از ابزار خط فرمان wget به شرح زیر آزمایش کنید که آیا یک URL باعث تغییر مسیر بین پروتکلی می‌شود یا خیر:

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 در بعضی از دستگاه‌ها به درستی کار نمی‌کند؟

هنگام اجرای نسخه اشکال‌زدایی (debug build) برنامه خود در اندروید M و قبل از آن، ممکن است هنگام استفاده از API مربوط setPlaybackParameters ، با عملکرد ناپایدار، صداهای غیرطبیعی و استفاده زیاد از CPU مواجه شوید. دلیل این امر غیرفعال بودن بهینه‌سازی مهم برای این API در نسخه‌های اشکال‌زدایی (debug build) اجرا شده روی این نسخه‌های اندروید است.

لازم به ذکر است که این مشکل فقط روی نسخه‌های اشکال‌زدایی‌شده تأثیر می‌گذارد. این مشکل روی نسخه‌های انتشاریافته که بهینه‌سازی برای آنها همیشه فعال است، تأثیری ندارد . از این رو، نسخه‌هایی که به کاربران نهایی ارائه می‌دهید، نباید تحت تأثیر این مشکل قرار گیرند.

معنی خطای «بازیکن در تاپیک اشتباهی مورد دسترسی قرار گرفته است» چیست؟

به یادداشتی در مورد نخ‌کشی در صفحه شروع به کار مراجعه کنید.

چگونه می‌توانم خطای «خط وضعیت غیرمنتظره: ICY 200 OK» را برطرف کنم؟

این مشکل زمانی رخ می‌دهد که پاسخ سرور شامل یک خط وضعیت ICY باشد، نه یک خط وضعیت سازگار با HTTP. خطوط وضعیت ICY منسوخ شده‌اند و نباید استفاده شوند، بنابراین اگر سرور را کنترل می‌کنید، باید آن را به‌روزرسانی کنید تا پاسخی سازگار با HTTP ارائه دهد. اگر قادر به انجام این کار نیستید، استفاده از کتابخانه ExoPlayer OkHttp مشکل را حل می‌کند، زیرا می‌تواند خطوط وضعیت ICY را به درستی مدیریت کند.

چطور می‌توانم بپرسم که آیا پخش زنده، پخش زنده است یا خیر؟

شما می‌توانید متد isCurrentWindowLive بازیکن را کوئری کنید. علاوه بر این، می‌توانید isCurrentWindowDynamic بررسی کنید تا بفهمید که آیا پنجره پویا است (یعنی هنوز با گذشت زمان به‌روزرسانی می‌شود).

چگونه می‌توانم وقتی برنامه‌ام در پس‌زمینه است، پخش صدا را ادامه دهم؟

برای اطمینان از پخش مداوم صدا در هنگام اجرای برنامه در پس‌زمینه، این مراحل را دنبال کنید:

  1. شما به یک سرویس پیش‌زمینه (foreground) در حال اجرا نیاز دارید. این کار مانع از آن می‌شود که سیستم، فرآیند شما را برای آزاد کردن منابع، متوقف کند.
  2. شما باید WifiLock و WakeLock را نگه دارید. این‌ها تضمین می‌کنند که سیستم، رادیو WiFi و CPU را بیدار نگه می‌دارد. این کار را می‌توان به راحتی با استفاده از ExoPlayer با فراخوانی setWakeMode انجام داد، که به طور خودکار قفل‌های مورد نیاز را در زمان‌های صحیح دریافت و آزاد می‌کند.

مهم است که قفل‌ها را آزاد کنید (اگر از setWakeMode استفاده نمی‌کنید) و به محض اینکه صدا دیگر پخش نمی‌شود، سرویس را متوقف کنید.

چرا ExoPlayer از محتوای من پشتیبانی می‌کند اما کتابخانه‌ی Cast ExoPlayer این کار را نمی‌کند؟

ممکن است محتوایی که می‌خواهید پخش کنید ، CORS فعال نباشد. چارچوب Cast برای پخش محتوا، فعال بودن CORS را الزامی می‌کند.

چرا محتوا پخش نمی‌شود، اما هیچ خطایی نمایش داده نمی‌شود؟

ممکن است دستگاهی که محتوا را روی آن پخش می‌کنید از یک قالب نمونه رسانه خاص پشتیبانی نکند. این را می‌توان به راحتی با اضافه کردن یک EventLogger به عنوان شنونده به پخش‌کننده خود و جستجوی خطی مشابه این در Logcat تأیید کرد:

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

NO_UNSUPPORTED_TYPE به این معنی است که دستگاه قادر به رمزگشایی فرمت نمونه رسانه‌ای مشخص شده توسط mimeType نیست. برای اطلاعات بیشتر در مورد فرمت‌های نمونه پشتیبانی شده، به مستندات فرمت‌های رسانه‌ای اندروید مراجعه کنید. چگونه می‌توانم یک کتابخانه رمزگشایی را برای بارگیری و استفاده برای پخش دریافت کنم؟ همچنین می‌تواند مفید باشد.

چگونه می‌توانم یک کتابخانه رمزگشایی را بارگذاری کنم و برای پخش استفاده کنم؟

  • اکثر کتابخانه‌های رمزگشا مراحل دستی برای بررسی و ساخت وابستگی‌ها دارند، بنابراین مطمئن شوید که مراحل موجود در README را برای کتابخانه مربوطه دنبال کرده‌اید. به عنوان مثال، برای کتابخانه ExoPlayer FFmpeg لازم است دستورالعمل‌های موجود در libraries/decoder_ffmpeg/README.md را دنبال کنید، از جمله ارسال پرچم‌های پیکربندی برای فعال کردن رمزگشاها برای هر فرمتی که می‌خواهید پخش کنید.
  • برای کتابخانه‌هایی که کد بومی دارند، مطمئن شوید که از نسخه صحیح Android NDK مطابق با آنچه در README مشخص شده است استفاده می‌کنید و مراقب هرگونه خطایی که در حین پیکربندی و ساخت ظاهر می‌شود باشید. پس از دنبال کردن مراحل موجود در README، باید فایل‌های .so را در زیرشاخه libs مسیر کتابخانه برای هر معماری پشتیبانی شده مشاهده کنید.
  • برای امتحان کردن پخش با استفاده از کتابخانه در برنامه آزمایشی ، به فعال کردن رمزگشاهای همراه مراجعه کنید. برای دستورالعمل‌های استفاده از کتابخانه از برنامه خودتان، به README کتابخانه مراجعه کنید.
  • اگر از DefaultRenderersFactory استفاده می‌کنید، هنگام بارگذاری رمزگشا، باید یک خط گزارش سطح اطلاعات مانند "Loaded FfmpegAudioRenderer" در Logcat مشاهده کنید. اگر این خط وجود ندارد، مطمئن شوید که برنامه به کتابخانه رمزگشایی وابستگی دارد.
  • اگر در Logcat لاگ‌های سطح هشدار از LibraryLoader مشاهده کردید، این نشان می‌دهد که بارگذاری مؤلفه بومی کتابخانه با شکست مواجه شده است. در این صورت، بررسی کنید که مراحل موجود در README کتابخانه را به درستی دنبال کرده‌اید و هنگام دنبال کردن دستورالعمل‌ها هیچ خطایی نمایش داده نشده است.

اگر هنوز در استفاده از کتابخانه‌های رمزگشایی با مشکل مواجه هستید، لطفاً برای هرگونه مشکل اخیر مرتبط، ردیاب مشکل Media3 را بررسی کنید. اگر نیاز به ثبت یک مشکل جدید دارید و مربوط به ساخت بخش بومی کتابخانه است، لطفاً خروجی کامل خط فرمان از اجرای دستورالعمل‌های README را برای کمک به ما در تشخیص مشکل، ضمیمه کنید.

آیا می‌توانم ویدیوهای یوتیوب را مستقیماً با ExoPlayer پخش کنم؟

خیر، ExoPlayer نمی‌تواند ویدیوهای یوتیوب، مانند URLهایی به شکل https://www.youtube.com/watch?v=... پخش کند. در عوض، باید از API پخش‌کننده IFrame یوتیوب استفاده کنید که روش رسمی پخش ویدیوهای یوتیوب در اندروید است.

پخش ویدیو با مشکل مواجه است

اگر مثلاً بیت‌ریت یا وضوح محتوا از قابلیت‌های دستگاه فراتر رود، ممکن است دستگاه نتواند محتوا را با سرعت کافی رمزگشایی کند. برای دستیابی به عملکرد خوب در چنین دستگاه‌هایی، ممکن است لازم باشد از محتوای با کیفیت پایین‌تر استفاده کنید.

اگر در دستگاهی که نسخه اندروید آن از اندروید ۶.۰ (سطح API ۲۳) تا اندروید ۱۱ (سطح API ۳۰) است، به خصوص هنگام پخش محتوای محافظت‌شده با DRM یا محتوای با نرخ فریم بالا، دچار لکنت تصویر در ویدیو می‌شوید، می‌توانید فعال کردن صف‌بندی بافر ناهمزمان را امتحان کنید.

خطاهای ناپایدار lint در API

Media3 سازگاری دودویی را برای زیرمجموعه‌ای از سطح API تضمین می‌کند. بخش‌هایی که سازگاری دودویی را تضمین نمی‌کنند با @UnstableApi مشخص شده‌اند. برای روشن شدن این تمایز، استفاده از نمادهای API ناپایدار، مگر اینکه با @OptIn حاشیه‌نویسی شوند، خطای lint ایجاد می‌کند.

حاشیه‌نویسی @UnstableApi هیچ چیزی در مورد کیفیت یا عملکرد یک API نشان نمی‌دهد، فقط این واقعیت را بیان می‌کند که "API-freezen" (منجمد API) نیست.

شما دو گزینه برای مدیریت خطاهای ناپایدار lint در API دارید:

  • به استفاده از یک API پایدار که همان نتیجه را به دست می‌آورد، روی بیاورید.
  • به استفاده از API ناپایدار ادامه دهید و نحوه‌ی استفاده را با استفاده از @OptIn ، همانطور که بعداً نشان داده شده است، حاشیه‌نویسی کنید.
حاشیه‌نویسی @OptIn را اضافه کنید

اندروید استودیو می‌تواند به شما در اضافه کردن حاشیه‌نویسی کمک کند:

تصویر صفحه: نحوه اضافه کردن حاشیه‌نویسی Optin
شکل ۲ : افزودن حاشیه‌نویسی ‎@androidx.annotations.OptIn با اندروید استودیو.

همچنین می‌توانید به صورت دستی سایت‌های استفاده خاص را در کاتلین حاشیه‌نویسی کنید:

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

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

و همچنین در جاوا:

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

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

با اضافه کردن فایل 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 مهم است.