Add Audio tool

This commit is contained in:
FalsinSoft 2021-03-16 10:03:33 +01:00
parent a188695de3
commit 19c82f4f08
13 changed files with 354 additions and 12 deletions

View File

@ -171,6 +171,14 @@ if(QTAT_USER_MESSAGING_PLATFORM)
list(APPEND QTAT_JAVA_FILES ${QTAT_JAVA_DIR}/AndroidUserMessagingPlatform.java)
endif()
option(QTAT_AUDIO "Enable QtAndroidTools Audio.")
if(QTAT_AUDIO)
add_compile_definitions(QTAT_AUDIO)
list(APPEND QTAT_SOURCE_FILES QAndroidAudio.cpp)
list(APPEND QTAT_HEADER_FILES QAndroidAudio.h)
list(APPEND QTAT_JAVA_FILES ${QTAT_JAVA_DIR}/AndroidAudio.java)
endif()
add_library(QtAndroidTools STATIC
${QTAT_SOURCE_FILES}
${QTAT_HEADER_FILES})

View File

@ -55,7 +55,6 @@ QAndroidAdMobBanner::QAndroidAdMobBanner(QQuickItem *parent) : QQuickItem(parent
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidAdMobBanner::applicationStateChanged);
connect(qGuiApp->primaryScreen(), &QScreen::geometryChanged, this, &QAndroidAdMobBanner::screenGeometryChanged);
setNewAppState(APP_STATE_CREATE);
}
QAndroidAdMobBanner::~QAndroidAdMobBanner()

View File

@ -0,0 +1,108 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "QAndroidAudio.h"
QAndroidAudio *QAndroidAudio::m_pInstance = nullptr;
QAndroidAudio::QAndroidAudio() : m_javaAudio("com/falsinsoft/qtandroidtools/AndroidAudio",
"(Landroid/app/Activity;)V",
QtAndroid::androidActivity().object<jobject>()),
m_focus(false)
{
m_pInstance = this;
if(m_javaAudio.isValid())
{
const JNINativeMethod jniMethod[] = {
{"focusChanged", "(Z)V", reinterpret_cast<void*>(&QAndroidAudio::deviceFocusChanged)},
};
QAndroidJniEnvironment jniEnv;
jclass objectClass;
objectClass = jniEnv->GetObjectClass(m_javaAudio.object<jobject>());
jniEnv->RegisterNatives(objectClass, jniMethod, sizeof(jniMethod)/sizeof(JNINativeMethod));
jniEnv->DeleteLocalRef(objectClass);
}
}
QAndroidAudio::~QAndroidAudio()
{
}
QObject* QAndroidAudio::qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new QAndroidAudio();
}
QAndroidAudio* QAndroidAudio::instance()
{
return m_pInstance;
}
void QAndroidAudio::deviceFocusChanged(JNIEnv *env, jobject thiz, jboolean focus)
{
Q_UNUSED(env)
Q_UNUSED(thiz)
if(m_pInstance != nullptr)
{
Q_EMIT m_pInstance->setFocus(focus);
}
}
bool QAndroidAudio::hasFocus()
{
return m_focus;
}
void QAndroidAudio::setFocus(bool focus)
{
m_focus = focus;
Q_EMIT focusChanged();
}
bool QAndroidAudio::requestFocus()
{
if(m_javaAudio.isValid())
{
if(m_javaAudio.callMethod<jboolean>("requestFocus"))
{
setFocus(true);
return true;
}
}
return false;
}
void QAndroidAudio::abandonFocus()
{
if(m_javaAudio.isValid())
{
m_javaAudio.callMethod<void>("abandonAudioFocus");
setFocus(false);
}
}

View File

@ -0,0 +1,59 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtAndroidExtras>
#include <QQmlEngine>
class QAndroidAudio : public QObject
{
Q_PROPERTY(int focus READ hasFocus NOTIFY focusChanged)
Q_DISABLE_COPY(QAndroidAudio)
Q_OBJECT
QAndroidAudio();
public:
~QAndroidAudio();
static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine);
static QAndroidAudio* instance();
Q_INVOKABLE bool requestFocus();
Q_INVOKABLE void abandonFocus();
bool hasFocus();
Q_SIGNALS:
void focusChanged();
private:
const QAndroidJniObject m_javaAudio;
static QAndroidAudio *m_pInstance;
bool m_focus;
void setFocus(bool focus);
static void deviceFocusChanged(JNIEnv *env, jobject thiz, jboolean focus);
};

View File

@ -73,6 +73,9 @@
#ifdef QTAT_USER_MESSAGING_PLATFORM
#include "QAndroidUserMessagingPlatform.h"
#endif
#ifdef QTAT_AUDIO
#include "QAndroidAudio.h"
#endif
#include "QtAndroidTools.h"
QtAndroidTools *QtAndroidTools::m_pInstance = nullptr;
@ -227,4 +230,7 @@ void QtAndroidTools::initializeQmlTools()
#ifdef QTAT_USER_MESSAGING_PLATFORM
qmlRegisterSingletonType<QAndroidUserMessagingPlatform>("QtAndroidTools", 1, 0, "QtAndroidUserMessagingPlatform", &QAndroidUserMessagingPlatform::qmlInstance);
#endif
#ifdef QTAT_AUDIO
qmlRegisterSingletonType<QAndroidAudio>("QtAndroidTools", 1, 0, "QtAndroidAudio", &QAndroidAudio::qmlInstance);
#endif
}

View File

