Settings: Add support for daily and weekly data usage cycles [2/2]
Change-Id: Ib43ca55f0f7fec5202982f5786176184809ab9f8
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cycle_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
||||
@@ -169,4 +169,17 @@
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Data Usage Cycle -->
|
||||
<string-array name="billing_cycle_type_entries" translatable="false">
|
||||
<item>@string/billing_cycle_type_monthly</item>
|
||||
<item>@string/billing_cycle_type_weekly</item>
|
||||
<item>@string/billing_cycle_type_daily</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="billing_cycle_type_values" translatable="false">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -369,4 +369,19 @@
|
||||
<!-- Force dark mode -->
|
||||
<string name="force_dark_title">Dark mode for third-party apps</string>
|
||||
<string name="force_dark_summary">Forces darker colors in apps lacking dark mode. Some screens may appear off.</string>
|
||||
|
||||
<!-- Data Usage Cycle -->
|
||||
<string name="billing_cycle_type_title">Mobile data usage cycle type</string>
|
||||
<string name="billing_cycle_type_monthly">Monthly</string>
|
||||
<string name="billing_cycle_type_weekly">Weekly</string>
|
||||
<string name="billing_cycle_type_daily">Daily</string>
|
||||
<string name="billing_cycle_less_than_one_hour_left">Less than 1 hour left</string>
|
||||
<string name="billing_cycle_hours_left">{count, plural,
|
||||
=1 {# hour left}
|
||||
other {# hours left}
|
||||
}</string>
|
||||
<string name="cycle_type_weekly_title">Usage cycle reset day</string>
|
||||
<string name="cycle_type_weekly_sub">Day of each week:\n1 = Monday</string>
|
||||
<string name="cycle_type_daily_title">Usage cycle reset hour</string>
|
||||
<string name="cycle_type_daily_sub">Hour of each day:</string>
|
||||
</resources>
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/billing_cycle">
|
||||
|
||||
<ListPreference
|
||||
android:key="billing_cycle_type"
|
||||
android:title="@string/billing_cycle_type_title"
|
||||
android:summary="%s"
|
||||
android:entries="@array/billing_cycle_type_entries"
|
||||
android:entryValues="@array/billing_cycle_type_values" />
|
||||
|
||||
<Preference
|
||||
android:key="billing_cycle"
|
||||
android:title="@string/app_usage_cycle" />
|
||||
|
||||
@@ -35,10 +35,12 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
@@ -69,10 +71,15 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
|
||||
private static final long MAX_DATA_LIMIT_BYTES = 50000 * GIB_IN_BYTES;
|
||||
|
||||
public static final int CYCLE_TYPE_MONTHLY = 0;
|
||||
public static final int CYCLE_TYPE_WEEKLY = 1;
|
||||
public static final int CYCLE_TYPE_DAILY = 2;
|
||||
|
||||
private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
|
||||
private static final String TAG_CYCLE_EDITOR = "cycleEditor";
|
||||
private static final String TAG_WARNING_EDITOR = "warningEditor";
|
||||
|
||||
private static final String KEY_BILLING_CYCLE_TYPE = "billing_cycle_type";
|
||||
private static final String KEY_BILLING_CYCLE = "billing_cycle";
|
||||
private static final String KEY_SET_DATA_WARNING = "set_data_warning";
|
||||
private static final String KEY_DATA_WARNING = "data_warning";
|
||||
@@ -82,6 +89,7 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkTemplate mNetworkTemplate;
|
||||
private ListPreference mBillingCycleType;
|
||||
private Preference mBillingCycle;
|
||||
private Preference mDataWarning;
|
||||
private TwoStatePreference mEnableDataWarning;
|
||||
@@ -104,6 +112,18 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
mEnableDataWarning = enableWarning;
|
||||
}
|
||||
|
||||
int getBillingCycleType() {
|
||||
if (services.mPolicyEditor.getPolicyCycleDay(mNetworkTemplate)
|
||||
!= NetworkPolicy.CYCLE_NONE) {
|
||||
return CYCLE_TYPE_MONTHLY;
|
||||
}
|
||||
if (services.mPolicyEditor.getPolicyCycleDayOfWeek(mNetworkTemplate)
|
||||
!= NetworkPolicy.CYCLE_NONE) {
|
||||
return CYCLE_TYPE_WEEKLY;
|
||||
}
|
||||
return CYCLE_TYPE_DAILY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
@@ -133,6 +153,8 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
mNetworkTemplate = NetworkTemplates.INSTANCE.getDefaultTemplate(context);
|
||||
}
|
||||
|
||||
mBillingCycleType = (ListPreference) findPreference(KEY_BILLING_CYCLE_TYPE);
|
||||
mBillingCycleType.setOnPreferenceChangeListener(this);
|
||||
mBillingCycle = findPreference(KEY_BILLING_CYCLE);
|
||||
mEnableDataWarning = (TwoStatePreference) findPreference(KEY_SET_DATA_WARNING);
|
||||
mEnableDataWarning.setOnPreferenceChangeListener(this);
|
||||
@@ -150,6 +172,7 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
|
||||
@VisibleForTesting
|
||||
void updatePrefs() {
|
||||
mBillingCycleType.setValue(String.valueOf(getBillingCycleType()));
|
||||
mBillingCycle.setSummary(null);
|
||||
final long warningBytes = services.mPolicyEditor.getPolicyWarningBytes(mNetworkTemplate);
|
||||
DataUsageFormatter dataUsageFormatter = new DataUsageFormatter(requireContext());
|
||||
@@ -211,6 +234,10 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
setPolicyWarningBytes(WARNING_DISABLED);
|
||||
}
|
||||
return true;
|
||||
} else if (mBillingCycleType == preference) {
|
||||
int value = Integer.parseInt((String) newValue);
|
||||
handleBillingCycleChanged(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -243,6 +270,28 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
updatePrefs();
|
||||
}
|
||||
|
||||
private void handleBillingCycleChanged(int cycleType) {
|
||||
if (getBillingCycleType() == cycleType) {
|
||||
// nothing changed
|
||||
return;
|
||||
}
|
||||
final String cycleTimezone = TimeZone.getDefault().getID();
|
||||
final NetworkPolicyEditor editor = services.mPolicyEditor;
|
||||
|
||||
switch (cycleType) {
|
||||
default:
|
||||
case CYCLE_TYPE_MONTHLY:
|
||||
editor.setPolicyCycleDay(mNetworkTemplate, 1, cycleTimezone);
|
||||
break;
|
||||
case CYCLE_TYPE_WEEKLY:
|
||||
editor.setPolicyCycleDayOfWeek(mNetworkTemplate, 1, cycleTimezone);
|
||||
break;
|
||||
case CYCLE_TYPE_DAILY:
|
||||
editor.setPolicyCycleHour(mNetworkTemplate, 0, cycleTimezone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkPolicyEditor getNetworkPolicyEditor() {
|
||||
return services.mPolicyEditor;
|
||||
@@ -395,13 +444,16 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
public static class CycleEditorFragment extends InstrumentedDialogFragment implements
|
||||
DialogInterface.OnClickListener {
|
||||
private static final String EXTRA_TEMPLATE = "template";
|
||||
private static final String EXTRA_CYCLE_TYPE = "cycle_type";
|
||||
private NumberPicker mCycleDayPicker;
|
||||
private int mCycleType = CYCLE_TYPE_MONTHLY;
|
||||
|
||||
public static void show(BillingCycleSettings parent) {
|
||||
if (!parent.isAdded()) return;
|
||||
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_TEMPLATE, parent.mNetworkTemplate);
|
||||
args.putInt(EXTRA_CYCLE_TYPE, parent.getBillingCycleType());
|
||||
|
||||
final CycleEditorFragment dialog = new CycleEditorFragment();
|
||||
dialog.setArguments(args);
|
||||
@@ -419,22 +471,39 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
final Context context = getActivity();
|
||||
final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
|
||||
final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
|
||||
final int cycleType = getArguments().getInt(EXTRA_CYCLE_TYPE);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
|
||||
|
||||
final View view = dialogInflater.inflate(R.layout.data_usage_cycle_editor, null, false);
|
||||
mCycleDayPicker = (NumberPicker) view.findViewById(R.id.cycle_day);
|
||||
final TextView textView = (TextView) view.findViewById(R.id.cycle_subtitle);
|
||||
|
||||
final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
|
||||
final int cycleDay = editor.getPolicyCycleDay(template);
|
||||
int cycleDay = editor.getPolicyCycleDay(template);
|
||||
int titleRedId = R.string.data_usage_cycle_editor_title;
|
||||
int minValue = 1;
|
||||
int maxValue = 31;
|
||||
if (cycleType == CYCLE_TYPE_WEEKLY) {
|
||||
cycleDay = editor.getPolicyCycleDayOfWeek(template);
|
||||
textView.setText(R.string.cycle_type_weekly_sub);
|
||||
titleRedId = R.string.cycle_type_weekly_title;
|
||||
maxValue = 7;
|
||||
} else if (cycleType == CYCLE_TYPE_DAILY) {
|
||||
cycleDay = editor.getPolicyCycleHour(template);
|
||||
textView.setText(R.string.cycle_type_daily_sub);
|
||||
titleRedId = R.string.cycle_type_daily_title;
|
||||
minValue = 0;
|
||||
maxValue = 23;
|
||||
}
|
||||
|
||||
mCycleDayPicker.setMinValue(1);
|
||||
mCycleDayPicker.setMaxValue(31);
|
||||
mCycleDayPicker.setMinValue(minValue);
|
||||
mCycleDayPicker.setMaxValue(maxValue);
|
||||
mCycleDayPicker.setValue(cycleDay);
|
||||
mCycleDayPicker.setWrapSelectorWheel(true);
|
||||
|
||||
Dialog dialog = builder.setTitle(R.string.data_usage_cycle_editor_title)
|
||||
Dialog dialog = builder.setTitle(titleRedId)
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.data_usage_cycle_editor_positive, this)
|
||||
.create();
|
||||
@@ -447,13 +516,20 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
|
||||
final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
|
||||
final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
|
||||
final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
|
||||
final int cycleType = getArguments().getInt(EXTRA_CYCLE_TYPE);
|
||||
|
||||
// clear focus to finish pending text edits
|
||||
mCycleDayPicker.clearFocus();
|
||||
|
||||
final int cycleDay = mCycleDayPicker.getValue();
|
||||
final String cycleTimezone = TimeZone.getDefault().getID();
|
||||
if (cycleType == CYCLE_TYPE_WEEKLY) {
|
||||
editor.setPolicyCycleDayOfWeek(template, cycleDay, cycleTimezone);
|
||||
} else if (cycleType == CYCLE_TYPE_DAILY) {
|
||||
editor.setPolicyCycleHour(template, cycleDay, cycleTimezone);
|
||||
} else {
|
||||
editor.setPolicyCycleDay(template, cycleDay, cycleTimezone);
|
||||
}
|
||||
target.updateDataUsage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class DataUsageSummaryPreference extends Preference {
|
||||
private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
|
||||
private static final long MILLIS_IN_A_HOUR = TimeUnit.HOURS.toMillis(1);
|
||||
private static final long WARNING_AGE = TimeUnit.HOURS.toMillis(6L);
|
||||
@VisibleForTesting
|
||||
static final Typeface SANS_SERIF_MEDIUM =
|
||||
@@ -221,16 +222,26 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
cycleTime.setText(getContext().getString(R.string.billing_cycle_none_left));
|
||||
} else {
|
||||
int daysLeft = (int) (millisLeft / MILLIS_IN_A_DAY);
|
||||
if (daysLeft >= 1) {
|
||||
MessageFormat msgFormat = new MessageFormat(
|
||||
getContext().getResources().getString(R.string.billing_cycle_days_left),
|
||||
Locale.getDefault());
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", daysLeft);
|
||||
cycleTime.setText(daysLeft < 1
|
||||
? getContext().getString(R.string.billing_cycle_less_than_one_day_left)
|
||||
cycleTime.setText(msgFormat.format(arguments));
|
||||
} else {
|
||||
int hoursLeft = (int) (millisLeft / MILLIS_IN_A_HOUR);
|
||||
MessageFormat msgFormat = new MessageFormat(
|
||||
getContext().getResources().getString(R.string.billing_cycle_hours_left),
|
||||
Locale.getDefault());
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", hoursLeft);
|
||||
cycleTime.setText(hoursLeft < 1
|
||||
? getContext().getString(R.string.billing_cycle_less_than_one_hour_left)
|
||||
: msgFormat.format(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateCarrierInfo(TextView carrierInfo) {
|
||||
|
||||
Reference in New Issue
Block a user