Qt Android и системный диалог управления звуком

Речь, конечно же, пойдёт не о том, что можно в приложении поймать событие нажатой клавиши и просто задать уровень звука. Дело в том, что можно работать с приложением и на фоне слушать музыку, запущенную на плеере. Или просто один раз исправить файл системны — и оно всегда будет работать. Необходимо, чтобы при нажатии на клавиши регулировки уровня звука на устройстве, менялся системный уровень звука (ну там, выпрыгивал регулятор громкости и т.д.; ну, вы меня поняли).

На момент написания статьи на русскоязычных сайтах ничего не было. Нашёл только на каком-то отдалённом заморском форуме, и то прописано было не полностью, пришлось самому доводить до ума.

Итак, приступим.

Необходимо зайти в папочку, где установлен Qt. Вот тут внимательно: не SDK, не где складируются откомпиленые проги, а именно сам Qt.

Там заходим в папочку 5.Х.Х (Где Х — это номер версии, у меня 5.2.1). Здесь заходим в папку где указано имя собирателя, которым вы пользуетесь для Android (у меня это android_armv7), а далее проходим следующий путь вложенных папок: \src\android\java\src\org\qtproject\qt5\android\bindings\

Вот мы и на месте. В папке открываем на редактирование файл QtActivity.java.
После строки:
import java.io.DataInputStream;

Примерно 36-я строка, вставляем следующий код:
import java.lang.Object;

После строки:
import android.graphics.Canvas;

Примерно 62-я строка, вставляем следующий код:
import android.media.AudioManager;

Далее, где объявляются разные объекты (я это сделал в 112 строке), необходимо вставить следующий код:
private AudioManager audio;

И напоследок, находите в коде функцию onKeyDown и в её начале вставляете код:

switch (keyCode)
 {
    case KeyEvent.KEYCODE_VOLUME_UP:
        audio.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
        return true;

    case KeyEvent.KEYCODE_VOLUME_DOWN:
        audio.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
        return true;
}

Это, по моему, единственный кусок, взятый из статьи на форуме.

В общем итоге функция будет иметь следующий вид:

public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        switch (keyCode) 
        {
            case KeyEvent.KEYCODE_VOLUME_UP:
                audio.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
                return true;

			case KeyEvent.KEYCODE_VOLUME_DOWN:
                audio.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
                return true;
        }
	
        if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null)
            return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, keyCode, event);
        else
            return super.onKeyDown(keyCode, event);
    }

Ну, вот и все. Теперь пересоберите свои проекты для Android и радуйтесь отображению диалога уровня звука при его регулировке.

