Clean up code

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2017-05-05 20:38:49 +02:00 committed by AndyScherzinger
parent 5701d3bd13
commit 0bae6fcfb2
No known key found for this signature in database
GPG key ID: 6CADC7E3523C308B
6 changed files with 2 additions and 877 deletions

View file

@ -131,7 +131,7 @@
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<service android:name=".services.observer.SyncedFolderObserverService"/>
<service
android:name=".syncadapter.FileSyncService"
android:exported="true" >

View file

@ -20,16 +20,12 @@
package com.owncloud.android;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.support.multidex.MultiDexApplication;
import android.support.v4.util.Pair;
@ -39,11 +35,10 @@ import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.jobs.NCJobCreator;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.jobs.NCJobCreator;
import com.owncloud.android.services.observer.SyncedFolderObserverService;
import com.owncloud.android.ui.activity.Preferences;
import com.owncloud.android.ui.activity.WhatsNewActivity;
import com.owncloud.android.utils.AnalyticsUtils;
@ -79,8 +74,6 @@ public class MainApp extends MultiDexApplication {
private static boolean mOnlyOnDevice = false;
private static SyncedFolderObserverService mObserverService;
@SuppressWarnings("unused")
private boolean mBound;
@ -121,12 +114,6 @@ public class MainApp extends MultiDexApplication {
cleanOldEntries();
updateAutoUploadEntries();
Log_OC.d("SyncedFolderObserverService", "Start service SyncedFolderObserverService");
Intent i = new Intent(this, SyncedFolderObserverService.class);
startService(i);
bindService(i, syncedFolderObserverServiceConnection, Context.BIND_AUTO_CREATE);
// register global protection with pass code
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@ -245,10 +232,6 @@ public class MainApp extends MultiDexApplication {
return mOnlyOnDevice;
}
public static SyncedFolderObserverService getSyncedFolderObserverService() {
return mObserverService;
}
// user agent
public static String getUserAgent() {
String appString = getAppContext().getResources().getString(R.string.user_agent);
@ -313,24 +296,4 @@ public class MainApp extends MultiDexApplication {
}
}
}
/**
* Defines callbacks for service binding, passed to bindService()
*/
private ServiceConnection syncedFolderObserverServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
SyncedFolderObserverService.SyncedFolderObserverBinder binder =
(SyncedFolderObserverService.SyncedFolderObserverBinder) service;
mObserverService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

View file

@ -27,7 +27,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import com.owncloud.android.MainApp;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.lib.common.utils.Log_OC;
@ -71,7 +70,6 @@ public class SyncedFolderProvider extends Observable {
Uri result = mContentResolver.insert(ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, cv);
if (result != null) {
notifyFolderSyncObservers(syncedFolder);
return Long.parseLong(result.getPathSegments().get(1));
} else {
Log_OC.e(TAG, "Failed to insert item " + syncedFolder.getLocalPath() + " into folder sync db.");
@ -299,10 +297,6 @@ public class SyncedFolderProvider extends Observable {
new String[]{String.valueOf(syncedFolder.getId())}
);
if (result > 0) {
notifyFolderSyncObservers(syncedFolder);
}
return result;
}
@ -362,16 +356,4 @@ public class SyncedFolderProvider extends Observable {
return cv;
}
/**
* Inform all observers about data change.
*
* @param syncedFolder changed, synchronized folder
*/
private void notifyFolderSyncObservers(SyncedFolder syncedFolder) {
if (syncedFolder != null) {
MainApp.getSyncedFolderObserverService().restartObserver(syncedFolder);
Log_OC.d(TAG, "notifying folder sync data observers for changed/added: " + syncedFolder.getLocalPath());
}
}
}

View file

@ -1,238 +0,0 @@
/**
* Nextcloud Android client application
*
* @author Mario Danic
* Copyright (C) 2017 Mario Danic
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* <p>
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.services;
import android.content.Context;
import android.content.res.Resources;
import android.media.ExifInterface;
import android.os.Handler;
import android.text.TextUtils;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.jobs.AutoUploadJob;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.Preferences;
import com.owncloud.android.utils.FileStorageUtils;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationObserver;
import java.io.File;
import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
/**
* Magical file alteration listener
*/
public class AdvancedFileAlterationListener implements FileAlterationListener {
public static final String TAG = "AdvancedFileAlterationListener";
public static final int DELAY_INVOCATION_MS = 2500;
private Context context;
private boolean lightVersion;
private SyncedFolder syncedFolder;
private Map<String, Runnable> uploadMap = new HashMap<>();
private Handler handler = new Handler();
public AdvancedFileAlterationListener(SyncedFolder syncedFolder, boolean lightVersion) {
super();
context = MainApp.getAppContext();
this.lightVersion = lightVersion;
this.syncedFolder = syncedFolder;
}
@Override
public void onStart(FileAlterationObserver observer) {
// This method is intentionally empty
}
@Override
public void onDirectoryCreate(File directory) {
// This method is intentionally empty
}
@Override
public void onDirectoryChange(File directory) {
// This method is intentionally empty
}
@Override
public void onDirectoryDelete(File directory) {
// This method is intentionally empty
}
@Override
public void onFileCreate(final File file) {
onFileCreate(file, DELAY_INVOCATION_MS);
}
public void onFileCreate(final File file, int delay) {
if (file != null) {
uploadMap.put(file.getAbsolutePath(), null);
String mimetypeString = FileStorageUtils.getMimeTypeFromName(file.getAbsolutePath());
Long lastModificationTime = file.lastModified();
final Locale currentLocale = context.getResources().getConfiguration().locale;
if ("image/jpeg".equalsIgnoreCase(mimetypeString) || "image/tiff".equalsIgnoreCase(mimetypeString)) {
try {
ExifInterface exifInterface = new ExifInterface(file.getAbsolutePath());
String exifDate = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
if (!TextUtils.isEmpty(exifDate)) {
ParsePosition pos = new ParsePosition(0);
SimpleDateFormat sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", currentLocale);
sFormatter.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getID()));
Date dateTime = sFormatter.parse(exifDate, pos);
lastModificationTime = dateTime.getTime();
}
} catch (IOException e) {
Log_OC.d(TAG, "Failed to get the proper time " + e.getLocalizedMessage());
}
}
final Long finalLastModificationTime = lastModificationTime;
Runnable runnable = new Runnable() {
@Override
public void run() {
String remotePath;
boolean subfolderByDate;
boolean chargingOnly;
boolean wifiOnly;
Integer uploadAction;
String accountName = syncedFolder.getAccount();
if (lightVersion) {
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context
.getContentResolver());
Resources resources = MainApp.getAppContext().getResources();
remotePath = resources.getString(R.string.syncedFolder_remote_folder) + OCFile.PATH_SEPARATOR +
new File(syncedFolder.getLocalPath()).getName() + OCFile.PATH_SEPARATOR;
subfolderByDate = resources.getBoolean(R.bool.syncedFolder_light_use_subfolders);
chargingOnly = resources.getBoolean(R.bool.syncedFolder_light_on_charging);
wifiOnly = arbitraryDataProvider.getBooleanValue(accountName,
Preferences.SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI);
String uploadActionString = resources.getString(R.string.syncedFolder_light_upload_behaviour);
uploadAction = getUploadAction(uploadActionString);
} else {
remotePath = syncedFolder.getRemotePath();
subfolderByDate = syncedFolder.getSubfolderByDate();
chargingOnly = syncedFolder.getChargingOnly();
wifiOnly = syncedFolder.getWifiOnly();
uploadAction = syncedFolder.getUploadAction();
}
PersistableBundleCompat bundle = new PersistableBundleCompat();
bundle.putString(AutoUploadJob.LOCAL_PATH, file.getAbsolutePath());
bundle.putString(AutoUploadJob.REMOTE_PATH, FileStorageUtils.getInstantUploadFilePath(
currentLocale,
remotePath, file.getName(),
finalLastModificationTime,
subfolderByDate));
bundle.putString(AutoUploadJob.ACCOUNT, accountName);
bundle.putInt(AutoUploadJob.UPLOAD_BEHAVIOUR, uploadAction);
new JobRequest.Builder(AutoUploadJob.TAG)
.setExecutionWindow(30_000L, 80_000L)
.setRequiresCharging(chargingOnly)
.setRequiredNetworkType(wifiOnly ? JobRequest.NetworkType.UNMETERED :
JobRequest.NetworkType.ANY)
.setExtras(bundle)
.setPersisted(false)
.setRequirementsEnforced(true)
.setUpdateCurrent(false)
.build()
.schedule();
uploadMap.remove(file.getAbsolutePath());
}
};
uploadMap.put(file.getAbsolutePath(), runnable);
handler.postDelayed(runnable, delay);
}
}
private Integer getUploadAction(String action) {
switch (action) {
case "LOCAL_BEHAVIOUR_FORGET":
return FileUploader.LOCAL_BEHAVIOUR_FORGET;
case "LOCAL_BEHAVIOUR_MOVE":
return FileUploader.LOCAL_BEHAVIOUR_MOVE;
case "LOCAL_BEHAVIOUR_DELETE":
return FileUploader.LOCAL_BEHAVIOUR_DELETE;
default:
return FileUploader.LOCAL_BEHAVIOUR_FORGET;
}
}
@Override
public void onFileChange(File file) {
onFileChange(file, 2500);
}
public void onFileChange(File file, int delay) {
Runnable runnable;
if ((runnable = uploadMap.get(file.getAbsolutePath())) != null) {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, delay);
}
}
@Override
public void onFileDelete(File file) {
Runnable runnable;
if ((runnable = uploadMap.get(file.getAbsolutePath())) != null) {
handler.removeCallbacks(runnable);
uploadMap.remove(file.getAbsolutePath());
}
}
@Override
public void onStop(FileAlterationObserver observer) {
// This method is intentionally empty
}
public int getActiveTasksCount() {
return uploadMap.size();
}
}

