คำแนะนำในการย้ายข้อมูล AndroidX Media3

แอปที่ใช้ไลบรารีแบบสแตนด์อโลน com.google.android.exoplayer2 และ androidx.media ในปัจจุบันควรย้ายข้อมูลไปยัง androidx.media3 ใช้ สคริปต์การย้ายข้อมูล เพื่อย้ายข้อมูลไฟล์บิลด์ Gradle, ไฟล์แหล่งที่มา Java และ Kotlin รวมถึงไฟล์เลย์เอาต์ XML จาก ExoPlayer 2.19.1 ไปยัง AndroidX Media3 1.1.1

ภาพรวม

ก่อนย้ายข้อมูล โปรดอ่านส่วนต่อไปนี้เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับสิทธิประโยชน์ของ API ใหม่, API ที่จะย้ายข้อมูล และข้อกำหนดเบื้องต้นที่โปรเจ็กต์ของแอปควรมี

เหตุผลที่ควรย้ายข้อมูลไปยัง Jetpack Media3

  • เป็นหน้าหลักใหม่ของ ExoPlayer ในขณะที่ com.google.android.exoplayer2 หยุดให้บริการแล้ว
  • เข้าถึง Player API ในคอมโพเนนต์/กระบวนการต่างๆ ด้วย MediaBrowser/MediaController
  • ใช้ความสามารถที่ขยายของ MediaSession และ MediaController API
  • โฆษณาความสามารถในการเล่นด้วยการควบคุมการเข้าถึงแบบละเอียด
  • ทำให้แอปง่ายขึ้น โดยนำ MediaSessionConnector และ PlayerNotificationManager ออก
  • เข้ากันได้แบบย้อนหลัง กับ Media-Compat Client API (MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)

Media API ที่จะย้ายข้อมูลไปยัง AndroidX Media3

  • ExoPlayer และส่วนขยาย
    ซึ่งรวมถึงโมดูลทั้งหมดของโปรเจ็กต์ ExoPlayer เดิม ยกเว้นโมดูล MediaSession ที่หยุดให้บริการแล้ว แอปหรือโมดูลที่ขึ้นต่อกันกับแพ็กเกจใน com.google.android.exoplayer2 สามารถย้ายข้อมูลได้ด้วยสคริปต์การย้ายข้อมูล
  • MediaSessionConnector (ขึ้นต่อกันกับ androidx.media.* ของ androidx.media:media:1.4.3+)
    นำ MediaSessionConnector ออกและใช้ androidx.media3.session.MediaSession แทน
  • MediaBrowserServiceCompat (ขึ้นต่อกันกับแพ็กเกจ androidx.media.* ของ androidx.media:media:1.4.3+)
    ย้ายข้อมูลคลาสย่อยของ androidx.media.MediaBrowserServiceCompat ไปยัง androidx.media3.session.MediaLibraryService และโค้ดที่ใช้ MediaBrowserCompat.MediaItem ไปยัง androidx.media3.common.MediaItem
  • MediaBrowserCompat (ขึ้นต่อกันกับ androidx.media:media:1.4.3+ แพ็กเกจของ
    ) MediaBrowserCompat ย้ายข้อมูลโค้ดไคลเอ็นต์ที่ใช้ MediaControllerCompat หรือ androidx.media3.session.MediaBrowser ไปใช้ androidx.media3.common.MediaItem กับ
    android.support.v4.media.*

