Home | History | Annotate | Download | only in preferences
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.mail.preferences;
     17 
     18 import com.google.android.mail.common.base.Strings;
     19 import com.google.common.collect.ImmutableSet;
     20 
     21 import android.content.ContentUris;
     22 import android.content.Context;
     23 import android.database.Cursor;
     24 import android.media.RingtoneManager;
     25 import android.net.Uri;
     26 import android.provider.Settings;
     27 
     28 import com.android.mail.providers.Account;
     29 import com.android.mail.providers.Folder;
     30 import com.android.mail.providers.UIProvider.AccountCapabilities;
     31 import com.android.mail.providers.UIProvider.FolderCapabilities;
     32 import com.android.mail.utils.NotificationActionUtils.NotificationActionType;
     33 
     34 import java.util.LinkedHashSet;
     35 import java.util.Set;
     36 
     37 /**
     38  * Preferences relevant to one specific folder. In Email, this would only be used for an account's
     39  * inbox. In Gmail, this is used for every account/label pair.
     40  */
     41 public class FolderPreferences extends VersionedPrefs {
     42 
     43     private static final String PREFS_NAME_PREFIX = "Folder";
     44 
     45     public static final class PreferenceKeys {
     46         /** Boolean value indicating whether notifications are enabled */
     47         public static final String NOTIFICATIONS_ENABLED = "notifications-enabled";
     48         /** String value of the notification ringtone URI */
     49         public static final String NOTIFICATION_RINGTONE = "notification-ringtone";
     50         /** Boolean value indicating whether we should explicitly vibrate */
     51         public static final String NOTIFICATION_VIBRATE = "notification-vibrate";
     52         /**
     53          * Boolean value indicating whether we notify for every message (<code>true</code>), or just
     54          * once for the folder (<code>false</code>)
     55          */
     56         public static final String NOTIFICATION_NOTIFY_EVERY_MESSAGE =
     57                 "notification-notify-every-message";
     58 
     59         public static final ImmutableSet<String> BACKUP_KEYS =
     60                 new ImmutableSet.Builder<String>()
     61                         .add(NOTIFICATIONS_ENABLED)
     62                         .add(NOTIFICATION_RINGTONE)
     63                         .add(NOTIFICATION_VIBRATE)
     64                         .add(NOTIFICATION_NOTIFY_EVERY_MESSAGE)
     65                         .build();
     66     }
     67 
     68     private final Folder mFolder;
     69     /** An id that is constant across app installations. */
     70     private final String mPersistentId;
     71     private final boolean mUseInboxDefaultNotificationSettings;
     72 
     73     /**
     74      * @param accountEmail The account email. This must never change for the account.
     75      * @param folder The folder
     76      */
     77     public FolderPreferences(final Context context, final String accountEmail, final Folder folder,
     78             final boolean useInboxDefaultNotificationSettings) {
     79         this(context, accountEmail, folder, folder.persistentId,
     80                 useInboxDefaultNotificationSettings);
     81     }
     82 
     83     /**
     84      * A constructor that can be used when no {@link Folder} object is available (like during a
     85      * restore). This will function as expected except when calling
     86      * {@link #getDefaultNotificationActions(Context)}, so
     87      * {@link #FolderPreferences(Context, String, Folder, boolean)} should be used if at all
     88      * possible.
     89      *
     90      * @param accountEmail The account email. This must never change for the account.
     91      * @param persistentId An identifier for the folder that does not change across app
     92      *        installations.
     93      */
     94     public FolderPreferences(final Context context, final String accountEmail, final String persistentId,
     95             final boolean useInboxDefaultNotificationSettings) {
     96         this(context, accountEmail, null, persistentId, useInboxDefaultNotificationSettings);
     97     }
     98 
     99     private FolderPreferences(final Context context, final String accountEmail, final Folder folder,
    100             final String persistentId, final boolean useInboxDefaultNotificationSettings) {
    101         super(context, buildSharedPrefsName(accountEmail, persistentId));
    102         mFolder = folder;
    103         mPersistentId = persistentId;
    104         mUseInboxDefaultNotificationSettings = useInboxDefaultNotificationSettings;
    105     }
    106 
    107     private static String buildSharedPrefsName(final String account, final String persistentId) {
    108         return PREFS_NAME_PREFIX + '-' + account + '-' + persistentId;
    109     }
    110 
    111     @Override
    112     protected void performUpgrade(final int oldVersion, final int newVersion) {
    113         if (oldVersion > newVersion) {
    114             throw new IllegalStateException(
    115                     "You appear to have downgraded your app. Please clear app data.");
    116         }
    117     }
    118 
    119     @Override
    120     protected boolean canBackup(final String key) {
    121         if (mPersistentId == null) {
    122             return false;
    123         }
    124 
    125         return PreferenceKeys.BACKUP_KEYS.contains(key);
    126     }
    127 
    128     @Override
    129     protected Object getBackupValue(final String key, final Object value) {
    130         if (PreferenceKeys.NOTIFICATION_RINGTONE.equals(key)) {
    131             return getRingtoneTitle((String) value);
    132         }
    133 
    134         return super.getBackupValue(key, value);
    135     }
    136 
    137     @Override
    138     protected Object getRestoreValue(final String key, final Object value) {
    139         if (PreferenceKeys.NOTIFICATION_RINGTONE.equals(key)) {
    140             return getRingtoneUri((String) value);
    141         }
    142 
    143         return super.getBackupValue(key, value);
    144     }
    145 
    146     private String getRingtoneTitle(final String ringtoneUriString) {
    147         if (ringtoneUriString.length() == 0) {
    148             return ringtoneUriString;
    149         }
    150         final Uri uri = Uri.parse(ringtoneUriString);
    151         if (RingtoneManager.isDefault(uri)) {
    152             return ringtoneUriString;
    153         }
    154         final RingtoneManager ringtoneManager = new RingtoneManager(getContext());
    155         ringtoneManager.setType(RingtoneManager.TYPE_NOTIFICATION);
    156         final Cursor cursor = ringtoneManager.getCursor();
    157         try {
    158             while (cursor.moveToNext()) {
    159                 final Uri cursorUri = ContentUris.withAppendedId(
    160                         Uri.parse(cursor.getString(RingtoneManager.URI_COLUMN_INDEX)),
    161                         cursor.getLong(RingtoneManager.ID_COLUMN_INDEX));
    162                 if (cursorUri.toString().equals(ringtoneUriString)) {
    163                     final String title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
    164                     if (!Strings.isNullOrEmpty(title)) {
    165                         return title;
    166                     }
    167                 }
    168             }
    169         } finally {
    170             cursor.close();
    171         }
    172         return null;
    173     }
    174 
    175     private String getRingtoneUri(final String name) {
    176         if (name.length() == 0 || RingtoneManager.isDefault(Uri.parse(name))) {
    177             return name;
    178         }
    179 
    180         final RingtoneManager ringtoneManager = new RingtoneManager(getContext());
    181         ringtoneManager.setType(RingtoneManager.TYPE_NOTIFICATION);
    182         final Cursor cursor = ringtoneManager.getCursor();
    183         try {
    184             while (cursor.moveToNext()) {
    185                 String title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
    186                 if (name.equals(title)) {
    187                     Uri uri = ContentUris.withAppendedId(
    188                             Uri.parse(cursor.getString(RingtoneManager.URI_COLUMN_INDEX)),
    189                             cursor.getLong(RingtoneManager.ID_COLUMN_INDEX));
    190                     return uri.toString();
    191                 }
    192             }
    193         } finally {
    194             cursor.close();
    195         }
    196         return null;
    197     }
    198 
    199     /**
    200      * If <code>true</code>, we use inbox-defaults for notification settings. If <code>false</code>,
    201      * we use standard defaults.
    202      */
    203     private boolean getUseInboxDefaultNotificationSettings() {
    204         return mUseInboxDefaultNotificationSettings;
    205     }
    206 
    207     public boolean isNotificationsEnabledSet() {
    208         return getSharedPreferences().contains(PreferenceKeys.NOTIFICATIONS_ENABLED);
    209     }
    210 
    211     public boolean areNotificationsEnabled() {
    212         return getSharedPreferences().getBoolean(
    213                 PreferenceKeys.NOTIFICATIONS_ENABLED, getUseInboxDefaultNotificationSettings());
    214     }
    215 
    216     public void setNotificationsEnabled(final boolean enabled) {
    217         getEditor().putBoolean(PreferenceKeys.NOTIFICATIONS_ENABLED, enabled).apply();
    218         notifyBackupPreferenceChanged();
    219     }
    220 
    221     public String getNotificationRingtoneUri() {
    222         return getSharedPreferences().getString(PreferenceKeys.NOTIFICATION_RINGTONE,
    223                 Settings.System.DEFAULT_NOTIFICATION_URI.toString());
    224     }
    225 
    226     public void setNotificationRingtoneUri(final String uri) {
    227         getEditor().putString(PreferenceKeys.NOTIFICATION_RINGTONE, uri).apply();
    228         notifyBackupPreferenceChanged();
    229     }
    230 
    231     public boolean isNotificationVibrateEnabled() {
    232         return getSharedPreferences().getBoolean(PreferenceKeys.NOTIFICATION_VIBRATE, false);
    233     }
    234 
    235     public void setNotificationVibrateEnabled(final boolean enabled) {
    236         getEditor().putBoolean(PreferenceKeys.NOTIFICATION_VIBRATE, enabled).apply();
    237         notifyBackupPreferenceChanged();
    238     }
    239 
    240     public boolean isEveryMessageNotificationEnabled() {
    241         return getSharedPreferences()
    242                 .getBoolean(PreferenceKeys.NOTIFICATION_NOTIFY_EVERY_MESSAGE, false);
    243     }
    244 
    245     public void setEveryMessageNotificationEnabled(final boolean enabled) {
    246         getEditor().putBoolean(PreferenceKeys.NOTIFICATION_NOTIFY_EVERY_MESSAGE, enabled).apply();
    247         notifyBackupPreferenceChanged();
    248     }
    249 
    250     public Set<String> getNotificationActions(final Account account) {
    251         final boolean supportsArchiveRemoveLabel =
    252                 mFolder.supportsCapability(FolderCapabilities.ARCHIVE)
    253                 || mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION);
    254         final boolean preferDelete = MailPrefs.RemovalActions.DELETE.equals(
    255                 MailPrefs.get(getContext()).getRemovalAction(
    256                         account.supportsCapability(AccountCapabilities.ARCHIVE)));
    257         final NotificationActionType destructiveActionType =
    258                 supportsArchiveRemoveLabel && !preferDelete ?
    259                         NotificationActionType.ARCHIVE_REMOVE_LABEL : NotificationActionType.DELETE;
    260         final String destructiveAction = destructiveActionType.getPersistedValue();
    261 
    262         final String replyAction =
    263                 MailPrefs.get(getContext()).getDefaultReplyAll()
    264                         ? NotificationActionType.REPLY_ALL.getPersistedValue()
    265                         : NotificationActionType.REPLY.getPersistedValue();
    266 
    267         final Set<String> notificationActions = new LinkedHashSet<String>(2);
    268         notificationActions.add(destructiveAction);
    269         notificationActions.add(replyAction);
    270 
    271         return notificationActions;
    272     }
    273 }
    274