X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/2ab9496b6e6bba15751c28295e9fd06c06aade6a..afaa2879d192be067cae523b51dad75d89a6c6cb:/src/com/owncloud/android/syncadapter/FileSyncAdapter.java diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 4f1cd68a..43ddae33 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -1,6 +1,10 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * + * @author Bartek Przybylski + * @author David A. Velasco * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * Copyright (C) 2015 ownCloud Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -26,22 +30,20 @@ import java.util.Map; import org.apache.jackrabbit.webdav.DavException; +import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.operations.UpdateOCVersionOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity; -import com.owncloud.android.utils.DisplayUtils; -import com.owncloud.android.utils.Log_OC; - import android.accounts.Account; import android.accounts.AccountsException; -import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.AbstractThreadedSyncAdapter; @@ -51,32 +53,37 @@ import android.content.Context; import android.content.Intent; import android.content.SyncResult; import android.os.Bundle; -//import android.support.v4.content.LocalBroadcastManager; +import android.support.v4.app.NotificationCompat; /** * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing * ownCloud files. * - * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}. - * - * @author Bartek Przybylski - * @author David A. Velasco + * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, + * String, ContentProviderClient, SyncResult)}. */ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { private final static String TAG = FileSyncAdapter.class.getSimpleName(); - /** Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation */ + /** Maximum number of failed folder synchronizations that are supported before finishing + * the synchronization operation */ private static final int MAX_FAILED_RESULTS = 3; - public static final String EVENT_FULL_SYNC_START = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_START"; - public static final String EVENT_FULL_SYNC_END = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_END"; - public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED"; - //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED = FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED"; + public static final String EVENT_FULL_SYNC_START = FileSyncAdapter.class.getName() + + ".EVENT_FULL_SYNC_START"; + public static final String EVENT_FULL_SYNC_END = FileSyncAdapter.class.getName() + + ".EVENT_FULL_SYNC_END"; + public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED = + FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED"; + //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED = + // FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED"; - public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() + ".EXTRA_ACCOUNT_NAME"; - public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() + ".EXTRA_FOLDER_PATH"; + public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() + + ".EXTRA_ACCOUNT_NAME"; + public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() + + ".EXTRA_FOLDER_PATH"; public static final String EXTRA_RESULT = FileSyncAdapter.class.getName() + ".EXTRA_RESULT"; @@ -86,7 +93,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { /** Flag made 'true' when a request to cancel the synchronization is received */ private boolean mCancellation; - /** When 'true' the process was requested by the user through the user interface; when 'false', it was requested automatically by the system */ + /** When 'true' the process was requested by the user through the user interface; + * when 'false', it was requested automatically by the system */ private boolean mIsManualSync; /** Counter for failed operations in the synchronization process */ @@ -101,7 +109,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { /** Counter of failed operations in synchronization of kept-in-sync files */ private int mFailsInFavouritesFound; - /** Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and couldn't be copied automatically into it */ + /** Map of remote and local paths to files that where locally stored in a location out + * of the ownCloud folder and couldn't be copied automatically into it */ private Map mForgottenLocalFiles; /** {@link SyncResult} instance to return to the system when the synchronization finish */ @@ -157,19 +166,22 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { try { this.initClientForCurrentAccount(); } catch (IOException e) { - /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again + /// the account is unknown for the Synchronization Manager, unreachable this context, + // or can not be authenticated; don't try this again mSyncResult.tooManyRetries = true; notifyFailedSynchronization(); return; } catch (AccountsException e) { - /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again + /// the account is unknown for the Synchronization Manager, unreachable this context, + // or can not be authenticated; don't try this again mSyncResult.tooManyRetries = true; notifyFailedSynchronization(); return; } Log_OC.d(TAG, "Synchronization of ownCloud account " + account.name + " starting"); - sendLocalBroadcast(EVENT_FULL_SYNC_START, null, null); // message to signal the start of the synchronization to the UI + sendLocalBroadcast(EVENT_FULL_SYNC_START, null, null); // message to signal the start + // of the synchronization to the UI try { updateOCVersion(); @@ -178,16 +190,19 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { synchronizeFolder(getStorageManager().getFileByPath(OCFile.ROOT_PATH)); } else { - Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder because cancelation request"); + Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder " + + "because cancelation request"); } } finally { - // it's important making this although very unexpected errors occur; that's the reason for the finally + // it's important making this although very unexpected errors occur; + // that's the reason for the finally if (mFailedResultsCounter > 0 && mIsManualSync) { /// don't let the system synchronization manager retries MANUAL synchronizations - // (be careful: "MANUAL" currently includes the synchronization requested when a new account is created and when the user changes the current account) + // (be careful: "MANUAL" currently includes the synchronization requested when + // a new account is created and when the user changes the current account) mSyncResult.tooManyRetries = true; /// notify the user about the failure of MANUAL synchronization @@ -199,7 +214,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { if (mForgottenLocalFiles.size() > 0) { notifyForgottenLocalFiles(); } - sendLocalBroadcast(EVENT_FULL_SYNC_END, null, mLastFailedResult); // message to signal the end to the UI + sendLocalBroadcast(EVENT_FULL_SYNC_END, null, mLastFailedResult); // message to signal + // the end to the UI } } @@ -212,7 +228,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { * locally saved. * * See {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)} - * and {@link #synchronizeFolder(String, long)}. + * and {@link #synchronizeFolder(OCFile)}. */ @Override public void onSyncCanceled() { @@ -263,13 +279,14 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } */ // folder synchronization - SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation( folder, - mCurrentSyncTime, - true, - mIsShareSupported, - getStorageManager(), - getAccount(), - getContext() + RefreshFolderOperation synchFolderOp = new RefreshFolderOperation( folder, + mCurrentSyncTime, + true, + mIsShareSupported, + false, + getStorageManager(), + getAccount(), + getContext() ); RemoteOperationResult result = synchFolderOp.execute(getClient()); @@ -290,15 +307,15 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { if (result.isSuccess()) { // synchronize children folders List children = synchFolderOp.getChildren(); - fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged()); // beware of the 'hidden' recursion here! + // beware of the 'hidden' recursion here! + fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged()); } } else { // in failures, the statistics for the global result are updated - if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED || - ( result.isIdPRedirection() && - getClient().getCredentials() == null )) { - //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) { + if ( result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED || + result.isIdPRedirection() + ) { mSyncResult.stats.numAuthExceptions++; } else if (result.getException() instanceof DavException) { @@ -314,11 +331,12 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } /** - * Checks if a failed result should terminate the synchronization process immediately, according to - * OUR OWN POLICY + * Checks if a failed result should terminate the synchronization process immediately, + * according to OUR OWN POLICY * * @param failedResult Remote operation result to check. - * @return 'True' if the result should immediately finish the synchronization + * @return 'True' if the result should immediately finish the + * synchronization */ private boolean isFinisher(RemoteOperationResult failedResult) { if (failedResult != null) { @@ -349,23 +367,29 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { syncDown = (parentEtagChanged || etag == null || etag.length() == 0); if(syncDown) { */ synchronizeFolder(newFile); - //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(), null); + //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(), + // null); //} } } - if (mCancellation && i 0) { - Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis()); - notification.flags |= Notification.FLAG_AUTO_CANCEL; + NotificationCompat.Builder notificationBuilder = createNotificationBuilder(); + notificationBuilder.setTicker(i18n(R.string.sync_fail_in_favourites_ticker)); + // TODO put something smart in the contentIntent below - notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); - notification.setLatestEventInfo(getContext().getApplicationContext(), - getContext().getString(R.string.sync_fail_in_favourites_ticker), - String.format(getContext().getString(R.string.sync_fail_in_favourites_content), mFailedResultsCounter + mConflictsFound, mConflictsFound), - notification.contentIntent); - ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification); + notificationBuilder + .setContentIntent(PendingIntent.getActivity( + getContext(), (int) System.currentTimeMillis(), new Intent(), 0 + )) + .setContentTitle(i18n(R.string.sync_fail_in_favourites_ticker)) + .setContentText(i18n(R.string.sync_fail_in_favourites_content, + mFailedResultsCounter + mConflictsFound, mConflictsFound)); + showNotification(R.string.sync_fail_in_favourites_ticker, notificationBuilder); } else { - Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis()); - notification.flags |= Notification.FLAG_AUTO_CANCEL; + NotificationCompat.Builder notificationBuilder = createNotificationBuilder(); + notificationBuilder.setTicker(i18n(R.string.sync_conflicts_in_favourites_ticker)); + // TODO put something smart in the contentIntent below - notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); - notification.setLatestEventInfo(getContext().getApplicationContext(), - getContext().getString(R.string.sync_conflicts_in_favourites_ticker), - String.format(getContext().getString(R.string.sync_conflicts_in_favourites_content), mConflictsFound), - notification.contentIntent); - ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_conflicts_in_favourites_ticker, notification); + notificationBuilder + .setContentIntent(PendingIntent.getActivity( + getContext(), (int) System.currentTimeMillis(), new Intent(), 0 + )) + .setContentTitle(i18n(R.string.sync_conflicts_in_favourites_ticker)) + .setContentText(i18n(R.string.sync_conflicts_in_favourites_ticker, mConflictsFound)); + + showNotification(R.string.sync_conflicts_in_favourites_ticker, notificationBuilder); } } /** - * Notifies the user about local copies of files out of the ownCloud local directory that were 'forgotten' because - * copying them inside the ownCloud local directory was not possible. + * Notifies the user about local copies of files out of the ownCloud local directory that + * were 'forgotten' because copying them inside the ownCloud local directory was not possible. * - * We don't want links to files out of the ownCloud local directory (foreign files) anymore. It's easy to have - * synchronization problems if a local file is linked to more than one remote file. + * We don't want links to files out of the ownCloud local directory (foreign files) anymore. + * It's easy to have synchronization problems if a local file is linked to more than one + * remote file. * - * We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory. + * We won't consider a synchronization as failed when foreign files can not be copied to + * the ownCloud local directory. */ private void notifyForgottenLocalFiles() { - Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis()); - notification.flags |= Notification.FLAG_AUTO_CANCEL; - + NotificationCompat.Builder notificationBuilder = createNotificationBuilder(); + notificationBuilder.setTicker(i18n(R.string.sync_foreign_files_forgotten_ticker)); + /// includes a pending intent in the notification showing a more detailed explanation Intent explanationIntent = new Intent(getContext(), ErrorsWhileCopyingHandlerActivity.class); explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_ACCOUNT, getAccount()); @@ -474,14 +507,46 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_REMOTE_PATHS, remotePaths); explanationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), explanationIntent, 0); - notification.setLatestEventInfo(getContext().getApplicationContext(), - getContext().getString(R.string.sync_foreign_files_forgotten_ticker), - String.format(getContext().getString(R.string.sync_foreign_files_forgotten_content), mForgottenLocalFiles.size(), getContext().getString(R.string.app_name)), - notification.contentIntent); - ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_foreign_files_forgotten_ticker, notification); + notificationBuilder + .setContentIntent(PendingIntent.getActivity( + getContext(), (int) System.currentTimeMillis(), explanationIntent, 0 + )) + .setContentTitle(i18n(R.string.sync_foreign_files_forgotten_ticker)) + .setContentText(i18n(R.string.sync_foreign_files_forgotten_content, + mForgottenLocalFiles.size(), i18n(R.string.app_name))); + showNotification(R.string.sync_foreign_files_forgotten_ticker, notificationBuilder); } + /** + * Creates a notification builder with some commonly used settings + * + * @return + */ + private NotificationCompat.Builder createNotificationBuilder() { + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext()); + notificationBuilder.setSmallIcon(R.drawable.notification_icon).setAutoCancel(true); + return notificationBuilder; + } + /** + * Builds and shows the notification + * + * @param id + * @param builder + */ + private void showNotification(int id, NotificationCompat.Builder builder) { + ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)) + .notify(id, builder.build()); + } + /** + * Shorthand translation + * + * @param key + * @param args + * @return + */ + private String i18n(int key, Object... args) { + return getContext().getString(key, args); + } }