สิ่งที่ต้องมีก่อน

  1. ตรวจสอบว่าโปรเจ็กต์อยู่ภายใต้การควบคุมแหล่งที่มา

    ตรวจสอบว่าคุณสามารถย้อนกลับการเปลี่ยนแปลงที่เครื่องมือการย้ายข้อมูลแบบสคริปต์นำไปใช้ได้อย่างง่ายดาย หากยังไม่ได้ควบคุมแหล่งที่มาของโปรเจ็กต์ ตอนนี้เป็นเวลาที่เหมาะสมที่จะเริ่มต้น หากไม่ต้องการดำเนินการดังกล่าวด้วยเหตุผลบางประการ ให้สร้างสำเนาสำรองของโปรเจ็กต์ก่อนเริ่มการย้ายข้อมูล

  2. อัปเดตแอป

    • เราขอแนะนำให้อัปเดตโปรเจ็กต์เพื่อใช้ ไลบรารี ExoPlayer เวอร์ชันล่าสุด และนำ การเรียกเมธอดที่เลิกใช้งานแล้วออก หากต้องการใช้สคริปต์สำหรับการย้ายข้อมูล คุณต้องใช้เวอร์ชันที่อัปเดตแล้วให้ตรงกับเวอร์ชันที่สคริปต์จัดการ

    • เพิ่ม compileSdkVersion ของแอปเป็นอย่างน้อย 32

    • อัปเกรด Gradle และปลั๊กอิน Android Studio Gradle เป็นเวอร์ชันล่าสุดที่ใช้ได้กับทรัพยากร Dependency ที่อัปเดตแล้วจากด้านบน ตัวอย่างเช่น

      • ปลั๊กอิน Android Gradle เวอร์ชัน 7.1.0
      • Gradle เวอร์ชัน 7.4
    • แทนที่คำสั่งนำเข้าแบบ Wildcard ทั้งหมด ที่ใช้ดอกจัน (*) และใช้คำสั่งนำเข้าแบบสมบูรณ์ในตัวเอง โดยลบคำสั่งนำเข้าแบบ Wildcard และใช้ Android Studio เพื่อนำเข้าคำสั่งแบบสมบูรณ์ในตัวเอง (F2 - Alt/Enter, F2 - Alt/Enter, ...)

    • ย้ายข้อมูลจาก com.google.android.exoplayer2.PlayerView ไปยัง com.google.android.exoplayer2.StyledPlayerView การดำเนินการนี้จำเป็นเนื่องจากไม่มี com.google.android.exoplayer2.PlayerView ที่เทียบเท่าใน AndroidX Media3

ย้ายข้อมูล ExoPlayer ด้วยการรองรับสคริปต์

สคริปต์ช่วยให้ย้ายข้อมูลจาก com.google.android.exoplayer2 ไปยังโครงสร้าง แพ็กเกจและโมดูลใหม่ภายใต้ androidx.media3 ได้ง่ายขึ้น สคริปต์จะใช้การตรวจสอบความถูกต้องบางอย่างกับโปรเจ็กต์และแสดงคำเตือนหากการตรวจสอบไม่สำเร็จ ไม่เช่นนั้น สคริปต์จะใช้การแมปคลาสและแพ็กเกจที่เปลี่ยนชื่อใน ทรัพยากรของโปรเจ็กต์ Android Gradle ที่เขียนด้วย Java หรือ Kotlin

usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
 PROJECT_ROOT: path to your project root (location of 'gradlew')
 -p: list package mappings and then exit
 -c: list class mappings (precedence over package mappings) and then exit
 -d: list dependency mappings and then exit
 -l: list files that will be considered for rewrite and then exit
 -x: exclude the path from the list of file to be changed: 'app/src/test'
 -m: migrate packages, classes and dependencies to AndroidX Media3
 -f: force the action even when validation fails
 -v: print the exoplayer2/media3 version strings of this script
 -h, --help: show this help text

การใช้สคริปต์การย้ายข้อมูล

  1. ดาวน์โหลดสคริปต์การย้ายข้อมูลจากแท็กของโปรเจ็กต์ ExoPlayer ใน GitHub ที่ตรงกับเวอร์ชันที่คุณอัปเดตแอปเป็น

    curl -o media3-migration.sh \
      "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
    
  2. ทำให้สคริปต์สามารถเรียกใช้งานได้

    chmod 744 media3-migration.sh
    
  3. เรียกใช้สคริปต์ด้วย --help เพื่อดูข้อมูลเกี่ยวกับตัวเลือก

  4. เรียกใช้สคริปต์ด้วย -l เพื่อแสดงรายการชุดไฟล์ที่เลือกสำหรับการย้ายข้อมูล (ใช้ -f เพื่อบังคับให้แสดงรายการโดยไม่มีคำเตือน)

    ./media3-migration.sh -l -f /path/to/gradle/project/root
    
  5. เรียกใช้สคริปต์ด้วย -m เพื่อแมปแพ็กเกจ คลาส และโมดูลกับ Media3 การเรียกใช้สคริปต์ด้วยตัวเลือก -m จะใช้การเปลี่ยนแปลงกับไฟล์ที่เลือก

    • หยุดที่ข้อผิดพลาดในการตรวจสอบโดยไม่ทำการเปลี่ยนแปลง
    ./media3-migration.sh -m /path/to/gradle/project/root
    
    • การดำเนินการแบบบังคับ

    หากสคริปต์พบการละเมิดข้อกำหนดเบื้องต้น คุณสามารถบังคับการย้ายข้อมูลได้ด้วยแฟล็ก -f

    ./media3-migration.sh -m -f /path/to/gradle/project/root
    
 # list files selected for migration when excluding paths
 ./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
 # migrate the selected files
 ./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root

