Skip to content

Commit c54f227

Browse files
author
Nicholas Harrison
committed
Google Drive auth and sync now working
May still have bugs with handling modification times
1 parent 8971730 commit c54f227

File tree

2 files changed

+74
-62
lines changed

2 files changed

+74
-62
lines changed

app/src/main/java/com/orgzly/android/repos/GoogleDriveClient.java

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.orgzly.android.repos;
22

3-
import android.app.Activity;
4-
import android.content.Intent;
53
import android.content.Context;
64
import android.net.Uri;
5+
import android.os.Build;
6+
7+
import androidx.annotation.RequiresApi;
78

89
import com.google.android.gms.auth.api.signin.GoogleSignIn;
910

11+
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
1012
import com.google.api.client.extensions.android.http.AndroidHttp;
1113
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
1214
import com.google.api.client.http.FileContent;
@@ -20,20 +22,16 @@
2022

2123
import java.io.BufferedOutputStream;
2224
// import java.io.File;
23-
import java.io.FileInputStream;
2425
import java.io.FileOutputStream;
2526
import java.io.IOException;
26-
import java.io.InputStream;
2727
import java.io.OutputStream;
2828
import java.util.ArrayList;
29+
import java.util.Arrays;
2930
import java.util.Collections;
3031
import java.util.HashMap;
3132
import java.util.List;
32-
import java.util.Locale;
3333
import java.util.Map;
3434

