Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAndroidUtils.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-3.0-or-later
3 */
4#include "KisAndroidUtils.h"
6#include <kis_debug.h>
7
8#include <QFile>
9#include <QTemporaryFile>
10
11#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
12#include <QJniEnvironment>
13#include <QJniObject>
14#else
15#include <QAndroidJniEnvironment>
16#include <QAndroidJniObject>
17using QJniEnvironment = QAndroidJniEnvironment;
18using QJniObject = QAndroidJniObject;
19#endif
20
22{
23
25{
27
28 QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
29 "activity",
30 "()Landroid/app/Activity;");
31 if (activity.isValid()) {
32 activity.callMethod<void>("copyAssets", "()V");
33 } else {
34 qWarning("performInitialSetup: activity not valid");
35 }
36}
37
39{
40 // The device isn't going to change, so let's cache the slow JNI call.
41 static bool checked;
42 static bool result;
43 if (!checked) {
44 checked = true;
45 result =
46 QJniObject::callStaticMethod<jboolean>("org/krita/android/MainActivity", "looksLikeXiaomiDevice", "()Z");
47 }
48 return result;
49}
50
52{
53 // The support is device-bound and will never change, so cache the JNI call.
54 static bool checked;
55 static bool result;
56 if (!checked) {
57 checked = true;
58 result = QJniObject::callStaticMethod<jboolean>("org/krita/android/MainActivity",
59 "isLowMemoryKillReportSupported",
60 "()Z");
61 }
62 return result;
63}
64
65void clearJniException(const QString &location)
66{
67 QJniEnvironment env;
68 if (env->ExceptionCheck()) {
69 warnKrita << "JNI exception occurred" << location;
70 env->ExceptionDescribe();
71 env->ExceptionClear();
72 }
73}
74
76{
77 QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
78 "activity",
79 "()Landroid/app/Activity;");
80 KisAndroidUtils::clearJniException(QStringLiteral("getting activity in isInFullScreen"));
81 if (activity.isValid()) {
82 bool fullScreen = activity.callMethod<jboolean>("isInFullScreen", "()Z");
83 KisAndroidUtils::clearJniException(QStringLiteral("calling isInFullScreen"));
84 return fullScreen;
85 } else {
86 qWarning("isInFullScreen: activity not valid");
87 return false;
88 }
89}
90
91void setFullScreen(bool fullScreen)
92{
93 QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
94 "activity",
95 "()Landroid/app/Activity;");
96 KisAndroidUtils::clearJniException(QStringLiteral("getting activity in setFullScreen"));
97 if (activity.isValid()) {
98 activity.callMethod<void>("setFullScreenOnUiThread", "(Z)V", jboolean(fullScreen));
99 KisAndroidUtils::clearJniException(QStringLiteral("calling setFullScreenOnUiThread"));
100 } else {
101 qWarning("setFullScreen: activity not valid");
102 }
103}
104
105namespace
106{
107bool copyFileContents(const QString &inputPath,
108 const QString &outputPath,
109 QFile &inputFile,
110 QFile &outputFile,
111 QString *outErrorMessage)
112{
113 QByteArray buffer;
114 buffer.resize(BUFSIZ);
115 while (true) {
116 qint64 read = inputFile.read(buffer.data(), BUFSIZ);
117 if (read < 0) {
118 if (outErrorMessage) {
119 *outErrorMessage = QStringLiteral("failed to read from input file '%1': %2")
120 .arg(inputPath)
121 .arg(inputFile.errorString());
122 }
123 return false;
124 } else if (read > 0) {
125 qint64 written = outputFile.write(buffer, read);
126 if (written < 0) {
127 if (outErrorMessage) {
128 *outErrorMessage = QStringLiteral("failed to write %1 byte(s) to output file '%2': %3")
129 .arg(read)
130 .arg(outputPath)
131 .arg(outputFile.errorString());
132 }
133 return false;
134 } else if (written != read) {
135 if (outErrorMessage) {
136 *outErrorMessage =
137 QStringLiteral("tried to write %1 byte(s) to output file '%2', but only wrote %3")
138 .arg(read)
139 .arg(outputPath)
140 .arg(written);
141 }
142 return false;
143 }
144 } else {
145 if (outputFile.flush()) {
146 if (outErrorMessage) {
147 outErrorMessage->clear();
148 }
149 return true;
150 } else {
151 if (outErrorMessage) {
152 *outErrorMessage = QStringLiteral("failed to flush output file '%1': %2")
153 .arg(outputPath)
154 .arg(outputFile.errorString());
155 }
156 return false;
157 }
158 }
159 }
160}
161} // namespace
162
163bool copyFile(const QString &inputPath, const QString &outputPath, QString *outErrorMessage)
164{
165 QFile inputFile(inputPath);
166 if (!inputFile.open(QIODevice::ReadOnly)) {
167 if (outErrorMessage) {
168 *outErrorMessage =
169 QStringLiteral("failed to open input file '%1': %2").arg(inputPath).arg(inputFile.errorString());
170 }
171 return false;
172 }
173
174 QFile outputFile(outputPath);
175 if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
176 if (outErrorMessage) {
177 *outErrorMessage =
178 QStringLiteral("failed to open output file '%1': %2").arg(outputPath).arg(outputFile.errorString());
179 }
180 return false;
181 }
182
183 return copyFileContents(inputPath, outputPath, inputFile, outputFile, outErrorMessage);
184}
185
186bool copyFileToTemporary(const QString &inputPath, QTemporaryFile &outputFile, QString *outErrorMessage)
187{
188 QFile inputFile(inputPath);
189 if (!inputFile.open(QIODevice::ReadOnly)) {
190 if (outErrorMessage) {
191 *outErrorMessage =
192 QStringLiteral("failed to open input file '%1': %2").arg(inputPath).arg(inputFile.errorString());
193 }
194 return false;
195 }
196
197 if (!outputFile.open()) {
198 if (outErrorMessage) {
199 *outErrorMessage = QStringLiteral("failed to open temporary output file: %1").arg(outputFile.errorString());
200 }
201 return false;
202 }
203
204 if (outErrorMessage) {
205 outErrorMessage->clear();
206 }
207 return copyFileContents(inputPath, outputFile.fileName(), inputFile, outputFile, outErrorMessage);
208}
209
210} // namespace KisAndroidUtils
#define warnKrita
Definition kis_debug.h:91
bool isLowMemoryKillReportSupported()
bool copyFile(const QString &inputPath, const QString &outputPath, QString *outErrorMessage)
void setFullScreen(bool fullScreen)
void clearJniException(const QString &location)
bool copyFileToTemporary(const QString &inputPath, QTemporaryFile &outputFile, QString *outErrorMessage)