More sync status messages
Added messaging for 2 more scenarios where auto-sync could be off:
- Global auto-sync is turned off
- Device is in airplane mode
Once user has dismissed the tip in conversation list,
continue to show 5 more times in the form of a toast every time they
do a manual refresh.
Bug 9825835
Change-Id: I33b1f2f0ac56ea7ec70f64c765447c05f6ed9b0e
diff --git a/res/layout/conversation_sync_disabled_tip_view.xml b/res/layout/conversation_sync_disabled_tip_view.xml
index ad19f7c..4cc3556 100644
--- a/res/layout/conversation_sync_disabled_tip_view.xml
+++ b/res/layout/conversation_sync_disabled_tip_view.xml
@@ -13,21 +13,33 @@
android:background="@drawable/conversation_read_selector"
android:orientation="horizontal" >
- <TextView
- android:id="@+id/text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginBottom="12dp"
- android:layout_marginTop="12dp"
- android:layout_marginLeft="16dp"
- android:layout_marginStart="16dp"
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
android:layout_weight="1"
- android:duplicateParentState="true"
- android:fontFamily="sans-serif-light"
- android:text="@string/account_sync_off"
- android:textColor="@color/teaser_main_text"
- android:textSize="16sp" />
+ android:orientation="vertical"
+ android:padding="16dp" >
+
+ <TextView
+ android:id="@+id/text_line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:duplicateParentState="true"
+ android:fontFamily="sans-serif-light"
+ android:textColor="@color/teaser_main_text"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/text_line2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:duplicateParentState="true"
+ android:fontFamily="sans-serif-light"
+ android:text="@string/tap_to_enable_sync"
+ android:textColor="@color/teaser_main_text"
+ android:textSize="16sp" />
+
+ </LinearLayout>
<View
android:id="@+id/dismiss_separator"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d299cbe..9ac321f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -980,15 +980,18 @@
<!-- Tip for letting user know that their device auto-sync setting
is turned off, in case they are wondering why they are not
receiving any new mail. [CHAR LIMIT=250] -->
- <string name="auto_sync_off">Auto-sync is off.\nTurn on in Data usage settings.</string>
+ <string name="auto_sync_off">Auto-sync is off.</string>
<!-- Tip for letting user know that their account level sync setting
is turned off, in case they are wondering why they are not
receiving any new mail. [CHAR LIMIT=250] -->
- <string name="account_sync_off">Account sync is off.\nTurn on in Account settings.</string>
+ <string name="account_sync_off">Account sync is off.</string>
<!-- Tip for letting user know that airplane mode is enabled on
their device, in case they are wondering why they are not
receiving any new mail. [CHAR LIMIT=250] -->
<string name="airplane_mode_on">Airplane mode is on</string>
+
+ <!-- Tap to turn on sync in settings. [CHAR LIMIT=250] -->
+ <string name="tap_to_enable_sync" translatable="false">Tap to turn sync on.</string>
</resources>
diff --git a/src/com/android/mail/preferences/AccountPreferences.java b/src/com/android/mail/preferences/AccountPreferences.java
index 30fe7ba..7746330 100644
--- a/src/com/android/mail/preferences/AccountPreferences.java
+++ b/src/com/android/mail/preferences/AccountPreferences.java
@@ -120,7 +120,6 @@
PreferenceKeys.ACCOUNT_SYNC_OFF_DISMISSES, 0);
if (value != 0) {
getEditor().putInt(PreferenceKeys.ACCOUNT_SYNC_OFF_DISMISSES, 0).apply();
- notifyBackupPreferenceChanged();
}
}
@@ -128,6 +127,5 @@
final int value = getSharedPreferences().getInt(
PreferenceKeys.ACCOUNT_SYNC_OFF_DISMISSES, 0);
getEditor().putInt(PreferenceKeys.ACCOUNT_SYNC_OFF_DISMISSES, value + 1).apply();
- notifyBackupPreferenceChanged();
}
}
diff --git a/src/com/android/mail/preferences/MailPrefs.java b/src/com/android/mail/preferences/MailPrefs.java
index dd01586..1b46fc2 100644
--- a/src/com/android/mail/preferences/MailPrefs.java
+++ b/src/com/android/mail/preferences/MailPrefs.java
@@ -94,6 +94,9 @@
public static final String EXPERIMENT_AP_PARALLAX_DIRECTION_ALTERNATIVE
= "ap-parallax-direction";
+ public static final String GLOBAL_SYNC_OFF_DISMISSES = "num-of-dismisses-auto-sync-off";
+ public static final String AIRPLANE_MODE_ON_DISMISSES = "num-of-dismisses-airplane-mode-on";
+
public static final ImmutableSet<String> BACKUP_KEYS =
new ImmutableSet.Builder<String>()
.add(DEFAULT_REPLY_ALL)
@@ -426,4 +429,40 @@
return sharedPreferences
.getBoolean(PreferenceKeys.EXPERIMENT_AP_PARALLAX_DIRECTION_ALTERNATIVE, false);
}
+
+ public int getNumOfDismissesForAutoSyncOff() {
+ return getSharedPreferences().getInt(PreferenceKeys.GLOBAL_SYNC_OFF_DISMISSES, 0);
+ }
+
+ public void resetNumOfDismissesForAutoSyncOff() {
+ final int value = getSharedPreferences().getInt(
+ PreferenceKeys.GLOBAL_SYNC_OFF_DISMISSES, 0);
+ if (value != 0) {
+ getEditor().putInt(PreferenceKeys.GLOBAL_SYNC_OFF_DISMISSES, 0).apply();
+ }
+ }
+
+ public void incNumOfDismissesForAutoSyncOff() {
+ final int value = getSharedPreferences().getInt(
+ PreferenceKeys.GLOBAL_SYNC_OFF_DISMISSES, 0);
+ getEditor().putInt(PreferenceKeys.GLOBAL_SYNC_OFF_DISMISSES, value + 1).apply();
+ }
+
+ public int getNumOfDismissesForAirplaneModeOn() {
+ return getSharedPreferences().getInt(PreferenceKeys.AIRPLANE_MODE_ON_DISMISSES, 0);
+ }
+
+ public void resetNumOfDismissesForAirplaneModeOn() {
+ final int value = getSharedPreferences().getInt(
+ PreferenceKeys.AIRPLANE_MODE_ON_DISMISSES, 0);
+ if (value != 0) {
+ getEditor().putInt(PreferenceKeys.AIRPLANE_MODE_ON_DISMISSES, 0).apply();
+ }
+ }
+
+ public void incNumOfDismissesForAirplaneModeOn() {
+ final int value = getSharedPreferences().getInt(
+ PreferenceKeys.AIRPLANE_MODE_ON_DISMISSES, 0);
+ getEditor().putInt(PreferenceKeys.AIRPLANE_MODE_ON_DISMISSES, value + 1).apply();
+ }
}
diff --git a/src/com/android/mail/ui/ConversationListView.java b/src/com/android/mail/ui/ConversationListView.java
index 7eda905..48e08b9 100644
--- a/src/com/android/mail/ui/ConversationListView.java
+++ b/src/com/android/mail/ui/ConversationListView.java
@@ -21,10 +21,14 @@
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.mail.ConversationListContext;
import com.android.mail.R;
import com.android.mail.analytics.Analytics;
+import com.android.mail.preferences.AccountPreferences;
+import com.android.mail.preferences.MailPrefs;
+import com.android.mail.ui.ConversationSyncDisabledTipView.ReasonSyncOff;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
@@ -45,6 +49,11 @@
private static final int SYNC_STATUS_BAR_FADE_DURATION_IN_MILLIS = 150;
private static final int SYNC_TRIGGER_SHRINK_DURATION_IN_MILLIS = 250;
+ // Max number of times we display the same sync turned off warning message in a toast.
+ // After we reach this max, and device/account still has sync off, we assume user has
+ // intentionally disabled sync and no longer warn.
+ private static final int MAX_NUM_OF_SYNC_TOASTS = 5;
+
private static final String LOG_TAG = LogTag.getLogTag();
private View mSyncTriggerBar;
@@ -80,6 +89,9 @@
private ConversationListContext mConvListContext;
+ private final MailPrefs mMailPrefs;
+ private AccountPreferences mAccountPreferences;
+
// Instantiated through view inflation
@SuppressWarnings("unused")
public ConversationListView(Context context) {
@@ -103,6 +115,8 @@
mSyncTriggerBar.setVisibility(GONE);
}
};
+
+ mMailPrefs = MailPrefs.get(context);
}
@Override
@@ -128,6 +142,7 @@
protected void setConversationContext(ConversationListContext convListContext) {
mConvListContext = convListContext;
+ mAccountPreferences = AccountPreferences.get(getContext(), convListContext.account.name);
}
@Override
@@ -303,6 +318,42 @@
mSyncTriggerBar.setVisibility(GONE);
mSyncProgressBar.setVisibility(VISIBLE);
mSyncProgressBar.setAlpha(1f);
+
+ showToastIfSyncIsOff();
+ }
+ }
+
+ // If sync is turned off on this device or account, remind the user with a toast.
+ private void showToastIfSyncIsOff() {
+ final int reasonSyncOff = ConversationSyncDisabledTipView.calculateReasonSyncOff(
+ getContext(), mMailPrefs, mConvListContext.account, mAccountPreferences);
+ switch (reasonSyncOff) {
+ case ReasonSyncOff.AUTO_SYNC_OFF:
+ // TODO: make this an actionable toast, tapping on it goes to Settings
+ int num = mMailPrefs.getNumOfDismissesForAutoSyncOff();
+ if (num > 0 && num <= MAX_NUM_OF_SYNC_TOASTS) {
+ Toast.makeText(getContext(), R.string.auto_sync_off, Toast.LENGTH_SHORT)
+ .show();
+ mMailPrefs.incNumOfDismissesForAutoSyncOff();
+ }
+ break;
+ case ReasonSyncOff.ACCOUNT_SYNC_OFF:
+ // TODO: make this an actionable toast, tapping on it goes to Settings
+ num = mAccountPreferences.getNumOfDismissesForAccountSyncOff();
+ if (num > 0 && num <= MAX_NUM_OF_SYNC_TOASTS) {
+ Toast.makeText(getContext(), R.string.account_sync_off, Toast.LENGTH_SHORT)
+ .show();
+ mAccountPreferences.incNumOfDismissesForAccountSyncOff();
+ }
+ break;
+ case ReasonSyncOff.AIRPLANE_MODE_ON:
+ num = mMailPrefs.getNumOfDismissesForAirplaneModeOn();
+ if (num > 0 && num <= MAX_NUM_OF_SYNC_TOASTS) {
+ Toast.makeText(getContext(), R.string.airplane_mode_on, Toast.LENGTH_SHORT)
+ .show();
+ mMailPrefs.incNumOfDismissesForAirplaneModeOn();
+ }
+ break;
}
}
diff --git a/src/com/android/mail/ui/ConversationSyncDisabledTipView.java b/src/com/android/mail/ui/ConversationSyncDisabledTipView.java
index 98824ed..122914a 100644
--- a/src/com/android/mail/ui/ConversationSyncDisabledTipView.java
+++ b/src/com/android/mail/ui/ConversationSyncDisabledTipView.java
@@ -20,7 +20,9 @@
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
@@ -30,8 +32,11 @@
import com.android.mail.R;
import com.android.mail.browse.ConversationCursor;
import com.android.mail.preferences.AccountPreferences;
+import com.android.mail.preferences.MailPrefs;
import com.android.mail.providers.Account;
import com.android.mail.providers.Folder;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
/**
@@ -41,19 +46,38 @@
public class ConversationSyncDisabledTipView extends FrameLayout
implements ConversationSpecialItemView, SwipeableItemView {
+ private static final String LOG_TAG = LogTag.getLogTag();
+
private static int sScrollSlop = 0;
private static int sShrinkAnimationDuration;
private Account mAccount = null;
+ private final MailPrefs mMailPrefs;
private AccountPreferences mAccountPreferences;
private AnimatedAdapter mAdapter;
private View mSwipeableContent;
- private TextView mText;
+ private TextView mText1;
+ private TextView mText2;
+ private final OnClickListener mAutoSyncOffTextClickedListener;
+ private final OnClickListener mAccountSyncOffTextClickedListener;
private int mAnimatedHeight = -1;
private boolean mAcceptUserTaps = false;
+ private int mReasonSyncOff = ReasonSyncOff.NONE;
+
+ public interface ReasonSyncOff {
+ // Background sync is enabled for current account, do not display this tip
+ public static final int NONE = 0;
+ // Global auto-sync (affects all apps and all accounts) is turned off
+ public static final int AUTO_SYNC_OFF = 1;
+ // Global auto-sync is on, but Gmail app level sync is disabled for this particular account
+ public static final int ACCOUNT_SYNC_OFF = 2;
+ // Auto-sync is enabled at both device and account level, but device is in airplane mode
+ public static final int AIRPLANE_MODE_ON = 3;
+ }
+
public ConversationSyncDisabledTipView(final Context context) {
this(context, null);
}
@@ -73,6 +97,23 @@
sShrinkAnimationDuration = resources.getInteger(
R.integer.shrink_animation_duration);
}
+
+ mMailPrefs = MailPrefs.get(context);
+
+ mAutoSyncOffTextClickedListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ openGlobalAutoSyncSettingDialog();
+ }
+ };
+
+ mAccountSyncOffTextClickedListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO: Link to account level settings instead of top level settings.
+ Utils.showSettings(getContext(), mAccount);
+ }
+ };
}
public void bindAccount(Account account) {
@@ -89,15 +130,8 @@
protected void onFinishInflate() {
mSwipeableContent = findViewById(R.id.swipeable_content);
- mText = (TextView) findViewById(R.id.text);
- mText.setText(R.string.account_sync_off);
- mText.setClickable(true);
- mText.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Utils.showSettings(getContext(), mAccount);
- }
- });
+ mText1 = (TextView) findViewById(R.id.text_line1);
+ mText2 = (TextView) findViewById(R.id.text_line2);
findViewById(R.id.dismiss_button).setOnClickListener(new OnClickListener() {
@Override
@@ -117,19 +151,89 @@
if (mAccount == null || mAccount.syncAuthority == null) {
return false;
}
- boolean globalSyncAutomatically = ContentResolver.getMasterSyncAutomatically();
- // Not sure why directly passing mAccount to ContentResolver doesn't just work.
- android.accounts.Account account = new android.accounts.Account(
- mAccount.name, mAccount.type);
- if (globalSyncAutomatically &&
- ContentResolver.getSyncAutomatically(account, mAccount.syncAuthority)) {
- // Sync is on, clear the number of times users has dismissed this
- // warning so that next time sync is off, warning gets displayed again.
- mAccountPreferences.resetNumOfDismissesForAccountSyncOff();
- return false;
+
+ // TODO: do not show this message for folders/labels that are not set to sync.
+ // We need a solution that works for both Gmail and Email.
+
+ setReasonSyncOff(calculateReasonSyncOff(
+ getContext(), mMailPrefs, mAccount, mAccountPreferences));
+
+ if (mReasonSyncOff != ReasonSyncOff.NONE) {
+ LogUtils.i(LOG_TAG, "Sync is off with reason %d", mReasonSyncOff);
+ }
+
+ switch (mReasonSyncOff) {
+ case ReasonSyncOff.AUTO_SYNC_OFF:
+ return (mMailPrefs.getNumOfDismissesForAutoSyncOff() == 0);
+ case ReasonSyncOff.ACCOUNT_SYNC_OFF:
+ return (mAccountPreferences.getNumOfDismissesForAccountSyncOff() == 0);
+ case ReasonSyncOff.AIRPLANE_MODE_ON:
+ return (mMailPrefs.getNumOfDismissesForAirplaneModeOn() == 0);
+ default:
+ return false;
+ }
+ }
+
+ public static int calculateReasonSyncOff(Context context, MailPrefs mailPrefs,
+ Account account, AccountPreferences accountPreferences) {
+ if (!ContentResolver.getMasterSyncAutomatically()) {
+ // Global sync is turned off
+ accountPreferences.resetNumOfDismissesForAccountSyncOff();
+ mailPrefs.resetNumOfDismissesForAirplaneModeOn();
+ return ReasonSyncOff.AUTO_SYNC_OFF;
} else {
- // Sync is off
- return (mAccountPreferences.getNumOfDismissesForAccountSyncOff() == 0);
+ // Global sync is on, clear the number of times users has dismissed this
+ // warning so that next time global sync is off, warning gets displayed again.
+ mailPrefs.resetNumOfDismissesForAutoSyncOff();
+
+ // Now check for whether account level sync is on/off.
+ // Not sure why directly passing mAccount to ContentResolver doesn't just work.
+ android.accounts.Account acct = new android.accounts.Account(
+ account.name, account.type);
+ if (!ContentResolver.getSyncAutomatically(acct, account.syncAuthority)) {
+ // Account level sync is off
+ mailPrefs.resetNumOfDismissesForAirplaneModeOn();
+ return ReasonSyncOff.ACCOUNT_SYNC_OFF;
+ } else {
+ // Account sync is on, clear the number of times users has dismissed this
+ // warning so that next time sync is off, warning gets displayed again.
+ accountPreferences.resetNumOfDismissesForAccountSyncOff();
+
+ // Now check for whether airplane mode is on
+ if (Utils.isAirplaneModeOn(context)) {
+ return ReasonSyncOff.AIRPLANE_MODE_ON;
+ } else {
+ mailPrefs.resetNumOfDismissesForAirplaneModeOn();
+ return ReasonSyncOff.NONE;
+ }
+ }
+ }
+ }
+
+ private void setReasonSyncOff(int reason) {
+ if (mReasonSyncOff != reason) {
+ mReasonSyncOff = reason;
+ switch (mReasonSyncOff) {
+ case ReasonSyncOff.AUTO_SYNC_OFF:
+ mText1.setText(R.string.auto_sync_off);
+ mText2.setClickable(true);
+ mText2.setVisibility(View.VISIBLE);
+ mText2.setOnClickListener(mAutoSyncOffTextClickedListener);
+ break;
+ case ReasonSyncOff.ACCOUNT_SYNC_OFF:
+ mText1.setText(R.string.account_sync_off);
+ mText2.setClickable(true);
+ mText2.setVisibility(View.VISIBLE);
+ mText2.setOnClickListener(mAccountSyncOffTextClickedListener);
+ break;
+ case ReasonSyncOff.AIRPLANE_MODE_ON:
+ mText1.setText(R.string.airplane_mode_on);
+ mText2.setClickable(false);
+ mText2.setVisibility(View.GONE);
+ break;
+ default:
+ // Doesn't matter what mText is since this view is not displayed
+ }
}
}
@@ -170,7 +274,17 @@
@Override
public void dismiss() {
- mAccountPreferences.incNumOfDismissesForAccountSyncOff();
+ switch (mReasonSyncOff) {
+ case ReasonSyncOff.AUTO_SYNC_OFF:
+ mMailPrefs.incNumOfDismissesForAutoSyncOff();
+ break;
+ case ReasonSyncOff.ACCOUNT_SYNC_OFF:
+ mAccountPreferences.incNumOfDismissesForAccountSyncOff();
+ break;
+ case ReasonSyncOff.AIRPLANE_MODE_ON:
+ mMailPrefs.incNumOfDismissesForAirplaneModeOn();
+ break;
+ }
startDestroyAnimation();
}
@@ -219,4 +333,11 @@
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mAnimatedHeight);
}
}
+
+ private void openGlobalAutoSyncSettingDialog() {
+ final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {mAccount.syncAuthority});
+ getContext().startActivity(intent);
+ }
}
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index ef366d9..be57c51 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -38,6 +38,7 @@
import android.os.Build;
import android.os.Bundle;
import android.provider.Browser;
+import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -1376,4 +1377,9 @@
return context.getResources().getColor(R.color.list_background_color);
}
}
+
+ public static boolean isAirplaneModeOn(Context context) {
+ return Settings.System.getInt(context.getContentResolver(),
+ Settings.System.AIRPLANE_MODE_ON, 0) != 0;
+ }
}