From 2625fb01eaea12678841bf8730bb7e3e2878ff46 Mon Sep 17 00:00:00 2001 From: FalsinSoft Date: Tue, 7 Jan 2020 04:40:17 +0100 Subject: [PATCH] Added method for get drive files list --- QtAndroidTools/QAndroidGoogleAccount.h | 2 +- QtAndroidTools/QAndroidGoogleDrive.cpp | 80 ++++++++++++++++ QtAndroidTools/QAndroidGoogleDrive.h | 11 +++ .../qtandroidtools/AndroidGoogleAccount.java | 5 +- .../qtandroidtools/AndroidGoogleDrive.java | 95 +++++++++++++++++++ .../android/AndroidManifest.xml | 1 + .../tools/AndroidGoogleAccount.qml | 4 +- .../tools/AndroidGoogleDrive.qml | 80 +++++++++++++++- 8 files changed, 270 insertions(+), 8 deletions(-) diff --git a/QtAndroidTools/QAndroidGoogleAccount.h b/QtAndroidTools/QAndroidGoogleAccount.h index 96a0cfd..0286b7e 100644 --- a/QtAndroidTools/QAndroidGoogleAccount.h +++ b/QtAndroidTools/QAndroidGoogleAccount.h @@ -71,7 +71,7 @@ class QAndroidGoogleAccount : public QObject, public QAndroidActivityResultRecei } private: - const QAndroidGoogleAccount const *m_pAccount; + const QAndroidGoogleAccount *const m_pAccount; }; QAndroidGoogleAccount(); diff --git a/QtAndroidTools/QAndroidGoogleDrive.cpp b/QtAndroidTools/QAndroidGoogleDrive.cpp index 9471c78..0938f02 100644 --- a/QtAndroidTools/QAndroidGoogleDrive.cpp +++ b/QtAndroidTools/QAndroidGoogleDrive.cpp @@ -46,6 +46,86 @@ QAndroidGoogleDrive* QAndroidGoogleDrive::instance() return m_pInstance; } +bool QAndroidGoogleDrive::authenticate(const QString &AppName, const QString &ScopeName) +{ + if(m_JavaGoogleDrive.isValid()) + { + m_isAuthenticated = m_JavaGoogleDrive.callMethod("authenticate", + "(Ljava/lang/String;Ljava/lang/String;)Z", + QAndroidJniObject::fromString(AppName).object(), + QAndroidJniObject::fromString(ScopeName).object() + ); + emit isAuthenticatedChanged(); + return m_isAuthenticated; + } + return false; +} + +QVariantList QAndroidGoogleDrive::getFilesList(const QString &Query) +{ + QAndroidJniEnvironment JniEnv; + QVariantList FilesList; + + if(m_JavaGoogleDrive.isValid()) + { + const QAndroidJniObject FilesListObj = m_JavaGoogleDrive.callObjectMethod("listFiles", + "(Ljava/lang/String;)[Lcom/falsinsoft/qtandroidtools/AndroidGoogleDrive$DriveFile;", + QAndroidJniObject::fromString(Query).object() + ); + if(FilesListObj.isValid()) + { + const jobjectArray FilesListJObjArray = FilesListObj.object(); + const int FilesNum = JniEnv->GetArrayLength(FilesListJObjArray); + + for(int i = 0; i < FilesNum; i++) + { + const QAndroidJniObject JniObject = JniEnv->GetObjectArrayElement(FilesListJObjArray, i); + QAndroidJniObject ParentsListObj; + QVariantList FileParents; + QVariantMap FileInfo; + + FileInfo["id"] = JniObject.getObjectField("id").toString(); + FileInfo["name"] = JniObject.getObjectField("name").toString(); + FileInfo["mimeType"] = JniObject.getObjectField("mimeType").toString(); + ParentsListObj = JniObject.getObjectField("parents", "[Ljava/lang/String;"); + if(ParentsListObj.isValid()) + { + const jobjectArray ParentsListJObjArray = ParentsListObj.object(); + const int ParentsNum = JniEnv->GetArrayLength(ParentsListJObjArray); + + for(int p = 0; p < ParentsNum; p++) + { + FileParents << QAndroidJniObject(JniEnv->GetObjectArrayElement(ParentsListJObjArray, p)).toString(); + } + } + FileInfo["parents"] = FileParents; + + FilesList << FileInfo; + } + } + } + + return FilesList; +} + +QString QAndroidGoogleDrive::getRootId() +{ + QString RootId; + + if(m_JavaGoogleDrive.isValid()) + { + const QAndroidJniObject RootIdObj = m_JavaGoogleDrive.callObjectMethod("getRootId", + "()Ljava/lang/String;" + ); + if(RootIdObj.isValid()) + { + RootId = RootIdObj.toString(); + } + } + + return RootId; +} + void QAndroidGoogleDrive::LoadScopeDefinitions() { const char ScopesClass[] = "com/google/api/services/drive/DriveScopes"; diff --git a/QtAndroidTools/QAndroidGoogleDrive.h b/QtAndroidTools/QAndroidGoogleDrive.h index e19034f..a1c6548 100644 --- a/QtAndroidTools/QAndroidGoogleDrive.h +++ b/QtAndroidTools/QAndroidGoogleDrive.h @@ -36,6 +36,7 @@ class QAndroidGoogleDrive : public QObject Q_PROPERTY(QString SCOPE_DRIVE_PHOTOS_READONLY MEMBER SCOPE_DRIVE_PHOTOS_READONLY CONSTANT) Q_PROPERTY(QString SCOPE_DRIVE_READONLY MEMBER SCOPE_DRIVE_READONLY CONSTANT) Q_PROPERTY(QString SCOPE_DRIVE_SCRIPTS MEMBER SCOPE_DRIVE_SCRIPTS CONSTANT) + Q_PROPERTY(bool isAuthenticated READ isAuthenticated NOTIFY isAuthenticatedChanged) Q_DISABLE_COPY(QAndroidGoogleDrive) Q_OBJECT @@ -54,9 +55,19 @@ public: static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine); static QAndroidGoogleDrive* instance(); + Q_INVOKABLE bool authenticate(const QString &AppName, const QString &ScopeName); + Q_INVOKABLE QVariantList getFilesList(const QString &Query = QString()); + Q_INVOKABLE QString getRootId(); + + bool isAuthenticated() { return m_isAuthenticated; } + +signals: + void isAuthenticatedChanged(); + private: const QAndroidJniObject m_JavaGoogleDrive; static QAndroidGoogleDrive *m_pInstance; + bool m_isAuthenticated = false; QString m_ScopeList[8]; void LoadScopeDefinitions(); diff --git a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleAccount.java b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleAccount.java index e9bbd29..77aa51c 100644 --- a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleAccount.java +++ b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleAccount.java @@ -53,6 +53,7 @@ import java.net.URL; public class AndroidGoogleAccount { + private static final String TAG = "AndroidGoogleAccount"; private final Activity mActivityInstance; private GoogleSignInClient mGoogleSignInClient = null; @@ -248,10 +249,10 @@ public class AndroidGoogleAccount switch(e.getStatusCode()) { case GoogleSignInStatusCodes.DEVELOPER_ERROR: - Log.d("AndroidGoogleAccount", "DEVELOPER_ERROR -> Have you signed your project on Android console?"); + Log.d(TAG, "DEVELOPER_ERROR -> Have you signed your project on Android console?"); break; case GoogleSignInStatusCodes.SIGN_IN_REQUIRED: - Log.d("AndroidGoogleAccount", "SIGN_IN_REQUIRED -> You have to signin by select account before use this call"); + Log.d(TAG, "SIGN_IN_REQUIRED -> You have to signin by select account before use this call"); break; } signInSuccessfully = false; diff --git a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleDrive.java b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleDrive.java index 79410e1..aec4169 100644 --- a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleDrive.java +++ b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidGoogleDrive.java @@ -40,16 +40,21 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions; import com.google.android.gms.auth.api.signin.GoogleSignInAccount; import com.google.android.gms.common.api.Scope; import com.google.api.client.extensions.android.http.AndroidHttp; +import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.model.File; +import com.google.api.services.drive.model.FileList; import java.util.Collections; +import java.util.List; +import java.io.IOException; public class AndroidGoogleDrive { + private static final String TAG = "AndroidGoogleDrive"; private final Activity mActivityInstance; private Drive mDriveService = null; @@ -77,6 +82,96 @@ public class AndroidGoogleDrive return true; } + Log.d(TAG, "You have to signin by select account before use this call!"); return false; } + + public boolean isAuthenticated() + { + return (mDriveService != null) ? true : false; + } + + public DriveFile[] listFiles(String Query) + { + if(mDriveService != null) + { + DriveFile[] DriveFileList; + File[] FileList; + + try + { + FileList = mDriveService.files() + .list() + .setQ(Query) + .setSpaces("drive") + .setFields("files(id, name, mimeType, parents)") + .execute() + .getFiles() + .toArray(new File[0]); + } + catch(UserRecoverableAuthIOException e) + { + Log.d(TAG, "Authorization scope not requested at signin!"); + return null; + } + catch(IOException e) + { + return null; + } + + DriveFileList = new DriveFile[FileList.length]; + for(int i = 0; i < FileList.length; i++) + { + DriveFile FileData = new DriveFile(); + final File FileInfo = FileList[i]; + + FileData.id = FileInfo.getId(); + FileData.name = FileInfo.getName(); + FileData.mimeType = FileInfo.getMimeType(); + FileData.parents = (FileInfo.getParents() != null) ? FileInfo.getParents().toArray(new String[0]) : null; + + DriveFileList[i] = FileData; + } + + return DriveFileList; + } + + return null; + } + + public String getRootId() + { + if(mDriveService != null) + { + File FileInfo; + + try + { + FileInfo = mDriveService.files() + .get("root") + .execute(); + } + catch(UserRecoverableAuthIOException e) + { + Log.d(TAG, "Authorization scope not requested at signin!"); + return null; + } + catch(IOException e) + { + return null; + } + + return FileInfo.getId(); + } + + return null; + } + + public static class DriveFile + { + public String id; + public String name; + public String mimeType; + public String[] parents; + } } diff --git a/QtAndroidToolsDemo/android/AndroidManifest.xml b/QtAndroidToolsDemo/android/AndroidManifest.xml index 6c98fa4..9ee5956 100644 --- a/QtAndroidToolsDemo/android/AndroidManifest.xml +++ b/QtAndroidToolsDemo/android/AndroidManifest.xml @@ -91,4 +91,5 @@ + diff --git a/QtAndroidToolsDemo/tools/AndroidGoogleAccount.qml b/QtAndroidToolsDemo/tools/AndroidGoogleAccount.qml index 4cf00e4..5693634 100644 --- a/QtAndroidToolsDemo/tools/AndroidGoogleAccount.qml +++ b/QtAndroidToolsDemo/tools/AndroidGoogleAccount.qml @@ -65,12 +65,12 @@ Page { Button { anchors.horizontalCenter: parent.horizontalCenter text: "sigIn" - onClicked: QtAndroidGoogleAccount.signIn() + onClicked: QtAndroidGoogleAccount.signIn(QtAndroidGoogleDrive.SCOPE_DRIVE) } Button { anchors.horizontalCenter: parent.horizontalCenter text: "sigIn select account" - onClicked: QtAndroidGoogleAccount.signInSelectAccount() + onClicked: QtAndroidGoogleAccount.signInSelectAccount(QtAndroidGoogleDrive.SCOPE_DRIVE) } Button { anchors.horizontalCenter: parent.horizontalCenter diff --git a/QtAndroidToolsDemo/tools/AndroidGoogleDrive.qml b/QtAndroidToolsDemo/tools/AndroidGoogleDrive.qml index e53d146..3681d0c 100644 --- a/QtAndroidToolsDemo/tools/AndroidGoogleDrive.qml +++ b/QtAndroidToolsDemo/tools/AndroidGoogleDrive.qml @@ -8,8 +8,82 @@ Page { id: page padding: 0 - Button { - anchors.horizontalCenter: parent.horizontalCenter - text: "test" + Column { + width: parent.width * 0.9 + height: parent.height * 0.9 + anchors.centerIn: parent + spacing: 5 + + Button { + anchors.horizontalCenter: parent.horizontalCenter + text: "Authenticate" + onClicked: QtAndroidGoogleDrive.authenticate("QtAndroidTools", QtAndroidGoogleDrive.SCOPE_DRIVE) + } + + Button { + anchors.horizontalCenter: parent.horizontalCenter + enabled: QtAndroidGoogleDrive.isAuthenticated + text: "Get files list" + onClicked: { + var filesList = QtAndroidGoogleDrive.getFilesList(); + var rootId = QtAndroidGoogleDrive.getRootId(); + + filesListModel.clear(); + for(var i = 0; i < filesList.length; i++) + { + var data = filesList[i]; + var parentId = "null"; + + if(data.parents.length > 0) + { + if(data.parents[0] === rootId) + parentId = "root"; + else + parentId = data.parents[0]; + } + + filesListModel.append({ "id": data.id, + "name": data.name, + "mimeType": data.mimeType, + "parentId": parentId + }); + } + } + } + Rectangle { + width: parent.width + height: parent.height * 0.4 + border.width: 1 + border.color: "black" + clip: true + + ListModel { id: filesListModel } + + ListView { + id: filesListView + width: parent.width * 0.95 + height: parent.height + anchors.centerIn: parent + model: filesListModel + boundsBehavior: Flickable.StopAtBounds + delegate: Item { + width: filesListView.width + height: fileInfoColumn.implicitHeight + 10 + Column { + id: fileInfoColumn + Text { font.pixelSize: 13; text: 'Id: ' + id } + Text { font.pixelSize: 13; text: 'Name: ' + name } + Text { font.pixelSize: 13; text: 'MimeType: ' + mimeType } + Text { font.pixelSize: 13; text: 'ParentId: ' + parentId } + } + } + + ScrollBar.vertical: ScrollBar { + width: 10 + anchors.left: parent.right + policy: ScrollBar.AlwaysOn + } + } + } } }