На всякий случай привожу ссылку на форум, где это было найдено. Всё работает, проверено.
Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 14
    –1
    >>> а далее проходим следующий путь вложенных папок: \src\android\java\src\org\qtproject\qt5\android\bindings\
    Выглядит кастыльно. При обновлении Qt — все занова? А при работе в команде, вы будете этот файл кидать другу и говорить положи его туда-сюда?
    Честно скажу толком не знаю решения, но все-же не лучше ли воспользоваться jni?
      0
      При работе в команде сборка проекта должна производиться на одном сервере и не зависеть от настроенного окружения на компе конкретного разработчика.

      И разработчики обязаны сами следить, чтобы их окружение соответствовало эталонному, как на сборочном сервере.

      Но вы правы в том, что лучше избегать правок стандартного окружения
        0
        Да согласен, просто тут явно можно этого избежать.
        0
        Наследоваться просто надо было от этого QtActivity и нужное добавлять уже в своих, проектных исходниках.
        +2
        После строки:

        import java.io.DataInputStream;

        Примерно 36-я строка, вставляем следующий код:

        import java.io.DataInputStream;


        Разорвало шаблон. Вы, видимо, опечатались?
          0
          Да, вышла очепятка. Спасибо за подсказку, исправил.
            0
            меня больше заинтересовало про
            Примерно 36-я строка, вставляем следующий код:

            import java.lang.Object;

            +1
            Мне тоже кажется, что это костыль. Ибо скорее всего, где-то в Qt клавиши громкости уже перехватываются, а надо избавиться от перехвата и передать эти нажатия системе. Вы же придумали костыль, с помощью которого регулируете громкость одного из потоков звука.

            Скорее всего, надо просто вместо вашего switch'а сделать так:

            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
            return super.onKeyDown(keyCode, event);

            П.С.: Извиняюсь, парсер Хабра не хочет принимать от меня разметку.
              0
              У меня тоже не принимает парсер =). Условие ни к чему. Оно и так прокидывает нажатия в Qt под видом Qt::Key_VolumeUp Qt::Key_VolumeDown
                0
                Вот именно для того, чтобы оно не прокидывало именно эти клавиши надо сделать так, как написал я.
              0
              Ну, вот и все. Теперь пересоберите свои проекты для Android и радуйтесь отображению диалога уровня звука при его регулировке.

              К сожалению, не всё. Если вы обновитесь до Qt 5.4.0, то с удивлением обнаружите, что ваш костыль отвалился.
              Виной тому исправление вот этого «бага»: bugreports.qt.io/browse/QTBUG-36570

              Кстати, исправление весьма занятное. Теперь при нажатии клавиш VOLUME_UP и VOLUME_DOWN априори вызывается регулировка системной громкости откуда-то из недр Qt'а. И я пока не нашёл способа, как это отключить или изменить поведение нажатия клавиш на то, чтобы была возможность регулировать этот самый STREAM_MUSIC, как в посте у топикстартера. Максимум чего я добился — одновременной регулировки STREAM_MUSIC и системной громкости. Буду рад, если кто-то подскажет решение этой проблемы для Qt 5.4.0 и выше.

              Здесь заходим в папку где указано имя собирателя, которым вы пользуетесь для Android (у меня это android_armv7), а далее проходим следующий путь вложенных папок: \src\android\java\src\org\qtproject\qt5\android\bindings\

              Ой, зачем же так сложно?
              Во-первых, править какие-либо файлы входящие в состав SDK — весьма плохой тон. Я вообще на всякий случай присваиваю этим файликам атрибут «Только для чтения».
              Во-вторых, ваше решение будет затрагивать абсолютно все ваши Android-проекты на Qt, а это может иметь побочные эффекты.

              Для подобных хаков в «QtActivity.java» достаточно его просто вынести в свой проект. То есть в директории вашего проекта создать каталог android/src/org/qtproject/qt5/android/bindings с похаченным файлом «QtActivity.java» и он подхватится при сборке apk-пакета.
              Таким образом и овцы целы, и волки сыты SDK нетронут и девственен и вы получили то, что хотели.
                0
                Целиком с вами согласен. Сверху меня за это заминусовали вон.

                Кстати. Достаточно сделать так:

                setenv(«QT_ANDROID_VOLUME_KEYS»,«value», 1);
                QApplication app(argc, argv);
                Все станет как раньше.

                А вообще лучше перехватить так:

                bool MyEventFilter::eventFilter(QObject *Object, QEvent *Event)
                // тут вызывать что надо через JNI для Qt::Key_VolumeUp
                  0
                  Ну т.е. если выставить setenv(«QT_ANDROID_VOLUME_KEYS»,«value», 1);, то не будет «VOLUME_UP и VOLUME_DOWN априори вызывается регулировка системной громкости откуда-то из недр Qt'а»
                  +1
                  Я у себя так делал:
                  1) Унаследовался от QtActivity и в манифесте прописал свой класс как основное Activity
                  2) В onCreate у своего activity написал this.setVolumeControlStream(AudioManager.STREAM_MUSIC);

                  После этого будет появляться диалог регулировки. Но я делал STREAM_MUSIC, т.к. в приложении аудио проигрывалось и нужен был регулятор громкости, а вообще другие приложения используют STREAM_RING кажется.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое