التعامل مع التغييرات في إخراج الصوت

يتوقّع المستخدمون أن يتمكّنوا من التحكّم في مستوى صوت تطبيق صوتي. ويشمل السلوك العادي إمكانية استخدام عناصر التحكّم في مستوى الصوت (الأزرار أو المقابض على الجهاز أو أشرطة التمرير في واجهة المستخدم) وتجنُّب التشغيل المفاجئ بصوت عالٍ في حال انقطاع اتصال جهاز ملحق، مثل سماعات الرأس، أثناء استخدامه.

استخدام عناصر التحكّم في مستوى الصوت

عندما يضغط المستخدم على أحد مفتاحَي مستوى الصوت في لعبة أو تطبيق موسيقى، من المفترض أن يتغيّر مستوى الصوت، حتى إذا كان المشغّل متوقفًا مؤقتًا بين الأغاني أو لم تتوفّر موسيقى في الموقع الجغرافي الحالي للّعبة.

يستخدم Android عمليات بث صوتية منفصلة لتشغيل الموسيقى والمنبّهات والإشعارات ورنين المكالمات الواردة وأصوات النظام ومستوى الصوت أثناء المكالمة ونغمات تقنية DTMF. يتيح ذلك للمستخدمين التحكّم في مستوى صوت كل بث بشكل مستقل.

يؤدي الضغط على عنصر التحكم في مستوى الصوت إلى تعديل مستوى صوت البث الصوتي النشط بشكل تلقائي. إذا كان تطبيقك لا يشغِّل أي صوت في الوقت الحالي، سيؤدي الضغط على مفتاحَي مستوى الصوت إلى ضبط مستوى صوت الموسيقى (أو مستوى صوت الرنين قبل الإصدار 9 من Android).

يجب تشغيل الصوت باستخدام AudioAttributes.USAGE_MEDIA، ما لم يكن تطبيقك منبهًا.

للتأكّد من أنّ عناصر التحكّم في مستوى الصوت تضبط البث الصحيح، عليك طلب setVolumeControlStream() تمرير نوع البث المطابق للسمات التي يمكن استردادها من AudioAttributes.getVolumeControlStream.

Kotlin

setVolumeControlStream(AudioManager.STREAM_MUSIC)

Java

setVolumeControlStream(AudioManager.STREAM_MUSIC);

يمكنك إجراء هذه العملية خلال مراحل نشاط تطبيقك، عادةً من خلال طريقة onResume() الخاصة بالنشاط أو الجزء الذي يتحكم في الوسائط. يربط هذا الإجراء عناصر التحكّم في مستوى الصوت بـ STREAM_MUSIC عندما يظهر النشاط أو الجزء المستهدف.

التحكّم في مستوى صوت البث آليًا

في حالات نادرة، يمكنك ضبط مستوى صوت البث الصوتي آليًا. على سبيل المثال، عندما يستبدل تطبيقك واجهة مستخدم حالية. لا ننصح بتنفيذ هذا الإجراء لأنّ AudioManager في Android يمزج بين كل عمليات البث الصوتي من النوع نفسه معًا. تؤدي هاتان الطريقتان إلى تغيير مستوى الصوت لكل تطبيق يستخدم البث. تجنب استخدامها:

العمل على الأجهزة ذات الصوت الثابت

تتضمّن بعض الأجهزة (مثل أجهزة Chromebook) عناصر تحكُّم في مستوى الصوت ولكنها لا تسمح للتطبيقات باستخدام طرق AudioManager الموضَّحة أعلاه لتغيير مستوى البث الصوتي. وتسمى هذه الأجهزة ذات الحجم الثابت. يمكنك معرفة ما إذا كان تطبيقك يعمل على جهاز بحجم ثابت من خلال الاتصال بـ isVolumeFixed().

ويجب أن يوفر تطبيق الصوت إمكانية موازنة مستوى مخرجات الصوت مع التطبيقات الأخرى التي يُحتمَل تشغيلها على البث نفسه. على الأجهزة ذات مستوى الصوت الثابت، يجب أن يربط التطبيق عناصر التحكّم في مستوى الصوت بطريقة setVolume() المناسبة في الجدول أدناه:

اللاعب الطريقة
مقطع صوتي AudioTrack.setVolume()
مشغّل الوسائط MediaPlayer.setVolume()
ExoPlayer يمكنك استخدام SimpleExoPlayer.setVolume() الذي يضبط مستوى صوت المقطع الصوتي الأساسي.

لا تكن مزعجًا

يتوفر للمستخدمين عدد من البدائل عندما يتعلق الأمر بتشغيل الصوت من أجهزة Android. وتشتمل معظم الأجهزة على مكبّر صوت مدمج ومقابس سماعة رأس لسماعات رأس سلكية، كما يتميّز العديد منها بإمكانية الاتصال عبر البلوتوث ودعم صوت A2DP.

عند فصل سماعة رأس أو فصل جهاز بلوتوث عن مصدر الطاقة، تتم إعادة توجيه البث الصوتي تلقائيًا إلى مكبّر الصوت المدمج. إذا كنت تستمع إلى الموسيقى بصوت عالٍ، فقد يكون ذلك مفاجأة صاخبة.

ويتوقع المستخدمون عادةً أن يتم إيقاف التشغيل مؤقتًا في هذه الحالة من خلال التطبيقات التي تشتمل على مشغّل موسيقى مزود بعناصر تحكم في التشغيل على الشاشة. وينبغي أن تستمر التطبيقات الأخرى، مثل الألعاب التي لا تتضمن عناصر تحكم في اللعب. يمكن للمستخدم ضبط مستوى الصوت باستخدام عناصر التحكم في الجهاز.

عند إعادة بث الصوت إلى مكبّر الصوت المُدمَج، يبث النظام هدف ACTION_AUDIO_BECOMING_NOISY. يجب إنشاء BroadcastReceiver للاستماع إلى هذا الهدف كلما تم تشغيل محتوى صوتي. يُفترض أن يظهر جهاز الاستقبال على النحو التالي:

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
      }
    }
}

سجِّل جهاز الاستقبال عند بدء التشغيل، وألغِ تسجيله عند التوقف. إذا صمّمت تطبيقك على النحو الموضّح في هذا الدليل، من المفترض أن تظهر هذه المكالمات في عمليات معاودة الاتصال بجلسات وسائط 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);
  }
}