ทำตามขั้นตอนด้วยตนเองต่อไปนี้หลังจากเรียกใช้สคริปต์ด้วยตัวเลือก -m

  1. ตรวจสอบวิธีที่สคริปต์เปลี่ยนแปลงโค้ด: ใช้เครื่องมือ Diff และแก้ไข ปัญหาที่อาจเกิดขึ้น (พิจารณายื่นรายงานข้อบกพร่องหากคิดว่าสคริปต์มี ปัญหาทั่วไปที่เกิดขึ้นโดยไม่ได้ส่งผ่านตัวเลือก -f)
  2. สร้างโปรเจ็กต์: ใช้ ./gradlew clean build หรือใน Android Studio ให้เลือก ไฟล์ > ซิงค์โปรเจ็กต์กับไฟล์ Gradle จากนั้นเลือก สร้าง > ล้างโปรเจ็กต์ แล้วเลือก สร้าง > สร้างโปรเจ็กต์ใหม่ (ตรวจสอบบิลด์ ในแท็บ 'บิลด์ - เอาต์พุตบิลด์' ของ Android Studio)

ขั้นตอนการติดตามที่แนะนำ

  1. แก้ไข การเลือกใช้ข้อผิดพลาดเกี่ยวกับการใช้ API ที่ไม่เสถียร
  2. แทนที่การเรียก API ที่เลิกใช้งานแล้ว: ใช้ API ที่แนะนำให้ใช้แทน วางตัวชี้เหนือคำเตือนใน Android Studio และดู JavaDoc ของสัญลักษณ์ที่เลิกใช้งานแล้วเพื่อดูว่าควรใช้สิ่งใดแทนการเรียกที่ระบุ
  3. จัดเรียงคำสั่งนำเข้า: เปิดโปรเจ็กต์ใน Android Studio จากนั้น คลิกขวาที่โหนดโฟลเดอร์แพ็กเกจในโปรแกรมดูโปรเจ็กต์ แล้วเลือก เพิ่มประสิทธิภาพการนำเข้า ในแพ็กเกจที่มีไฟล์แหล่งที่มาที่เปลี่ยนแปลง

แทนที่ MediaSessionConnector ด้วย androidx.media3.session.MediaSession

