diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index fa2ec0f3b399..1f602a461044 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -112,6 +112,7 @@
+
diff --git a/src/main/java/com/owncloud/android/db/PreferenceManager.java b/src/main/java/com/owncloud/android/db/PreferenceManager.java
index 5d42b7d1ff1b..76a4ee1615bb 100644
--- a/src/main/java/com/owncloud/android/db/PreferenceManager.java
+++ b/src/main/java/com/owncloud/android/db/PreferenceManager.java
@@ -67,6 +67,7 @@ public final class PreferenceManager {
private static final String PREF__FOLDER_SORT_ORDER = "folder_sort_order";
private static final String PREF__FOLDER_LAYOUT = "folder_layout";
public static final String PREF__LOCK_TIMESTAMP = "lock_timestamp";
+ private static final String PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications";
private PreferenceManager() {
}
@@ -550,6 +551,14 @@ public static void setShowDetailedTimestamp(Context context, boolean showDetaile
saveBooleanPreference(context, AUTO_PREF__SHOW_DETAILED_TIMESTAMP, showDetailedTimestamp);
}
+ public static boolean isShowMediaScanNotifications(Context context) {
+ return getDefaultSharedPreferences(context).getBoolean(PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS, true);
+ }
+
+ public static void setShowMediaScanNotifications(Context context, boolean value) {
+ saveBooleanPreference(context, PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS, value);
+ }
+
private static void saveBooleanPreference(Context context, String key, boolean value) {
SharedPreferences.Editor appPreferences = getDefaultSharedPreferences(context.getApplicationContext()).edit();
appPreferences.putBoolean(key, value).apply();
diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java
index ae0add5fdc72..5adc5a166f60 100644
--- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java
+++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java
@@ -23,8 +23,10 @@
import android.accounts.Account;
+import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -41,6 +43,8 @@
import com.owncloud.android.datamodel.MediaFoldersModel;
import com.owncloud.android.datamodel.MediaProvider;
import com.owncloud.android.datamodel.SyncedFolderProvider;
+import com.owncloud.android.db.PreferenceManager;
+import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.ManageAccountsActivity;
import com.owncloud.android.ui.activity.SyncedFoldersActivity;
import com.owncloud.android.ui.notifications.NotificationUtils;
@@ -48,10 +52,13 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Random;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+@SuppressFBWarnings(value = "PREDICTABLE_RANDOM", justification = "Only used for notification id.")
public class MediaFoldersDetectionJob extends Job {
public static final String TAG = "MediaFoldersDetectionJob";
@@ -60,6 +67,11 @@ public class MediaFoldersDetectionJob extends Job {
private static final String ACCOUNT_NAME_GLOBAL = "global";
private static final String KEY_MEDIA_FOLDERS = "media_folders";
+ public static final String NOTIFICATION_ID = "NOTIFICATION_ID";
+
+ private static final String DISABLE_DETECTION_CLICK = "DISABLE_DETECTION_CLICK";
+
+ private Random randomId = new Random();
@NonNull
@Override
@@ -78,11 +90,11 @@ protected Result onRunJob(@NonNull Params params) {
List imageMediaFolderPaths = new ArrayList<>();
List videoMediaFolderPaths = new ArrayList<>();
- for (MediaFolder imageMediaFolder: imageMediaFolders) {
+ for (MediaFolder imageMediaFolder : imageMediaFolders) {
imageMediaFolderPaths.add(imageMediaFolder.absolutePath);
}
- for (MediaFolder videoMediaFolder: videoMediaFolders) {
+ for (MediaFolder videoMediaFolder : videoMediaFolders) {
imageMediaFolderPaths.add(videoMediaFolder.absolutePath);
}
@@ -92,38 +104,41 @@ protected Result onRunJob(@NonNull Params params) {
// Store updated values
arbitraryDataProvider.storeOrUpdateKeyValue(ACCOUNT_NAME_GLOBAL, KEY_MEDIA_FOLDERS, gson.toJson(new
- MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths)));
+ MediaFoldersModel(imageMediaFolderPaths, videoMediaFolderPaths)));
- imageMediaFolderPaths.removeAll(mediaFoldersModel.getImageMediaFolders());
- videoMediaFolderPaths.removeAll(mediaFoldersModel.getVideoMediaFolders());
- if (!imageMediaFolderPaths.isEmpty() || !videoMediaFolderPaths.isEmpty()) {
- Account[] accounts = AccountUtils.getAccounts(getContext());
- List accountList = new ArrayList<>();
- for (Account account : accounts) {
- if (!arbitraryDataProvider.getBooleanValue(account, ManageAccountsActivity.PENDING_FOR_REMOVAL)) {
- accountList.add(account);
+ if (PreferenceManager.isShowMediaScanNotifications(context)) {
+ imageMediaFolderPaths.removeAll(mediaFoldersModel.getImageMediaFolders());
+ videoMediaFolderPaths.removeAll(mediaFoldersModel.getVideoMediaFolders());
+
+ if (!imageMediaFolderPaths.isEmpty() || !videoMediaFolderPaths.isEmpty()) {
+ 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 (String imageMediaFolder : imageMediaFolderPaths) {
- if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolder, account) == null) {
- sendNotification(String.format(context.getString(R.string.new_media_folder_detected),
+ for (Account account : accountList) {
+ for (String imageMediaFolder : imageMediaFolderPaths) {
+ if (syncedFolderProvider.findByLocalPathAndAccount(imageMediaFolder, account) == null) {
+ sendNotification(String.format(context.getString(R.string.new_media_folder_detected),
context.getString(R.string.new_media_folder_photos)),
- imageMediaFolder.substring(imageMediaFolder.lastIndexOf('/') + 1
- ),
- account, imageMediaFolder, 1);
+ imageMediaFolder.substring(imageMediaFolder.lastIndexOf('/') + 1
+ ),
+ account, imageMediaFolder, 1);
+ }
}
- }
- for (String videoMediaFolder : videoMediaFolderPaths) {
- if (syncedFolderProvider.findByLocalPathAndAccount(videoMediaFolder, account) == null) {
- sendNotification(String.format(context.getString(R.string.new_media_folder_detected),
+ for (String videoMediaFolder : videoMediaFolderPaths) {
+ if (syncedFolderProvider.findByLocalPathAndAccount(videoMediaFolder, account) == null) {
+ sendNotification(String.format(context.getString(R.string.new_media_folder_detected),
context.getString(R.string.new_media_folder_videos)),
- videoMediaFolder.substring(videoMediaFolder.lastIndexOf('/') + 1
- ),
- account, videoMediaFolder, 2);
+ videoMediaFolder.substring(videoMediaFolder.lastIndexOf('/') + 1
+ ),
+ account, videoMediaFolder, 2);
+ }
}
}
}
@@ -139,8 +154,11 @@ protected Result onRunJob(@NonNull Params params) {
}
private void sendNotification(String contentTitle, String subtitle, Account account, String path, int type) {
+ int notificationId = randomId.nextInt();
+
Context context = getContext();
Intent intent = new Intent(getContext(), SyncedFoldersActivity.class);
+ intent.putExtra(NOTIFICATION_ID, notificationId);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(NotificationJob.KEY_NOTIFICATION_ACCOUNT, account.name);
intent.putExtra(KEY_MEDIA_FOLDER_PATH, path);
@@ -149,22 +167,76 @@ private void sendNotification(String contentTitle, String subtitle, Account acco
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
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()))
- .setSubText(account.name)
- .setContentTitle(contentTitle)
- .setContentText(subtitle)
- .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
- .setAutoCancel(true)
- .setContentIntent(pendingIntent);
+ context, NotificationUtils.NOTIFICATION_CHANNEL_GENERAL)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.notification_icon))
+ .setColor(ThemeUtils.primaryColor(getContext()))
+ .setSubText(account.name)
+ .setContentTitle(contentTitle)
+ .setContentText(subtitle)
+ .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent);
+
+ Intent disableDetection = new Intent(context, NotificationReceiver.class);
+ disableDetection.putExtra(NOTIFICATION_ID, notificationId);
+ disableDetection.setAction(DISABLE_DETECTION_CLICK);
+
+ PendingIntent disableIntent = PendingIntent.getBroadcast(
+ context,
+ notificationId,
+ disableDetection,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ );
+ notificationBuilder.addAction(
+ new NotificationCompat.Action(
+ R.drawable.ic_close,
+ context.getString(R.string.disable_new_media_folder_detection_notifications),
+ disableIntent
+ )
+ );
+
+ PendingIntent configureIntent = PendingIntent.getActivity(
+ context,
+ notificationId,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ );
+ notificationBuilder.addAction(
+ new NotificationCompat.Action(
+ R.drawable.ic_settings,
+ context.getString(R.string.configure_new_media_folder_detection_notifications),
+ configureIntent
+ )
+ );
NotificationManager notificationManager = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
- notificationManager.notify(0, notificationBuilder.build());
+ notificationManager.notify(notificationId, notificationBuilder.build());
+ }
+ }
+
+
+ public static class NotificationReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ int notificationId = intent.getIntExtra(NOTIFICATION_ID, 0);
+
+ if (DISABLE_DETECTION_CLICK.equals(action)) {
+ Log_OC.d(this, "Disable media scan notifications");
+ PreferenceManager.setShowMediaScanNotifications(context, false);
+ cancel(context, notificationId);
+ }
+ }
+
+ private void cancel(Context context, int notificationId) {
+ NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
+ notificationManager.cancel(notificationId);
}
}
}
diff --git a/src/main/java/com/owncloud/android/ui/activity/Preferences.java b/src/main/java/com/owncloud/android/ui/activity/Preferences.java
index b28a94c4201f..4cbec4bd2f4f 100644
--- a/src/main/java/com/owncloud/android/ui/activity/Preferences.java
+++ b/src/main/java/com/owncloud/android/ui/activity/Preferences.java
@@ -96,6 +96,7 @@ public class Preferences extends PreferenceActivity
public static final String LOCK_DEVICE_CREDENTIALS = "device_credentials";
public final static String PREFERENCE_USE_FINGERPRINT = "use_fingerprint";
+ public static final String PREFERENCE_SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications";
private static final int ACTION_REQUEST_PASSCODE = 5;
private static final int ACTION_CONFIRM_PASSCODE = 6;
@@ -506,16 +507,30 @@ private void setupDetailsCategory(int accentColor, PreferenceScreen preferenceSc
boolean fDeviceCredentialsEnabled = getResources().getBoolean(R.bool.device_credentials_enabled);
boolean fShowHiddenFilesEnabled = getResources().getBoolean(R.bool.show_hidden_files_enabled);
boolean fSyncedFolderLightEnabled = getResources().getBoolean(R.bool.syncedFolder_light);
+ boolean fShowMediaScanNotifications = com.owncloud.android.db.PreferenceManager
+ .isShowMediaScanNotifications(this);
setupLockPreference(preferenceCategoryDetails, fPassCodeEnabled, fDeviceCredentialsEnabled);
setupHiddenFilesPreference(preferenceCategoryDetails, fShowHiddenFilesEnabled);
- if (!fPassCodeEnabled && !fDeviceCredentialsEnabled && !fShowHiddenFilesEnabled && fSyncedFolderLightEnabled) {
+ setupShowMediaScanNotifications(preferenceCategoryDetails, fShowMediaScanNotifications);
+
+ if (!fPassCodeEnabled && !fDeviceCredentialsEnabled && !fShowHiddenFilesEnabled && fSyncedFolderLightEnabled
+ && fShowMediaScanNotifications) {
preferenceScreen.removePreference(preferenceCategoryDetails);
}
}
+ private void setupShowMediaScanNotifications(PreferenceCategory preferenceCategoryDetails,
+ boolean fShowMediaScanNotifications) {
+ SwitchPreference mShowMediaScanNotifications = (SwitchPreference) findPreference(PREFERENCE_SHOW_MEDIA_SCAN_NOTIFICATIONS);
+
+ if (fShowMediaScanNotifications) {
+ preferenceCategoryDetails.removePreference(mShowMediaScanNotifications);
+ }
+ }
+
private void setupHiddenFilesPreference(PreferenceCategory preferenceCategoryDetails,
boolean fShowHiddenFilesEnabled) {
mShowHiddenFiles = (SwitchPreference) findPreference("show_hidden_files");
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 f6bc5ce4b72f..b612f933b1e3 100644
--- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java
@@ -23,6 +23,8 @@
import android.accounts.Account;
import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -131,6 +133,12 @@ protected void onCreate(Bundle savedInstanceState) {
path = getIntent().getStringExtra(MediaFoldersDetectionJob.KEY_MEDIA_FOLDER_PATH);
type = getIntent().getIntExtra(MediaFoldersDetectionJob.KEY_MEDIA_FOLDER_TYPE, -1);
+
+ // Cancel notification
+ int notificationId = getIntent().getIntExtra(MediaFoldersDetectionJob.NOTIFICATION_ID, 0);
+ NotificationManager notificationManager =
+ (NotificationManager) getSystemService(Activity.NOTIFICATION_SERVICE);
+ notificationManager.cancel(notificationId);
}
// setup toolbar
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 2c9bf150e312..6817d882d23d 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -45,6 +45,8 @@
Device credentials enabled
No device credentials have been set up.
Show hidden files
+ Show media scan notifications
+ Notify about newly found media folders
Delete history
Sync calendar & contacts
Set up DAVdroid (v1.3.0+) for current account
@@ -788,6 +790,8 @@
General notifications
Show notifications for new media folders and similar
New %1$s media folder detected.
+ Configure
+ Disable
photo
video
The server has reached end of life, please upgrade!
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index b88f7740b051..4354a36440c0 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -47,6 +47,10 @@
+