Làm quen với Trình phát nội dung đa phương tiện

Tài liệu này giới thiệu các khái niệm cơ bản mà bạn nên nắm rõ trước khi làm việc với Trình phát nội dung đa phương tiện.

Lớp âm thanh và video

Các lớp sau đây phát âm thanh và video trong khung Android:

  • MediaPlayer: Lớp này là API chính để phát âm thanh và video.
  • AudioManager: Lớp này quản lý nguồn âm thanh và đầu ra âm thanh trên một thiết bị.

Nội dung khai báo trong tệp kê khai

Trước khi bắt đầu phát triển ứng dụng bằng MediaPlayer, hãy đảm bảo tệp kê khai của bạn có các nội dung khai báo thích hợp để cho phép sử dụng các tính năng có liên quan.

  • Quyền truy cập Internet: Nếu bạn đang sử dụng MediaPlayer để truyền trực tuyến nội dung dựa trên mạng, thì ứng dụng của bạn phải yêu cầu quyền truy cập mạng.

    <uses-permission android:name="android.permission.INTERNET" />
    
  • Quyền khoá chế độ thức: Nếu ứng dụng trình phát của bạn cần ngăn màn hình giảm độ sáng hoặc bộ xử lý chuyển sang chế độ ngủ, hoặc sử dụng các phương thức MediaPlayer.setScreenOnWhilePlaying(boolean) hoặc MediaPlayer.setWakeMode(android.content.Context, int), thì bạn phải yêu cầu quyền này.

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

Sử dụng lớp MediaPlayer

Lớp MediaPlayer là một thành phần thiết yếu của khung nội dung nghe nhìn. Một đối tượng của lớp này có thể tìm nạp, giải mã và phát cả âm thanh và video với chế độ thiết lập tối thiểu. MediaPlayer hỗ trợ một số nguồn nội dung đa phương tiện, bao gồm:

  • Tài nguyên cục bộ
  • URI nội bộ, chẳng hạn như URI bạn có thể lấy từ Trình phân giải nội dung
  • URL bên ngoài (phát trực tuyến)

Để biết danh sách các định dạng nội dung nghe nhìn mà Android hỗ trợ, hãy xem trang Các định dạng nội dung nghe nhìn được hỗ trợ.

Ví dụ về cách xử lý nguồn âm thanh

Dưới đây là ví dụ về cách phát âm thanh có sẵn dưới dạng tài nguyên thô cục bộ (được lưu trong thư mục res/raw/ của ứng dụng):

Kotlin

var mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1)
mediaPlayer.start() // no need to call prepare(); create() does that for you

Java

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

Trong trường hợp này, tài nguyên "thô" là một tệp mà hệ thống không cố gắng phân tích cú pháp theo bất kỳ cách cụ thể nào. Tuy nhiên, nội dung của tài nguyên này không được là âm thanh thô. Đây phải là tệp nội dung nghe nhìn được mã hoá và định dạng đúng cách ở một trong các định dạng được hỗ trợ.

Sau đây là cách bạn có thể phát từ một URI có sẵn cục bộ trong hệ thống (ví dụ: URI bạn nhận được thông qua Trình phân giải nội dung):

Kotlin

val myUri: Uri = .... // initialize Uri here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, myUri)
    prepare()
    start()
}

Java

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

Cách phát từ URL từ xa bằng tính năng truyền trực tuyến HTTP như sau:

Kotlin

val url = "http://........" // your URL here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(url)
    prepare() // might take long! (for buffering, etc)
    start()
}

Java

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

Sử dụng tính năng chuẩn bị không đồng bộ để cải thiện hiệu suất

Hãy lưu ý đến hiệu suất khi bạn sử dụng MediaPlayer. Ví dụ: lệnh gọi đến prepare() có thể mất nhiều thời gian để thực thi, vì lệnh gọi này có thể liên quan đến việc tìm nạp và giải mã dữ liệu phương tiện. Vì vậy, giống như mọi phương thức có thể mất nhiều thời gian để thực thi, đừng bao giờ gọi phương thức đó từ luồng giao diện người dùng của ứng dụng. Việc này khiến giao diện người dùng ngừng phản hồi cho đến khi phương thức trả về. Đây là trải nghiệm người dùng không tốt và có thể gây ra lỗi ANR (Ứng dụng không phản hồi).

Để tránh treo luồng giao diện người dùng, hãy tạo một luồng khác để chuẩn bị MediaPlayer và thông báo cho luồng chính khi hoàn tất. Khung này cung cấp một cách thuận tiện để hoàn thành phương thức prepareAsync() cho việc này. Phương thức này bắt đầu chuẩn bị nội dung nghe nhìn ở chế độ nền và trả về ngay lập tức. Khi nội dung nghe nhìn đã chuẩn bị xong, phương thức onPrepared() của MediaPlayer.OnPreparedListener được định cấu hình thông qua setOnPreparedListener() sẽ được gọi.

Tìm hiểu thêm

Jetpack Media3 là giải pháp được đề xuất để phát nội dung đa phương tiện trong ứng dụng của bạn. Hãy đọc thêm về giải pháp này.

Các trang này đề cập đến các chủ đề liên quan đến việc ghi âm, lưu trữ và phát âm thanh và video: