Also sync "Shared with me" KML files.

This commit is contained in:
Jimmy Shih
2013-02-02 13:16:04 -08:00
parent 0fac9767fe
commit f26a8799fa
7 changed files with 144 additions and 78 deletions
+5 -5
View File
@@ -1732,8 +1732,9 @@ limitations under the License.
account. account.
%1$s account name. E.g., 'foo@foo.com'."> %1$s account name. E.g., 'foo@foo.com'.">
This will remove any mappings between tracks and %1$s Google Drive. After removal, when sending This will remove mappings between tracks and %1$s Google Drive. No tracks and no Google Drive
to Google Drive or syncing with Google Drive, all tracks will be treated as new. files will get removed. After switching account, when sending to Google Drive or syncing with
Google Drive, all tracks will be treated as new.
</string> </string>
<string name="settings_google_account_title" <string name="settings_google_account_title"
translation_description="In the 'Google' settings, the option to switch Google account. translation_description="In the 'Google' settings, the option to switch Google account.
@@ -1747,9 +1748,8 @@ limitations under the License.
%1$s account name. E.g., 'foo@foo.com'. %1$s account name. E.g., 'foo@foo.com'.
%2$s folder name. E.g., 'My Tracks'."> %2$s folder name. E.g., 'My Tracks'.">
Check the files in %1$s Google Drive &#8216;%2$s&#8217; folder. Files not mapped to existing All files in the %1$s Google Drive &#8216;%2$s&#8217; folder will be treated as new. If not
tracks will be synced as new tracks. If not desired, move those files to a different folder desired, move the files to a different folder beforehand.
beforehand.
</string> </string>
<string name="settings_google_drive_sync_summary_on" <string name="settings_google_drive_sync_summary_on"
translation_description="In the 'Google' settings, the summary for the 'Sync Google Drive' translation_description="In the 'Google' settings, the summary for the 'Sync Google Drive'
@@ -208,7 +208,7 @@ public class MyTracksProvider extends ContentProvider {
getContext(), R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT); getContext(), R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT);
if (driveSync) { if (driveSync) {
driveIds = where != null ? getDriveIds(null, where, selectionArgs) driveIds = where != null ? getDriveIds(null, where, selectionArgs)
: getDriveIds(new String[] { TracksColumns.DRIVEID }, SyncUtils.DRIVE_IDS_QUERY, null); : getDriveIds(new String[] { TracksColumns.DRIVEID }, SyncUtils.DRIVE_ID_TRACKS_BY_ME_QUERY, null);
} }
} }
@@ -84,11 +84,10 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
String driveId = track.getDriveId(); String driveId = track.getDriveId();
if (driveId != null && !driveId.equals("")) { if (driveId != null && !driveId.equals("")) {
File driveFile = drive.files().get(driveId).execute(); File driveFile = drive.files().get(driveId).execute();
if (SyncUtils.isDriveFileValid(driveFile, folderId)) { if (SyncUtils.isValid(driveFile, folderId)
if (SyncUtils.updateDriveFile(context, myTracksProviderUtils, drive, driveFile, track)) { && SyncUtils.updateDriveFile(context, myTracksProviderUtils, drive, driveFile, track)) {
addPermission(drive, driveId); addPermission(drive, driveId);
return true; return true;
}
} }
track.setDriveId(""); track.setDriveId("");
track.setModifiedTime(-1L); track.setModifiedTime(-1L);
@@ -134,27 +134,17 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
About about = drive.about().get().setFields(ABOUT_GET_FIELDS).execute(); About about = drive.about().get().setFields(ABOUT_GET_FIELDS).execute();
long largestChangeId = about.getLargestChangeId(); long largestChangeId = about.getLargestChangeId();
// Get all drive files // Get all the KML files in the "My Drive:/My Tracks" folder
Files.List request = drive.files() Files.List request = drive.files().list()
.list().setQ(String.format(Locale.US, SyncUtils.GET_KML_FILES_QUERY, folderId)); .setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId));
Map<String, File> idToFileMap = new HashMap<String, File>(); Map<String, File> idToFileMap = getFiles(request);
do {
try {
FileList files = request.execute();
for (File file : files.getItems()) {
idToFileMap.put(file.getId(), file);
}
request.setPageToken(files.getNextPageToken());
} catch (IOException e) {
Log.e(TAG, "IOException", e);
request.setPageToken(null);
}
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
// Handle new drive files
insertNewDriveFiles(idToFileMap.values()); insertNewDriveFiles(idToFileMap.values());
// Get all the KML files in the "Shared with me:/" folder
request = drive.files().list().setQ(SyncUtils.SHARED_WITH_ME_FILES_QUERY);
idToFileMap = getFiles(request);
insertNewDriveFiles(idToFileMap.values());
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, largestChangeId); PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, largestChangeId);
} }
@@ -172,8 +162,13 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
String deletedIds[] = TextUtils.split(driveDeletedList, ";"); String deletedIds[] = TextUtils.split(driveDeletedList, ";");
for (String id : deletedIds) { for (String id : deletedIds) {
File driveFile = drive.files().get(id).execute(); File driveFile = drive.files().get(id).execute();
if (SyncUtils.isDriveFileValid(driveFile, folderId)) { if (SyncUtils.isInFolder(driveFile, folderId)) {
drive.files().trash(id).execute(); if (!driveFile.getLabels().getTrashed()) {
drive.files().trash(id).execute();
}
// if trashed, ignore
} else if (SyncUtils.isSharedWithMe(driveFile)) {
drive.files().delete(id).execute();
} }
} }
PreferencesUtils.setString( PreferencesUtils.setString(
@@ -185,7 +180,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
Cursor cursor = null; Cursor cursor = null;
try { try {
// Get all the local tracks with drive file id // Get all the local tracks with drive file id
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_IDS_QUERY, null, null); cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
do { do {
Track track = myTracksProviderUtils.createTrack(cursor); Track track = myTracksProviderUtils.createTrack(cursor);
@@ -203,19 +198,22 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
} }
changes.remove(driveId); changes.remove(driveId);
} else { } else {
if (!track.isSharedWithMe()) {
// Handle the case the track has changed // Handle the case the track has changed
File driveFile = drive.files().get(driveId).execute(); File driveFile = drive.files().get(driveId).execute();
if (SyncUtils.isDriveFileValid(driveFile, folderId)) { if (SyncUtils.isValid(driveFile, folderId)) {
mergeFiles(track, driveFile); mergeFiles(track, driveFile);
} else { } else {
/* /*
* Track has a drive id, but the drive id is no longer valid. * Track has a drive id, but the drive id is no longer valid.
* E.g., the file is moved to another folder. Clear the drive id. * E.g., the file is moved to another folder. Clear the drive
*/ * id.
track.setDriveId(""); */
track.setModifiedTime(-1L); track.setDriveId("");
myTracksProviderUtils.updateTrack(track); track.setModifiedTime(-1L);
myTracksProviderUtils.updateTrack(track);
}
} }
} }
} while (cursor.moveToNext()); } while (cursor.moveToNext());
@@ -243,7 +241,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
private void insertNewTracks(String folderId) throws IOException { private void insertNewTracks(String folderId) throws IOException {
Cursor cursor = null; Cursor cursor = null;
try { try {
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.NO_DRIVE_ID_QUERY, null, null); cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.NO_DRIVE_ID_TRACKS_QUERY, null, null);
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key); long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
@@ -280,6 +278,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
Track track = myTracksProviderUtils.getTrack(tracksIds[0]); Track track = myTracksProviderUtils.getTrack(tracksIds[0]);
track.setDriveId(driveFile.getId()); track.setDriveId(driveFile.getId());
track.setModifiedTime(driveFile.getModifiedDate().getValue()); track.setModifiedTime(driveFile.getModifiedDate().getValue());
track.setSharedWithMe(driveFile.getSharedWithMeDate() != null);
myTracksProviderUtils.updateTrack(track); myTracksProviderUtils.updateTrack(track);
Log.d(TAG, "Add from Google Drive " + track.getName()); Log.d(TAG, "Add from Google Drive " + track.getName());
} }
@@ -289,6 +288,30 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
} }
} }
/**
* Gets all the files from a request.
*
* @param request the request
* @return a map of file id to file
*/
private Map<String, File> getFiles(Files.List request) {
Map<String, File> idToFileMap = new HashMap<String, File>();
do {
try {
FileList files = request.execute();
for (File file : files.getItems()) {
idToFileMap.put(file.getId(), file);
}
request.setPageToken(files.getNextPageToken());
} catch (IOException e) {
Log.e(TAG, "IOException", e);
request.setPageToken(null);
}
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
return idToFileMap;
}
/** /**
* Gets the Drive changes in the My Tracks folder. Includes deleted files. * Gets the Drive changes in the My Tracks folder. Includes deleted files.
* *
@@ -310,7 +333,13 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
} else { } else {
File file = change.getFile(); File file = change.getFile();
if (SyncUtils.isInFolder(file, folderId)) { if (SyncUtils.isInFolder(file, folderId)) {
changes.put(change.getFileId(), file.getLabels().getTrashed() ? null : file); if (file.getLabels().getTrashed()) {
changes.put(change.getFileId(), null);
} else {
changes.put(change.getFileId(), file);
}
} else if (SyncUtils.isSharedWithMe(file)) {
changes.put(change.getFileId(), file);
} }
} }
} }
@@ -359,6 +388,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
Track newTrack = myTracksProviderUtils.getTrack(tracksIds[0]); Track newTrack = myTracksProviderUtils.getTrack(tracksIds[0]);
newTrack.setDriveId(driveFile.getId()); newTrack.setDriveId(driveFile.getId());
newTrack.setModifiedTime(driveModifiedTime); newTrack.setModifiedTime(driveModifiedTime);
newTrack.setSharedWithMe(driveFile.getSharedWithMeDate() != null);
myTracksProviderUtils.updateTrack(newTrack); myTracksProviderUtils.updateTrack(newTrack);
} else { } else {
@@ -65,20 +65,38 @@ import java.util.Locale;
*/ */
public class SyncUtils { public class SyncUtils {
// Request code to obtain Drive permission
public static final int DRIVE_PERMISSION_REQUEST_CODE = 1; public static final int DRIVE_PERMISSION_REQUEST_CODE = 1;
public static final String DRIVE_IDS_QUERY = TracksColumns.DRIVEID + " IS NOT NULL AND " // Get tracks with drive id
public static final String DRIVE_ID_TRACKS_QUERY = TracksColumns.DRIVEID + " IS NOT NULL AND "
+ TracksColumns.DRIVEID + "!=''"; + TracksColumns.DRIVEID + "!=''";
public static final String NO_DRIVE_ID_QUERY = TracksColumns.DRIVEID + " IS NULL OR "
// Get tracks with drive id that are owned by me, not tracks ashared with me.
public static final String DRIVE_ID_TRACKS_BY_ME_QUERY = DRIVE_ID_TRACKS_QUERY + " AND "
+ TracksColumns.SHAREDWITHME + "!=1";
// Get tracks without drive id
public static final String NO_DRIVE_ID_TRACKS_QUERY = TracksColumns.DRIVEID + " IS NULL OR "
+ TracksColumns.DRIVEID + "=''"; + TracksColumns.DRIVEID + "=''";
// KML mime type
public static final String KML_MIME_TYPE = "application/vnd.google-earth.kml+xml"; public static final String KML_MIME_TYPE = "application/vnd.google-earth.kml+xml";
public static final String GET_KML_FILES_QUERY = "'%s' in parents and mimeType = '"
// Get My Tracks folder KML files
public static final String MY_TRACKS_FOLDER_FILES_QUERY = "'%s' in parents and mimeType = '"
+ KML_MIME_TYPE + "' and trashed = false"; + KML_MIME_TYPE + "' and trashed = false";
// Get shared with me KML files
public static final String SHARED_WITH_ME_FILES_QUERY = "sharedWithMe and mimeType = '"
+ KML_MIME_TYPE + "'";
// Folder mime type
private static final String FOLDER_MIME_TYPE = "application/vnd.google-apps.folder"; private static final String FOLDER_MIME_TYPE = "application/vnd.google-apps.folder";
// Get My Tracks folder
@VisibleForTesting @VisibleForTesting
public static final String GET_MY_TRACKS_FOLDER_QUERY = public static final String MY_TRACKS_FOLDER_QUERY =
"'root' in parents and title = '%s' and mimeType = '" + FOLDER_MIME_TYPE "'root' in parents and title = '%s' and mimeType = '" + FOLDER_MIME_TYPE
+ "' and trashed = false"; + "' and trashed = false";
@@ -236,7 +254,7 @@ public class SyncUtils {
try { try {
String folderName = context.getString(R.string.my_tracks_app_name); String folderName = context.getString(R.string.my_tracks_app_name);
List list = drive.files() List list = drive.files()
.list().setQ(String.format(Locale.US, GET_MY_TRACKS_FOLDER_QUERY, folderName)); .list().setQ(String.format(Locale.US, MY_TRACKS_FOLDER_QUERY, folderName));
FileList result = list.execute(); FileList result = list.execute();
for (File file : result.getItems()) { for (File file : result.getItems()) {
if (file.getTitle().equals(folderName)) { if (file.getTitle().equals(folderName)) {
@@ -254,21 +272,33 @@ public class SyncUtils {
} }
/** /**
* Returns true if the drive file is a kml file in the My Tracks folder and * Returns true if the drive file is a Shared with me KML file.
* not trashed. *
* @param driveFile the drive file
*/
public static boolean isSharedWithMe(File driveFile) {
if (driveFile == null) {
return false;
}
if (!SyncUtils.KML_MIME_TYPE.equals(driveFile.getMimeType())) {
return false;
}
return driveFile.getSharedWithMeDate() != null;
}
/**
* Returns true if the drive file is a valid KML file in the My Tracks folder
* and not trashed.
* *
* @param driveFile the drive file * @param driveFile the drive file
* @param folderId the My Tracks folder id * @param folderId the My Tracks folder id
*/ */
public static boolean isDriveFileValid(File driveFile, String folderId) { public static boolean isValid(File driveFile, String folderId) {
if (isInFolder(driveFile, folderId)) { return isInFolder(driveFile, folderId) && !driveFile.getLabels().getTrashed();
return !driveFile.getLabels().getTrashed();
}
return false;
} }
/** /**
* Returns true if the drive file is a kml file in the My Tracks folder. * Returns true if the drive file is a KML file in the My Tracks folder.
* *
* @param driveFile the drive file * @param driveFile the drive file
* @param folderId the My Tracks folder id * @param folderId the My Tracks folder id
@@ -121,6 +121,7 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
showDialog(DIALOG_CONFIRM_DRIVE_SYNC_ON); showDialog(DIALOG_CONFIRM_DRIVE_SYNC_ON);
} else { } else {
handleSync(false); handleSync(false);
clearSyncState();
} }
return false; return false;
} }
@@ -198,8 +199,8 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
@Override @Override
public void onClick(DialogInterface d, int button) { public void onClick(DialogInterface d, int button) {
googleAccountPreference.setValue(newValue); googleAccountPreference.setValue(newValue);
clearSyncState();
handleSync(false); handleSync(false);
clearSyncState();
updateUiByAccountName(newValue); updateUiByAccountName(newValue);
} }
}); });
@@ -215,25 +216,25 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
} }
/** /**
* Clears the sync state. * Clears the sync state. Assumes sync is turned off. Do not want clearing the
* state to cause sync activities.
*/ */
private void clearSyncState() { private void clearSyncState() {
PreferencesUtils.setLong(this, R.string.drive_largest_change_id_key,
PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT);
PreferencesUtils.setString(
this, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this); MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this);
Cursor cursor = null; Cursor cursor = null;
try { try {
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_IDS_QUERY, null, null); cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
do { do {
Track track = myTracksProviderUtils.createTrack(cursor); Track track = myTracksProviderUtils.createTrack(cursor);
track.setDriveId(""); if (track.isSharedWithMe()) {
track.setModifiedTime(-1L); myTracksProviderUtils.deleteTrack(track.getId());
track.setSharedWithMe(false); } else {
myTracksProviderUtils.updateTrack(track); track.setDriveId("");
track.setModifiedTime(-1L);
track.setSharedWithMe(false);
myTracksProviderUtils.updateTrack(track);
}
} while (cursor.moveToNext()); } while (cursor.moveToNext());
} }
} finally { } finally {
@@ -241,6 +242,12 @@ public class GoogleSettingsActivity extends AbstractSettingsActivity {
cursor.close(); cursor.close();
} }
} }
PreferencesUtils.setLong(this, R.string.drive_largest_change_id_key,
PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT);
// Clear the driveDeletedList last
PreferencesUtils.setString(
this, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
} }
/** /**
@@ -138,7 +138,7 @@ public class SyncTestUtils {
} }
String folderId = folder.getId(); String folderId = folder.getId();
return drive.files().list() return drive.files().list()
.setQ(String.format(Locale.US, SyncUtils.GET_KML_FILES_QUERY, folderId)).execute() .setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId)).execute()
.getItems(); .getItems();
} }
@@ -330,7 +330,7 @@ public class SyncTestUtils {
try { try {
String folderName = context.getString(R.string.my_tracks_app_name); String folderName = context.getString(R.string.my_tracks_app_name);
com.google.api.services.drive.Drive.Files.List list = drive.files().list() com.google.api.services.drive.Drive.Files.List list = drive.files().list()
.setQ(String.format(Locale.US, SyncUtils.GET_MY_TRACKS_FOLDER_QUERY, folderName)); .setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_QUERY, folderName));
FileList result = list.execute(); FileList result = list.execute();
for (File file : result.getItems()) { for (File file : result.getItems()) {
if (file.getTitle().equals(folderName)) { if (file.getTitle().equals(folderName)) {