forked from upstream-mirrors/OpenTracks
Performance optimization, during sync, getFolderId only when needed
This commit is contained in:
@@ -78,6 +78,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
private final MyTracksProviderUtils myTracksProviderUtils;
|
private final MyTracksProviderUtils myTracksProviderUtils;
|
||||||
private Drive drive;
|
private Drive drive;
|
||||||
private String driveAccountName; // the account name associated with the drive
|
private String driveAccountName; // the account name associated with the drive
|
||||||
|
private String folderId;
|
||||||
|
|
||||||
public SyncAdapter(Context context) {
|
public SyncAdapter(Context context) {
|
||||||
super(context, true);
|
super(context, true);
|
||||||
@@ -119,22 +120,14 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
driveAccountName = account.name;
|
driveAccountName = account.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
File folder = SyncUtils.getMyTracksFolder(context, drive);
|
|
||||||
if (folder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String folderId = folder.getId();
|
|
||||||
if (folderId == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long largestChangeId = PreferencesUtils.getLong(
|
long largestChangeId = PreferencesUtils.getLong(
|
||||||
context, R.string.drive_largest_change_id_key);
|
context, R.string.drive_largest_change_id_key);
|
||||||
if (largestChangeId == PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT) {
|
if (largestChangeId == PreferencesUtils.DRIVE_LARGEST_CHANGE_ID_DEFAULT) {
|
||||||
performInitialSync(folderId);
|
performInitialSync();
|
||||||
} else {
|
} else {
|
||||||
performIncrementalSync(folderId, largestChangeId);
|
performIncrementalSync(largestChangeId);
|
||||||
}
|
}
|
||||||
insertNewDriveFiles(folderId);
|
insertNewDriveFiles();
|
||||||
} catch (UserRecoverableAuthException e) {
|
} catch (UserRecoverableAuthException e) {
|
||||||
SendToGoogleUtils.sendNotification(
|
SendToGoogleUtils.sendNotification(
|
||||||
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
context, account.name, e.getIntent(), SendToGoogleUtils.DRIVE_NOTIFICATION_ID);
|
||||||
@@ -149,23 +142,38 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs initial sync.
|
* Gets the folder id..
|
||||||
*
|
|
||||||
* @param folderId the folder id
|
|
||||||
*/
|
*/
|
||||||
private void performInitialSync(String folderId) throws IOException {
|
private String getFolderId() throws IOException {
|
||||||
|
if (folderId == null) {
|
||||||
|
File folder = SyncUtils.getMyTracksFolder(context, drive);
|
||||||
|
if (folder == null) {
|
||||||
|
throw new IOException("folder is null");
|
||||||
|
}
|
||||||
|
folderId = folder.getId();
|
||||||
|
if (folderId == null) {
|
||||||
|
throw new IOException("folder id is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs initial sync.
|
||||||
|
*/
|
||||||
|
private void performInitialSync() throws IOException {
|
||||||
|
|
||||||
// Get the largest change id first to avoid race conditions
|
// Get the largest change id first to avoid race conditions
|
||||||
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 the KML/KMZ files in the "My Drive:/My Tracks" folder
|
// Get all the KML/KMZ files in the "My Drive:/My Tracks" folder
|
||||||
Files.List myTracksFolderRequest = drive.files()
|
Files.List myTracksFolderRequest = drive.files().list()
|
||||||
.list().setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId));
|
.setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, getFolderId()));
|
||||||
Map<String, File> myTracksFolderMap = getFiles(myTracksFolderRequest, true);
|
Map<String, File> myTracksFolderMap = getFiles(myTracksFolderRequest, true);
|
||||||
|
|
||||||
// Handle tracks that are already uploaded to Google Drive
|
// Handle tracks that are already uploaded to Google Drive
|
||||||
Set<String> syncedDriveIds = updateSyncedTracks(folderId);
|
Set<String> syncedDriveIds = updateSyncedTracks();
|
||||||
for (String driveId : syncedDriveIds) {
|
for (String driveId : syncedDriveIds) {
|
||||||
myTracksFolderMap.remove(driveId);
|
myTracksFolderMap.remove(driveId);
|
||||||
}
|
}
|
||||||
@@ -205,10 +213,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
/**
|
/**
|
||||||
* Updates synced tracks.
|
* Updates synced tracks.
|
||||||
*
|
*
|
||||||
* @param folderId the folder id
|
|
||||||
* @return drive ids of the synced tracks
|
* @return drive ids of the synced tracks
|
||||||
*/
|
*/
|
||||||
private Set<String> updateSyncedTracks(String folderId) throws IOException {
|
private Set<String> updateSyncedTracks() throws IOException {
|
||||||
Set<String> result = new HashSet<String>();
|
Set<String> result = new HashSet<String>();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
@@ -220,7 +227,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
if (driveId != null && !driveId.equals("")) {
|
if (driveId != null && !driveId.equals("")) {
|
||||||
if (!track.isSharedWithMe()) {
|
if (!track.isSharedWithMe()) {
|
||||||
File driveFile = drive.files().get(driveId).execute();
|
File driveFile = drive.files().get(driveId).execute();
|
||||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)) {
|
if (SyncUtils.isInMyTracksAndValid(driveFile, getFolderId())) {
|
||||||
merge(track, driveFile);
|
merge(track, driveFile);
|
||||||
result.add(driveId);
|
result.add(driveId);
|
||||||
} else {
|
} else {
|
||||||
@@ -246,104 +253,107 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
/**
|
/**
|
||||||
* Performs incremental sync.
|
* Performs incremental sync.
|
||||||
*
|
*
|
||||||
* @param folderId the folder id
|
|
||||||
* @param largestChangeId the largest change id
|
* @param largestChangeId the largest change id
|
||||||
*/
|
*/
|
||||||
private void performIncrementalSync(String folderId, long largestChangeId) throws IOException {
|
private void performIncrementalSync(long largestChangeId) throws IOException {
|
||||||
|
|
||||||
// Handle deleted tracks
|
// Handle deleted tracks
|
||||||
String driveDeletedList = PreferencesUtils.getString(
|
String driveDeletedList = PreferencesUtils.getString(
|
||||||
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
||||||
String deletedIds[] = TextUtils.split(driveDeletedList, ";");
|
if (!PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT.equals(driveDeletedList)) {
|
||||||
for (String driveId : deletedIds) {
|
String deletedIds[] = TextUtils.split(driveDeletedList, ";");
|
||||||
deleteDriveFile(driveId, folderId, true);
|
for (String driveId : deletedIds) {
|
||||||
|
deleteDriveFile(driveId, true);
|
||||||
|
}
|
||||||
|
PreferencesUtils.setString(
|
||||||
|
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
||||||
}
|
}
|
||||||
PreferencesUtils.setString(
|
|
||||||
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
|
|
||||||
|
|
||||||
// Handle edited tracks
|
// Handle edited tracks
|
||||||
String driveEditedList = PreferencesUtils.getString(
|
String driveEditedList = PreferencesUtils.getString(
|
||||||
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
||||||
String editedIds[] = TextUtils.split(driveEditedList, ";");
|
if (!PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT.equals(driveEditedList)) {
|
||||||
for (String id : editedIds) {
|
String editedIds[] = TextUtils.split(driveEditedList, ";");
|
||||||
Track track = myTracksProviderUtils.getTrack(Long.valueOf(id));
|
for (String id : editedIds) {
|
||||||
if (track == null) {
|
Track track = myTracksProviderUtils.getTrack(Long.valueOf(id));
|
||||||
continue;
|
if (track == null) {
|
||||||
}
|
continue;
|
||||||
if (track.isSharedWithMe()) {
|
}
|
||||||
continue;
|
if (track.isSharedWithMe()) {
|
||||||
}
|
continue;
|
||||||
String driveId = track.getDriveId();
|
}
|
||||||
if (driveId == null || driveId.equals("")) {
|
String driveId = track.getDriveId();
|
||||||
continue;
|
if (driveId == null || driveId.equals("")) {
|
||||||
}
|
continue;
|
||||||
File driveFile = drive.files().get(driveId).execute();
|
}
|
||||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)) {
|
File driveFile = drive.files().get(driveId).execute();
|
||||||
merge(track, driveFile);
|
if (SyncUtils.isInMyTracksAndValid(driveFile, getFolderId())) {
|
||||||
}
|
merge(track, driveFile);
|
||||||
}
|
|
||||||
PreferencesUtils.setString(
|
|
||||||
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
|
||||||
|
|
||||||
Map<String, File> changes = new HashMap<String, File>();
|
|
||||||
largestChangeId = getDriveChangesInfo(largestChangeId, changes);
|
|
||||||
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
// Get all the local tracks with drive file id
|
|
||||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
Track track = myTracksProviderUtils.createTrack(cursor);
|
|
||||||
String driveId = track.getDriveId();
|
|
||||||
|
|
||||||
if (changes.containsKey(driveId)) {
|
|
||||||
|
|
||||||
// Track has changed
|
|
||||||
File driveFile = changes.get(driveId);
|
|
||||||
if (driveFile == null) {
|
|
||||||
Log.d(TAG, "Delete local track " + track.getName());
|
|
||||||
myTracksProviderUtils.deleteTrack(track.getId());
|
|
||||||
} else {
|
|
||||||
if (SyncUtils.isInMyTracksAndValid(driveFile, folderId)
|
|
||||||
|| SyncUtils.isInSharedWithMe(driveFile)) {
|
|
||||||
merge(track, driveFile);
|
|
||||||
} else {
|
|
||||||
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
changes.remove(driveId);
|
|
||||||
}
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert valid new drive file changes as new tracks
|
|
||||||
Iterator<String> iterator = changes.keySet().iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
String driveId = iterator.next();
|
|
||||||
File file = changes.get(driveId);
|
|
||||||
if (!SyncUtils.isInMyTracksAndValid(file, folderId)
|
|
||||||
&& !SyncUtils.isInSharedWithMeAndValid(file)) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PreferencesUtils.setString(
|
||||||
|
context, R.string.drive_edited_list_key, PreferencesUtils.DRIVE_EDITED_LIST_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
insertNewTracks(changes.values());
|
// Handle changes from Google Drive
|
||||||
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, largestChangeId);
|
Map<String, File> changes = new HashMap<String, File>();
|
||||||
} finally {
|
long newLargestChangeId = getDriveChangesInfo(largestChangeId, changes);
|
||||||
if (cursor != null) {
|
if (newLargestChangeId != largestChangeId) {
|
||||||
cursor.close();
|
Cursor cursor = null;
|
||||||
|
try {
|
||||||
|
// Get all the local tracks with drive file id
|
||||||
|
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.DRIVE_ID_TRACKS_QUERY, null, null);
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
Track track = myTracksProviderUtils.createTrack(cursor);
|
||||||
|
String driveId = track.getDriveId();
|
||||||
|
|
||||||
|
if (changes.containsKey(driveId)) {
|
||||||
|
|
||||||
|
// Track has changed
|
||||||
|
File driveFile = changes.get(driveId);
|
||||||
|
if (driveFile == null) {
|
||||||
|
Log.d(TAG, "Delete local track " + track.getName());
|
||||||
|
myTracksProviderUtils.deleteTrack(track.getId());
|
||||||
|
} else {
|
||||||
|
if (SyncUtils.isInMyTracksAndValid(driveFile, getFolderId())
|
||||||
|
|| SyncUtils.isInSharedWithMe(driveFile)) {
|
||||||
|
merge(track, driveFile);
|
||||||
|
} else {
|
||||||
|
SyncUtils.updateTrack(myTracksProviderUtils, track, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changes.remove(driveId);
|
||||||
|
}
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert valid new drive file changes as new tracks
|
||||||
|
Iterator<String> iterator = changes.keySet().iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
String driveId = iterator.next();
|
||||||
|
File file = changes.get(driveId);
|
||||||
|
if (!SyncUtils.isInMyTracksAndValid(file, getFolderId())
|
||||||
|
&& !SyncUtils.isInSharedWithMeAndValid(file)) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insertNewTracks(changes.values());
|
||||||
|
PreferencesUtils.setLong(context, R.string.drive_largest_change_id_key, newLargestChangeId);
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts new drive files from tracks without a drive id.
|
* Inserts new drive files from tracks without a drive id.
|
||||||
*
|
|
||||||
* @param folderId the folder id
|
|
||||||
*/
|
*/
|
||||||
private void insertNewDriveFiles(String folderId) throws IOException {
|
private void insertNewDriveFiles() throws IOException {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.NO_DRIVE_ID_TRACKS_QUERY, null, null);
|
cursor = myTracksProviderUtils.getTrackCursor(SyncUtils.NO_DRIVE_ID_TRACKS_QUERY, null, null);
|
||||||
@@ -356,7 +366,8 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// If not successful, the next sync will retry again
|
// If not successful, the next sync will retry again
|
||||||
SyncUtils.insertDriveFile(drive, folderId, context, myTracksProviderUtils, track, true);
|
SyncUtils.insertDriveFile(
|
||||||
|
drive, getFolderId(), context, myTracksProviderUtils, track, true);
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -568,14 +579,14 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
* Deletes a drive file.
|
* Deletes a drive file.
|
||||||
*
|
*
|
||||||
* @param driveId the drive id
|
* @param driveId the drive id
|
||||||
* @param folderId the folder id
|
|
||||||
* @param canRetry true if can retry the request
|
* @param canRetry true if can retry the request
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void deleteDriveFile(String driveId, String folderId, boolean canRetry)
|
private void deleteDriveFile(String driveId, boolean canRetry)
|
||||||
throws UserRecoverableAuthIOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
File driveFile = drive.files().get(driveId).execute();
|
File driveFile = drive.files().get(driveId).execute();
|
||||||
if (SyncUtils.isInMyTracks(driveFile, folderId)) {
|
if (SyncUtils.isInMyTracks(driveFile, getFolderId())) {
|
||||||
if (!driveFile.getLabels().getTrashed()) {
|
if (!driveFile.getLabels().getTrashed()) {
|
||||||
drive.files().trash(driveId).execute();
|
drive.files().trash(driveId).execute();
|
||||||
}
|
}
|
||||||
@@ -590,7 +601,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
throw e;
|
throw e;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (canRetry) {
|
if (canRetry) {
|
||||||
deleteDriveFile(driveId, folderId, false);
|
deleteDriveFile(driveId, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.e(TAG, "Unable to delete Drive file for " + driveId, e);
|
Log.e(TAG, "Unable to delete Drive file for " + driveId, e);
|
||||||
|
|||||||
Reference in New Issue
Block a user