คำแนะนำในการย้ายข้อมูล 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)

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.8.0"
    
  3. แทนที่ MediaSessionCompat ด้วย androidx.media3.session.MediaSession

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

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

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

    mediaSession?.run {
      player.release()
      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.8.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 แทน

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

      mediaLibrarySession =
            MediaLibrarySession.Builder(this, player, 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 และรอการเชื่อมต่อกับ บริการที่กำลังสร้างได้โดยทำดังนี้

scope.launch {
    val sessionToken =
        SessionToken(context, ComponentName(context, MusicService::class.java)
    browser =
        MediaBrowser.Builder(context, sessionToken))
            .setListener(BrowserListener())
            .buildAsync()
            .await()
    // Get the library root to start browsing the library.
    root = browser.getLibraryRoot(/* params= */ null).await();
    // Add a MediaController.Listener to listen to player state events.
    browser.addListener(playerListener)
    playerView.setPlayer(browser)
}

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

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

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

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

ฉากหลัง

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

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

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

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

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

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

จัดการข้อผิดพลาดของ Linters 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 Media Player (สาขา media3) (อุปกรณ์เคลื่อนที่, AutomotiveOS)
    • การแจ้งเตือน UI ของระบบ, MediaButton/BT, การเล่นต่อ
    • การควบคุมการเล่นของ Google Assistant/WearOS
    • AutomotiveOS: คำสั่งและการลงชื่อเข้าใช้ที่กำหนดเอง