ในโลกของ MediaSessionCompat เดิม MediaSessionConnector มีหน้าที่ซิงค์สถานะของเพลเยอร์กับสถานะของเซสชัน และรับคำสั่งจากตัวควบคุมที่ต้องมอบหมายไปยังเมธอดเพลเยอร์ที่เหมาะสม AndroidX Media3 จะดำเนินการนี้โดย MediaSession โดยตรงโดยไม่ต้องใช้ตัวเชื่อมต่อ

  1. นำการอ้างอิงและการใช้งาน MediaSessionConnector ทั้งหมดออก: หากคุณใช้สคริปต์อัตโนมัติเพื่อย้ายข้อมูลคลาสและแพ็กเกจ ExoPlayer สคริปต์น่าจะปล่อยให้โค้ดของคุณอยู่ในสถานะที่คอมไพล์ไม่ได้เกี่ยวกับ MediaSessionConnector ซึ่งไม่สามารถแก้ไขได้ Android Studio จะแสดงโค้ดที่เสียหายเมื่อคุณพยายามสร้างหรือเริ่มแอป

  2. ในไฟล์ build.gradle ที่คุณดูแลทรัพยากร Dependency ให้เพิ่มทรัพยากร Dependency การใช้งานไปยังโมดูลเซสชัน AndroidX Media3 และนำทรัพยากร Dependency เดิมออก

    implementation "androidx.media3:media3-session:1.10.0"
    
  3. แทนที่ MediaSessionCompat ด้วย androidx.media3.session.MediaSession

  4. ในไซต์โค้ดที่คุณสร้าง MediaSessionCompat เดิม ให้ใช้ androidx.media3.session.MediaSession.Builder เพื่อ สร้าง MediaSession ส่งเพลเยอร์ เพื่อสร้างตัวสร้างเซสชัน

    Kotlin

    val player = ExoPlayer.Builder(context).build()
    mediaSession = MediaSession.Builder(context, player).setCallback(MySessionCallback()).build()

    Java

    ExoPlayer player = new ExoPlayer.Builder(context).build();
    mediaSession =
        new MediaSession.Builder(context, player).setCallback(new MySessionCallback()).build();

    ForwardingSimpleBasePlayer
  5. ใช้ MySessionCallback ตามที่แอปกำหนด ซึ่งเป็นขั้นตอนที่ไม่บังคับ หากต้องการอนุญาตให้ตัวควบคุมเพิ่มรายการสื่อลงในเพลเยอร์ ให้ใช้ MediaSession.Callback.onAddMediaItems() ซึ่งจะให้บริการเมธอด API ปัจจุบันและเดิมต่างๆ ที่เพิ่มรายการสื่อลงในเพลเยอร์เพื่อเล่นในลักษณะที่เข้ากันได้แบบย้อนหลัง ซึ่งรวมถึงเมธอด MediaController.set/addMediaItems() ของตัวควบคุม Media3 รวมถึงเมธอด TransportControls.prepareFrom*/playFrom* ของ API เดิม ดูตัวอย่างการใช้งาน onAddMediaItems ได้ ใน PlaybackService ของแอปเดโมของเซสชัน

  6. ปล่อยเซสชันสื่อในไซต์โค้ดที่คุณทำลายเซสชันก่อนการย้ายข้อมูล

    Kotlin

    mediaSession?.run {
      player.release()
      release()
      mediaSession = null
    }

    Java

    if (mediaSession != null) {
      mediaSession.getPlayer().release();
      mediaSession.release();
      mediaSession = null;
    }

ฟังก์ชันการทำงานของ MediaSessionConnector ใน Media3

ตารางต่อไปนี้แสดง Media3 API ที่จัดการฟังก์ชันการทำงานที่ก่อนหน้านี้ใช้ใน MediaSessionConnector

MediaSessionConnectorAndroidX Media3
CustomActionProvider MediaSession.Callback.onCustomCommand()/ MediaSession.setMediaButtonPreferences()
PlaybackPreparer MediaSession.Callback.onAddMediaItems() (prepare() จะถูกเรียกภายใน)
QueueNavigator ForwardingSimpleBasePlayer
QueueEditor MediaSession.Callback.onAddMediaItems()
RatingCallback MediaSession.Callback.onSetRating()
PlayerNotificationManager DefaultMediaNotificationProvider/ MediaNotification.Provider

ย้ายข้อมูล MediaBrowserService ไปยัง MediaLibraryService

AndroidX Media3 เปิดตัว MediaLibraryService ที่จะมาแทนที่ MediaBrowserServiceCompat JavaDoc ของ MediaLibraryService และคลาสระดับบน MediaSessionService จะให้ข้อมูลเบื้องต้นเกี่ยวกับ API และโมเดลการเขียนโปรแกรมแบบไม่พร้อมกันของบริการ

MediaLibraryService เข้ากันได้แบบย้อนหลังกับ MediaBrowserService แอปไคลเอ็นต์ที่ใช้ MediaBrowserCompat หรือ MediaControllerCompat จะทำงานต่อไปได้โดยไม่ต้องเปลี่ยนแปลงโค้ดเมื่อเชื่อมต่อกับ MediaLibraryService สำหรับไคลเอ็นต์ จะไม่เห็นความแตกต่างว่าแอปของคุณใช้ MediaLibraryService หรือ MediaBrowserServiceCompat เดิม