35-
import android.util.Log;
36-
3735
public class GoogleDriveClient {
3836
private static final String TAG = GoogleDriveClient.class.getName();
3937

@@ -48,10 +46,10 @@ public class GoogleDriveClient {
4846

4947
private final Context mContext;
5048
private final long repoId;
51-
private Drive mDriveService;
49+
private static Drive mDriveService;
5250

53-
private Map<String, String> pathIds;
54-
{
51+
private static Map<String, String> pathIds;
52+
static {
5553
pathIds = new HashMap<>();
5654
pathIds.put("My Drive", "root");
5755
pathIds.put("", "root");
@@ -61,30 +59,61 @@ public GoogleDriveClient(Context context, long id) {
6159
mContext = context;
6260

6361
repoId = id;
64-
}
6562

66-
public void setService(Drive driveService) {
67-
mDriveService = driveService;
63+
if (isLinked()) setDriveService();
6864
}
6965

7066
public boolean isLinked() {
7167
// Check for existing Google Sign In account, if the user is already signed in
7268
// the GoogleSignInAccount will be non-null.
73-
return GoogleSignIn.getLastSignedInAccount(mContext) != null;
69+
return getGoogleAccount() != null;
70+
}
71+
72+
private GoogleSignInAccount getGoogleAccount() {
73+
return GoogleSignIn.getLastSignedInAccount(mContext);
74+
}
75+
76+
public Drive getDriveService(GoogleSignInAccount googleAccount) {
77+
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(
78+
mContext, Collections.singleton(DriveScopes.DRIVE));
79+
credential.setSelectedAccount(googleAccount.getAccount());
80+
return new Drive.Builder(
81+
AndroidHttp.newCompatibleTransport(),
82+
new GsonFactory(),
83+
credential)
84+
.setApplicationName("Orgzly")
85+
.build();
86+
}
87+
88+
public Drive getDriveService() {
89+
if (mDriveService != null) return mDriveService;
90+
return getDriveService(getGoogleAccount());
91+
}
92+
93+
public void setDriveService() {
94+
if (mDriveService == null) mDriveService = getDriveService();
95+
}
96+
97+
public void setDriveService(GoogleSignInAccount googleAccount) {
98+
mDriveService = getDriveService(googleAccount);
7499
}
75100

76101
private void linkedOrThrow() throws IOException {
77102
if (! isLinked()) {
78103
throw new IOException(NOT_LINKED);
104+
} else {
105+
setDriveService();
79106
}
80107
}
81108

109+
@RequiresApi(api = Build.VERSION_CODES.N)
82110
private String findId(String path) throws IOException {
83111
if (pathIds.containsKey(path)) {
84112
return pathIds.get(path);
85113
}
86114

87115
String[] parts = path.split("/");
116+
parts = Arrays.stream(parts).filter(s -> !s.isEmpty()).toArray(String[]::new);
88117
String[] ids = new String[parts.length+1];
89118

90119
ids[0] = "root";
@@ -95,23 +124,21 @@ private String findId(String path) throws IOException {
95124
.setSpaces("drive")
96125
.setFields("files(id, name, mimeType)")
97126
.execute();
98-
List files = result.getFiles();
127+
List<File> files = result.getFiles();
99128
if (!files.isEmpty()) {
100129
File file = (File) files.get(0);
101130
ids[i+1] = file.getId();
102131
}
103132
}
104133

105-
for (int i = 0; i < ids.length; ++i) {
106-
if (ids[i] == null) {
107-
break;
108-
}
109-
pathIds.put(path, ids[i]);
134+
if (ids[ids.length-1] != null) {
135+
pathIds.put(path, ids[ids.length-1]);
110136
}
111137

112138
return ids[ids.length-1]; // Returns null if no file is found
113139
}
114140

141+
@RequiresApi(api = Build.VERSION_CODES.N)
115142
public List<VersionedRook> getBooks(Uri repoUri) throws IOException {
116143
linkedOrThrow();
117144

@@ -129,24 +156,23 @@ public List<VersionedRook> getBooks(Uri repoUri) throws IOException {
129156

130157
try {
131158

132-
String folderId = findId(path);
133-
159+
String pathId = findId(path);
134160

135-
if (folderId != null) {
161+
if (pathId != null) {
136162

137-
File folder = mDriveService.files().get(folderId)
138-
.setFields("id, mimeType")
163+
File folder = mDriveService.files().get(pathId)
164+
.setFields("id, name, mimeType, version, modifiedTime")
139165
.execute();
140166

141-
if (folder.getMimeType() == "application/vnd.google-apps.folder") {
167+
if (folder.getMimeType().equals("application/vnd.google-apps.folder")) {
142168

143169
String pageToken = null;
144170
do {
145171
FileList result = mDriveService.files().list()
146172
.setQ(String.format("mimeType != 'application/vnd.google-apps.folder' " +
147-
"and '%s' in parents and trashed = false", folderId))
173+
"and '%s' in parents and trashed = false", pathId))
148174
.setSpaces("drive")
149-
.setFields("nextPageToken, files(id, name, mimeType)")
175+
.setFields("nextPageToken, files(id, name, mimeType, version, modifiedTime)")
150176
.setPageToken(pageToken)
151177
.execute();
152178
for (File file : result.getFiles()) {
@@ -170,7 +196,7 @@ public List<VersionedRook> getBooks(Uri repoUri) throws IOException {
170196
throw new IOException("Not a directory: " + repoUri);
171197
}
172198
} else {
173-
throw new IOException("Not a directory: " + repoUri);
199+
throw new IOException("Path not found: " + repoUri);
174200
}
175201

176202
} catch (Exception e) {
@@ -187,6 +213,7 @@ public List<VersionedRook> getBooks(Uri repoUri) throws IOException {
187213
/**
188214
* Download file from Google Drive and store it to a local file.
189215
*/
216+
@RequiresApi(api = Build.VERSION_CODES.N)
190217
public VersionedRook download(Uri repoUri, String fileName, java.io.File localFile) throws IOException {
191218
linkedOrThrow();
192219

@@ -200,10 +227,10 @@ public VersionedRook download(Uri repoUri, String fileName, java.io.File localFi
200227

201228
if (fileId != null) {
202229
File file = mDriveService.files().get(fileId)
203-
.setFields("id, mimeType, version, modifiedDate")
230+
.setFields("id, mimeType, version, modifiedTime")
204231
.execute();
205232

206-
if (file.getMimeType() != "application/vnd.google-apps.folder") {
233+
if (!file.getMimeType().equals("application/vnd.google-apps.folder")) {
207234

208235
String rev = Long.toString(file.getVersion());
209236
long mtime = file.getModifiedTime().getValue();
@@ -231,6 +258,7 @@ public VersionedRook download(Uri repoUri, String fileName, java.io.File localFi
231258

232259

233260
/** Upload file to Google Drive. */
261+
@RequiresApi(api = Build.VERSION_CODES.N)
234262
public VersionedRook upload(java.io.File file, Uri repoUri, String fileName) throws IOException {
235263
linkedOrThrow();
236264

@@ -267,7 +295,7 @@ public VersionedRook upload(java.io.File file, Uri repoUri, String fileName) thr
267295
pathIds.put(filePath, fileId);
268296
} else {
269297
fileMetadata = mDriveService.files().update(fileId, fileMetadata, mediaContent)
270-
.setFields("id")
298+
.setFields("id, version, modifiedTime")
271299
.execute();
272300
}
273301

@@ -285,6 +313,7 @@ public VersionedRook upload(java.io.File file, Uri repoUri, String fileName) thr
285313
return new VersionedRook(repoId, RepoType.GOOGLE_DRIVE, repoUri, bookUri, rev, mtime);
286314
}
287315

316+
@RequiresApi(api = Build.VERSION_CODES.N)
288317
public void delete(String path) throws IOException {
289318
linkedOrThrow();
290319

@@ -293,7 +322,7 @@ public void delete(String path) throws IOException {
293322

294323
if (fileId != null) {
295324
File file = mDriveService.files().get(fileId).setFields("id, mimeType").execute();
296-
if (file.getMimeType() != "application/vnd.google-apps.folder") {
325+
if (!file.getMimeType().equals("application/vnd.google-apps.folder")) {
297326
File fileMetadata = new File();
298327
fileMetadata.setTrashed(true);
299328
mDriveService.files().update(fileId, fileMetadata).execute();
@@ -313,6 +342,7 @@ public void delete(String path) throws IOException {
313342
}
314343
}
315344

345+
@RequiresApi(api = Build.VERSION_CODES.N)
316346
public VersionedRook move(Uri repoUri, Uri from, Uri to) throws IOException {
317347
linkedOrThrow();
318348

@@ -324,10 +354,10 @@ public VersionedRook move(Uri repoUri, Uri from, Uri to) throws IOException {
324354

325355
if (fileId != null) {
326356
fileMetadata = mDriveService.files().update(fileId, fileMetadata)
327-
.setFields("id, mimeType, version, modifiedDate")
357+
.setFields("id, mimeType, version, modifiedTime")
328358
.execute();
329359

330-
if (fileMetadata.getMimeType() == "application/vnd.google-apps.folder") {
360+
if (fileMetadata.getMimeType().equals("application/vnd.google-apps.folder")) {
331361
throw new IOException("Relocated object not a file?");
332362
}
333363

@@ -336,7 +366,7 @@ public VersionedRook move(Uri repoUri, Uri from, Uri to) throws IOException {
336366
String rev = Long.toString(fileMetadata.getVersion());
337367
long mtime = fileMetadata.getModifiedTime().getValue();
338368

339-
return new VersionedRook(repoId, RepoType.DROPBOX, repoUri, to, rev, mtime);
369+
return new VersionedRook(repoId, RepoType.GOOGLE_DRIVE, repoUri, to, rev, mtime);
340370

341371
} catch (Exception e) {
342372
e.printStackTrace();

app/src/main/java/com/orgzly/android/ui/repo/googledrive/GoogleDriveRepoActivity.kt

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.orgzly.android.ui.repo.googledrive
22

3-
import android.annotation.SuppressLint
43
import android.app.Activity
54
import android.app.AlertDialog
65
import android.content.DialogInterface
@@ -10,7 +9,6 @@ import android.os.Bundle
109
import android.text.TextUtils
1110
import android.view.Menu
1211
import android.view.MenuItem
13-
import android.widget.EditText
1412
import androidx.databinding.DataBindingUtil
1513
import androidx.lifecycle.Observer
1614
import androidx.lifecycle.ViewModelProviders
@@ -39,14 +37,9 @@ import com.google.android.gms.common.api.Scope;
3937
import com.google.android.gms.tasks.Task;
4038
import com.google.android.gms.tasks.OnCompleteListener;
4139

42-
import com.google.api.client.extensions.android.http.AndroidHttp;
43-
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
44-
import com.google.api.client.json.gson.GsonFactory;
45-
import com.google.api.services.drive.Drive;
4640
import com.google.api.services.drive.DriveScopes;
4741

4842
import androidx.annotation.NonNull;
49-
import java.util.Collections;
5043

5144
import android.util.Log;
5245

@@ -154,28 +147,17 @@ class GoogleDriveRepoActivity : CommonActivity() {
154147
handleSignInResult(requestCode, resultData)
155148
}
156149

157-
fun handleSignInResult(requestCode:Int, result:Intent?) {
150+
private fun handleSignInResult(requestCode:Int, result:Intent?) {
158151
if (requestCode == REQUEST_CODE_SIGN_IN)
159152
{
160153
GoogleSignIn.getSignedInAccountFromIntent(result)
161-
.addOnSuccessListener({ googleAccount->
162-
Log.d(TAG, "Signed in as " + googleAccount.getEmail())
163-
// Use the authenticated account to sign in to the Drive service.
164-
val credential = GoogleAccountCredential.usingOAuth2(
165-
this, Collections.singleton(DriveScopes.DRIVE))
166-
credential.setSelectedAccount(googleAccount.getAccount())
167-
val googleDriveService = Drive.Builder(
168-
AndroidHttp.newCompatibleTransport(),
169-
GsonFactory(),
170-
credential)
171-
.setApplicationName("Orgzly")
172-
.build()
173-
// The DriveServiceHelper encapsulates all REST API and SAF functionality.
174-
// Its instantiation is required before handling any onClick actions.
175-
client.setService(googleDriveService);
176-
showSnackbar(R.string.message_google_drive_linked)
177-
})
178-
.addOnFailureListener({ exception-> Log.d(TAG, "Unable to sign in." + exception) })
154+
.addOnSuccessListener { googleAccount ->
155+
Log.d(TAG, "Signed in as " + googleAccount.getEmail())
156+
// Use the authenticated account to sign in to the Drive service.
157+
client.setDriveService(googleAccount)
158+
showSnackbar(R.string.message_google_drive_linked)
159+
}
160+
.addOnFailureListener { exception -> Log.d(TAG, "Unable to sign in.$exception") }
179161
}
180162
}
181163

0 commit comments

Comments
 (0)