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