แผนภาพคอมโพเนนต์ของแอปที่มีบริการ กิจกรรม และแอปภายนอก
รูปที่ 1: ภาพรวมคอมโพเนนต์แอปสื่อ
  1. คุณต้องลงทะเบียนอินเทอร์เฟซบริการทั้ง 2 รายการ กับบริการของคุณใน AndroidManifest.xml เพื่อให้การเข้ากันได้แบบย้อนหลังทำงานได้ วิธีนี้จะช่วยให้ไคลเอ็นต์ค้นหาบริการของคุณได้โดยใช้อินเทอร์เฟซบริการที่จำเป็น

    <service android:name=".MusicService" android:exported="true">
        <intent-filter>
            <action android:name="androidx.media3.session.MediaLibraryService"/>
            <action android:name="android.media.browse.MediaBrowserService" />
        </intent-filter>
    </service>
    
  2. ในไฟล์ build.gradle ที่คุณดูแลทรัพยากร Dependency ให้เพิ่มทรัพยากร Dependency การใช้งานไปยังโมดูลเซสชัน AndroidX Media3 และนำทรัพยากร Dependency เดิมออก

    implementation "androidx.media3:media3-session:1.10.0"
    
  3. เปลี่ยนบริการให้รับค่ามาจาก MediaLibraryService แทน MediaBrowserService ดังที่กล่าวไว้ก่อนหน้านี้ MediaLibraryService เข้ากันได้กับ MediaBrowserService เดิม ดังนั้น API ที่กว้างขึ้นซึ่งบริการนำเสนอต่อไคลเอ็นต์จึงยังคงเหมือนเดิม แอปจึงน่าจะเก็บตรรกะส่วนใหญ่ที่จำเป็นในการใช้ MediaBrowserService ไว้และปรับให้เหมาะกับ MediaLibraryService ใหม่ได้

    ความแตกต่างหลักเมื่อเทียบกับ MediaBrowserServiceCompat เดิมมีดังนี้

    • ใช้เมธอดวงจรการทำงานของบริการ: เมธอดที่ต้องมีการลบล้างในบริการเองคือ onCreate/onDestroy ซึ่งแอปจะจัดสรร/ปล่อยเซสชันไลบรารี เพลเยอร์ และทรัพยากรอื่นๆ นอกเหนือจากเมธอดวงจรการทำงานของบริการมาตรฐานแล้ว แอปยังต้องลบล้าง onGetSession(MediaSession.ControllerInfo) เพื่อแสดงผล MediaLibrarySession ที่สร้างขึ้นใน onCreate

    • ใช้ MediaLibraryService.MediaLibrarySessionCallback: การสร้าง เซสชันต้องใช้ MediaLibraryService.MediaLibrarySessionCallback ที่ใช้ เมธอด API ของโดเมนจริง ดังนั้นแทนที่จะลบล้างเมธอด API ของบริการเดิม คุณจะลบล้างเมธอดของ MediaLibrarySession.Callback แทน

      จากนั้นจะใช้ Callback เพื่อสร้าง MediaLibrarySession ดังนี้

      Kotlin

      mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()

      Java

      mediaLibrarySession =
          new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();

      ดู API ทั้งหมดของ MediaLibrarySessionCallback ได้ในเอกสารประกอบ API

    • ใช้ MediaSession.Callback.onAddMediaItems(): Callback onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>) จะให้บริการ เมธอด API ปัจจุบันและเดิมต่างๆ ที่เพิ่มรายการสื่อลงในเพลเยอร์ เพื่อเล่นในลักษณะที่เข้ากันได้แบบย้อนหลัง ซึ่งรวมถึงเมธอด MediaController.set/addMediaItems() ของตัวควบคุม Media3 รวมถึงเมธอด TransportControls.prepareFrom*/playFrom* ของ API เดิม ดูตัวอย่างการใช้งาน Callback ได้ใน ของแอปเดโมของเซสชันPlaybackService

    • AndroidX Media3 ใช้ androidx.media3.common.MediaItem แทน MediaBrowserCompat.MediaItem และ MediaMetadataCompat คุณต้องเปลี่ยนโค้ดบางส่วนที่ผูกกับคลาสเดิมตามความเหมาะสมหรือแมปกับ MediaItem ของ Media3 แทน

    • โมเดลการเขียนโปรแกรมแบบไม่พร้อมกันทั่วไปเปลี่ยนเป็น Futures ซึ่งแตกต่างจากแนวทาง Result ที่แยกออกได้ของ MediaBrowserServiceCompat การใช้งานบริการของคุณสามารถแสดงผล asynchronous ListenableFuture แทนที่จะแยกผลลัพธ์ออก หรือ แสดงผล Future ทันทีเพื่อแสดงผลค่าโดยตรง

นำ PlayerNotificationManager ออก

MediaLibraryService รองรับการแจ้งเตือนสื่อโดยอัตโนมัติ และคุณสามารถนำ PlayerNotificationManager ออกได้เมื่อใช้ MediaLibraryService หรือ MediaSessionService

แอปสามารถปรับแต่งการแจ้งเตือน ได้โดยการตั้งค่า MediaNotification.Provider ที่กำหนดเองใน onCreate() ซึ่งจะมาแทนที่ DefaultMediaNotificationProvider จากนั้น MediaLibraryService จะจัดการการเริ่มบริการในเบื้องหน้าตามที่จำเป็น

การลบล้าง MediaLibraryService.updateNotification() จะช่วยให้แอปเป็นเจ้าของทั้งหมดในการโพสต์การแจ้งเตือนและเริ่ม/หยุดบริการในเบื้องหน้าตามที่จำเป็น

ย้ายข้อมูลโค้ดไคลเอ็นต์โดยใช้ MediaBrowser

AndroidX Media3 ทำให้ MediaBrowser ใช้ MediaController/Player อินเทอร์เฟซและใช้เพื่อควบคุมการเล่นสื่อนอกเหนือจากการเรียกดูไลบรารีสื่อได้ หากคุณต้องสร้าง MediaBrowserCompat และ MediaControllerCompat ในโลกเดิม คุณสามารถทำเช่นเดียวกันได้โดยใช้ MediaBrowser ใน Media3 เท่านั้น

คุณสามารถสร้าง MediaBrowser และรอให้การเชื่อมต่อกับบริการเสร็จสมบูรณ์ได้ดังนี้

Kotlin

scope.launch {
  val sessionToken = SessionToken(context, ComponentName(context, "MusicService"))
  browser =
    MediaBrowser.Builder(context, sessionToken)
      .setListener(BrowserListener())
      .buildAsync()
      .await()
}

Java

SessionToken sessionToken =
    new SessionToken(context, new ComponentName(context, "MusicService"));
ListenableFuture<MediaBrowser> browserFuture =
    new MediaBrowser.Builder(context, sessionToken)
        .setListener(new BrowserListener())
        .buildAsync();

ดู ควบคุมการเล่นในเซสชันสื่อ เพื่อดูวิธีสร้าง MediaController สำหรับควบคุมการเล่นใน เบื้องหลัง

ขั้นตอนเพิ่มเติมและการล้างข้อมูล

ข้อผิดพลาดของ API ที่ไม่เสถียร

หลังจากย้ายข้อมูลไปยัง Media3 แล้ว คุณอาจเห็นข้อผิดพลาด Lint เกี่ยวกับการใช้ API ที่ไม่เสถียร API เหล่านี้ปลอดภัยที่จะใช้และข้อผิดพลาด Lint เป็นผลพลอยได้จากการรับประกันความเข้ากันได้แบบไบนารีใหม่ของเรา หากไม่ต้องการความเข้ากันได้แบบไบนารีที่เข้มงวด คุณสามารถระงับข้อผิดพลาดเหล่านี้ได้อย่างปลอดภัยด้วยคำอธิบายประกอบ @OptIn

ฉากหลัง

ทั้ง ExoPlayer v1 และ v2 ไม่ได้ให้การรับประกันที่เข้มงวดเกี่ยวกับความเข้ากันได้แบบไบนารีของไลบรารีระหว่างเวอร์ชันที่ตามมา พื้นผิว API ของ ExoPlayer มีขนาดใหญ่มากตามการออกแบบ เพื่อให้แอปปรับแต่งการเล่นได้เกือบทุกด้าน ExoPlayer เวอร์ชันที่ตามมาจะเปลี่ยนชื่อสัญลักษณ์หรือมีการเปลี่ยนแปลงที่ทำให้เกิดข้อขัดข้องอื่นๆ เป็นครั้งคราว (เช่น เมธอดใหม่ที่จำเป็นในอินเทอร์เฟซ) ในกรณีส่วนใหญ่ การขัดข้องเหล่านี้ได้รับการบรรเทาลงโดยการนำสัญลักษณ์ใหม่มาใช้ควบคู่ไปกับการเลิกใช้งานสัญลักษณ์เก่าเป็นเวลา 2-3 เวอร์ชัน เพื่อให้นักพัฒนาแอปมีเวลาในการย้ายข้อมูลการใช้งาน แต่ก็ไม่สามารถทำได้เสมอไป

