Tạo ứng dụng trình duyệt đa phương tiện

Để hoàn tất thiết kế ứng dụng/máy chủ, bạn phải tạo thành phần hoạt động chứa mã giao diện người dùng, MediaController được liên kết và MediaBrowser.

MediaBrowser thực hiện hai chức năng quan trọng: Trình duyệt này kết nối với MediaBrowserService và sau khi kết nối, trình duyệt này sẽ tạo MediaController cho giao diện người dùng của bạn.

Lưu ý: Cách triển khai MediaBrowser được đề xuất là MediaBrowserCompat, được xác định trong phần tử Thư viện hỗ trợ Media-Compat. Xuyên suốt trang này, thuật ngữ "MediaBrowser" đề cập đến một thực thể của MediaBrowserCompat.

Kết nối với MediaBrowserService

Khi hoạt động của ứng dụng được tạo, hoạt động đó sẽ kết nối với MediaBrowserService. Có một chút bắt tay và nhảy múa. Sửa đổi phương thức gọi lại trong vòng đời của hoạt động như sau:

  • onCreate() tạo MediaBrowserCompat. Truyền tên của MediaBrowserService và MediaBrowserCompat.ConnectionCallback mà bạn đã xác định.
  • onStart() kết nối với MediaBrowserService. Đây là lúc sự kỳ diệu của MediaBrowserCompat.ConnectionCallback xuất hiện. Nếu kết nối thành công, lệnh gọi lại onConnect() sẽ tạo trình điều khiển nội dung nghe nhìn, liên kết nó với phiên phát nội dung đa phương tiện, liên kết các chế độ điều khiển trên giao diện người dùng với MediaController và đăng ký trình điều khiển để nhận lệnh gọi lại từ phiên phát nội dung đa phương tiện.
  • onResume() thiết lập luồng âm thanh để ứng dụng của bạn phản hồi chế độ điều chỉnh âm lượng trên thiết bị.
  • onStop() ngắt kết nối MediaBrowser và huỷ đăng ký MediaController.Callback khi hoạt động của bạn dừng.

Kotlin

class MediaPlayerActivity : AppCompatActivity() {

    private lateinit var mediaBrowser: MediaBrowserCompat

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        // Create MediaBrowserServiceCompat
        mediaBrowser = MediaBrowserCompat(
                this,
                ComponentName(this, MediaPlaybackService::class.java),
                connectionCallbacks,
                null // optional Bundle
        )
    }

    public override fun onStart() {
        super.onStart()
        mediaBrowser.connect()
    }

    public override fun onResume() {
        super.onResume()
        volumeControlStream = AudioManager.STREAM_MUSIC
    }

    public override fun onStop() {
        super.onStop()
        // (see "stay in sync with the MediaSession")
        MediaControllerCompat.getMediaController(this)?.unregisterCallback(controllerCallback)
        mediaBrowser.disconnect()
    }
}

Java

public class MediaPlayerActivity extends AppCompatActivity {
  private MediaBrowserCompat mediaBrowser;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    // Create MediaBrowserServiceCompat
    mediaBrowser = new MediaBrowserCompat(this,
      new ComponentName(this, MediaPlaybackService.class),
        connectionCallbacks,
        null); // optional Bundle
  }

  @Override
  public void onStart() {
    super.onStart();
    mediaBrowser.connect();
  }

  @Override
  public void onResume() {
    super.onResume();
    setVolumeControlStream(AudioManager.STREAM_MUSIC);
  }

  @Override
  public void onStop() {
    super.onStop();
    // (see "stay in sync with the MediaSession")
    if (MediaControllerCompat.getMediaController(MediaPlayerActivity.this) != null) {
      MediaControllerCompat.getMediaController(MediaPlayerActivity.this).unregisterCallback(controllerCallback);
    }
    mediaBrowser.disconnect();

  }
}

Tuỳ chỉnh MediaBrowserCompat.ConnectionCallback

