คำแนะนำในการย้ายข้อมูล 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 ออก
  • เข้ากันได้แบบย้อนหลังกับ 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 (ขึ้นอยู่กับแพ็กเกจของ android.support.v4.media.* androidx.media:media:1.4.3+)
    ย้ายข้อมูลโค้ดไคลเอ็นต์โดยใช้ MediaBrowserCompat หรือ MediaControllerCompat เพื่อใช้ androidx.media3.session.MediaBrowser กับ androidx.media3.common.MediaItem

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

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

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

  2. อัปเดตแอป

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

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

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

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

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

ย้ายข้อมูล 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.11.1"
    
  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();

  5. ใช้ MySessionCallback ตามที่แอปของคุณกำหนด ขั้นตอนนี้ไม่บังคับ หากต้องการอนุญาตให้ตัวควบคุมเพิ่มรายการสื่อลงในเพลเยอร์ ให้ใช้MediaSession.Callback.onAddMediaItems() โดยจะให้บริการเมธอด API ปัจจุบันและเมธอด 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. หากต้องการให้ความเข้ากันได้แบบย้อนหลังทำงานได้ คุณต้องลงทะเบียนทั้งอินเทอร์เฟซบริการกับบริการของคุณใน 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.11.1"
    
  3. เปลี่ยนบริการให้รับค่าจาก MediaLibraryService แทน MediaBrowserService ดังที่กล่าวไว้ก่อนหน้านี้ MediaLibraryService เข้ากันได้กับ MediaBrowserService รุ่นเดิม ดังนั้น API ที่กว้างขึ้นซึ่งบริการ นำเสนอต่อไคลเอ็นต์จึงยังคงเหมือนเดิม ดังนั้นแอปจึงน่าจะยังคงใช้ตรรกะส่วนใหญ่ที่จำเป็นต่อการใช้งาน MediaBrowserService และปรับให้เข้ากับ MediaLibraryService ใหม่ได้

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

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

    • ใช้ MediaLibraryService.MediaLibrarySessionCallback: การสร้าง เซสชันต้องใช้ MediaLibraryService.MediaLibrarySessionCallback ที่ใช้ เมธอด API ของโดเมนจริง ดังนั้นแทนที่จะลบล้างเมธอด API ของบริการเดิม คุณจะลบล้างเมธอดของ MediaLibrarySession.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 เดิม ดูตัวอย่างการใช้งานการเรียกกลับได้ใน PlaybackService ของแอปเดโมของเซสชัน

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

    • รูปแบบการเขียนโปรแกรมแบบอะซิงโครนัสทั่วไปเปลี่ยนเป็น Futures ใน ทางตรงกันข้ามกับแนวทาง Result ที่ถอดออกได้ของ MediaBrowserServiceCompat การติดตั้งใช้งานบริการของคุณสามารถส่งคืน 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 เวอร์ชัน เพื่อให้เวลาแก่นักพัฒนาซอฟต์แวร์ ในการย้ายข้อมูลการใช้งาน แต่ก็ไม่ใช่ทุกครั้งที่จะทำได้

การเปลี่ยนแปลงที่ไม่รองรับนี้ส่งผลให้ผู้ใช้ไลบรารี ExoPlayer เวอร์ชัน 1 และเวอร์ชัน 2 พบปัญหา 2 อย่างดังนี้

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

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

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

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