@ -219,3 +219,13 @@ contains(DEFINES, QTAT_USER_MESSAGING_PLATFORM) {
QMAKE_EXTRA_TARGETS += copy_user_messaging_platform
}
}
contains(DEFINES, QTAT_AUDIO) {
HEADERS += $$PWD/QAndroidAudio.h
SOURCES += $$PWD/QAndroidAudio.cpp
OTHER_FILES += $$PWD/src/com/falsinsoft/qtandroidtools/AndroidAudio.java
equals(COPY_JAVA_FILE, true) {
copy_audio.commands = $(COPY_FILE) $$shell_path($$PWD/src/com/falsinsoft/qtandroidtools/AndroidAudio.java) $$shell_path($$ANDROID_PACKAGE_SOURCE_DIR/src/com/falsinsoft/qtandroidtools/)
PRE_TARGETDEPS += copy_audio
QMAKE_EXTRA_TARGETS += copy_audio
}
}

View File

@ -0,0 +1,111 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.falsinsoft.qtandroidtools;
import android.content.Context;
import android.app.Activity;
import android.util.Log;
import android.media.AudioManager;
import android.media.AudioFocusRequest;
import android.media.AudioAttributes;
import android.media.AudioManager.OnAudioFocusChangeListener;
public class AndroidAudio
{
private static final String TAG = "AndroidAudio";
private final Activity mActivityInstance;
private final AudioManager mAudioManager;
private AudioFocusChangeListener mAudioFocusChangeListener = null;
public AndroidAudio(Activity activityInstance)
{
mAudioManager = (AudioManager) activityInstance.getSystemService(Context.AUDIO_SERVICE);
mActivityInstance = activityInstance;
}
public boolean requestFocus()
{
if(mAudioFocusChangeListener == null)
{
mAudioFocusChangeListener = new AudioFocusChangeListener();
if(mAudioManager.requestAudioFocus(createAudioFocusRequest(mAudioFocusChangeListener)) == AudioManager.AUDIOFOCUS_REQUEST_FAILED)
{
mAudioFocusChangeListener = null;
return false;
}
}
return true;
}
public void abandonFocus()
{
if(mAudioFocusChangeListener != null)
{
mAudioManager.abandonAudioFocusRequest(createAudioFocusRequest(mAudioFocusChangeListener));
mAudioFocusChangeListener = null;
}
}
private AudioFocusRequest createAudioFocusRequest(AudioFocusChangeListener listener)
{
AudioAttributes audioAttributes;
AudioFocusRequest focusRequest;
audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(audioAttributes)
.setAcceptsDelayedFocusGain(true)
.setWillPauseWhenDucked(true)
.setOnAudioFocusChangeListener(listener)
.build();
return focusRequest;
}
private class AudioFocusChangeListener implements OnAudioFocusChangeListener
{
@Override
public void onAudioFocusChange(int focusChange)
{
switch(focusChange)
{
case AudioManager.AUDIOFOCUS_GAIN:
focusChanged(true);
break;
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
focusChanged(false);
break;
}
}
}
private static native void focusChanged(boolean focus);
}

View File

@ -22,16 +22,16 @@
* SOFTWARE.
*/
package com.falsinsoft.qtandroidtools;
package com.falsinsoft.qtandroidtools;
import android.content.Context;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.content.Context;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
public class AndroidTools
{
public class AndroidTools
{
private static final String TAG = "AndroidTools";
private final Activity mActivityInstance;

View File

@ -35,7 +35,7 @@ if(ANDROID)
set(QTAT_GOOGLE_DRIVE ON)
set(QTAT_SHARING ON)
set(QTAT_USER_MESSAGING_PLATFORM ON)
set(QTAT_PLAY_STORE ON)
set(QTAT_AUDIO ON)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS AndroidExtras REQUIRED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../QtAndroidTools build)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../QtAndroidTools)

View File

@ -107,6 +107,7 @@ ApplicationWindow {
ListElement { title: "GoogleDrive"; source: "qrc:/tools/AndroidGoogleDrive.qml" }
ListElement { title: "Sharing"; source: "qrc:/tools/AndroidSharing.qml" }
ListElement { title: "UserMessagingPlatform"; source: "qrc:/tools/AndroidUserMessagingPlatform.qml" }
ListElement { title: "Audio"; source: "qrc:/tools/AndroidAudio.qml" }
ListElement { title: "System"; source: "qrc:/tools/AndroidSystem.qml" }
}
@ -131,7 +132,7 @@ ApplicationWindow {
}
Label {
text: "Small collections of tools for manage some Android features from Qt and QML app"
text: "Small collections of tools to manage some Android features from Qt and QML app"
anchors.margins: 20
anchors.top: logo.bottom
anchors.left: parent.left

View File

@ -35,7 +35,8 @@ DEFINES += \
QTAT_GOOGLE_ACCOUNT \
QTAT_GOOGLE_DRIVE \
QTAT_SHARING \
QTAT_USER_MESSAGING_PLATFORM
QTAT_USER_MESSAGING_PLATFORM \
QTAT_AUDIO
include(../QtAndroidTools/QtAndroidTools.pri)
}

View File

@ -19,5 +19,6 @@
<file>tools/AndroidSystem.qml</file>
<file>tools/AndroidSharing.qml</file>
<file>tools/AndroidUserMessagingPlatform.qml</file>
<file>tools/AndroidAudio.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,38 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3
import QtAndroidTools 1.0
Page {
id: page
padding: 40
Column {
width: parent.width * 0.9
height: parent.height * 0.9
anchors.centerIn: parent
spacing: 15
Label {
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 15
text: "Focus:"
}
Label {
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 15
text: QtAndroidAudio.focus ? "Yes" : "No"
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "requestFocus"
onClicked: QtAndroidAudio.requestFocus()
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "abandonFocus"
onClicked: QtAndroidAudio.abandonFocus()
}
}
}