Khi hoạt động của bạn tạo MediaBrowserCompat, bạn phải tạo một thực thể của ConnectionCallback. Sửa đổi phương thức onConnected() để truy xuất mã thông báo phiên đa phương tiện từ MediaBrowserService và sử dụng mã thông báo để tạo MediaControllerCompat.

Sử dụng phương thức tiện lợi MediaControllerCompat.setMediaController() để lưu liên kết vào bộ điều khiển. Thao tác này cho phép xử lý các nút nội dung đa phương tiện. Ứng dụng này cũng cho phép bạn gọi MediaControllerCompat.getMediaController() để truy xuất trình điều khiển khi tạo bộ điều khiển phương tiện giao thông.

Mã mẫu sau đây cho biết cách sửa đổi phương thức onConnected().

Kotlin

private val connectionCallbacks = object : MediaBrowserCompat.ConnectionCallback() {
    override fun onConnected() {

        // Get the token for the MediaSession
        mediaBrowser.sessionToken.also { token ->

            // Create a MediaControllerCompat
            val mediaController = MediaControllerCompat(
                    this@MediaPlayerActivity, // Context
                    token
            )

            // Save the controller
            MediaControllerCompat.setMediaController(this@MediaPlayerActivity, mediaController)
        }

        // Finish building the UI
        buildTransportControls()
    }

    override fun onConnectionSuspended() {
        // The Service has crashed. Disable transport controls until it automatically reconnects
    }

    override fun onConnectionFailed() {
        // The Service has refused our connection
    }
}

Java

private final MediaBrowserCompat.ConnectionCallback connectionCallbacks =
  new MediaBrowserCompat.ConnectionCallback() {
    @Override
    public void onConnected() {

      // Get the token for the MediaSession
      MediaSessionCompat.Token token = mediaBrowser.getSessionToken();

      // Create a MediaControllerCompat
      MediaControllerCompat mediaController =
        new MediaControllerCompat(MediaPlayerActivity.this, // Context
        token);

      // Save the controller
      MediaControllerCompat.setMediaController(MediaPlayerActivity.this, mediaController);

      // Finish building the UI
      buildTransportControls();
    }

    @Override
    public void onConnectionSuspended() {
      // The Service has crashed. Disable transport controls until it automatically reconnects
    }

    @Override
    public void onConnectionFailed() {
      // The Service has refused our connection
    }
  };

Kết nối giao diện người dùng với trình điều khiển nội dung nghe nhìn

Trong mã mẫu ConnectionCallback ở trên, bao gồm lệnh gọi đến buildTransportControls() để bổ sung thêm cho giao diện người dùng của bạn. Bạn cần đặt onClickListener cho các phần tử trên giao diện người dùng điều khiển trình phát. Chọn lựa chọn phù hợp MediaControllerCompat.TransportControls cho mỗi phần tử.

Mã của bạn sẽ trông giống như sau, với một onClickListener cho mỗi nút:

Kotlin

fun buildTransportControls() {
    val mediaController = MediaControllerCompat.getMediaController(this@MediaPlayerActivity)
    // Grab the view for the play/pause button
    playPause = findViewById<ImageView>(R.id.play_pause).apply {
        setOnClickListener {
            // Since this is a play/pause button, you'll need to test the current state
            // and choose the action accordingly

            val pbState = mediaController.playbackState.state
            if (pbState == PlaybackStateCompat.STATE_PLAYING) {
                mediaController.transportControls.pause()
            } else {
                mediaController.transportControls.play()
            }
        }
    }

    // Display the initial state
    val metadata = mediaController.metadata
    val pbState = mediaController.playbackState

    // Register a Callback to stay in sync
    mediaController.registerCallback(controllerCallback)
}

Java

void buildTransportControls()
{
  // Grab the view for the play/pause button
  playPause = (ImageView) findViewById(R.id.play_pause);

  // Attach a listener to the button
  playPause.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      // Since this is a play/pause button, you'll need to test the current state
      // and choose the action accordingly

      int pbState = MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getPlaybackState().getState();
      if (pbState == PlaybackStateCompat.STATE_PLAYING) {
        MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().pause();
      } else {
        MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().play();
      }
  });

  MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(MediaPlayerActivity.this);

  // Display the initial state
  MediaMetadataCompat metadata = mediaController.getMetadata();
  PlaybackStateCompat pbState = mediaController.getPlaybackState();

  // Register a Callback to stay in sync
  mediaController.registerCallback(controllerCallback);
}
}

