123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /**
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- * Copyright (C) 2017 Nextcloud
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * 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.
- *
- * 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.utils;
- import android.accounts.Account;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.database.Cursor;
- import android.net.Uri;
- import android.provider.MediaStore;
- import android.text.TextUtils;
- import android.util.Log;
- import com.evernote.android.job.JobManager;
- import com.evernote.android.job.JobRequest;
- import com.evernote.android.job.util.Device;
- import com.owncloud.android.MainApp;
- import com.owncloud.android.authentication.AccountUtils;
- import com.owncloud.android.datamodel.ArbitraryDataProvider;
- import com.owncloud.android.datamodel.FilesystemDataProvider;
- import com.owncloud.android.datamodel.MediaFolder;
- import com.owncloud.android.datamodel.SyncedFolder;
- import com.owncloud.android.datamodel.SyncedFolderProvider;
- import com.owncloud.android.datamodel.UploadsStorageManager;
- import com.owncloud.android.db.OCUpload;
- import com.owncloud.android.db.UploadResult;
- import com.owncloud.android.files.services.FileUploader;
- import com.owncloud.android.jobs.AutoUploadJob;
- import com.owncloud.android.operations.UploadFileOperation;
- import org.lukhnos.nnio.file.FileVisitResult;
- import org.lukhnos.nnio.file.Files;
- import org.lukhnos.nnio.file.Path;
- import org.lukhnos.nnio.file.Paths;
- import org.lukhnos.nnio.file.SimpleFileVisitor;
- import org.lukhnos.nnio.file.attribute.BasicFileAttributes;
- import java.io.File;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- import java.nio.channels.FileChannel;
- import java.nio.channels.FileLock;
- import java.nio.channels.OverlappingFileLockException;
- public class FilesSyncHelper {
- public static final String TAG = "FileSyncHelper";
- public static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) {
- final Context context = MainApp.getAppContext();
- final ContentResolver contentResolver = context.getContentResolver();
- ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver);
- String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + syncedFolder.getId();
- boolean dryRun = TextUtils.isEmpty(arbitraryDataProvider.getValue
- ("global", syncedFolderInitiatedKey));
- if (MediaFolder.IMAGE == syncedFolder.getType()) {
- FilesSyncHelper.insertContentIntoDB(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI
- , dryRun, syncedFolder);
- FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, dryRun,
- syncedFolder);
- if (dryRun) {
- arbitraryDataProvider.storeOrUpdateKeyValue("global", syncedFolderInitiatedKey,
- "1");
- }
- } else if (MediaFolder.VIDEO == syncedFolder.getType()) {
- FilesSyncHelper.insertContentIntoDB(android.provider.MediaStore.Video.Media.INTERNAL_CONTENT_URI,
- dryRun, syncedFolder);
- FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, dryRun,
- syncedFolder);
- if (dryRun) {
- arbitraryDataProvider.storeOrUpdateKeyValue("global", syncedFolderInitiatedKey,
- "1");
- }
- } else {
- try {
- FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
- Path path = Paths.get(syncedFolder.getLocalPath());
- Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
- File file = path.toFile();
- FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
- FileLock lock = channel.lock();
- try {
- lock = channel.tryLock();
- filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(),
- attrs.lastModifiedTime().toMillis(), file.isDirectory(), syncedFolder, dryRun);
- } catch (OverlappingFileLockException e) {
- filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(),
- attrs.lastModifiedTime().toMillis(), file.isDirectory(), syncedFolder, dryRun);
- } finally {
- lock.release();
- }
- return FileVisitResult.CONTINUE;
- }
- @Override
- public FileVisitResult visitFileFailed(Path file, IOException exc) {
- return FileVisitResult.CONTINUE;
- }
- });
- if (dryRun) {
- arbitraryDataProvider.storeOrUpdateKeyValue("global", syncedFolderInitiatedKey,
- "1");
- }
- } catch (IOException e) {
- Log.d(TAG, "Something went wrong while indexing files for auto upload");
- }
- }
- }
- public static void insertAllDBEntries() {
- final Context context = MainApp.getAppContext();
- final ContentResolver contentResolver = context.getContentResolver();
- SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver);
- for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
- if (syncedFolder.isEnabled()) {
- insertAllDBEntriesForSyncedFolder(syncedFolder);
- }
- }
- }
- private static void insertContentIntoDB(Uri uri, boolean dryRun, SyncedFolder syncedFolder) {
- final Context context = MainApp.getAppContext();
- final ContentResolver contentResolver = context.getContentResolver();
- Cursor cursor;
- int column_index_data;
- int column_index_date_modified;
- final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
- String contentPath;
- boolean isFolder;
- String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DATE_MODIFIED};
- String path = syncedFolder.getLocalPath();
- if (!path.endsWith("/")) {
- path = path + "/%";
- } else {
- path = path + "%";
- }
- cursor = context.getContentResolver().query(uri, projection, MediaStore.MediaColumns.DATA + " LIKE ?",
- new String[]{path}, null);
- if (cursor != null) {
- column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
- column_index_date_modified = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED);
- while (cursor.moveToNext()) {
- contentPath = cursor.getString(column_index_data);
- isFolder = new File(contentPath).isDirectory();
- filesystemDataProvider.storeOrUpdateFileValue(cursor.getString(column_index_data),
- cursor.getLong(column_index_date_modified), isFolder, syncedFolder, dryRun);
- }
- cursor.close();
- }
- }
- public static void restartJobsIfNeeded() {
- final Context context = MainApp.getAppContext();
- boolean restartedInCurrentIteration;
- int countRestartedJobs = 0;
- FileUploader.UploadRequester uploadRequester = new FileUploader.UploadRequester();
- boolean accountExists;
- boolean fileExists;
- for (JobRequest jobRequest : JobManager.instance().getAllJobRequestsForTag(AutoUploadJob.TAG)) {
- restartedInCurrentIteration = false;
- accountExists = false;
- fileExists = new File(jobRequest.getExtras().getString(AutoUploadJob.LOCAL_PATH, "")).exists();
- // check if accounts still exists
- for (Account account : AccountUtils.getAccounts(context)) {
- if (account.name.equals(jobRequest.getExtras().getString(AutoUploadJob.ACCOUNT, ""))) {
- accountExists = true;
- break;
- }
- }
- if (accountExists && fileExists) {
- if (countRestartedJobs < 5) {
- // Handle case of charging
- if (jobRequest.requiresCharging() && Device.isCharging(context)) {
- if (jobRequest.requiredNetworkType().equals(JobRequest.NetworkType.CONNECTED) &&
- !Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
- jobRequest.cancelAndEdit().build().schedule();
- countRestartedJobs++;
- restartedInCurrentIteration = true;
- } else if (jobRequest.requiredNetworkType().equals(JobRequest.NetworkType.UNMETERED) &&
- Device.getNetworkType(context).equals(JobRequest.NetworkType.UNMETERED)) {
- jobRequest.cancelAndEdit().build().schedule();
- countRestartedJobs++;
- restartedInCurrentIteration = true;
- }
- }
- // Handle case of wifi
- if (!restartedInCurrentIteration) {
- if (jobRequest.requiredNetworkType().equals(JobRequest.NetworkType.CONNECTED) &&
- !Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
- jobRequest.cancelAndEdit().build().schedule();
- countRestartedJobs++;
- } else if (jobRequest.requiredNetworkType().equals(JobRequest.NetworkType.UNMETERED) &&
- Device.getNetworkType(context).equals(JobRequest.NetworkType.UNMETERED)) {
- jobRequest.cancelAndEdit().build().schedule();
- countRestartedJobs++;
- }
- }
- }
- } else {
- JobManager.instance().cancel(jobRequest.getJobId());
- }
- }
- UploadsStorageManager uploadsStorageManager = new UploadsStorageManager(context.getContentResolver(), context);
- OCUpload[] failedUploads = uploadsStorageManager.getFailedUploads();
- for (OCUpload failedUpload: failedUploads) {
- accountExists = false;
- fileExists = new File(failedUpload.getLocalPath()).exists();
- restartedInCurrentIteration = false;
- // check if accounts still exists
- for (Account account : AccountUtils.getAccounts(context)) {
- if (account.name.equals(failedUpload.getAccountName())) {
- accountExists = true;
- break;
- }
- }
- if (!failedUpload.getLastResult().equals(UploadResult.UPLOADED)) {
- if (failedUpload.getCreadtedBy() == UploadFileOperation.CREATED_AS_INSTANT_PICTURE) {
- if (accountExists && fileExists) {
- if (countRestartedJobs < 5) {
- // Handle case of charging
- if (failedUpload.isWhileChargingOnly() && Device.isCharging(context)) {
- if (failedUpload.isUseWifiOnly() &&
- Device.getNetworkType(context).equals(JobRequest.NetworkType.UNMETERED)) {
- uploadRequester.retry(context, failedUpload);
- restartedInCurrentIteration = true;
- countRestartedJobs++;
- } else if (!failedUpload.isUseWifiOnly() &&
- !Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
- uploadRequester.retry(context, failedUpload);
- restartedInCurrentIteration = true;
- countRestartedJobs++;
- }
- }
- // Handle case of wifi
- if (!restartedInCurrentIteration) {
- if (failedUpload.isUseWifiOnly() &&
- Device.getNetworkType(context).equals(JobRequest.NetworkType.UNMETERED)) {
- uploadRequester.retry(context, failedUpload);
- countRestartedJobs++;
- } else if (!failedUpload.isUseWifiOnly() &&
- !Device.getNetworkType(context).equals(JobRequest.NetworkType.ANY)) {
- uploadRequester.retry(context, failedUpload);
- countRestartedJobs++;
- }
- }
- }
- } else {
- uploadsStorageManager.removeUpload(failedUpload);
- }
- } else {
- if (accountExists && fileExists) {
- if (countRestartedJobs < 5) {
- uploadRequester.retry(context, failedUpload);
- countRestartedJobs++;
- }
- } else {
- uploadsStorageManager.removeUpload(failedUpload);
- }
- }
- }
- }
- }
- }
|