mirror of https://github.com/qt/qtdoc.git
206 lines
7.8 KiB
C++
206 lines
7.8 KiB
C++
// Copyright (C) 2025 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
#include "backend.h"
|
|
|
|
BackEnd::BackEnd(QObject *parent) : QObject{ parent }
|
|
{
|
|
using namespace android::os;
|
|
using namespace android::app;
|
|
|
|
// Initialize members
|
|
m_qAndroidApp = qGuiApp->nativeInterface<QNativeInterface::QAndroidApplication>();
|
|
m_context = ContextProxy(m_qAndroidApp->context());
|
|
m_activityContext = ActivityProxy(m_qAndroidApp->context());
|
|
PowerManagerProxy powerManager = m_activityContext.getSystemService(
|
|
QJniObject::fromString(m_context.POWER_SERVICE).object<jstring>());
|
|
m_audioManager = m_activityContext.getSystemService(
|
|
QJniObject::fromString(m_context.AUDIO_SERVICE).object<jstring>());
|
|
m_window = m_activityContext.getWindow();
|
|
m_layoutParams = m_window.getAttributes();
|
|
m_partialWakeLock = powerManager.newWakeLock(powerManager.PARTIAL_WAKE_LOCK,
|
|
QJniObject::fromString("PARTIALWAKELOCK").object<jstring>());
|
|
|
|
// If system implements a fixed volume policy, disable volume slider
|
|
if (m_audioManager.isVolumeFixed())
|
|
handleVolumeError("Device implements fixed volume setting.", "");
|
|
|
|
m_qAndroidApp->runOnAndroidMainThread([&]() {
|
|
m_layoutParams.setScreenBrightness(0.5);
|
|
m_window.setAttributes(m_layoutParams);
|
|
});
|
|
|
|
createNotification();
|
|
}
|
|
|
|
void BackEnd::vibrate()
|
|
{
|
|
using namespace android::os;
|
|
|
|
VibrationEffectProxy effect;
|
|
VibratorManagerProxy vibratorManager;
|
|
VibratorProxy vibrator;
|
|
|
|
if (m_systemVersion >= 12) {
|
|
vibratorManager = m_activityContext.getSystemService(
|
|
QJniObject::fromString(m_context.VIBRATOR_MANAGER_SERVICE).object<jstring>());
|
|
vibrator = vibratorManager.getDefaultVibrator();
|
|
} else {
|
|
vibrator = m_activityContext.getSystemService(
|
|
QJniObject::fromString(m_context.VIBRATOR_SERVICE).object<jstring>());
|
|
}
|
|
|
|
effect = VibrationEffectProxy().createOneShot(
|
|
vibrateTimeInMillisecs, VibrationEffectProxy().DEFAULT_AMPLITUDE);
|
|
vibrator.vibrate(effect->object<jobject>());
|
|
}
|
|
|
|
// Posts an Android notification
|
|
void BackEnd::notify()
|
|
{
|
|
using namespace QtAndroidPrivate;
|
|
|
|
PermissionResult result = checkPermission("android.permission.POST_NOTIFICATIONS").result();
|
|
|
|
if (result == Authorized || m_systemVersion <= 12) {
|
|
m_notificationManager.notify(0, m_notification);
|
|
} else {
|
|
requestPermission("android.permission.POST_NOTIFICATIONS").then(
|
|
[&](PermissionResult result) {
|
|
if (result == Denied)
|
|
qWarning() << "POST_NOTIFICATIONS permission was denied";
|
|
else if (result == Authorized)
|
|
m_notificationManager.notify(0, m_notification);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Adjust system volume, either lowering or raising based on given direction
|
|
void BackEnd::adjustVolume(enum Direction direction)
|
|
{
|
|
if (m_global.getInt(m_context.getContentResolver().object<jobject>(),
|
|
QJniObject::fromString("zen_mode").object<jstring>()) != 0) {
|
|
handleVolumeError("Do not Disturb mode is on",
|
|
"Disable Do not Disturb mode to adjust the volume");
|
|
} else if (m_audioManager.getRingerMode() != m_audioManager.RINGER_MODE_NORMAL) {
|
|
if (m_audioManager.getRingerMode() == m_audioManager.RINGER_MODE_VIBRATE) {
|
|
handleVolumeError("Vibrate only mode is on",
|
|
"Disable vibrate only mode to adjust volume.");
|
|
} else if (m_audioManager.getRingerMode() == m_audioManager.RINGER_MODE_SILENT) {
|
|
handleVolumeError("Silent mode is on", "Disable Silent mode to adjust the volume.");
|
|
}
|
|
} else if (direction == Direction::Up) {
|
|
m_audioManager.adjustVolume(m_audioManager.ADJUST_RAISE, m_audioManager.FLAG_SHOW_UI);
|
|
} else if (direction == Direction::Down) {
|
|
m_audioManager.adjustVolume(m_audioManager.ADJUST_LOWER, m_audioManager.FLAG_SHOW_UI);
|
|
}
|
|
}
|
|
|
|
// Adjust system brightness, either lowering or raising based on given direction
|
|
void BackEnd::adjustBrightness(enum Direction direction)
|
|
{
|
|
using namespace android::content;
|
|
using namespace android::provider;
|
|
|
|
IntentProxy m_intent = m_intent.newInstance(QJniObject::fromString(
|
|
SettingsProxy::ACTION_MANAGE_WRITE_SETTINGS).object<jstring>());
|
|
|
|
// Check if app has permission to write system settings.
|
|
// Start an Activity with the ACTION_MANAGE_WRITE_SETTINGS intent if app
|
|
// does not have permission to write said settings, after which user
|
|
// has to manually give the permission to this app.
|
|
if (!m_system.canWrite(m_context))
|
|
m_context.startActivity(m_intent);
|
|
|
|
int brightness = m_system.getInt(m_context.getContentResolver().object<jobject>(),
|
|
QJniObject::fromString(m_system.SCREEN_BRIGHTNESS).object<jstring>());
|
|
|
|
if (direction == Direction::Up) {
|
|
if (brightness <= maxBrightness)
|
|
brightness += 10;
|
|
} else if (direction == Direction::Down) {
|
|
if (brightness >= minBrightness)
|
|
brightness -= 10;
|
|
}
|
|
|
|
double brightnessToDouble = brightnessStep * (brightness / 10.0);
|
|
|
|
// We need to set the brightness to system settings and to Window separately, as
|
|
// synchronization does not happen automatically and updating one or
|
|
// the other only, leaves the other one out of sync.
|
|
m_system.putInt(m_context.getContentResolver().object<jobject>(),
|
|
QJniObject::fromString(m_system.SCREEN_BRIGHTNESS).object<jstring>(),
|
|
brightness);
|
|
m_qAndroidApp->runOnAndroidMainThread([this, brightness = brightnessToDouble]() {
|
|
m_layoutParams.setScreenBrightness(brightness);
|
|
m_window.setAttributes(m_layoutParams);
|
|
});
|
|
}
|
|
|
|
void BackEnd::setPartialWakeLock()
|
|
{
|
|
m_partialWakeLock.acquire(m_activityContext);
|
|
}
|
|
|
|
void BackEnd::disablePartialWakeLock()
|
|
{
|
|
m_partialWakeLock.release(m_activityContext);
|
|
}
|
|
|
|
void BackEnd::setFullWakeLock()
|
|
{
|
|
m_qAndroidApp->runOnAndroidMainThread([&]() {
|
|
m_window.addFlags(m_layoutParams.FLAG_KEEP_SCREEN_ON);
|
|
}).then([]() {
|
|
qInfo() << "Full WakeLock set";
|
|
});
|
|
}
|
|
|
|
void BackEnd::disableFullWakeLock()
|
|
{
|
|
m_qAndroidApp->runOnAndroidMainThread([&]() {
|
|
m_window.clearFlags(m_layoutParams.FLAG_KEEP_SCREEN_ON);
|
|
}).then([]() {
|
|
qInfo() << "Full WakeLock released";
|
|
});
|
|
}
|
|
|
|
// Creates a notification that is later posted in notify() method
|
|
void BackEnd::createNotification()
|
|
{
|
|
using namespace android::app;
|
|
using namespace android::drawable;
|
|
|
|
NotificationChannelProxy channel;
|
|
BuilderProxy builder;
|
|
|
|
channel = NotificationChannelProxy().newInstance(
|
|
QJniObject::fromString("01").object<jstring>(),
|
|
QJniObject::fromString("QtJenny").object<jstring>(),
|
|
m_notificationManager.IMPORTANCE_HIGH);
|
|
|
|
m_notificationManager = m_activityContext.getSystemService(
|
|
QJniObject::fromString(m_context.NOTIFICATION_SERVICE).object<jstring>());
|
|
m_notificationManager.createNotificationChannel(channel);
|
|
|
|
builder = BuilderProxy().newInstance(m_context,
|
|
QJniObject::fromString(channel.getId().toString()).object<jstring>());
|
|
builder.setSmallIcon(drawableProxy::ic_dialog_info);
|
|
builder.setContentTitle(QJniObject::fromString("QtJenny").object<jstring>());
|
|
builder.setContentText(QJniObject::fromString(
|
|
"Hello from QtJenny app!").object<jstring>());
|
|
builder.setDefaults(m_notification.DEFAULT_SOUND);
|
|
builder.setAutoCancel(true);
|
|
m_notification = builder.build();
|
|
}
|
|
|
|
void BackEnd::handleVolumeError(const QString &problem, const QString &solution)
|
|
{
|
|
if (!problem.isEmpty())
|
|
qWarning() << problem;
|
|
|
|
const QString message = problem.isEmpty() ? solution
|
|
: problem + "\n" + solution;
|
|
emit showPopup(message);
|
|
}
|