การเปลี่ยนแปลงที่ทำให้เกิดข้อขัดข้องเหล่านี้ส่งผลให้เกิดปัญหา 2 ประการสำหรับผู้ใช้ไลบรารี ExoPlayer v1 และ v2

  1. การอัปเกรดจาก เป็น ExoPlayer เวอร์ชันอาจทำให้โค้ดหยุดคอมไพล์
  2. แอปที่ขึ้นต่อกันกับ ExoPlayer ทั้งโดยตรงและผ่านไลบรารีระดับกลางต้องตรวจสอบว่าทรัพยากร Dependency ทั้ง 2 รายการเป็นเวอร์ชันเดียวกัน ไม่เช่นนั้นความเข้ากันไม่ได้แบบไบนารีอาจทำให้เกิดข้อขัดข้องขณะรันไทม์

การปรับปรุงใน Media3

Media3 รับประกันความเข้ากันได้แบบไบนารีสำหรับพื้นผิว API บางส่วน ส่วนที่ ไม่ รับประกันความเข้ากันได้แบบไบนารีจะมี @UnstableApi กำกับ เพื่อให้การแยกความแตกต่างนี้ชัดเจน การใช้งานสัญลักษณ์ API ที่ไม่เสถียรจะสร้างข้อผิดพลาด Lint เว้นแต่จะมี @OptIn กำกับ

หลังจากย้ายข้อมูลจาก ExoPlayer v2 ไปยัง Media3 แล้ว คุณอาจเห็นข้อผิดพลาด Lint ของ API ที่ไม่เสถียรจำนวนมาก ซึ่งอาจทำให้ดูเหมือนว่า Media3 "เสถียรน้อยกว่า" ExoPlayer v2 แต่ไม่เป็นเช่นนั้น ส่วน "ไม่เสถียร" ของ Media3 API มีระดับความเสถียรเท่ากับพื้นผิว API ของ ExoPlayer v2 ทั้งหมด และการรับประกันพื้นผิว API ที่เสถียรของ Media3 ไม่มีใน ExoPlayer v2 เลย ความแตกต่างก็คือ ตอนนี้ข้อผิดพลาด Lint จะแจ้งเตือนคุณถึงระดับความเสถียรที่แตกต่างกัน

จัดการข้อผิดพลาด Lint ของ API ที่ไม่เสถียร

ดูรายละเอียดเกี่ยวกับวิธี ใส่คำอธิบายประกอบในการใช้งาน API ที่ไม่เสถียรของ Java และ Kotlin ด้วย @OptIn ได้ในส่วนการแก้ปัญหาเกี่ยวกับข้อผิดพลาด Lint เหล่านี้

API ที่เลิกใช้งานแล้ว

คุณอาจสังเกตเห็นว่าการเรียก API ที่เลิกใช้งานแล้วจะมีขีดฆ่าใน Android Studio เราขอแนะนำให้แทนที่การเรียกดังกล่าวด้วยตัวเลือกที่เหมาะสม วางเมาส์เหนือสัญลักษณ์เพื่อดู JavaDoc ที่บอกว่าควรใช้ API ใดแทน

ภาพหน้าจอ: วิธีแสดง JavaDoc พร้อมทางเลือกแทนเมธอดที่เลิกใช้งานแล้ว
รูปที่ 3: เคล็ดลับเครื่องมือ JavaDoc ใน Android Studio แนะนำตัวเลือกแทนสำหรับสัญลักษณ์ที่เลิกใช้งานแล้ว

ตัวอย่างโค้ดและแอปเดโม

  • แอปเดโมของเซสชัน AndroidX Media3 (อุปกรณ์เคลื่อนที่และ WearOS)
    • การทำงานที่กำหนดเอง
    • การแจ้งเตือน UI ของระบบ, MediaButton/BT
    • การควบคุมการเล่นของ Google Assistant
  • UAMP: Android มีเดียเพลเยอร์ (สาขา media3) (อุปกรณ์เคลื่อนที่, AutomotiveOS)
    • การแจ้งเตือน UI ของระบบ, MediaButton/BT, การเล่นต่อ
    • การควบคุมการเล่นของ Google Assistant/WearOS
    • AutomotiveOS: คำสั่งที่กำหนดเองและการลงชื่อเข้าใช้