Xử lý các thay đổi trong đầu ra âm thanh

Người dùng muốn có thể điều chỉnh âm lượng của ứng dụng âm thanh. Hành vi tiêu chuẩn bao gồm khả năng sử dụng các nút điều chỉnh âm lượng (nút hoặc núm trên thiết bị hoặc thanh trượt trong giao diện người dùng) và tránh phát âm lượng lớn đột ngột nếu thiết bị ngoại vi như tai nghe bị ngắt kết nối trong khi sử dụng.

Sử dụng các nút điều chỉnh âm lượng

Khi người dùng nhấn phím âm lượng trong trò chơi hoặc ứng dụng nhạc, âm lượng sẽ thay đổi, ngay cả khi trình phát bị tạm dừng giữa các bài hát hoặc không có nhạc cho vị trí trò chơi hiện tại.

Android sử dụng các luồng âm thanh riêng biệt để phát nhạc, chuông báo, thông báo, chuông cuộc gọi đến, âm thanh hệ thống, âm lượng trong cuộc gọi và âm DTMF. Điều này cho phép người dùng kiểm soát âm lượng của từng luồng một cách độc lập.

Theo mặc định, thao tác nhấn nút điều chỉnh âm lượng sẽ sửa đổi âm lượng của luồng âm thanh đang hoạt động. Nếu ứng dụng của bạn hiện không phát nội dung nào, thì việc nhấn các phím âm lượng sẽ điều chỉnh âm lượng nhạc (hoặc âm lượng chuông trước Android 9).

Trừ phi ứng dụng của bạn là đồng hồ báo thức, bạn nên phát âm thanh bằng cách sử dụng AudioAttributes.USAGE_MEDIA.

Để đảm bảo rằng các chế độ điều khiển âm lượng điều chỉnh đúng luồng, bạn nên gọi setVolumeControlStream() truyền vào loại luồng khớp với các thuộc tính mà bạn có thể truy xuất từ AudioAttributes.getVolumeControlStream.

Kotlin

setVolumeControlStream(AudioManager.STREAM_MUSIC)

Java

setVolumeControlStream(AudioManager.STREAM_MUSIC);

Thực hiện lệnh gọi này trong vòng đời của ứng dụng, thường là từ phương thức onResume() của hoạt động hoặc mảnh kiểm soát nội dung nghe nhìn. Thao tác này sẽ kết nối các nút điều khiển âm lượng với STREAM_MUSIC bất cứ khi nào hoạt động hoặc mảnh mục tiêu hiển thị.

Điều khiển âm lượng luồng theo phương thức lập trình

Trong một số ít trường hợp, bạn có thể đặt âm lượng của luồng âm thanh theo phương thức lập trình. Ví dụ: khi ứng dụng của bạn thay thế giao diện người dùng hiện có. Bạn không nên làm như vậy vì AudioManager của Android sẽ kết hợp tất cả các luồng âm thanh cùng loại với nhau. Các phương thức này thay đổi âm lượng của mọi ứng dụng sử dụng luồng. Tránh sử dụng các tính năng này:

Làm việc với các thiết bị có âm lượng cố định

Một số thiết bị (như Chromebook và ô tô chạy Android Automotive OS) có các chế độ điều khiển âm lượng nhưng không cho phép ứng dụng sử dụng các phương thức AudioManager được mô tả trước đó để thay đổi mức độ của luồng âm thanh. Đây được gọi là thiết bị có âm lượng cố định. Bạn có thể khám phá xem ứng dụng của mình có đang chạy trên thiết bị có âm lượng cố định hay không bằng cách gọi isVolumeFixed().

Ứng dụng âm thanh phải có khả năng cân bằng âm lượng đầu ra với các ứng dụng khác có thể đang phát trên cùng một luồng. Trên các thiết bị có âm lượng cố định, ứng dụng phải kết nối các chế độ điều khiển âm lượng của riêng ứng dụng với phương thức setVolume() thích hợp:

Người chơi Phương thức
AudioTrack AudioTrack.setVolume()
MediaPlayer MediaPlayer.setVolume()
ExoPlayer Sử dụng SimpleExoPlayer.setVolume() để đặt âm lượng của AudioTrack cơ bản.
Web Đặt thuộc tính volume của HTMLMediaElement

Không gây ồn ào

Người dùng có một số lựa chọn thay thế khi thưởng thức âm thanh từ thiết bị Android. Hầu hết thiết bị đều có loa tích hợp, giắc cắm tai nghe cho tai nghe có dây và nhiều thiết bị cũng có tính năng kết nối Bluetooth và hỗ trợ âm thanh A2DP.

Khi bạn rút tai nghe hoặc ngắt kết nối thiết bị Bluetooth, luồng âm thanh sẽ tự động chuyển hướng đến loa tích hợp. Nếu bạn nghe nhạc với âm lượng lớn, thì đây có thể là một bất ngờ ồn ào.

Trong trường hợp này, người dùng thường mong đợi các ứng dụng có trình phát nhạc với các chế độ điều khiển phát trên màn hình sẽ tạm dừng phát. Các ứng dụng khác, chẳng hạn như trò chơi không có chế độ điều khiển, sẽ tiếp tục phát. Người dùng có thể điều chỉnh âm lượng bằng các nút điều khiển phần cứng của thiết bị.

Khi đầu ra âm thanh chuyển về loa tích hợp, hệ thống sẽ truyền đi một ý định ACTION_AUDIO_BECOMING_NOISY. Bạn nên tạo một BroadcastReceiver để theo dõi ý định này bất cứ khi nào bạn phát âm thanh. Trình thu của bạn sẽ có dạng như sau:

Kotlin

private class BecomingNoisyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) {
            // Pause the playback
        }
    }
}

Java

private class BecomingNoisyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
      if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
          // Pause the playback
      }
    }
}

Đăng ký trình thu khi bạn bắt đầu phát và huỷ đăng ký trình thu khi bạn dừng phát. Nếu bạn thiết kế ứng dụng như mô tả trong hướng dẫn này, các lệnh gọi này sẽ xuất hiện trong lệnh gọi lại phiên phát nội dung đa phương tiện onPlay()onStop().

Kotlin

private val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
private val myNoisyAudioStreamReceiver = BecomingNoisyReceiver()

private val callback = object : MediaSessionCompat.Callback() {

    override fun onPlay() {
        registerReceiver(myNoisyAudioStreamReceiver, intentFilter)
    }

    override fun onStop() {
        unregisterReceiver(myNoisyAudioStreamReceiver)
    }
}

Java

private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private BecomingNoisyReceiver myNoisyAudioStreamReceiver = new BecomingNoisyReceiver();

MediaSessionCompat.Callback callback = new
MediaSessionCompat.Callback() {
  @Override
  public void onPlay() {
    registerReceiver(myNoisyAudioStreamReceiver, intentFilter);
  }

  @Override
  public void onStop() {
    unregisterReceiver(myNoisyAudioStreamReceiver);
  }
}