mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
1 Commits
2.20.25
...
crossQFile
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d157685be4 |
165
src/CrossQFile.cpp
Normal file
165
src/CrossQFile.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#include "CrossQFile.h"
|
||||
#include <QFileInfo>
|
||||
#ifdef __ANDROID__
|
||||
#include <jni.h>
|
||||
#include <QtAndroidExtras/QtAndroid>
|
||||
#include <QtAndroidExtras/qandroidjnienvironment.h>
|
||||
#endif
|
||||
#include <QCoreApplication>
|
||||
|
||||
CrossQFile::CrossQFile(const QString& nameOrUri, const bool isUri) : QFile(nameOrUri), isWorkingWithUri(isUri){
|
||||
#ifdef __ANDROID__
|
||||
mainActivityObj = QtAndroid::androidActivity();
|
||||
contentResolverObj = mainActivityObj.callObjectMethod
|
||||
("getContentResolver","()Landroid/content/ContentResolver;");
|
||||
checkJenvExceptions();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool CrossQFile::checkJenvExceptions() const{
|
||||
QAndroidJniEnvironment env;
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
QAndroidJniObject CrossQFile::parseUriString(const QString& uriString) const{
|
||||
return QAndroidJniObject::callStaticObjectMethod
|
||||
("android/net/Uri" , "parse",
|
||||
"(Ljava/lang/String;)Landroid/net/Uri;",
|
||||
QAndroidJniObject::fromString(uriString).object());
|
||||
}
|
||||
#endif
|
||||
|
||||
void CrossQFile::setFileName(const QString& nameOrUri, bool isUri){
|
||||
QFile::setFileName(nameOrUri);
|
||||
isWorkingWithUri = isUri;
|
||||
}
|
||||
|
||||
|
||||
qint64 CrossQFile::size() const{
|
||||
#ifdef __ANDROID__
|
||||
if(isWorkingWithUri){
|
||||
QAndroidJniObject cursorObj {contentResolverObj.callObjectMethod
|
||||
("query",
|
||||
"(Landroid/net/Uri;[Ljava/lang/String;Landroid/os/Bundle;Landroid/os/CancellationSignal;)Landroid/database/Cursor;",
|
||||
parseUriString(fileName()).object(), QAndroidJniObject().object(), QAndroidJniObject().object()
|
||||
, QAndroidJniObject().object(), QAndroidJniObject().object())};
|
||||
int sizeIndex {cursorObj.callMethod<jint>
|
||||
("getColumnIndex","(Ljava/lang/String;)I",
|
||||
QAndroidJniObject::getStaticObjectField<jstring>
|
||||
("android/provider/OpenableColumns","SIZE").object())};
|
||||
cursorObj.callMethod<jboolean>("moveToFirst");
|
||||
qint64 ret {cursorObj.callMethod<jlong>("getLong","(I)J",sizeIndex)};
|
||||
if(checkJenvExceptions()){
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return QFile::size();
|
||||
}
|
||||
|
||||
bool CrossQFile::open(CrossQFile::OpenMode openMode){
|
||||
#ifdef __ANDROID__
|
||||
if(isWorkingWithUri){
|
||||
QAndroidJniObject jopenMode {QAndroidJniObject::fromString("rw")};
|
||||
switch (openMode){
|
||||
case QFile::ReadOnly:
|
||||
jopenMode = QAndroidJniObject::fromString("r");
|
||||
break;
|
||||
case QFile::WriteOnly:
|
||||
jopenMode = QAndroidJniObject::fromString("w");
|
||||
break;
|
||||
default:
|
||||
jopenMode = QAndroidJniObject::fromString("rw");
|
||||
}
|
||||
QAndroidJniObject pfdObj{contentResolverObj.callObjectMethod
|
||||
("openFileDescriptor", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
|
||||
parseUriString(fileName()).object(), jopenMode.object())};
|
||||
int fd{pfdObj.callMethod<jint>("detachFd")};
|
||||
bool ret {false};
|
||||
if(QFile::open(fd, openMode)){
|
||||
ret = true;
|
||||
}
|
||||
if(checkJenvExceptions()){
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return QFile::open(openMode);
|
||||
}
|
||||
QString CrossQFile::displayName(){
|
||||
#ifdef __ANDROID__
|
||||
if(isWorkingWithUri){
|
||||
QAndroidJniObject cursorObj {contentResolverObj.callObjectMethod
|
||||
("query",
|
||||
"(Landroid/net/Uri;[Ljava/lang/String;Landroid/os/Bundle;Landroid/os/CancellationSignal;)Landroid/database/Cursor;",
|
||||
parseUriString(fileName()).object(), QAndroidJniObject().object(), QAndroidJniObject().object(),
|
||||
QAndroidJniObject().object(), QAndroidJniObject().object())};
|
||||
cursorObj.callMethod<jboolean>("moveToFirst");
|
||||
QAndroidJniObject retObj{cursorObj.callObjectMethod
|
||||
("getString","(I)Ljava/lang/String;", cursorObj.callMethod<jint>
|
||||
("getColumnIndex","(Ljava/lang/String;)I",
|
||||
QAndroidJniObject::getStaticObjectField<jstring>
|
||||
("android/provider/OpenableColumns","DISPLAY_NAME").object()))};
|
||||
QString ret {retObj.toString()};
|
||||
if(checkJenvExceptions()){
|
||||
ret = "";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
QFileInfo fileInfo(fileName());
|
||||
return fileInfo.fileName();
|
||||
}
|
||||
|
||||
bool CrossQFile::remove(){
|
||||
#ifdef __ANDROID__
|
||||
if(isWorkingWithUri){
|
||||
bool ret {static_cast<bool>(QAndroidJniObject::callStaticMethod<jboolean>
|
||||
("android/provider/DocumentsContract", "deleteDocument",
|
||||
"(Landroid/content/ContentResolver;Landroid/net/Uri;)Z",
|
||||
contentResolverObj.object(), parseUriString(fileName()).object()))};
|
||||
if(checkJenvExceptions()){
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return QFile::remove();
|
||||
}
|
||||
|
||||
bool CrossQFile::rename(const QString& newName){
|
||||
if(!isWorkingWithUri){
|
||||
return QFile::rename(newName);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CrossQFile::exists() const{
|
||||
#ifdef __ANDROID__
|
||||
if(isWorkingWithUri){
|
||||
bool ret {static_cast<bool>(QAndroidJniObject::callStaticMethod<jboolean>
|
||||
("android/provider/DocumentsContract", "isDocumentUri",
|
||||
"(Landroid/content/Context;Landroid/net/Uri;)Z",
|
||||
mainActivityObj.object(), parseUriString(fileName()).object()))};
|
||||
if(checkJenvExceptions()){
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return QFile::exists();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
40
src/CrossQFile.h
Normal file
40
src/CrossQFile.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef CROSSQFILE_H
|
||||
#define CROSSQFILE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QSharedPointer>
|
||||
#ifdef __ANDROID__
|
||||
#include <QtAndroidExtras/QAndroidJniObject>
|
||||
#endif
|
||||
|
||||
class CrossQFile : public QFile
|
||||
{
|
||||
public:
|
||||
CrossQFile(const QString& nameOrUri, const bool isUri = false);
|
||||
virtual qint64 size() const override;
|
||||
|
||||
//if working with uri, it uses QAndroidjniObject to open the file using the uri.
|
||||
//otherwise it would act like a normal QFile.
|
||||
bool open(CrossQFile::OpenMode openMode) override;
|
||||
bool remove();
|
||||
//if working with uri, it does nothing.
|
||||
//otherwise it would act like a normal QFile.
|
||||
bool rename(const QString& newName);
|
||||
bool exists() const;
|
||||
//returns the display name of the file.
|
||||
QString displayName();
|
||||
void setFileName(const QString& nameOrUri, bool isUri = false);
|
||||
private:
|
||||
bool isWorkingWithUri{false};
|
||||
#ifdef __ANDROID__
|
||||
QAndroidJniObject mainActivityObj;
|
||||
QAndroidJniObject contentResolverObj;
|
||||
bool checkJenvExceptions() const;
|
||||
QAndroidJniObject parseUriString(const QString& uriString) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // CROSSQFILE_H
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="com.android.vending.BILLING"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
|
||||
|
||||
@@ -466,6 +466,14 @@ int main(int argc, char *argv[]) {
|
||||
qDebug() << "READ_EXTERNAL_STORAGE denied!";
|
||||
}
|
||||
|
||||
result = QtAndroid::checkPermission(QString("android.permission.MANAGE_EXTERNAL_STORAGE"));
|
||||
if (result == QtAndroid::PermissionResult::Denied) {
|
||||
QtAndroid::PermissionResultMap resultHash =
|
||||
QtAndroid::requestPermissionsSync(QStringList({"android.permission.MANAGE_EXTERNAL_STORAGE"}));
|
||||
if (resultHash["android.permission.MANAGE_EXTERNAL_STORAGE"] == QtAndroid::PermissionResult::Denied)
|
||||
qDebug() << "MANAGE_EXTERNAL_STORAGE denied!";
|
||||
}
|
||||
|
||||
result = QtAndroid::checkPermission(QString("android.permission.ACCESS_FINE_LOCATION"));
|
||||
if (result == QtAndroid::PermissionResult::Denied) {
|
||||
QtAndroid::PermissionResultMap resultHash =
|
||||
|
||||
@@ -63,6 +63,7 @@ DEFINES += QT_DEPRECATED_WARNINGS IO_UNDER_QT SMTP_BUILD
|
||||
# include(../qtzeroconf/qtzeroconf.pri)
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/CrossQFile.cpp \
|
||||
$$PWD/androidactivityresultreceiver.cpp \
|
||||
$$PWD/androidadblog.cpp \
|
||||
$$PWD/apexbike.cpp \
|
||||
@@ -259,6 +260,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
INCLUDEPATH += fit-sdk/
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/CrossQFile.h \
|
||||
$$PWD/androidactivityresultreceiver.h \
|
||||
$$PWD/androidadblog.h \
|
||||
$$PWD/apexbike.h \
|
||||
|
||||
@@ -984,13 +984,18 @@ bool trainprogram::saveXML(const QString &filename, const QList<trainrow> &rows)
|
||||
void trainprogram::save(const QString &filename) { saveXML(filename, rows); }
|
||||
|
||||
trainprogram *trainprogram::load(const QString &filename, bluetooth *b) {
|
||||
if (!filename.right(3).toUpper().compare(QStringLiteral("ZWO"))) {
|
||||
// on android we can't check anymore the extension
|
||||
// because it returns something like this
|
||||
// content://com.android.providers.downloads.documents/document/126
|
||||
// reference https://stackoverflow.com/questions/58715547/how-to-open-a-file-in-android-with-qt-having-the-content-uri
|
||||
|
||||
QString description = "";
|
||||
QString tags = "";
|
||||
return new trainprogram(zwiftworkout::load(filename, &description, &tags), b, &description, &tags);
|
||||
QString description = "";
|
||||
QString tags = "";
|
||||
QList<trainrow> r = zwiftworkout::load(filename, &description, &tags);
|
||||
qDebug() << r.length();
|
||||
if(r.length() > 0) {
|
||||
return new trainprogram(r, b, &description, &tags);
|
||||
} else {
|
||||
|
||||
return new trainprogram(loadXML(filename), b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "zwiftworkout.h"
|
||||
#include "CrossQFile.h"
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
@@ -8,8 +9,9 @@
|
||||
QList<trainrow> zwiftworkout::load(const QString &filename, QString *description, QString *tags) {
|
||||
QSettings settings;
|
||||
// QList<trainrow> list; //NOTE: clazy-unuzed-non-trivial-variable
|
||||
QFile input(filename);
|
||||
CrossQFile input(filename, true);
|
||||
input.open(QIODevice::ReadOnly);
|
||||
qDebug() << input.size();
|
||||
return load(input.readAll(), description, tags);
|
||||
}
|
||||
|
||||
@@ -325,7 +327,7 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
|
||||
if (tags != nullptr)
|
||||
tags->clear();
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
while (!stream.atEnd()) {
|
||||
stream.readNext();
|
||||
QString name = stream.name().toString();
|
||||
QString text = stream.text().toString();
|
||||
|
||||
Reference in New Issue
Block a user