View file

@ -1,402 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Original source code:
* https://github.com/apache/commons-io/blob/master/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
*
* Modified by Mario Danic
* Changes are Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud GmbH
*
* All changes are under the same licence as the original.
*
*/
package com.owncloud.android.services.observer;
import android.os.SystemClock;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.services.AdvancedFileAlterationListener;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.comparator.NameFileComparator;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.io.monitor.FileEntry;
import java.io.File;
import java.io.FileFilter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class AdvancedFileAlterationObserver extends FileAlterationObserver implements Serializable {
private static final long serialVersionUID = 1185122225658782848L;
private static final int DELAY_INVOCATION_MS = 2500;
private final List<AdvancedFileAlterationListener> listeners = new CopyOnWriteArrayList<>();
private FileEntry rootEntry;
private FileFilter fileFilter;
private Comparator<File> comparator;
private SyncedFolder syncedFolder;
private static final FileEntry[] EMPTY_ENTRIES = new FileEntry[0];
public AdvancedFileAlterationObserver(SyncedFolder syncedFolder, FileFilter fileFilter) {
super(syncedFolder.getLocalPath(), fileFilter);
this.rootEntry = new FileEntry(new File(syncedFolder.getLocalPath()));
this.fileFilter = fileFilter;
this.syncedFolder = syncedFolder;
comparator = NameFileComparator.NAME_SYSTEM_COMPARATOR;
}
public long getSyncedFolderID() {
return syncedFolder.getId();
}
public SyncedFolder getSyncedFolder() {
return syncedFolder;
}
/**
* Return the directory being observed.
*
* @return the directory being observed
*/
public File getDirectory() {
return rootEntry.getFile();
}
/**
* Return the fileFilter.
*
* @return the fileFilter
* @since 2.1
*/
public FileFilter getFileFilter() {
return fileFilter;
}
public FileEntry getRootEntry() {
return rootEntry;
}
public void setRootEntry(FileEntry rootEntry) {
this.rootEntry = rootEntry;
}
/**
* Add a file system listener.
*
* @param listener The file system listener
*/
public void addListener(final AdvancedFileAlterationListener listener) {
if (listener != null) {
listeners.add(listener);
}
}
/**
* Remove a file system listener.
*
* @param listener The file system listener
*/
public void removeListener(final AdvancedFileAlterationListener listener) {
if (listener != null) {
while (listeners.remove(listener)) {
}
}
}
/**
* Returns the set of registered file system listeners.
*
* @return The file system listeners
*/
public Iterable<AdvancedFileAlterationListener> getMagicListeners() {
return listeners;
}
/**
* Does nothing - hack for the monitor
*
*
*/
public void initialize() {
// does nothing - hack the monitor
}
/**
* Initializes everything
*
* @throws Exception if an error occurs
*/
public void init() throws Exception {
rootEntry.refresh(rootEntry.getFile());
final FileEntry[] children = doListFiles(rootEntry.getFile(), rootEntry);
rootEntry.setChildren(children);
}
/**
* Final processing.
*
* @throws Exception if an error occurs
*/
public void destroy() throws Exception {
Iterator iterator = getMagicListeners().iterator();
while (iterator.hasNext()) {
AdvancedFileAlterationListener AdvancedFileAlterationListener = (AdvancedFileAlterationListener) iterator.next();
while (AdvancedFileAlterationListener.getActiveTasksCount() > 0) {
SystemClock.sleep(250);
}
}
}
public void checkAndNotifyNow() {
/* fire onStart() */
for (final AdvancedFileAlterationListener listener : listeners) {
listener.onStart(this);
}
/* fire directory/file events */
final File rootFile = rootEntry.getFile();
if (rootFile.exists()) {
checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootFile), 0);
} else if (rootEntry.isExists()) {
try {
// try to init once more
init();
if (rootEntry.getFile().exists()) {
checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootEntry.getFile()), 0);
} else {
checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY, 0);
}
} catch (Exception e) {
Log_OC.d("AdvancedFileAlterationObserver", "Failed getting an observer to intialize " + e);
checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY, 0);
}
} // else didn't exist and still doesn't
/* fire onStop() */
for (final AdvancedFileAlterationListener listener : listeners) {
listener.onStop(this);
}
}
/**
* Check whether the file and its children have been created, modified or deleted.
*/
public void checkAndNotify() {
/* fire onStart() */
for (final AdvancedFileAlterationListener listener : listeners) {
listener.onStart(this);
}
/* fire directory/file events */
final File rootFile = rootEntry.getFile();
if (rootFile.exists()) {
checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootFile), DELAY_INVOCATION_MS);
} else if (rootEntry.isExists()) {
try {
// try to init once more
init();
if (rootEntry.getFile().exists()) {
checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootEntry.getFile()),
DELAY_INVOCATION_MS);
} else {
checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY, DELAY_INVOCATION_MS);
}
} catch (Exception e) {
Log_OC.d("AdvancedFileAlterationObserver", "Failed getting an observer to intialize " + e);
checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY, DELAY_INVOCATION_MS);
}
} // else didn't exist and still doesn't
/* fire onStop() */
for (final AdvancedFileAlterationListener listener : listeners) {
listener.onStop(this);
}
}
/**
* Compare two file lists for files which have been created, modified or deleted.
*
* @param parent The parent entry
* @param previous The original list of files
* @param files The current list of files
*/
private void checkAndNotify(final FileEntry parent, final FileEntry[] previous, final File[] files, int delay) {
if (files != null && files.length > 0) {
int c = 0;
final FileEntry[] current = files.length > 0 ? new FileEntry[files.length] : EMPTY_ENTRIES;
for (final FileEntry entry : previous) {
while (c < files.length && comparator.compare(entry.getFile(), files[c]) > 0) {
current[c] = createFileEntry(parent, files[c]);
doCreate(current[c], delay);
c++;
}
if (c < files.length && comparator.compare(entry.getFile(), files[c]) == 0) {
doMatch(entry, files[c], delay);
checkAndNotify(entry, entry.getChildren(), listFiles(files[c]), delay);
current[c] = entry;
c++;
} else {
checkAndNotify(entry, entry.getChildren(), FileUtils.EMPTY_FILE_ARRAY, delay);
doDelete(entry);
}
}
for (; c < files.length; c++) {
current[c] = createFileEntry(parent, files[c]);
doCreate(current[c], delay);
}
parent.setChildren(current);
}
}
/**
* Create a new file entry for the specified file.
*
* @param parent The parent file entry
* @param file The file to create an entry for
* @return A new file entry
*/
private FileEntry createFileEntry(final FileEntry parent, final File file) {
final FileEntry entry = parent.newChildInstance(file);
entry.refresh(file);
final FileEntry[] children = doListFiles(file, entry);
entry.setChildren(children);
return entry;
}
/**
* List the files
*
* @param file The file to list files for
* @param entry the parent entry
* @return The child files
*/
private FileEntry[] doListFiles(File file, FileEntry entry) {
final File[] files = listFiles(file);
final FileEntry[] children = files.length > 0 ? new FileEntry[files.length] : EMPTY_ENTRIES;
for (int i = 0; i < files.length; i++) {
children[i] = createFileEntry(entry, files[i]);
}
return children;
}
/**
* Fire directory/file created events to the registered listeners.
*
* @param entry The file entry
*/
private void doCreate(final FileEntry entry, int delay) {
for (final AdvancedFileAlterationListener listener : listeners) {
if (entry.isDirectory()) {
listener.onDirectoryCreate(entry.getFile());
} else {
listener.onFileCreate(entry.getFile(), delay);
}
}
final FileEntry[] children = entry.getChildren();
for (final FileEntry aChildren : children) {
doCreate(aChildren, delay);
}
}
/**
* Fire directory/file change events to the registered listeners.
*
* @param entry The previous file system entry
* @param file The current file
*/
private void doMatch(final FileEntry entry, final File file, int delay) {
if (entry.refresh(file)) {
for (final AdvancedFileAlterationListener listener : listeners) {
if (entry.isDirectory()) {
listener.onDirectoryChange(file);
} else {
listener.onFileChange(file, delay);
}
}
}
}
/**
* Fire directory/file delete events to the registered listeners.
*
* @param entry The file entry
*/
private void doDelete(final FileEntry entry) {
for (final AdvancedFileAlterationListener listener : listeners) {
if (entry.isDirectory()) {
listener.onDirectoryDelete(entry.getFile());
} else {
listener.onFileDelete(entry.getFile());
}
}
}
/**
* List the contents of a directory
*
* @param file The file to list the contents of
* @return the directory contents or a zero length array if
* the empty or the file is not a directory
*/
private File[] listFiles(final File file) {
File[] children = null;
if (file.isDirectory()) {
children = fileFilter == null ? file.listFiles() : file.listFiles(fileFilter);
}
if (children == null) {
children = FileUtils.EMPTY_FILE_ARRAY;
}
if (comparator != null && children.length > 1) {
Arrays.sort(children, comparator);
}
return children;
}
/**
* Provide a String representation of this observer.
*
* @return a String representation of this observer
*/
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(getClass().getSimpleName());
builder.append("[file='");
builder.append(getDirectory().getPath());
builder.append('\'');
if (fileFilter != null) {
builder.append(", ");
builder.append(fileFilter.toString());
}
builder.append(", listeners=");
builder.append(listeners.size());
builder.append("]");
return builder.toString();
}
}

