Skip to content

Commit

Permalink
#77 Added an option to set Sync frequency of any individual account t…
Browse files Browse the repository at this point in the history
…o a custom value or to a common default value set for all accounts in Settings->Syncing->Default Sync frequency
  • Loading branch information
yvolk committed Jul 5, 2016
1 parent bd42246 commit 34dd223
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 63 deletions.
20 changes: 11 additions & 9 deletions app/src/main/java/org/andstatus/app/account/AccountData.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public static AccountData fromAndroidAccount(MyContext myContext, Account androi
ContentResolver.getIsSyncable(androidAccount, MatchedUri.AUTHORITY) != 0);
accountData.setDataBoolean(MyAccount.KEY_IS_SYNCED_AUTOMATICALLY,
ContentResolver.getSyncAutomatically(androidAccount, MatchedUri.AUTHORITY));
accountData.setDataLong(MyPreferences.KEY_SYNC_FREQUENCY_SECONDS, getSyncFrequencySeconds(androidAccount));
return accountData;
}

Expand Down Expand Up @@ -109,12 +108,13 @@ void saveDataToAndroidAccount(MyContext myContext, Account androidAccount, SaveR
AccountData oldData = fromAndroidAccount(myContext, androidAccount);
result.changed = !this.equals(oldData);
if (result.changed) {

long syncFrequencySeconds = getDataLong(MyPreferences.KEY_SYNC_FREQUENCY_SECONDS, 0);
if (syncFrequencySeconds > 0
&& syncFrequencySeconds != getSyncFrequencySeconds(androidAccount)) {
result.changed = true;
setSyncFrequencySeconds(androidAccount, syncFrequencySeconds);
if (syncFrequencySeconds <= 0) {
syncFrequencySeconds = MyPreferences.getSyncFrequencySeconds();
}
setSyncFrequencySeconds(androidAccount, syncFrequencySeconds);

boolean isSyncable = getDataBoolean(MyAccount.KEY_IS_SYNCABLE, true);
if (isSyncable != (ContentResolver.getIsSyncable(androidAccount, MatchedUri.AUTHORITY) != 0)) {
ContentResolver.setIsSyncable(androidAccount, MatchedUri.AUTHORITY, isSyncable ? 1
Expand Down Expand Up @@ -156,14 +156,16 @@ public int hashCode() {
return text.hashCode();
}

private void setSyncFrequencySeconds(Account androidAccount, long syncFrequencySeconds) {
public static void setSyncFrequencySeconds(Account androidAccount, long syncFrequencySeconds) {
// See
// http://developer.android.com/reference/android/content/ContentResolver.html#addPeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long)
// and
// http://stackoverflow.com/questions/11090604/android-syncadapter-automatically-initialize-syncing
ContentResolver.removePeriodicSync(androidAccount, MatchedUri.AUTHORITY, new Bundle());
if (syncFrequencySeconds > 0) {
ContentResolver.addPeriodicSync(androidAccount, MatchedUri.AUTHORITY, new Bundle(), syncFrequencySeconds);
if (syncFrequencySeconds != getSyncFrequencySeconds(androidAccount)) {
ContentResolver.removePeriodicSync(androidAccount, MatchedUri.AUTHORITY, new Bundle());
if (syncFrequencySeconds > 0) {
ContentResolver.addPeriodicSync(androidAccount, MatchedUri.AUTHORITY, new Bundle(), syncFrequencySeconds);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.andstatus.app.R;
import org.andstatus.app.account.MyAccount.CredentialsVerificationStatus;
import org.andstatus.app.context.MyContextHolder;
import org.andstatus.app.context.MyPreferences;
import org.andstatus.app.context.MySettingsActivity;
import org.andstatus.app.msg.TimelineActivity;
import org.andstatus.app.net.http.ConnectionException;
Expand All @@ -62,6 +63,8 @@
import org.andstatus.app.util.MyLog;
import org.andstatus.app.util.MyUrlSpan;
import org.andstatus.app.util.RelativeTime;
import org.andstatus.app.util.SharedPreferencesUtil;
import org.andstatus.app.util.StringUtils;
import org.andstatus.app.util.TriState;
import org.json.JSONException;
import org.json.JSONObject;
Expand Down Expand Up @@ -286,6 +289,7 @@ private void updateScreen() {
showVerifyCredentialsButton();
showDefaultAccountCheckbox();
showIsSyncedAutomatically();
showSyncFrequency();
showLastSyncSucceededDate();
}

Expand Down Expand Up @@ -494,6 +498,40 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
});
}

private void showSyncFrequency() {
TextView label = (TextView) findFragmentViewById(R.id.label_sync_frequency);
EditText view = (EditText) findFragmentViewById(R.id.sync_frequency);
if (label != null && view != null) {
String labelText = getText(R.string.sync_frequency_minutes).toString() + " " +
SharedPreferencesUtil.getSummaryForListPreference(this, Long.toString(MyPreferences.getSyncFrequencySeconds()),
R.array.fetch_frequency_values, R.array.fetch_frequency_entries,
R.string.summary_preference_frequency);
label.setText(labelText);

String value = state.builder.getAccount().getSyncFrequencySeconds() <= 0 ? "" :
Long.toString(state.builder.getAccount().getSyncFrequencySeconds() / 60);
view.setText(value);
view.setHint(labelText);
view.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Empty
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Empty
}

@Override
public void afterTextChanged(Editable s) {
long value = StringUtils.toLong(s.toString());
state.builder.setSyncFrequencySeconds(value > 0 ? value * 60 : 0);
}
});
}
}

private void showLastSyncSucceededDate() {
long lastSyncSucceededDate = state.getAccount().getLastSyncSucceededDate(MyContextHolder.get());
MyUrlSpan.showText((TextView) findFragmentViewById(R.id.last_synced),
Expand Down
30 changes: 19 additions & 11 deletions app/src/main/java/org/andstatus/app/account/MyAccount.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,6 @@ private void fixInconsistenciesWithChangedEnvironmentSilently() {
assignUserId();
MyLog.e(TAG, "MyAccount '" + myAccount.getAccountName() + "' was not connected to the User table. UserId=" + myAccount.userId);
}
if (myAccount.syncFrequencySeconds == 0) {
changed = true;
}
if (!myAccount.getCredentialsPresent()
&& myAccount.getCredentialsVerified() == CredentialsVerificationStatus.SUCCEEDED) {
MyLog.e(TAG, "User's credentials were lost?! Fixing...");
Expand Down Expand Up @@ -311,9 +308,6 @@ SaveResult saveSilently() {
myAccount.accountData.setPersistent(true);
myAccount.accountData.setDataBoolean(MyAccount.KEY_IS_SYNCABLE, myAccount.isSyncable);
myAccount.accountData.setDataBoolean(MyAccount.KEY_IS_SYNCED_AUTOMATICALLY, myAccount.isSyncedAutomatically);
if (myAccount.syncFrequencySeconds == 0) {
setSyncFrequency(MyPreferences.getSyncFrequencySeconds());
}
myAccount.accountData.setDataLong(MyPreferences.KEY_SYNC_FREQUENCY_SECONDS, myAccount.syncFrequencySeconds);
myAccount.accountData.setDataInt(KEY_VERSION, myAccount.version);
if (androidAccount != null) {
Expand Down Expand Up @@ -553,7 +547,7 @@ protected int getVersion() {
return myAccount.version;
}

void setSyncFrequency(long syncFrequencySeconds) {
void setSyncFrequencySeconds(long syncFrequencySeconds) {
myAccount.syncFrequencySeconds = syncFrequencySeconds;
}

Expand Down Expand Up @@ -588,7 +582,7 @@ public boolean onOriginNameChanged(String originNameNew) {
private CredentialsVerificationStatus credentialsVerified = CredentialsVerificationStatus.NEVER;
/** Is this user authenticated with OAuth? */
private boolean isOAuth = true;
private long syncFrequencySeconds;
private long syncFrequencySeconds = 0;
private boolean isSyncable = true;
private boolean isSyncedAutomatically = true;
private final int version;
Expand Down Expand Up @@ -877,7 +871,7 @@ public void requestSync() {
}
}

private Account getExistingAndroidAccount() {
Account getExistingAndroidAccount() {
Account androidAccount = null;
// Let's check if there is such an Android Account already
android.accounts.AccountManager am = AccountManager.get(MyContextHolder.get().context());
Expand All @@ -890,7 +884,19 @@ private Account getExistingAndroidAccount() {
}
return androidAccount;
}


public long getSyncFrequencySeconds() {
return syncFrequencySeconds;
}

public long getEffectiveSyncFrequencySeconds() {
long effectiveSyncFrequencySeconds = getSyncFrequencySeconds();
if (effectiveSyncFrequencySeconds <= 0) {
effectiveSyncFrequencySeconds= MyPreferences.getSyncFrequencySeconds();
}
return effectiveSyncFrequencySeconds;
}

@Override
public String toString() {
String members = (isValid() ? "" : "(invalid) ") + "accountName:" + getAccountName() + ",";
Expand All @@ -916,7 +922,9 @@ public String toString() {
if (connection == null) {
members += "connection:null,";
}
members += "syncFrequency:" + syncFrequencySeconds + ",";
if (syncFrequencySeconds > 0) {
members += "syncFrequency:" + syncFrequencySeconds + ",";
}
if (isSyncable) {
members += "syncable,";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.andstatus.app.account;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
Expand Down Expand Up @@ -369,12 +370,15 @@ public void setDefaultAccount(MyAccount ma) {
.putString(KEY_DEFAULT_ACCOUNT_NAME, defaultAccountName).commit();
}

public void onMyPreferencesChanged(MyContext myContext) {
public void onDefaultSyncFrequencyChanged() {
long syncFrequencySeconds = MyPreferences.getSyncFrequencySeconds();
for (MyAccount ma : mAccounts.values()) {
Builder builder = Builder.fromMyAccount(myContext, ma, "onMyPreferencesChanged", false);
builder.setSyncFrequency(syncFrequencySeconds);
builder.save();
if (ma.getSyncFrequencySeconds() <= 0) {
Account account = ma.getExistingAndroidAccount();
if (account != null) {
AccountData.setSyncFrequencySeconds(account, syncFrequencySeconds);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
showDontSynchronizeOldMessages();
break;
case MyPreferences.KEY_SYNC_FREQUENCY_SECONDS:
MyContextHolder.get().persistentAccounts().onMyPreferencesChanged(MyContextHolder.get());
MyContextHolder.get().persistentAccounts().onDefaultSyncFrequencyChanged();
showFrequency();
break;
case MyPreferences.KEY_CONNECTION_TIMEOUT_SECONDS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
public enum DisplayedInSelector implements SelectableEnum {
ALWAYS("always", R.string.always),
IN_CONTEXT("in_context", R.string.in_context),
NO("no", R.string.no);
NEVER("no", R.string.never);

/** Code - identifier of the type */
private final String code;
Expand All @@ -37,15 +37,15 @@ public enum DisplayedInSelector implements SelectableEnum {
this.titleResId = titleResId;
}

/** Returns the enum or NO */
/** Returns the enum or NEVER */
@NonNull
public static DisplayedInSelector load(String strCode) {
for (DisplayedInSelector value : DisplayedInSelector.values()) {
if (value.code.equals(strCode)) {
return value;
}
}
return NO;
return NEVER;
}

/** String to be used for persistence */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

Expand Down Expand Up @@ -149,7 +145,7 @@ public List<Timeline> getFiltered(boolean isForSelector,
boolean include;
if (isForSelector && timeline.isDisplayedInSelector() == DisplayedInSelector.ALWAYS) {
include = true;
} else if (isForSelector && timeline.isDisplayedInSelector() == DisplayedInSelector.NO) {
} else if (isForSelector && timeline.isDisplayedInSelector() == DisplayedInSelector.NEVER) {
include = false;
} else {
include = isTimelineCombined.isBoolean(timeline.isCombined()) &&
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/org/andstatus/app/timeline/Timeline.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public class Timeline implements Comparable<Timeline> {
private volatile boolean isSyncedAutomatically = false;

/** If the timeline should be shown in a Timeline selector */
private volatile DisplayedInSelector isDisplayedInSelector = DisplayedInSelector.NO;
private volatile DisplayedInSelector isDisplayedInSelector = DisplayedInSelector.NEVER;
/** Used for sorting timelines in a selector */
private volatile long selectorOrder = 0;

Expand Down Expand Up @@ -717,9 +717,9 @@ public boolean isUserDifferentFromAccount() {
* @return true if it's time to auto update this timeline
*/
public boolean isTimeToAutoSync() {
long frequencyMs = MyPreferences.getSyncFrequencyMs();
long syncFrequencyMs = myAccount.getEffectiveSyncFrequencySeconds() * 1000;
long passedMs = System.currentTimeMillis() - getSyncSucceededDate();
boolean blnOut = passedMs > frequencyMs;
boolean blnOut = passedMs > syncFrequencyMs;

if (blnOut && MyLog.isVerboseEnabled()) {
MyLog.v(this, "It's time to auto update " + this +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

protected void showDisplayedInSelector(View parentView, final TimelineListViewItem item) {
CheckBox view = (CheckBox) parentView.findViewById(R.id.displayedInSelector);
MyCheckBox.show(parentView, R.id.displayedInSelector, item.timeline.isDisplayedInSelector() != DisplayedInSelector.NO,
MyCheckBox.show(parentView, R.id.displayedInSelector, item.timeline.isDisplayedInSelector() != DisplayedInSelector.NEVER,
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Expand All @@ -265,7 +265,7 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ActivityRequestCode.SELECT_DISPLAYED_IN_SELECTOR,
DisplayedInSelector.class).show(TimelineList.this);
} else {
item.timeline.setDisplayedInSelector(DisplayedInSelector.NO);
item.timeline.setDisplayedInSelector(DisplayedInSelector.NEVER);
buttonView.setText("");
MyLog.v("isDisplayedInSelector", (isChecked ? "+ " : "- ") + item.timeline);
}
Expand Down
35 changes: 20 additions & 15 deletions app/src/main/java/org/andstatus/app/util/SharedPreferencesUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,28 @@ public static void showListPreference(PreferenceFragment fragment, String prefer
int valuesR, int entriesR, int summaryR) {
ListPreference listPref = (ListPreference) fragment.findPreference(preferenceKey);
if (listPref != null) {
String[] values = fragment.getResources().getStringArray(valuesR);
String[] entries = fragment.getResources().getStringArray(entriesR);
String summary = entries[0];
String listValue = listPref.getValue();
for (int i = 0; i < values.length; i++) {
if (listValue.equals(values[i])) {
summary = entries[i];
break;
}
}
if (summaryR != 0) {
MessageFormat messageFormat = new MessageFormat(fragment.getText(summaryR)
.toString());
summary = messageFormat.format(new Object[] { summary });
listPref.setSummary(getSummaryForListPreference(fragment.getActivity(),
listPref.getValue(), valuesR, entriesR, summaryR));
}
}

public static String getSummaryForListPreference(Context context, String listValue,
int valuesR, int entriesR, int summaryR) {
String[] values = context.getResources().getStringArray(valuesR);
String[] entries = context.getResources().getStringArray(entriesR);
String summary = entries[0];
for (int i = 0; i < values.length; i++) {
if (listValue.equals(values[i])) {
summary = entries[i];
break;
}
listPref.setSummary(summary);
}
if (summaryR != 0) {
MessageFormat messageFormat = new MessageFormat(context.getText(summaryR)
.toString());
summary = messageFormat.format(new Object[] { summary });
}
return summary;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/org/andstatus/app/util/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@ public static String notEmpty(String value, String valueIfEmpty) {
public static String notNull(String value) {
return value == null ? "" : value;
}

public static long toLong(String s) {
long value = 0;
try {
value = Long.parseLong(s);
} catch (NumberFormatException e) {
MyLog.ignored(s, e);
}
return value;
}
}

0 comments on commit 34dd223

Please sign in to comment.