com.owncloud.android.services.AdvancedFileAlterationListener.java Source code

Java tutorial

Introduction

Here is the source code for com.owncloud.android.services.AdvancedFileAlterationListener.java

Source

/**
 * 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.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.datamodel.SyncedFolder;
import com.owncloud.android.lib.common.utils.Log_OC;
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 SyncedFolder syncedFolder;

    private Map<String, Runnable> uploadMap = new HashMap<>();
    private Handler handler = new Handler();

    public AdvancedFileAlterationListener(SyncedFolder syncedFolder) {
        super();

        context = MainApp.getAppContext();
        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() {
                    PersistableBundleCompat bundle = new PersistableBundleCompat();
                    bundle.putString(AutoUploadJob.LOCAL_PATH, file.getAbsolutePath());
                    bundle.putString(AutoUploadJob.REMOTE_PATH,
                            FileStorageUtils.getInstantUploadFilePath(currentLocale, syncedFolder.getRemotePath(),
                                    file.getName(), finalLastModificationTime, syncedFolder.getSubfolderByDate()));
                    bundle.putString(AutoUploadJob.ACCOUNT, syncedFolder.getAccount());
                    bundle.putInt(AutoUploadJob.UPLOAD_BEHAVIOUR, syncedFolder.getUploadAction());

                    new JobRequest.Builder(AutoUploadJob.TAG).setExecutionWindow(30_000L, 80_000L)
                            .setRequiresCharging(syncedFolder.getChargingOnly())
                            .setRequiredNetworkType(syncedFolder.getWifiOnly() ? 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);
        }
    }

    @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();
    }
}