View file

@ -1,180 +0,0 @@
/**
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* @author Andy Scherzinger
* @author Mario Danic
* Copyright (C) 2016 Tobias Kaminsky, Andy Scherzinger
* Copyright (C) 2017 Mario Danic
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* <p>
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.services.observer;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.services.AdvancedFileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import java.io.File;
import java.io.FileFilter;
public class SyncedFolderObserverService extends Service {
private static final String TAG = "SyncedFolderObserverService";
private static final int MONITOR_SCAN_INTERVAL = 1000;
private final IBinder mBinder = new SyncedFolderObserverBinder();
private FileAlterationMonitor monitor;
private FileFilter fileFilter;
@Override
public void onCreate() {
SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(MainApp.getAppContext().
getContentResolver());
monitor = new FileAlterationMonitor(MONITOR_SCAN_INTERVAL);
fileFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return !pathname.getName().startsWith(".") && !pathname.getName().endsWith(".tmp") &&
!pathname.getName().endsWith(".temp") && !pathname.getName().endsWith(".thumbnail");
}
};
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled()) {
AdvancedFileAlterationObserver observer = new AdvancedFileAlterationObserver(syncedFolder, fileFilter);
try {
observer.init();
observer.addListener(new AdvancedFileAlterationListener(syncedFolder,
getResources().getBoolean(R.bool.syncedFolder_light)));
monitor.addObserver(observer);
} catch (Exception e) {
Log_OC.d(TAG, "Failed getting an observer to initialize " + e);
}
}
}
try {
monitor.start();
} catch (Exception e) {
Log_OC.d(TAG, "Something went very wrong at onStartCommand");
}
}
@Override
public void onDestroy() {
super.onDestroy();
for (FileAlterationObserver fileAlterationObserver : monitor.getObservers()) {
AdvancedFileAlterationObserver advancedFileAlterationObserver = (AdvancedFileAlterationObserver)
fileAlterationObserver;
try {
monitor.removeObserver(advancedFileAlterationObserver);
advancedFileAlterationObserver.checkAndNotifyNow();
advancedFileAlterationObserver.destroy();
} catch (Exception e) {
Log_OC.d(TAG, "Something went very wrong on trying to destroy observers");
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
/**
* Restart oberver if it is enabled
* If syncedFolder exists already, use it, otherwise create new observer
*
* @param syncedFolder
*/
public void restartObserver(SyncedFolder syncedFolder) {
boolean found = false;
AdvancedFileAlterationObserver advancedFileAlterationObserver;
for (FileAlterationObserver fileAlterationObserver : monitor.getObservers()) {
advancedFileAlterationObserver =
(AdvancedFileAlterationObserver) fileAlterationObserver;
if (advancedFileAlterationObserver.getSyncedFolderID() == syncedFolder.getId()) {
monitor.removeObserver(fileAlterationObserver);
advancedFileAlterationObserver.checkAndNotifyNow();
try {
advancedFileAlterationObserver.destroy();
} catch (Exception e) {
Log_OC.d(TAG, "Failed to destroy the observer in restart");
}
if (syncedFolder.isEnabled()) {
try {
advancedFileAlterationObserver = new AdvancedFileAlterationObserver(syncedFolder, fileFilter);
advancedFileAlterationObserver.init();
advancedFileAlterationObserver.addListener(new AdvancedFileAlterationListener(syncedFolder,
getResources().getBoolean(R.bool.syncedFolder_light)));
monitor.addObserver(advancedFileAlterationObserver);
} catch (Exception e) {
Log_OC.d(TAG, "Failed getting an observer to initialize");
}
} else {
monitor.removeObserver(fileAlterationObserver);
}
found = true;
break;
}
}
if (!found && syncedFolder.isEnabled()) {
try {
advancedFileAlterationObserver = new AdvancedFileAlterationObserver(syncedFolder, fileFilter);
advancedFileAlterationObserver.init();
advancedFileAlterationObserver.addListener(new AdvancedFileAlterationListener(syncedFolder,
getResources().getBoolean(R.bool.syncedFolder_light)));
monitor.addObserver(advancedFileAlterationObserver);
} catch (Exception e) {
Log_OC.d(TAG, "Failed getting an observer to initialize");
}
}
}
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class SyncedFolderObserverBinder extends Binder {
public SyncedFolderObserverService getService() {
return SyncedFolderObserverService.this;
}
}
}