From 1f8d5dddfe11ea636f03358f3549c32508e3ab91 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 14:04:01 +0200 Subject: [PATCH 01/20] Add support for detecting media folders Signed-off-by: Mario Danic --- .../java/com/owncloud/android/MainApp.java | 25 ++- .../android/datamodel/MediaFoldersModel.java | 50 ++++++ .../android/datamodel/MediaProvider.java | 12 +- .../datamodel/SyncedFolderProvider.java | 33 +++- .../jobs/MediaFoldersDetectionJob.java | 167 ++++++++++++++++++ .../owncloud/android/jobs/NCJobCreator.java | 2 + .../android/jobs/NContentObserverJob.java | 7 + .../ui/activity/SyncedFoldersActivity.java | 14 +- .../ui/notifications/NotificationUtils.java | 1 + src/main/res/values/strings.xml | 7 + 10 files changed, 307 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java create mode 100644 src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java index 9dcbc15dbfae..0e44857294eb 100644 --- a/src/main/java/com/owncloud/android/MainApp.java +++ b/src/main/java/com/owncloud/android/MainApp.java @@ -44,6 +44,7 @@ import android.view.WindowManager; import com.evernote.android.job.JobManager; +import com.evernote.android.job.JobRequest; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.authentication.PassCodeManager; import com.owncloud.android.datamodel.ArbitraryDataProvider; @@ -56,6 +57,7 @@ import com.owncloud.android.datastorage.DataStorageProvider; import com.owncloud.android.datastorage.StoragePoint; import com.owncloud.android.db.PreferenceManager; +import com.owncloud.android.jobs.MediaFoldersDetectionJob; import com.owncloud.android.jobs.NCJobCreator; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy; @@ -77,6 +79,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -164,6 +167,20 @@ public void onCreate() { initContactsBackup(); notificationChannels(); + + new JobRequest.Builder(MediaFoldersDetectionJob.TAG) + .setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5)) + .setUpdateCurrent(true) + .build() + .schedule(); + + new JobRequest.Builder(MediaFoldersDetectionJob.TAG) + .startNow() + .setUpdateCurrent(false) + .build() + .schedule(); + + // register global protection with pass code registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @@ -336,6 +353,10 @@ public static void notificationChannels() { createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_PUSH, R.string.notification_channel_push_name, R.string .notification_channel_push_description, context, NotificationManager.IMPORTANCE_DEFAULT); + + createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_GENERAL, R.string + .notification_channel_general_name, R.string.notification_channel_general_description, + context, NotificationManager.IMPORTANCE_DEFAULT); } else { Log_OC.e(TAG, "Notification manager is null"); } @@ -546,8 +567,8 @@ private static void splitOutAutoUploadEntries() { SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver); - final List imageMediaFolders = MediaProvider.getImageFolders(contentResolver, 1, null); - final List videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null); + final List imageMediaFolders = MediaProvider.getImageFolders(contentResolver, 1, null, true); + final List videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null, true); ArrayList idsToDelete = new ArrayList<>(); List syncedFolders = syncedFolderProvider.getSyncedFolders(); diff --git a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java new file mode 100644 index 000000000000..caf95ef3f435 --- /dev/null +++ b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java @@ -0,0 +1,50 @@ +/* + * Nextcloud Android client application + * + * @author Mario Danic + * Copyright (C) 2018 Mario Danic + * + * 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 . + */package com.owncloud.android.datamodel; + +import java.util.List; + +public class MediaFoldersModel { + private List imageMediaFolders; + private List videoMediaFolders; + + public MediaFoldersModel() { + } + + public MediaFoldersModel(List imageMediaFolders, List videoMediaFolders) { + this.imageMediaFolders = imageMediaFolders; + this.videoMediaFolders = videoMediaFolders; + } + + public List getImageMediaFolders() { + return imageMediaFolders; + } + + public void setImageMediaFolders(List imageMediaFolders) { + this.imageMediaFolders = imageMediaFolders; + } + + public List getVideoMediaFolders() { + return videoMediaFolders; + } + + public void setVideoMediaFolders(List videoMediaFolders) { + this.videoMediaFolders = videoMediaFolders; + } +} diff --git a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java index 12fe8b3e095a..72997bcac178 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java @@ -66,14 +66,14 @@ public class MediaProvider { * @return list with media folders */ public static List getImageFolders(ContentResolver contentResolver, int itemLimit, - @Nullable final Activity activity) { + @Nullable final Activity activity, boolean getWithoutActivity) { // check permissions checkPermissions(activity); // query media/image folders Cursor cursorFolders = null; - if (activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), - Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + if ((activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), + Manifest.permission.WRITE_EXTERNAL_STORAGE)) || getWithoutActivity) { cursorFolders = contentResolver.query(IMAGES_MEDIA_URI, IMAGES_FOLDER_PROJECTION, null, null, IMAGES_FOLDER_SORT_ORDER); } @@ -171,14 +171,14 @@ private static void checkPermissions(@Nullable Activity activity) { } public static List getVideoFolders(ContentResolver contentResolver, int itemLimit, - @Nullable final Activity activity) { + @Nullable final Activity activity, boolean getWithoutActivity) { // check permissions checkPermissions(activity); // query media/image folders Cursor cursorFolders = null; - if (activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), - Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + if ((activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), + Manifest.permission.WRITE_EXTERNAL_STORAGE)) || getWithoutActivity) { cursorFolders = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, VIDEOS_FOLDER_PROJECTION, null, null, null); } diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index 1ead7c225e3d..7e89980eee74 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -160,6 +160,37 @@ public int updateSyncedFolderEnabled(long id, Boolean enabled) { return result; } + public SyncedFolder findByLocalPathAndAccount(String localPath, Account account) { + + SyncedFolder result = null; + Cursor cursor = mContentResolver.query( + ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, + null, + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH + " == \"" + localPath + "\"" + " AND " + + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT + " == " + account.name, + null, + null + ); + + if (cursor != null && cursor.getCount() == 1) { + result = createSyncedFolderFromCursor(cursor); + } else { + if (cursor == null) { + Log_OC.e(TAG, "Sync folder db cursor for local path=" + localPath + " in NULL."); + } else { + Log_OC.e(TAG, cursor.getCount() + " items for local path=" + localPath + + " available in sync folder db. Expected 1. Failed to update sync folder db."); + } + } + + if (cursor != null) { + cursor.close(); + } + + return result; + + } + /** * find a synced folder by local path. * @@ -171,7 +202,7 @@ public SyncedFolder findByLocalPath(String localPath) { Cursor cursor = mContentResolver.query( ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, null, - ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH + "== \"" + localPath + "\"", + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH + " == \"" + localPath + "\"", null, null ); diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java new file mode 100644 index 000000000000..7936b4f97acd --- /dev/null +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -0,0 +1,167 @@ +/* + * Nextcloud Android client application + * + * @author Mario Danic + * Copyright (C) 2018 Mario Danic + * + * 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 . + */ +package com.owncloud.android.jobs; + + +import android.accounts.Account; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.media.RingtoneManager; +import android.support.annotation.NonNull; +import android.support.v4.app.NotificationCompat; +import android.text.TextUtils; + +import com.evernote.android.job.Job; +import com.google.gson.Gson; +import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.datamodel.ArbitraryDataProvider; +import com.owncloud.android.datamodel.MediaFolder; +import com.owncloud.android.datamodel.MediaFoldersModel; +import com.owncloud.android.datamodel.MediaProvider; +import com.owncloud.android.datamodel.SyncedFolderProvider; +import com.owncloud.android.ui.activity.ManageAccountsActivity; +import com.owncloud.android.ui.activity.SyncedFoldersActivity; +import com.owncloud.android.ui.notifications.NotificationUtils; +import com.owncloud.android.utils.ThemeUtils; + +import java.util.ArrayList; +import java.util.List; + +public class MediaFoldersDetectionJob extends Job { + public static final String TAG = "MediaFoldersDetectionJob"; + + @NonNull + @Override + protected Result onRunJob(@NonNull Params params) { + Context context = getContext(); + ContentResolver contentResolver = context.getContentResolver(); + ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver); + SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver); + Gson gson = new Gson(); + String arbitraryDataString; + MediaFoldersModel mediaFoldersModel; + + List imageMediaFolders = MediaProvider.getImageFolders(contentResolver, 1, + null, true); + List videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null, + true); + + + List imageMediaFolderPaths = new ArrayList<>(); + List videoMediaFolderPaths = new ArrayList<>(); + + for (int i = 0; i < imageMediaFolders.size(); i++) { + imageMediaFolderPaths.add(imageMediaFolders.get(i).absolutePath); + } + + for (int i = 0; i < videoMediaFolders.size(); i++) { + videoMediaFolderPaths.add(videoMediaFolders.get(i).absolutePath); + } + + if (!TextUtils.isEmpty(arbitraryDataString = arbitraryDataProvider.getValue("global", "media_folders"))) { + mediaFoldersModel = gson.fromJson(arbitraryDataString, MediaFoldersModel.class); + + // Store updated values + arbitraryDataProvider.storeOrUpdateKeyValue("global", "media_folders", gson.toJson(new + MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths))); + + imageMediaFolderPaths.removeAll(mediaFoldersModel.getImageMediaFolders()); + videoMediaFolderPaths.removeAll(mediaFoldersModel.getVideoMediaFolders()); + + if (imageMediaFolderPaths.size() > 0 || videoMediaFolderPaths.size() > 0) { + Account[] accounts = AccountUtils.getAccounts(getContext()); + List accountList = new ArrayList<>(); + for (Account account : accounts) { + if (!arbitraryDataProvider.getBooleanValue(account, ManageAccountsActivity.PENDING_FOR_REMOVAL)) { + accountList.add(account); + } + } + + + for (Account account : accountList) { + for (int i = 0; i < imageMediaFolderPaths.size(); i++) { + if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolderPaths.get(i), + account) == null) { + String imageMediaFolder = imageMediaFolderPaths.get(i); + sendNotification(String.format(context.getString(R.string.new_media_folder_detected), + context.getString(R.string.new_media_folder_photos)), + imageMediaFolder.substring(imageMediaFolder.lastIndexOf("/"), + imageMediaFolder.length()), + account); + } + } + + for (int i = 0; i < videoMediaFolderPaths.size(); i++) { + if (syncedFolderProvider.findByLocalPathAndAccount(videoMediaFolderPaths.get(i), + account) == null) { + String videoMediaFolder = videoMediaFolderPaths.get(i); + sendNotification(String.format(context.getString(R.string.new_media_folder_detected), + context.getString(R.string.new_media_folder_photos)), + videoMediaFolder.substring(videoMediaFolder.lastIndexOf("/") + 1, + videoMediaFolder.length()), + account); + } + } + } + } + + + } else { + mediaFoldersModel = new MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths); + arbitraryDataProvider.storeOrUpdateKeyValue("global", "media_folders", gson.toJson(mediaFoldersModel)); + } + + return Result.SUCCESS; + } + + private void sendNotification(String contentTitle, String subtitle, Account account) { + Context context = getContext(); + Intent intent = new Intent(getContext(), SyncedFoldersActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.putExtra(NotificationJob.KEY_NOTIFICATION_ACCOUNT, account.name); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); + + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.notification_icon) + .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.notification_icon)) + .setColor(ThemeUtils.primaryColor()) + .setSubText(account.name) + .setContentTitle(contentTitle) + .setContentText(subtitle) + .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) + .setAutoCancel(true) + .setContentIntent(pendingIntent); + + if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)) { + notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_GENERAL); + } + + NotificationManager notificationManager = (NotificationManager) + context.getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.notify(0, notificationBuilder.build()); + } + +} diff --git a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java index 9aeaec306a02..a63b47485f42 100644 --- a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java +++ b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java @@ -43,6 +43,8 @@ public Job create(String tag) { return new OfflineSyncJob(); case NotificationJob.TAG: return new NotificationJob(); + case MediaFoldersDetectionJob.TAG: + return new MediaFoldersDetectionJob(); default: return null; } diff --git a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java index 2ecc4dc7839c..935198f5c929 100644 --- a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java +++ b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java @@ -54,6 +54,13 @@ public boolean onStartJob(JobParameters params) { .setUpdateCurrent(false) .build() .schedule(); + + new JobRequest.Builder(MediaFoldersDetectionJob.TAG) + .startNow() + .setUpdateCurrent(false) + .build() + .schedule(); + } FilesSyncHelper.scheduleNJobs(true, getApplicationContext()); diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 9c056102c674..af8533f6e5d0 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -56,6 +56,7 @@ import com.owncloud.android.datamodel.SyncedFolderDisplayItem; import com.owncloud.android.datamodel.SyncedFolderProvider; import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.jobs.NotificationJob; import com.owncloud.android.ui.adapter.SyncedFolderAdapter; import com.owncloud.android.ui.decoration.MediaGridItemDecoration; import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment; @@ -110,6 +111,15 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.synced_folders_layout); + String account; + Account currentAccount; + if (getIntent() != null && getIntent().getExtras() != null && + (account = getIntent().getExtras().getString(NotificationJob.KEY_NOTIFICATION_ACCOUNT)) != null && + (currentAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext())) != null && + !account.equalsIgnoreCase(currentAccount.name)) { + AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account); + setAccount(AccountUtils.getCurrentOwnCloudAccount(this)); + } // setup toolbar setupToolbar(); CollapsingToolbarLayout mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar); @@ -199,9 +209,9 @@ private void load(final int perFolderMediaItemLimit, boolean force) { } setListShown(false); final List mediaFolders = MediaProvider.getImageFolders(getContentResolver(), - perFolderMediaItemLimit, SyncedFoldersActivity.this); + perFolderMediaItemLimit, SyncedFoldersActivity.this, false); mediaFolders.addAll(MediaProvider.getVideoFolders(getContentResolver(), perFolderMediaItemLimit, - SyncedFoldersActivity.this)); + SyncedFoldersActivity.this, false)); List syncedFolderArrayList = mSyncedFolderProvider.getSyncedFolders(); List currentAccountSyncedFoldersList = new ArrayList<>(); diff --git a/src/main/java/com/owncloud/android/ui/notifications/NotificationUtils.java b/src/main/java/com/owncloud/android/ui/notifications/NotificationUtils.java index fa9917eb8d70..3d68b5077752 100644 --- a/src/main/java/com/owncloud/android/ui/notifications/NotificationUtils.java +++ b/src/main/java/com/owncloud/android/ui/notifications/NotificationUtils.java @@ -34,6 +34,7 @@ public class NotificationUtils { + public static final String NOTIFICATION_CHANNEL_GENERAL = "NOTIFICATION_CHANNEL_GENERAL"; public static final String NOTIFICATION_CHANNEL_DOWNLOAD = "NOTIFICATION_CHANNEL_DOWNLOAD"; public static final String NOTIFICATION_CHANNEL_UPLOAD = "NOTIFICATION_CHANNEL_UPLOAD"; public static final String NOTIFICATION_CHANNEL_MEDIA = "NOTIFICATION_CHANNEL_MEDIA"; diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index ac6aa97033fa..106b32c31d94 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -781,6 +781,7 @@ Push notifications Show push notifications sent by the server: Mentions in comments, reception of new remote shares, announcements posted by an admin etc. Send button icon + Auth end point address Access end point address * @@ -804,6 +805,12 @@ Error commenting file Successfully restored file version. Error restoring file version! + General notifications + Show notifications for new media folders and similar + New %1$s media folder detected. + photo + video + The server has reached end of life, please upgrade! Dismiss No app available to send mails! From 7d2d6465f67600a26e977d4c96019821cd60685d Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 14:35:46 +0200 Subject: [PATCH 02/20] Add automated configuration opener Signed-off-by: Mario Danic --- .../jobs/MediaFoldersDetectionJob.java | 14 +- .../ui/activity/SyncedFoldersActivity.java | 147 ++++++++++-------- 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 7936b4f97acd..e699465a644a 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -52,6 +52,9 @@ public class MediaFoldersDetectionJob extends Job { public static final String TAG = "MediaFoldersDetectionJob"; + public static final String KEY_MEDIA_FOLDER_PATH = "KEY_MEDIA_FOLDER_PATH"; + public static final String KEY_MEDIA_FOLDER_TYPE = "KEY_MEDIA_FOLDER_TYPE"; + @NonNull @Override protected Result onRunJob(@NonNull Params params) { @@ -107,9 +110,9 @@ protected Result onRunJob(@NonNull Params params) { String imageMediaFolder = imageMediaFolderPaths.get(i); sendNotification(String.format(context.getString(R.string.new_media_folder_detected), context.getString(R.string.new_media_folder_photos)), - imageMediaFolder.substring(imageMediaFolder.lastIndexOf("/"), + imageMediaFolder.substring(imageMediaFolder.lastIndexOf("/") + 1, imageMediaFolder.length()), - account); + account, imageMediaFolder, 1); } } @@ -121,7 +124,7 @@ protected Result onRunJob(@NonNull Params params) { context.getString(R.string.new_media_folder_photos)), videoMediaFolder.substring(videoMediaFolder.lastIndexOf("/") + 1, videoMediaFolder.length()), - account); + account, videoMediaFolder, 2); } } } @@ -136,11 +139,14 @@ protected Result onRunJob(@NonNull Params params) { return Result.SUCCESS; } - private void sendNotification(String contentTitle, String subtitle, Account account) { + private void sendNotification(String contentTitle, String subtitle, Account account, + String path, int type) { Context context = getContext(); Intent intent = new Intent(getContext(), SyncedFoldersActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.putExtra(NotificationJob.KEY_NOTIFICATION_ACCOUNT, account.name); + intent.putExtra(KEY_MEDIA_FOLDER_PATH, path); + intent.putExtra(KEY_MEDIA_FOLDER_TYPE, type); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context) diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index af8533f6e5d0..34754ed6ce38 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -37,6 +37,7 @@ import android.support.v7.app.ActionBar; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; import android.view.View; @@ -56,6 +57,7 @@ import com.owncloud.android.datamodel.SyncedFolderDisplayItem; import com.owncloud.android.datamodel.SyncedFolderProvider; import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.jobs.MediaFoldersDetectionJob; import com.owncloud.android.jobs.NotificationJob; import com.owncloud.android.ui.adapter.SyncedFolderAdapter; import com.owncloud.android.ui.decoration.MediaGridItemDecoration; @@ -86,10 +88,9 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderAdapter.ClickListener, SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener { - private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG"; - public static final String[] PRIORITIZED_FOLDERS = new String[] { "Camera", "Screenshots" }; + public static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"}; public static final String EXTRA_SHOW_SIDEBAR = "SHOW_SIDEBAR"; - + private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG"; private static final String TAG = SyncedFoldersActivity.class.getSimpleName(); private RecyclerView mRecyclerView; @@ -101,6 +102,56 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA private boolean showSidebar = true; private RelativeLayout mCustomFolderRelativeLayout; + private String path; + private int type; + /** + * Sorts list of {@link SyncedFolderDisplayItem}s. + * + * @param syncFolderItemList list of items to be sorted + * @return sorted list of items + */ + public static List sortSyncedFolderItems(List + syncFolderItemList) { + Collections.sort(syncFolderItemList, new Comparator() { + public int compare(SyncedFolderDisplayItem f1, SyncedFolderDisplayItem f2) { + if (f1 == null && f2 == null) { + return 0; + } else if (f1 == null) { + return -1; + } else if (f2 == null) { + return 1; + } else if (f1.isEnabled() && f2.isEnabled()) { + return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( + f2.getFolderName().toLowerCase(Locale.getDefault())); + } else if (f1.isEnabled()) { + return -1; + } else if (f2.isEnabled()) { + return 1; + } else if (f1.getFolderName() == null && f2.getFolderName() == null) { + return 0; + } else if (f1.getFolderName() == null) { + return -1; + } else if (f2.getFolderName() == null) { + return 1; + } + for (String folder : PRIORITIZED_FOLDERS) { + if (folder.equals(f1.getFolderName()) && + folder.equals(f2.getFolderName())) { + return 0; + } else if (folder.equals(f1.getFolderName())) { + return -1; + } else if (folder.equals(f2.getFolderName())) { + return 1; + } + } + return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( + f2.getFolderName().toLowerCase(Locale.getDefault())); + } + }); + + return syncFolderItemList; + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -113,13 +164,18 @@ protected void onCreate(Bundle savedInstanceState) { String account; Account currentAccount; - if (getIntent() != null && getIntent().getExtras() != null && - (account = getIntent().getExtras().getString(NotificationJob.KEY_NOTIFICATION_ACCOUNT)) != null && - (currentAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext())) != null && - !account.equalsIgnoreCase(currentAccount.name)) { - AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account); - setAccount(AccountUtils.getCurrentOwnCloudAccount(this)); + if (getIntent() != null && getIntent().getExtras() != null) { + if ((account = getIntent().getExtras().getString(NotificationJob.KEY_NOTIFICATION_ACCOUNT)) != null && + (currentAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext())) != null && + !account.equalsIgnoreCase(currentAccount.name)) { + AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account); + setAccount(AccountUtils.getCurrentOwnCloudAccount(this)); + } + + path = getIntent().getStringExtra(MediaFoldersDetectionJob.KEY_MEDIA_FOLDER_PATH); + type = getIntent().getIntExtra(MediaFoldersDetectionJob.KEY_MEDIA_FOLDER_TYPE, -1); } + // setup toolbar setupToolbar(); CollapsingToolbarLayout mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar); @@ -228,6 +284,17 @@ private void load(final int perFolderMediaItemLimit, boolean force) { mAdapter.setSyncFolderItems(syncFolderItems); mAdapter.notifyDataSetChanged(); setListShown(true); + + if (!TextUtils.isEmpty(path)) { + for (int i = 0; i < syncFolderItems.size(); i++) { + SyncedFolderDisplayItem syncedFolderDisplayItem = syncFolderItems.get(i); + if (syncedFolderDisplayItem.getLocalPath().equalsIgnoreCase(path) && + syncedFolderDisplayItem.getType().getId().equals(type)) { + mRecyclerView.getLayoutManager().scrollToPosition(i); + onSyncFolderSettingsClick(1, syncedFolderDisplayItem); + } + } + } } /** @@ -244,9 +311,9 @@ private List mergeFolderData(List syncedF List result = new ArrayList<>(); for (MediaFolder mediaFolder : mediaFolders) { - if (syncedFoldersMap.containsKey(mediaFolder.absolutePath+"-"+mediaFolder.type)) { - SyncedFolder syncedFolder = syncedFoldersMap.get(mediaFolder.absolutePath+"-"+mediaFolder.type); - syncedFoldersMap.remove(mediaFolder.absolutePath+"-"+mediaFolder.type); + if (syncedFoldersMap.containsKey(mediaFolder.absolutePath + "-" + mediaFolder.type)) { + SyncedFolder syncedFolder = syncedFoldersMap.get(mediaFolder.absolutePath + "-" + mediaFolder.type); + syncedFoldersMap.remove(mediaFolder.absolutePath + "-" + mediaFolder.type); if (MediaFolderType.CUSTOM == syncedFolder.getType()) { result.add(createSyncedFolderWithoutMediaFolder(syncedFolder)); @@ -265,54 +332,6 @@ private List mergeFolderData(List syncedF return result; } - /** - * Sorts list of {@link SyncedFolderDisplayItem}s. - * - * @param syncFolderItemList list of items to be sorted - * @return sorted list of items - */ - public static List sortSyncedFolderItems(List - syncFolderItemList) { - Collections.sort(syncFolderItemList, new Comparator() { - public int compare(SyncedFolderDisplayItem f1, SyncedFolderDisplayItem f2) { - if (f1 == null && f2 == null) { - return 0; - } else if (f1 == null) { - return -1; - } else if (f2 == null) { - return 1; - } else if (f1.isEnabled() && f2.isEnabled()) { - return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( - f2.getFolderName().toLowerCase(Locale.getDefault())); - } else if (f1.isEnabled()) { - return -1; - } else if (f2.isEnabled()) { - return 1; - } else if (f1.getFolderName() == null && f2.getFolderName() == null) { - return 0; - } else if (f1.getFolderName() == null) { - return -1; - } else if (f2.getFolderName() == null) { - return 1; - } - for (String folder : PRIORITIZED_FOLDERS) { - if (folder.equals(f1.getFolderName()) && - folder.equals(f2.getFolderName())) { - return 0; - } else if (folder.equals(f1.getFolderName())) { - return -1; - } else if (folder.equals(f2.getFolderName())) { - return 1; - } - } - return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( - f2.getFolderName().toLowerCase(Locale.getDefault())); - } - }); - - return syncFolderItemList; - } - @NonNull private SyncedFolderDisplayItem createSyncedFolderWithoutMediaFolder(@NonNull SyncedFolder syncedFolder) { @@ -430,7 +449,7 @@ private Map createSyncedFoldersMap(List sync Map result = new HashMap<>(); if (syncFolders != null) { for (SyncedFolder syncFolder : syncFolders) { - result.put(syncFolder.getLocalPath()+"-"+syncFolder.getType(), syncFolder); + result.put(syncFolder.getLocalPath() + "-" + syncFolder.getType(), syncFolder); } } return result; @@ -532,12 +551,12 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { && resultCode == RESULT_OK && mSyncedFolderPreferencesDialogFragment != null) { OCFile chosenFolder = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER); mSyncedFolderPreferencesDialogFragment.setRemoteFolderSummary(chosenFolder.getRemotePath()); - } if (requestCode == SyncedFolderPreferencesDialogFragment.REQUEST_CODE__SELECT_LOCAL_FOLDER + } + if (requestCode == SyncedFolderPreferencesDialogFragment.REQUEST_CODE__SELECT_LOCAL_FOLDER && resultCode == RESULT_OK && mSyncedFolderPreferencesDialogFragment != null) { String localPath = data.getStringExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES); mSyncedFolderPreferencesDialogFragment.setLocalFolderSummary(localPath); - } - else { + } else { super.onActivityResult(requestCode, resultCode, data); } } From 3d972e3b6bc38f302dd8952be2838cfbadff5592 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 14:45:07 +0200 Subject: [PATCH 03/20] Clean up Signed-off-by: Mario Danic --- .../com/owncloud/android/ui/activity/SyncedFoldersActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 34754ed6ce38..d36e22b0a646 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -290,7 +290,6 @@ private void load(final int perFolderMediaItemLimit, boolean force) { SyncedFolderDisplayItem syncedFolderDisplayItem = syncFolderItems.get(i); if (syncedFolderDisplayItem.getLocalPath().equalsIgnoreCase(path) && syncedFolderDisplayItem.getType().getId().equals(type)) { - mRecyclerView.getLayoutManager().scrollToPosition(i); onSyncFolderSettingsClick(1, syncedFolderDisplayItem); } } From d2b2a3f57ca386f8634a2e4ec7780da25b824c1e Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 19:55:34 +0200 Subject: [PATCH 04/20] Improve media folders detection Signed-off-by: Mario Danic --- .../datamodel/SyncedFolderProvider.java | 18 ++++++ .../android/jobs/NContentObserverJob.java | 27 ++++---- .../android/utils/FilesSyncHelper.java | 64 ++----------------- 3 files changed, 39 insertions(+), 70 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index 7e89980eee74..4704350f83a8 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -78,6 +78,24 @@ public long storeSyncedFolder(SyncedFolder syncedFolder) { } } + public int countEnabledSyncedFolders() { + int count = 0; + Cursor cursor = mContentResolver.query( + ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, + new String[]{ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED}, + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED + " == 1", + null, + null + ); + + if (cursor != null) { + count = cursor.getCount(); + cursor.close(); + } + + return count; + } + /** * get all synced folder entries. * diff --git a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java index 935198f5c929..3417009c76e7 100644 --- a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java +++ b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java @@ -28,11 +28,13 @@ import com.evernote.android.job.JobRequest; import com.evernote.android.job.util.support.PersistableBundleCompat; +import com.owncloud.android.datamodel.SyncedFolderProvider; import com.owncloud.android.utils.FilesSyncHelper; import com.owncloud.android.utils.PowerUtils; /* Job that triggers new FilesSyncJob in case new photo or video were detected + and starts a job to find new media folders */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class NContentObserverJob extends JobService { @@ -42,18 +44,21 @@ public boolean onStartJob(JobParameters params) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (params.getJobId() == FilesSyncHelper.ContentSyncJobId && params.getTriggeredContentAuthorities() != null && params.getTriggeredContentUris() != null - && params.getTriggeredContentUris().length > 0 - && !PowerUtils.isPowerSaveMode(getApplicationContext())) { + && params.getTriggeredContentUris().length > 0) { - PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat(); - persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true); + SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(getContentResolver()); + if (!PowerUtils.isPowerSaveMode(getApplicationContext()) && syncedFolderProvider + .countEnabledSyncedFolders() > 0) { + PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat(); + persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true); - new JobRequest.Builder(FilesSyncJob.TAG) - .startNow() - .setExtras(persistableBundleCompat) - .setUpdateCurrent(false) - .build() - .schedule(); + new JobRequest.Builder(FilesSyncJob.TAG) + .startNow() + .setExtras(persistableBundleCompat) + .setUpdateCurrent(false) + .build() + .schedule(); + } new JobRequest.Builder(MediaFoldersDetectionJob.TAG) .startNow() @@ -63,7 +68,7 @@ public boolean onStartJob(JobParameters params) { } - FilesSyncHelper.scheduleNJobs(true, getApplicationContext()); + FilesSyncHelper.scheduleJobOnN(); } return true; diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 94f8a4420a4c..ad007ab22b6e 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -60,7 +60,6 @@ import java.io.File; import java.io.IOException; -import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -241,51 +240,6 @@ public static void restartJobsIfNeeded() { } @RequiresApi(api = Build.VERSION_CODES.N) - public static boolean isContentObserverJobScheduled() { - JobScheduler js = MainApp.getAppContext().getSystemService(JobScheduler.class); - List jobs = js.getAllPendingJobs(); - - if (jobs == null || jobs.size() == 0) { - return false; - } - - for (int i = 0; i < jobs.size(); i++) { - if (jobs.get(i).getId() == ContentSyncJobId) { - return true; - } - } - - return false; - } - - public static void scheduleNJobs(boolean force, Context context) { - SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(context.getContentResolver()); - - - boolean hasVideoFolders = false; - boolean hasImageFolders = false; - - if (syncedFolderProvider.getSyncedFolders() != null) { - for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { - if (MediaFolderType.VIDEO == syncedFolder.getType()) { - hasVideoFolders = true; - } else if (MediaFolderType.IMAGE == syncedFolder.getType()) { - hasImageFolders = true; - } - } - } - - if (hasImageFolders || hasVideoFolders) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - scheduleJobOnN(hasImageFolders, hasVideoFolders, force); - } - } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - cancelJobOnN(); - } - } - } - public static void scheduleFilesSyncIfNeeded(Context context) { // always run this because it also allows us to perform retries of manual uploads new JobRequest.Builder(FilesSyncJob.TAG) @@ -295,7 +249,9 @@ public static void scheduleFilesSyncIfNeeded(Context context) { .schedule(); if (context != null) { - scheduleNJobs(false, context); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + scheduleJobOnN(); + } } } @@ -310,21 +266,11 @@ public static void scheduleOfflineSyncIfNeeded() { } } - - @RequiresApi(api = Build.VERSION_CODES.N) - private static void cancelJobOnN() { - JobScheduler jobScheduler = MainApp.getAppContext().getSystemService(JobScheduler.class); - if (isContentObserverJobScheduled()) { - jobScheduler.cancel(ContentSyncJobId); - } - } - @RequiresApi(api = Build.VERSION_CODES.N) - private static void scheduleJobOnN(boolean hasImageFolders, boolean hasVideoFolders, - boolean force) { + public static void scheduleJobOnN() { JobScheduler jobScheduler = MainApp.getAppContext().getSystemService(JobScheduler.class); - if ((hasImageFolders || hasVideoFolders) && (!isContentObserverJobScheduled() || force)) { + if (jobScheduler != null) { JobInfo.Builder builder = new JobInfo.Builder(ContentSyncJobId, new ComponentName(MainApp.getAppContext(), NContentObserverJob.class.getName())); builder.addTriggerContentUri(new JobInfo.TriggerContentUri(android.provider.MediaStore. From b609aa8844301002f50f881ec3ba2e2987ff496c Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 19:58:16 +0200 Subject: [PATCH 05/20] Remove obsolete call Signed-off-by: Mario Danic --- .../owncloud/android/ui/activity/SyncedFoldersActivity.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index d36e22b0a646..20b6d617befe 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -529,8 +529,6 @@ public void onSyncStatusToggleClick(int section, SyncedFolderDisplayItem syncedF String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + syncedFolderDisplayItem.getId(); arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } - FilesSyncHelper.scheduleNJobs(false, getApplicationContext()); - } @Override @@ -582,7 +580,6 @@ public void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder) { String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + newCustomFolder.getId(); arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } - FilesSyncHelper.scheduleNJobs(false, getApplicationContext()); } mAdapter.addSyncFolderItem(newCustomFolder); } else { @@ -602,7 +599,6 @@ public void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder) { String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } - FilesSyncHelper.scheduleNJobs(false, getApplicationContext()); } } else { // existing synced folder setup to be updated @@ -613,7 +609,6 @@ public void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder) { String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } - FilesSyncHelper.scheduleNJobs(false, getApplicationContext()); } mAdapter.setSyncFolderItem(syncedFolder.getSection(), item); From b125b9b702bf45d229cb1c162c86d2187b80d874 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 20:04:59 +0200 Subject: [PATCH 06/20] remove requiresapi Signed-off-by: Mario Danic --- src/main/java/com/owncloud/android/utils/FilesSyncHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index ad007ab22b6e..19831a7ca55a 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -239,7 +239,6 @@ public static void restartJobsIfNeeded() { }).start(); } - @RequiresApi(api = Build.VERSION_CODES.N) public static void scheduleFilesSyncIfNeeded(Context context) { // always run this because it also allows us to perform retries of manual uploads new JobRequest.Builder(FilesSyncJob.TAG) From 50bb580a4d171d487eb05f42806b722a6655c01b Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 27 Mar 2018 20:23:39 +0200 Subject: [PATCH 07/20] Merge nested ifs Signed-off-by: Mario Danic --- .../java/com/owncloud/android/utils/FilesSyncHelper.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 19831a7ca55a..6131a5a7c233 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -247,10 +247,8 @@ public static void scheduleFilesSyncIfNeeded(Context context) { .build() .schedule(); - if (context != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - scheduleJobOnN(); - } + if (context != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + scheduleJobOnN(); } } From 19195b2314733771183ca6bae65b00fad1c123a5 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Thu, 29 Mar 2018 11:43:56 +0200 Subject: [PATCH 08/20] Fix a typo Signed-off-by: Mario Danic --- .../com/owncloud/android/jobs/MediaFoldersDetectionJob.java | 2 +- src/main/res/values/strings.xml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index e699465a644a..439b51e9f46e 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -121,7 +121,7 @@ protected Result onRunJob(@NonNull Params params) { account) == null) { String videoMediaFolder = videoMediaFolderPaths.get(i); sendNotification(String.format(context.getString(R.string.new_media_folder_detected), - context.getString(R.string.new_media_folder_photos)), + context.getString(R.string.new_media_folder_videos)), videoMediaFolder.substring(videoMediaFolder.lastIndexOf("/") + 1, videoMediaFolder.length()), account, videoMediaFolder, 2); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 106b32c31d94..0fe18c90bd96 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -652,7 +652,6 @@ Backup scheduled and will start shortly Import scheduled and will start shortly - Log out No app found to set a picture with Privacy From 37b3f6f04cb64e248b94750f66785f1e79c7fff6 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Wed, 11 Apr 2018 16:38:41 +0200 Subject: [PATCH 09/20] Fixed a bug with detection Signed-off-by: Mario Danic --- .../com/owncloud/android/datamodel/SyncedFolderProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index 4704350f83a8..bcc97a7572fe 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -82,9 +82,9 @@ public int countEnabledSyncedFolders() { int count = 0; Cursor cursor = mContentResolver.query( ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, - new String[]{ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED}, - ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED + " == 1", null, + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED + " = ?", + new String[]{"1"}, null ); From cbb8431cfc08ce3746bdb6733057aded710bc0d9 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Tue, 24 Apr 2018 14:01:43 +0200 Subject: [PATCH 10/20] fix after rebase --- .../owncloud/android/jobs/MediaFoldersDetectionJob.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 439b51e9f46e..8710dcbf2b50 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -152,7 +152,7 @@ private void sendNotification(String contentTitle, String subtitle, Account acc NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.notification_icon) .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.notification_icon)) - .setColor(ThemeUtils.primaryColor()) + .setColor(ThemeUtils.primaryColor(getContext())) .setSubText(account.name) .setContentTitle(contentTitle) .setContentText(subtitle) @@ -167,7 +167,8 @@ private void sendNotification(String contentTitle, String subtitle, Account acc NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.notify(0, notificationBuilder.build()); + if (notificationManager != null) { + notificationManager.notify(0, notificationBuilder.build()); + } } - } From 64cd3ac6643b000de2222be8f47b841a7bab6498 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:08:15 +0200 Subject: [PATCH 11/20] cleanup model --- .../android/datamodel/MediaFoldersModel.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java index caf95ef3f435..2041cddb9802 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java @@ -16,7 +16,9 @@ * * You should have received a copy of the GNU Affero General Public * License along with this program. If not, see . - */package com.owncloud.android.datamodel; + */ + +package com.owncloud.android.datamodel; import java.util.List; @@ -24,9 +26,6 @@ public class MediaFoldersModel { private List imageMediaFolders; private List videoMediaFolders; - public MediaFoldersModel() { - } - public MediaFoldersModel(List imageMediaFolders, List videoMediaFolders) { this.imageMediaFolders = imageMediaFolders; this.videoMediaFolders = videoMediaFolders; @@ -36,15 +35,7 @@ public List getImageMediaFolders() { return imageMediaFolders; } - public void setImageMediaFolders(List imageMediaFolders) { - this.imageMediaFolders = imageMediaFolders; - } - public List getVideoMediaFolders() { return videoMediaFolders; } - - public void setVideoMediaFolders(List videoMediaFolders) { - this.videoMediaFolders = videoMediaFolders; - } } From e1137661a69c84c0ec72fcaa9b4c83ecba585b62 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:09:21 +0200 Subject: [PATCH 12/20] revert code changes --- .../android/datamodel/MediaFoldersModel.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java index 2041cddb9802..f082e1f9e9ed 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java @@ -26,6 +26,12 @@ public class MediaFoldersModel { private List imageMediaFolders; private List videoMediaFolders; + /** + * default constructor. + */ + public MediaFoldersModel() { + } + public MediaFoldersModel(List imageMediaFolders, List videoMediaFolders) { this.imageMediaFolders = imageMediaFolders; this.videoMediaFolders = videoMediaFolders; @@ -35,7 +41,15 @@ public List getImageMediaFolders() { return imageMediaFolders; } + public void setImageMediaFolders(List imageMediaFolders) { + this.imageMediaFolders = imageMediaFolders; + } + public List getVideoMediaFolders() { return videoMediaFolders; } + + public void setVideoMediaFolders(List videoMediaFolders) { + this.videoMediaFolders = videoMediaFolders; + } } From ec303f6493dbcff136237466bde8983430ee1502 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:10:41 +0200 Subject: [PATCH 13/20] codacy: fix Useless parentheses --- .../java/com/owncloud/android/datamodel/MediaProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java index 72997bcac178..b70ebd33554f 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java @@ -72,8 +72,8 @@ public static List getImageFolders(ContentResolver contentResolver, // query media/image folders Cursor cursorFolders = null; - if ((activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), - Manifest.permission.WRITE_EXTERNAL_STORAGE)) || getWithoutActivity) { + if (activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), + Manifest.permission.WRITE_EXTERNAL_STORAGE) || getWithoutActivity) { cursorFolders = contentResolver.query(IMAGES_MEDIA_URI, IMAGES_FOLDER_PROJECTION, null, null, IMAGES_FOLDER_SORT_ORDER); } From c767b93b761643385d1c82c594a32f16ce2f3c8b Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:14:26 +0200 Subject: [PATCH 14/20] revert to have parenthesis (for readability) --- .../java/com/owncloud/android/datamodel/MediaProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java index b70ebd33554f..72997bcac178 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaProvider.java @@ -72,8 +72,8 @@ public static List getImageFolders(ContentResolver contentResolver, // query media/image folders Cursor cursorFolders = null; - if (activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), - Manifest.permission.WRITE_EXTERNAL_STORAGE) || getWithoutActivity) { + if ((activity != null && PermissionUtil.checkSelfPermission(activity.getApplicationContext(), + Manifest.permission.WRITE_EXTERNAL_STORAGE)) || getWithoutActivity) { cursorFolders = contentResolver.query(IMAGES_MEDIA_URI, IMAGES_FOLDER_PROJECTION, null, null, IMAGES_FOLDER_SORT_ORDER); } From d52d97b1157bb5deb93ba088f3dd17db9476d671 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:20:57 +0200 Subject: [PATCH 15/20] codacy: fix issues about String performance and for loops --- .../jobs/MediaFoldersDetectionJob.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 8710dcbf2b50..0b4290bb3f14 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -2,7 +2,9 @@ * Nextcloud Android client application * * @author Mario Danic + * @author Andy Scherzinger * Copyright (C) 2018 Mario Danic + * Copyright (C) 2018 Andy Scherzinger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -71,16 +73,15 @@ protected Result onRunJob(@NonNull Params params) { List videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null, true); - List imageMediaFolderPaths = new ArrayList<>(); List videoMediaFolderPaths = new ArrayList<>(); - for (int i = 0; i < imageMediaFolders.size(); i++) { - imageMediaFolderPaths.add(imageMediaFolders.get(i).absolutePath); + for (MediaFolder imageMediaFolder: imageMediaFolders) { + imageMediaFolderPaths.add(imageMediaFolder.absolutePath); } - for (int i = 0; i < videoMediaFolders.size(); i++) { - videoMediaFolderPaths.add(videoMediaFolders.get(i).absolutePath); + for (MediaFolder videoMediaFolder: videoMediaFolders) { + imageMediaFolderPaths.add(videoMediaFolder.absolutePath); } if (!TextUtils.isEmpty(arbitraryDataString = arbitraryDataProvider.getValue("global", "media_folders"))) { @@ -104,25 +105,23 @@ protected Result onRunJob(@NonNull Params params) { for (Account account : accountList) { - for (int i = 0; i < imageMediaFolderPaths.size(); i++) { - if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolderPaths.get(i), + for (String imageMediaFolder : imageMediaFolderPaths) { + if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolder, account) == null) { - String imageMediaFolder = imageMediaFolderPaths.get(i); sendNotification(String.format(context.getString(R.string.new_media_folder_detected), context.getString(R.string.new_media_folder_photos)), - imageMediaFolder.substring(imageMediaFolder.lastIndexOf("/") + 1, + imageMediaFolder.substring(imageMediaFolder.lastIndexOf('/') + 1, imageMediaFolder.length()), account, imageMediaFolder, 1); } } - for (int i = 0; i < videoMediaFolderPaths.size(); i++) { - if (syncedFolderProvider.findByLocalPathAndAccount(videoMediaFolderPaths.get(i), + for (String videoMediaFolder : videoMediaFolderPaths) { + if (syncedFolderProvider.findByLocalPathAndAccount(videoMediaFolder, account) == null) { - String videoMediaFolder = videoMediaFolderPaths.get(i); sendNotification(String.format(context.getString(R.string.new_media_folder_detected), context.getString(R.string.new_media_folder_videos)), - videoMediaFolder.substring(videoMediaFolder.lastIndexOf("/") + 1, + videoMediaFolder.substring(videoMediaFolder.lastIndexOf('/') + 1, videoMediaFolder.length()), account, videoMediaFolder, 2); } @@ -130,7 +129,6 @@ protected Result onRunJob(@NonNull Params params) { } } - } else { mediaFoldersModel = new MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths); arbitraryDataProvider.storeOrUpdateKeyValue("global", "media_folders", gson.toJson(mediaFoldersModel)); From 54e592e4fc728576204e462778dfeabae036c304 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:36:15 +0200 Subject: [PATCH 16/20] fix further codacy issues --- .../android/datamodel/MediaFoldersModel.java | 1 + .../jobs/MediaFoldersDetectionJob.java | 3 +- .../android/jobs/NContentObserverJob.java | 31 ++++++++++--------- .../ui/activity/SyncedFoldersActivity.java | 20 ++++++------ 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java index f082e1f9e9ed..dbc9ee0a4d3a 100644 --- a/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java +++ b/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java @@ -30,6 +30,7 @@ public class MediaFoldersModel { * default constructor. */ public MediaFoldersModel() { + // keep default constructor for GSON } public MediaFoldersModel(List imageMediaFolders, List videoMediaFolders) { diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 0b4290bb3f14..23d91f436038 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -103,7 +103,6 @@ protected Result onRunJob(@NonNull Params params) { } } - for (Account account : accountList) { for (String imageMediaFolder : imageMediaFolderPaths) { if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolder, @@ -158,7 +157,7 @@ private void sendNotification(String contentTitle, String subtitle, Account acc .setAutoCancel(true) .setContentIntent(pendingIntent); - if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_GENERAL); } diff --git a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java index 3417009c76e7..978d4aca28ea 100644 --- a/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java +++ b/src/main/java/com/owncloud/android/jobs/NContentObserverJob.java @@ -1,4 +1,4 @@ -/** +/* * Nextcloud Android client application * * @author Mario Danic @@ -46,19 +46,7 @@ public boolean onStartJob(JobParameters params) { != null && params.getTriggeredContentUris() != null && params.getTriggeredContentUris().length > 0) { - SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(getContentResolver()); - if (!PowerUtils.isPowerSaveMode(getApplicationContext()) && syncedFolderProvider - .countEnabledSyncedFolders() > 0) { - PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat(); - persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true); - - new JobRequest.Builder(FilesSyncJob.TAG) - .startNow() - .setExtras(persistableBundleCompat) - .setUpdateCurrent(false) - .build() - .schedule(); - } + checkAndStartFileSyncJob(); new JobRequest.Builder(MediaFoldersDetectionJob.TAG) .startNow() @@ -74,6 +62,21 @@ public boolean onStartJob(JobParameters params) { return true; } + private void checkAndStartFileSyncJob() { + if (!PowerUtils.isPowerSaveMode(getApplicationContext()) && + new SyncedFolderProvider(getContentResolver()).countEnabledSyncedFolders() > 0) { + PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat(); + persistableBundleCompat.putBoolean(FilesSyncJob.SKIP_CUSTOM, true); + + new JobRequest.Builder(FilesSyncJob.TAG) + .startNow() + .setExtras(persistableBundleCompat) + .setUpdateCurrent(false) + .build() + .schedule(); + } + } + @Override public boolean onStopJob(JobParameters params) { return false; diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 20b6d617befe..a0b547ccf8a5 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -165,9 +165,10 @@ protected void onCreate(Bundle savedInstanceState) { String account; Account currentAccount; if (getIntent() != null && getIntent().getExtras() != null) { - if ((account = getIntent().getExtras().getString(NotificationJob.KEY_NOTIFICATION_ACCOUNT)) != null && - (currentAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext())) != null && - !account.equalsIgnoreCase(currentAccount.name)) { + account = getIntent().getExtras().getString(NotificationJob.KEY_NOTIFICATION_ACCOUNT); + currentAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()); + + if (account != null && currentAccount != null && !account.equalsIgnoreCase(currentAccount.name)) { AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account); setAccount(AccountUtils.getCurrentOwnCloudAccount(this)); } @@ -265,9 +266,9 @@ private void load(final int perFolderMediaItemLimit, boolean force) { } setListShown(false); final List mediaFolders = MediaProvider.getImageFolders(getContentResolver(), - perFolderMediaItemLimit, SyncedFoldersActivity.this, false); + perFolderMediaItemLimit, this, false); mediaFolders.addAll(MediaProvider.getVideoFolders(getContentResolver(), perFolderMediaItemLimit, - SyncedFoldersActivity.this, false)); + this, false)); List syncedFolderArrayList = mSyncedFolderProvider.getSyncedFolders(); List currentAccountSyncedFoldersList = new ArrayList<>(); @@ -286,11 +287,10 @@ private void load(final int perFolderMediaItemLimit, boolean force) { setListShown(true); if (!TextUtils.isEmpty(path)) { - for (int i = 0; i < syncFolderItems.size(); i++) { - SyncedFolderDisplayItem syncedFolderDisplayItem = syncFolderItems.get(i); - if (syncedFolderDisplayItem.getLocalPath().equalsIgnoreCase(path) && - syncedFolderDisplayItem.getType().getId().equals(type)) { - onSyncFolderSettingsClick(1, syncedFolderDisplayItem); + for(SyncedFolderDisplayItem syncFolderItem : syncFolderItems) { + if (syncFolderItem.getLocalPath().equalsIgnoreCase(path) && + syncFolderItem.getType().getId().equals(type)) { + onSyncFolderSettingsClick(1, syncFolderItem); } } } From e15f6a97ebc55a93957901e5450a709423793f75 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 17:46:59 +0200 Subject: [PATCH 17/20] set notification channel in constructor with newly introduced NotificationCompat constructor --- .../android/jobs/MediaFoldersDetectionJob.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 23d91f436038..e43a212f91df 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -57,6 +57,9 @@ public class MediaFoldersDetectionJob extends Job { public static final String KEY_MEDIA_FOLDER_PATH = "KEY_MEDIA_FOLDER_PATH"; public static final String KEY_MEDIA_FOLDER_TYPE = "KEY_MEDIA_FOLDER_TYPE"; + private static final String ACCOUNT_NAME_GLOBAL = "global"; + private static final String KEY_MEDIA_FOLDERS = "media_folders"; + @NonNull @Override protected Result onRunJob(@NonNull Params params) { @@ -84,11 +87,12 @@ protected Result onRunJob(@NonNull Params params) { imageMediaFolderPaths.add(videoMediaFolder.absolutePath); } - if (!TextUtils.isEmpty(arbitraryDataString = arbitraryDataProvider.getValue("global", "media_folders"))) { + arbitraryDataString = arbitraryDataProvider.getValue(ACCOUNT_NAME_GLOBAL, KEY_MEDIA_FOLDERS); + if (!TextUtils.isEmpty(arbitraryDataString)) { mediaFoldersModel = gson.fromJson(arbitraryDataString, MediaFoldersModel.class); // Store updated values - arbitraryDataProvider.storeOrUpdateKeyValue("global", "media_folders", gson.toJson(new + arbitraryDataProvider.storeOrUpdateKeyValue(ACCOUNT_NAME_GLOBAL, KEY_MEDIA_FOLDERS, gson.toJson(new MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths))); imageMediaFolderPaths.removeAll(mediaFoldersModel.getImageMediaFolders()); @@ -146,7 +150,8 @@ private void sendNotification(String contentTitle, String subtitle, Account acc intent.putExtra(KEY_MEDIA_FOLDER_TYPE, type); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); - NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context) + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder( + context, NotificationUtils.NOTIFICATION_CHANNEL_GENERAL) .setSmallIcon(R.drawable.notification_icon) .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.notification_icon)) .setColor(ThemeUtils.primaryColor(getContext())) @@ -157,10 +162,6 @@ private void sendNotification(String contentTitle, String subtitle, Account acc .setAutoCancel(true) .setContentIntent(pendingIntent); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_GENERAL); - } - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); From 73fd9d493131b656f5ff4ff1053a9f2241e9fa19 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 18:01:17 +0200 Subject: [PATCH 18/20] fix auto upload navigation for newly detected media folder triggered launch --- .../com/owncloud/android/jobs/MediaFoldersDetectionJob.java | 1 + src/main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index e43a212f91df..a097bcfc5ce6 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -148,6 +148,7 @@ private void sendNotification(String contentTitle, String subtitle, Account acc intent.putExtra(NotificationJob.KEY_NOTIFICATION_ACCOUNT, account.name); intent.putExtra(KEY_MEDIA_FOLDER_PATH, path); intent.putExtra(KEY_MEDIA_FOLDER_TYPE, type); + intent.putExtra(SyncedFoldersActivity.EXTRA_SHOW_SIDEBAR, true); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder( diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 6131a5a7c233..07146381530d 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -1,4 +1,4 @@ -/** +/* * Nextcloud Android client application * * @author Mario Danic From fff8aa6a306203a408150d9dda429ea4b32914bf Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 18:07:16 +0200 Subject: [PATCH 19/20] move sorting method back to its original place for a proper diff! --- .../ui/activity/SyncedFoldersActivity.java | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index a0b547ccf8a5..1eef6d29ce85 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -104,53 +104,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA private String path; private int type; - /** - * Sorts list of {@link SyncedFolderDisplayItem}s. - * - * @param syncFolderItemList list of items to be sorted - * @return sorted list of items - */ - public static List sortSyncedFolderItems(List - syncFolderItemList) { - Collections.sort(syncFolderItemList, new Comparator() { - public int compare(SyncedFolderDisplayItem f1, SyncedFolderDisplayItem f2) { - if (f1 == null && f2 == null) { - return 0; - } else if (f1 == null) { - return -1; - } else if (f2 == null) { - return 1; - } else if (f1.isEnabled() && f2.isEnabled()) { - return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( - f2.getFolderName().toLowerCase(Locale.getDefault())); - } else if (f1.isEnabled()) { - return -1; - } else if (f2.isEnabled()) { - return 1; - } else if (f1.getFolderName() == null && f2.getFolderName() == null) { - return 0; - } else if (f1.getFolderName() == null) { - return -1; - } else if (f2.getFolderName() == null) { - return 1; - } - for (String folder : PRIORITIZED_FOLDERS) { - if (folder.equals(f1.getFolderName()) && - folder.equals(f2.getFolderName())) { - return 0; - } else if (folder.equals(f1.getFolderName())) { - return -1; - } else if (folder.equals(f2.getFolderName())) { - return 1; - } - } - return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( - f2.getFolderName().toLowerCase(Locale.getDefault())); - } - }); - - return syncFolderItemList; - } @Override protected void onCreate(Bundle savedInstanceState) { @@ -296,6 +249,54 @@ private void load(final int perFolderMediaItemLimit, boolean force) { } } + /** + * Sorts list of {@link SyncedFolderDisplayItem}s. + * + * @param syncFolderItemList list of items to be sorted + * @return sorted list of items + */ + public static List sortSyncedFolderItems(List + syncFolderItemList) { + Collections.sort(syncFolderItemList, new Comparator() { + public int compare(SyncedFolderDisplayItem f1, SyncedFolderDisplayItem f2) { + if (f1 == null && f2 == null) { + return 0; + } else if (f1 == null) { + return -1; + } else if (f2 == null) { + return 1; + } else if (f1.isEnabled() && f2.isEnabled()) { + return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( + f2.getFolderName().toLowerCase(Locale.getDefault())); + } else if (f1.isEnabled()) { + return -1; + } else if (f2.isEnabled()) { + return 1; + } else if (f1.getFolderName() == null && f2.getFolderName() == null) { + return 0; + } else if (f1.getFolderName() == null) { + return -1; + } else if (f2.getFolderName() == null) { + return 1; + } + for (String folder : PRIORITIZED_FOLDERS) { + if (folder.equals(f1.getFolderName()) && + folder.equals(f2.getFolderName())) { + return 0; + } else if (folder.equals(f1.getFolderName())) { + return -1; + } else if (folder.equals(f2.getFolderName())) { + return 1; + } + } + return f1.getFolderName().toLowerCase(Locale.getDefault()).compareTo( + f2.getFolderName().toLowerCase(Locale.getDefault())); + } + }); + + return syncFolderItemList; + } + /** * merges two lists of {@link SyncedFolder} and {@link MediaFolder} items into one of SyncedFolderItems. * From 47217e7355117fd1356089039b0bf961d4371be2 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Thu, 5 Jul 2018 18:50:44 +0200 Subject: [PATCH 20/20] fix updating the (right) list item --- .../ui/activity/SyncedFoldersActivity.java | 8 +++----- .../ui/adapter/SyncedFolderAdapter.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 1eef6d29ce85..2267636230d8 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -240,11 +240,9 @@ private void load(final int perFolderMediaItemLimit, boolean force) { setListShown(true); if (!TextUtils.isEmpty(path)) { - for(SyncedFolderDisplayItem syncFolderItem : syncFolderItems) { - if (syncFolderItem.getLocalPath().equalsIgnoreCase(path) && - syncFolderItem.getType().getId().equals(type)) { - onSyncFolderSettingsClick(1, syncFolderItem); - } + int section = mAdapter.getSectionByLocalPathAndType(path, type); + if (section >= 0) { + onSyncFolderSettingsClick(section, mAdapter.get(section)); } } } diff --git a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java index f5bd355a86f1..e7af2e555a2e 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java @@ -108,6 +108,24 @@ public SyncedFolderDisplayItem get(int section) { return mSyncFolderItems.get(section); } + /** + * returns the section of a synced folder for the given local path and type. + * + * @param localPath the local path of the synced folder + * @param type the of the synced folder + * @return the section index of the looked up synced folder, -1 if not present + */ + public int getSectionByLocalPathAndType(String localPath, int type) { + for (int i = 0; i < mSyncFolderItems.size(); i++) { + if (mSyncFolderItems.get(i).getLocalPath().equalsIgnoreCase(localPath) && + mSyncFolderItems.get(i).getType().getId().equals(type)) { + return i; + } + } + + return -1; + } + @Override public void onBindHeaderViewHolder(final MainViewHolder holder, final int section, boolean expanded) { holder.mainHeaderContainer.setVisibility(View.VISIBLE);