QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
AndroidInterface.cc
Go to the documentation of this file.
1#include "AndroidInterface.h"
2
3#include <QAndroidScreen.h>
4#include <QtAndroidHelpers/QAndroidPartialWakeLocker.h>
5#include <QtAndroidHelpers/QAndroidWiFiLocker.h>
6#include <QtCore/QCoreApplication>
7#include <QtCore/QDir>
8#include <QtCore/QFileInfo>
9#include <QtCore/QJniEnvironment>
10#include <QtCore/QJniObject>
11#include <QtCore/QMetaObject>
12#include <QtCore/QSharedPointer>
13#include <QtCore/QStandardPaths>
14
15#include "AppSettings.h"
16#include "QGCApplication.h"
17#include "QGCLoggingCategory.h"
18#include "SettingsFact.h"
19#include "SettingsManager.h"
20
21QGC_LOGGING_CATEGORY(AndroidInterfaceLog, "Android.AndroidInterface")
22
24
25static void jniLogDebug(JNIEnv*, jobject, jstring message)
26{
27 qCDebug(AndroidInterfaceLog) << QJniObject(message).toString();
28}
29
30static void jniLogWarning(JNIEnv*, jobject, jstring message)
31{
32 qCWarning(AndroidInterfaceLog) << QJniObject(message).toString();
33}
34
35static void jniStoragePermissionsResult(JNIEnv*, jobject, jboolean granted)
36{
37 if (!granted) {
38 qCWarning(AndroidInterfaceLog) << "Storage permission request denied";
39 return;
40 }
41
42 if (!qgcApp()) {
43 return;
44 }
45
46 (void)QMetaObject::invokeMethod(
47 qgcApp(),
48 []() {
49 SettingsManager* const settingsManager = SettingsManager::instance();
50 if (!settingsManager) {
51 return;
52 }
53
54 AppSettings* const appSettings = settingsManager->appSettings();
55 if (!appSettings || appSettings->androidDontSaveToSDCard()->rawValue().toBool()) {
56 return;
57 }
58
59 SettingsFact* const savePathFact = qobject_cast<SettingsFact*>(appSettings->savePath());
60 if (!savePathFact) {
61 return;
62 }
63
64 const QString appName = QCoreApplication::applicationName();
65 const QString currentSavePath = savePathFact->rawValue().toString();
66 const QString internalBasePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
67 const QString internalSavePath = QDir(internalBasePath).filePath(appName);
68
69 if (!currentSavePath.isEmpty() && (currentSavePath != internalSavePath)) {
70 return;
71 }
72
73 const QString sdCardRootPath = getSDCardPath();
74 if (sdCardRootPath.isEmpty() || !QDir(sdCardRootPath).exists() || !QFileInfo(sdCardRootPath).isWritable()) {
75 return;
76 }
77
78 const QString sdSavePath = QDir(sdCardRootPath).filePath(appName);
79 if (currentSavePath != sdSavePath) {
80 qCDebug(AndroidInterfaceLog) << "Applying SD card save path after permission grant:" << sdSavePath;
81 savePathFact->setRawValue(sdSavePath);
82 }
83 },
84 Qt::QueuedConnection);
85}
86
88{
89 qCDebug(AndroidInterfaceLog) << "Registering Native Functions";
90
91 const JNINativeMethod javaMethods[]{
92 {"qgcLogDebug", "(Ljava/lang/String;)V", reinterpret_cast<void*>(jniLogDebug)},
93 {"qgcLogWarning", "(Ljava/lang/String;)V", reinterpret_cast<void*>(jniLogWarning)},
94 {"nativeStoragePermissionsResult", "(Z)V", reinterpret_cast<void*>(jniStoragePermissionsResult)}};
95
96 QJniEnvironment env;
97 if (!env.registerNativeMethods(kJniQGCActivityClassName, javaMethods, std::size(javaMethods))) {
98 qCWarning(AndroidInterfaceLog) << "Failed to register native methods for" << kJniQGCActivityClassName;
99 } else {
100 qCDebug(AndroidInterfaceLog) << "Native Functions Registered";
101 }
102}
103
105{
106 const bool hasPermission =
107 QJniObject::callStaticMethod<jboolean>(kJniQGCActivityClassName, "checkStoragePermissions", "()Z");
108 QJniEnvironment env;
109 if (env.checkAndClearExceptions()) {
110 qCWarning(AndroidInterfaceLog) << "Exception in checkStoragePermissions";
111 return false;
112 }
113
114 if (hasPermission) {
115 qCDebug(AndroidInterfaceLog) << "Storage permissions granted";
116 } else {
117 qCWarning(AndroidInterfaceLog) << "Storage permissions not granted";
118 }
119
120 return hasPermission;
121}
122
124{
126 qCWarning(AndroidInterfaceLog) << "Storage Permission Denied";
127 return QString();
128 }
129
130 const QJniObject result =
131 QJniObject::callStaticObjectMethod(kJniQGCActivityClassName, "getSDCardPath", "()Ljava/lang/String;");
132 QJniEnvironment env;
133 if (env.checkAndClearExceptions()) {
134 qCWarning(AndroidInterfaceLog) << "Exception in getSDCardPath";
135 return QString();
136 }
137 if (!result.isValid()) {
138 qCWarning(AndroidInterfaceLog) << "Call to java getSDCardPath failed: Invalid Result";
139 return QString();
140 }
141
142 return result.toString();
143}
144
145static QSharedPointer<QLocks::QLockBase> s_partialWakeLock;
146static QSharedPointer<QLocks::QLockBase> s_wifiLock;
147
148void setKeepScreenOn(bool on)
149{
150 if (!QAndroidScreen::instance()) {
151 new QAndroidScreen(QCoreApplication::instance());
152 }
153 QAndroidScreen::instance()->keepScreenOn(on);
154
155 if (on) {
156 s_partialWakeLock = QAndroidPartialWakeLocker::instance().getLock();
157 s_wifiLock = QAndroidWiFiLocker::instance().getLock();
158 } else {
159 s_partialWakeLock.reset();
160 s_wifiLock.reset();
161 }
162}
163
164} // namespace AndroidInterface
#define qgcApp()
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Application Settings.
Definition AppSettings.h:9
Fact *savePath READ savePath CONSTANT Fact * savePath()
Fact *androidDontSaveToSDCard READ androidDontSaveToSDCard CONSTANT Fact * androidDontSaveToSDCard()
A SettingsFact is Fact which holds a QSettings value.
Provides access to all app settings.
static void jniLogDebug(JNIEnv *, jobject, jstring message)
static void jniStoragePermissionsResult(JNIEnv *, jobject, jboolean granted)
static void jniLogWarning(JNIEnv *, jobject, jstring message)
static QSharedPointer< QLocks::QLockBase > s_wifiLock
void setKeepScreenOn(bool on)
constexpr const char * kJniQGCActivityClassName
static QSharedPointer< QLocks::QLockBase > s_partialWakeLock