Các phương thức TransportControls sẽ gửi lệnh gọi lại đến phiên phát nội dung đa phương tiện của dịch vụ. Hãy đảm bảo bạn đã xác định Phương thức MediaSessionCompat.Callback cho từng chế độ điều khiển.

Đồng bộ hoá với phiên phát nội dung nghe nhìn

Giao diện người dùng phải cho thấy trạng thái hiện tại của phiên phát nội dung đa phương tiện, như mô tả trong PlaybackState và Metadata. Khi tạo các thành phần điều khiển phương tiện giao thông, bạn có thể lấy trạng thái hiện tại của phiên, hiển thị phiên đó trong giao diện người dùng, cũng như bật và tắt các thành phần điều khiển phương tiện giao thông dựa trên trạng thái và các hành động có sẵn.

Để nhận lệnh gọi lại từ phiên đa phương tiện mỗi khi trạng thái hoặc siêu dữ liệu của phiên thay đổi, hãy xác định MediaControllerCompat.Callback bằng 2 phương thức sau:

Kotlin

private var controllerCallback = object : MediaControllerCompat.Callback() {

    override fun onMetadataChanged(metadata: MediaMetadataCompat?) {}

    override fun onPlaybackStateChanged(state: PlaybackStateCompat?) {}
}

Java

MediaControllerCompat.Callback controllerCallback =
  new MediaControllerCompat.Callback() {
    @Override
    public void onMetadataChanged(MediaMetadataCompat metadata) {}

    @Override
    public void onPlaybackStateChanged(PlaybackStateCompat state) {}
  };

Đăng ký lệnh gọi lại khi bạn tạo các phương thức điều khiển truyền tải (xem phương thức buildTransportControls()) và huỷ đăng ký lệnh gọi lại đó khi hoạt động dừng (trong phương thức vòng đời onStop() của hoạt động).

Ngắt kết nối khi phiên đa phương tiện bị huỷ

Nếu phiên đa phương tiện không hợp lệ, onSessionDestroyed() lệnh gọi lại được phát hành. Khi điều đó xảy ra, phiên không thể hoạt động trong vòng đời của MediaBrowserService. Mặc dù hàm liên quan đến MediaBrowser có thể tiếp tục hoạt động, người dùng không thể xem hoặc kiểm soát từ phiên phát nội dung đa phương tiện đã bị huỷ bỏ, điều này có thể làm giảm giá trị của ứng dụng của bạn.

Do đó, khi phiên bị huỷ, bạn phải ngắt kết nối khỏi MediaBrowserService bằng cách gọi disconnect(). Điều này đảm bảo rằng dịch vụ trình duyệt không có ứng dụng khách bị ràng buộc và có thể bị huỷ bỏ bởi Hệ điều hành. Nếu sau này bạn cần kết nối lại với MediaBrowserService (ví dụ: nếu ứng dụng của bạn muốn duy trì kết nối liên tục với ứng dụng đa phương tiện), tạo một phiên bản mới của MediaBrowser thay vì sử dụng lại phiên bản cũ.

Đoạn mã sau đây minh hoạ cách triển khai lệnh gọi lại ngắt kết nối khỏi dịch vụ trình duyệt khi phiên đa phương tiện bị huỷ:

Kotlin

private var controllerCallback = object : MediaControllerCompat.Callback() {
    override fun onSessionDestroyed() {
      mediaBrowser.disconnect()
      // maybe schedule a reconnection using a new MediaBrowser instance
    }
}

Java

MediaControllerCompat.Callback controllerCallback =
  new MediaControllerCompat.Callback() {
    @Override
    public void onSessionDestroyed() {
      mediaBrowser.disconnect();
      // maybe schedule a reconnection using a new MediaBrowser instance
    }
  };