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 и радуйтесь отображению диалога уровня звука при его регулировке.

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

Подробнее
Реклама

Комментарии 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 кажется.

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

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