First pass at detailed app data usage, policy.
Fragment to show application data usage details, including chart with inspection ranges. Button that invokes ACTION_MANAGE_NETWORK_USAGE towards application, and UID-specific policy controls. Fragment is launched when clicking list items from data usage summary page. Change-Id: Ie1564aa8af98e1a7083817a997059a5a7b1caa50
This commit is contained in:
56
res/layout/data_usage_detail.xml
Normal file
56
res/layout/data_usage_detail.xml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/chart_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="233dip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dip" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/data_usage_app_settings"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dip"
|
||||||
|
android:text="@string/data_usage_app_settings" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/switches"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
@@ -3395,4 +3395,11 @@ found in the list of installed applications.</string>
|
|||||||
<!-- Toggle switch title for enabling 4G data network connection. [CHAR LIMIT=32] -->
|
<!-- Toggle switch title for enabling 4G data network connection. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_enable_4g">4G data</string>
|
<string name="data_usage_enable_4g">4G data</string>
|
||||||
|
|
||||||
|
<!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
|
||||||
|
<string name="data_usage_app_settings">View application settings</string>
|
||||||
|
<!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=32] -->
|
||||||
|
<string name="data_usage_app_restrict_background">Restrict background data usage</string>
|
||||||
|
<!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=32] -->
|
||||||
|
<string name="data_usage_app_restrict_background_summary">Only allow application background data when using an unlimited network</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
224
src/com/android/settings/DataUsageAppDetail.java
Normal file
224
src/com/android/settings/DataUsageAppDetail.java
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings;
|
||||||
|
|
||||||
|
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||||
|
import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
|
||||||
|
import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
|
||||||
|
import static com.android.settings.DataUsageSummary.getHistoryBounds;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.net.INetworkPolicyManager;
|
||||||
|
import android.net.INetworkStatsService;
|
||||||
|
import android.net.NetworkStatsHistory;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
|
import android.text.format.Formatter;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.settings.widget.DataUsageChartView;
|
||||||
|
import com.android.settings.widget.DataUsageChartView.DataUsageChartListener;
|
||||||
|
|
||||||
|
public class DataUsageAppDetail extends Fragment {
|
||||||
|
private static final String TAG = "DataUsage";
|
||||||
|
private static final boolean LOGD = true;
|
||||||
|
|
||||||
|
private int mUid;
|
||||||
|
|
||||||
|
private INetworkStatsService mStatsService;
|
||||||
|
private INetworkPolicyManager mPolicyService;
|
||||||
|
|
||||||
|
private CheckBoxPreference mRestrictBackground;
|
||||||
|
private View mRestrictBackgroundView;
|
||||||
|
|
||||||
|
private FrameLayout mChartContainer;
|
||||||
|
private TextView mTitle;
|
||||||
|
private TextView mText1;
|
||||||
|
private Button mAppSettings;
|
||||||
|
private LinearLayout mSwitches;
|
||||||
|
|
||||||
|
private DataUsageChartView mChart;
|
||||||
|
|
||||||
|
private int mUidPolicy;
|
||||||
|
private NetworkStatsHistory mHistory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
mStatsService = INetworkStatsService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||||
|
mPolicyService = INetworkPolicyManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
final Context context = inflater.getContext();
|
||||||
|
final View view = inflater.inflate(R.layout.data_usage_detail, container, false);
|
||||||
|
|
||||||
|
mChartContainer = (FrameLayout) view.findViewById(R.id.chart_container);
|
||||||
|
mTitle = (TextView) view.findViewById(android.R.id.title);
|
||||||
|
mText1 = (TextView) view.findViewById(android.R.id.text1);
|
||||||
|
mAppSettings = (Button) view.findViewById(R.id.data_usage_app_settings);
|
||||||
|
mSwitches = (LinearLayout) view.findViewById(R.id.switches);
|
||||||
|
|
||||||
|
mRestrictBackground = new CheckBoxPreference(context);
|
||||||
|
mRestrictBackground.setTitle(R.string.data_usage_app_restrict_background);
|
||||||
|
mRestrictBackground.setSummary(R.string.data_usage_app_restrict_background_summary);
|
||||||
|
|
||||||
|
// kick refresh once to force-create views
|
||||||
|
refreshPreferenceViews();
|
||||||
|
|
||||||
|
mSwitches.addView(mRestrictBackgroundView);
|
||||||
|
mRestrictBackgroundView.setOnClickListener(mRestrictBackgroundListener);
|
||||||
|
|
||||||
|
mAppSettings.setOnClickListener(mAppSettingsListener);
|
||||||
|
|
||||||
|
mChart = new DataUsageChartView(context);
|
||||||
|
mChartContainer.addView(mChart);
|
||||||
|
|
||||||
|
mChart.setListener(mChartListener);
|
||||||
|
mChart.setChartColor(Color.parseColor("#d88d3a"), Color.parseColor("#c0ba7f3e"),
|
||||||
|
Color.parseColor("#88566abc"));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
final Context context = getActivity();
|
||||||
|
|
||||||
|
mUid = getArguments().getInt(Intent.EXTRA_UID);
|
||||||
|
mTitle.setText(context.getPackageManager().getNameForUid(mUid));
|
||||||
|
|
||||||
|
updateBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBody() {
|
||||||
|
try {
|
||||||
|
// load stats for current uid and template
|
||||||
|
// TODO: read template from extras
|
||||||
|
mUidPolicy = mPolicyService.getUidPolicy(mUid);
|
||||||
|
mHistory = mStatsService.getHistoryForUid(mUid, TEMPLATE_MOBILE_ALL);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// since we can't do much without policy or history, and we don't
|
||||||
|
// want to leave with half-baked UI, we bail hard.
|
||||||
|
throw new RuntimeException("problem reading network stats", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind chart to historical stats
|
||||||
|
mChart.bindNetworkStats(mHistory);
|
||||||
|
|
||||||
|
// show entire history known
|
||||||
|
final long[] bounds = getHistoryBounds(mHistory);
|
||||||
|
mChart.setVisibleRange(bounds[0], bounds[1] + DateUtils.WEEK_IN_MILLIS, bounds[1]);
|
||||||
|
updateDetailData();
|
||||||
|
|
||||||
|
// update policy checkbox
|
||||||
|
final boolean restrictBackground = (mUidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0;
|
||||||
|
mRestrictBackground.setChecked(restrictBackground);
|
||||||
|
|
||||||
|
// kick preference views so they rebind from changes above
|
||||||
|
refreshPreferenceViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDetailData() {
|
||||||
|
if (LOGD) Log.d(TAG, "updateDetailData()");
|
||||||
|
|
||||||
|
final Context context = mChart.getContext();
|
||||||
|
final long[] range = mChart.getInspectRange();
|
||||||
|
final long[] total = mHistory.getTotalData(range[0], range[1], null);
|
||||||
|
final long totalCombined = total[0] + total[1];
|
||||||
|
mText1.setText(Formatter.formatFileSize(context, totalCombined));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force rebind of hijacked {@link Preference} views.
|
||||||
|
*/
|
||||||
|
private void refreshPreferenceViews() {
|
||||||
|
mRestrictBackgroundView = mRestrictBackground.getView(mRestrictBackgroundView, mSwitches);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataUsageChartListener mChartListener = new DataUsageChartListener() {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void onInspectRangeChanged() {
|
||||||
|
if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
|
||||||
|
updateDetailData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void onWarningChanged() {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void onLimitChanged() {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private OnClickListener mAppSettingsListener = new OnClickListener() {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void onClick(View v) {
|
||||||
|
// TODO: target torwards entire UID instead of just first package
|
||||||
|
final PackageManager pm = getActivity().getPackageManager();
|
||||||
|
final String packageName = pm.getPackagesForUid(mUid)[0];
|
||||||
|
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
|
||||||
|
intent.setPackage(packageName);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private OnClickListener mRestrictBackgroundListener = new OnClickListener() {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void onClick(View v) {
|
||||||
|
final boolean restrictBackground = !mRestrictBackground.isChecked();
|
||||||
|
mRestrictBackground.setChecked(restrictBackground);
|
||||||
|
refreshPreferenceViews();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mPolicyService.setUidPolicy(
|
||||||
|
mUid, restrictBackground ? POLICY_REJECT_PAID_BACKGROUND : POLICY_NONE);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new RuntimeException("unable to save policy", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@@ -27,6 +27,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
|||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.INetworkPolicyManager;
|
import android.net.INetworkPolicyManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
@@ -38,6 +39,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.SwitchPreference;
|
import android.preference.SwitchPreference;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
@@ -348,7 +350,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
// bind chart to historical stats
|
// bind chart to historical stats
|
||||||
mChart.bindNetworkStats(mHistory);
|
mChart.bindNetworkStats(mHistory);
|
||||||
|
|
||||||
updatePolicy();
|
updatePolicy(true);
|
||||||
|
|
||||||
// force scroll to top of body
|
// force scroll to top of body
|
||||||
mListView.smoothScrollToPosition(0);
|
mListView.smoothScrollToPosition(0);
|
||||||
@@ -361,15 +363,17 @@ public class DataUsageSummary extends Fragment {
|
|||||||
* Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
|
* Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
|
||||||
* current {@link #mTemplate}.
|
* current {@link #mTemplate}.
|
||||||
*/
|
*/
|
||||||
private void updatePolicy() {
|
private void updatePolicy(boolean refreshCycle) {
|
||||||
final NetworkPolicy policy = mPolicyModifier.getPolicy(mTemplate);
|
final NetworkPolicy policy = mPolicyModifier.getPolicy(mTemplate);
|
||||||
|
|
||||||
// reflect policy limit in checkbox
|
// reflect policy limit in checkbox
|
||||||
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
|
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
|
||||||
mChart.bindNetworkPolicy(policy);
|
mChart.bindNetworkPolicy(policy);
|
||||||
|
|
||||||
// generate cycle list based on policy and available history
|
if (refreshCycle) {
|
||||||
updateCycleList(policy);
|
// generate cycle list based on policy and available history
|
||||||
|
updateCycleList(policy);
|
||||||
|
}
|
||||||
|
|
||||||
// kick preference views so they rebind from changes above
|
// kick preference views so they rebind from changes above
|
||||||
refreshPreferenceViews();
|
refreshPreferenceViews();
|
||||||
@@ -379,7 +383,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
* Return full time bounds (earliest and latest time recorded) of the given
|
* Return full time bounds (earliest and latest time recorded) of the given
|
||||||
* {@link NetworkStatsHistory}.
|
* {@link NetworkStatsHistory}.
|
||||||
*/
|
*/
|
||||||
private static long[] getHistoryBounds(NetworkStatsHistory history) {
|
public static long[] getHistoryBounds(NetworkStatsHistory history) {
|
||||||
final long currentTime = System.currentTimeMillis();
|
final long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
long start = currentTime;
|
long start = currentTime;
|
||||||
@@ -471,17 +475,21 @@ public class DataUsageSummary extends Fragment {
|
|||||||
// TODO: show interstitial warning dialog to user
|
// TODO: show interstitial warning dialog to user
|
||||||
final long limitBytes = disableAtLimit ? 5 * GB_IN_BYTES : LIMIT_DISABLED;
|
final long limitBytes = disableAtLimit ? 5 * GB_IN_BYTES : LIMIT_DISABLED;
|
||||||
mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes);
|
mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes);
|
||||||
updatePolicy();
|
updatePolicy(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private OnItemClickListener mListListener = new OnItemClickListener() {
|
private OnItemClickListener mListListener = new OnItemClickListener() {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
final Object object = parent.getItemAtPosition(position);
|
final AppUsageItem app = (AppUsageItem) parent.getItemAtPosition(position);
|
||||||
|
|
||||||
// TODO: show app details
|
final Bundle args = new Bundle();
|
||||||
Log.d(TAG, "showing app details for " + object);
|
args.putInt(Intent.EXTRA_UID, app.uid);
|
||||||
|
|
||||||
|
final PreferenceActivity activity = (PreferenceActivity) getActivity();
|
||||||
|
activity.startPreferencePanel(DataUsageAppDetail.class.getName(), args,
|
||||||
|
R.string.data_usage_summary_title, null, null, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -547,7 +555,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
if (LOGD) Log.d(TAG, "onWarningChanged()");
|
if (LOGD) Log.d(TAG, "onWarningChanged()");
|
||||||
final long warningBytes = mChart.getWarningBytes();
|
final long warningBytes = mChart.getWarningBytes();
|
||||||
mPolicyModifier.setPolicyWarningBytes(mTemplate, warningBytes);
|
mPolicyModifier.setPolicyWarningBytes(mTemplate, warningBytes);
|
||||||
updatePolicy();
|
updatePolicy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@@ -556,7 +564,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
final long limitBytes = mDisableAtLimit.isChecked() ? mChart.getLimitBytes()
|
final long limitBytes = mDisableAtLimit.isChecked() ? mChart.getLimitBytes()
|
||||||
: LIMIT_DISABLED;
|
: LIMIT_DISABLED;
|
||||||
mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes);
|
mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes);
|
||||||
updatePolicy();
|
updatePolicy(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -615,22 +623,22 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class AppUsageItem implements Comparable<AppUsageItem> {
|
||||||
|
public int uid;
|
||||||
|
public long total;
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int compareTo(AppUsageItem another) {
|
||||||
|
return Long.compare(another.total, total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter of applications, sorted by total usage descending.
|
* Adapter of applications, sorted by total usage descending.
|
||||||
*/
|
*/
|
||||||
public static class DataUsageAdapter extends BaseAdapter {
|
public static class DataUsageAdapter extends BaseAdapter {
|
||||||
private ArrayList<AppUsageItem> mItems = Lists.newArrayList();
|
private ArrayList<AppUsageItem> mItems = Lists.newArrayList();
|
||||||
|
|
||||||
private static class AppUsageItem implements Comparable<AppUsageItem> {
|
|
||||||
public int uid;
|
|
||||||
public long total;
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
public int compareTo(AppUsageItem another) {
|
|
||||||
return Long.compare(another.total, total);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bindStats(NetworkStats stats) {
|
public void bindStats(NetworkStats stats) {
|
||||||
mItems.clear();
|
mItems.clear();
|
||||||
|
|
||||||
|
@@ -40,9 +40,9 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
private final ChartAxis mHoriz;
|
private final ChartAxis mHoriz;
|
||||||
private final ChartAxis mVert;
|
private final ChartAxis mVert;
|
||||||
|
|
||||||
private final Paint mPaintStroke;
|
private Paint mPaintStroke;
|
||||||
private final Paint mPaintFill;
|
private Paint mPaintFill;
|
||||||
private final Paint mPaintFillDisabled;
|
private Paint mPaintFillDisabled;
|
||||||
|
|
||||||
private NetworkStatsHistory mStats;
|
private NetworkStatsHistory mStats;
|
||||||
|
|
||||||
@@ -58,24 +58,29 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
|
mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
|
||||||
mVert = Preconditions.checkNotNull(vert, "missing vert");
|
mVert = Preconditions.checkNotNull(vert, "missing vert");
|
||||||
|
|
||||||
|
setChartColor(Color.parseColor("#24aae1"), Color.parseColor("#c050ade5"),
|
||||||
|
Color.parseColor("#88566abc"));
|
||||||
|
|
||||||
|
mPathStroke = new Path();
|
||||||
|
mPathFill = new Path();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChartColor(int stroke, int fill, int disabled) {
|
||||||
mPaintStroke = new Paint();
|
mPaintStroke = new Paint();
|
||||||
mPaintStroke.setStrokeWidth(6.0f);
|
mPaintStroke.setStrokeWidth(6.0f);
|
||||||
mPaintStroke.setColor(Color.parseColor("#24aae1"));
|
mPaintStroke.setColor(stroke);
|
||||||
mPaintStroke.setStyle(Style.STROKE);
|
mPaintStroke.setStyle(Style.STROKE);
|
||||||
mPaintStroke.setAntiAlias(true);
|
mPaintStroke.setAntiAlias(true);
|
||||||
|
|
||||||
mPaintFill = new Paint();
|
mPaintFill = new Paint();
|
||||||
mPaintFill.setColor(Color.parseColor("#c050ade5"));
|
mPaintFill.setColor(fill);
|
||||||
mPaintFill.setStyle(Style.FILL);
|
mPaintFill.setStyle(Style.FILL);
|
||||||
mPaintFill.setAntiAlias(true);
|
mPaintFill.setAntiAlias(true);
|
||||||
|
|
||||||
mPaintFillDisabled = new Paint();
|
mPaintFillDisabled = new Paint();
|
||||||
mPaintFillDisabled.setColor(Color.parseColor("#88566abc"));
|
mPaintFillDisabled.setColor(disabled);
|
||||||
mPaintFillDisabled.setStyle(Style.FILL);
|
mPaintFillDisabled.setStyle(Style.FILL);
|
||||||
mPaintFillDisabled.setAntiAlias(true);
|
mPaintFillDisabled.setAntiAlias(true);
|
||||||
|
|
||||||
mPathStroke = new Path();
|
|
||||||
mPathFill = new Path();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindNetworkStats(NetworkStatsHistory stats) {
|
public void bindNetworkStats(NetworkStatsHistory stats) {
|
||||||
|
@@ -86,6 +86,13 @@ public class DataUsageChartView extends ChartView {
|
|||||||
mSweepTime1.addOnSweepListener(mSweepListener);
|
mSweepTime1.addOnSweepListener(mSweepListener);
|
||||||
mSweepTime2.addOnSweepListener(mSweepListener);
|
mSweepTime2.addOnSweepListener(mSweepListener);
|
||||||
|
|
||||||
|
mSweepDataWarn.setVisibility(View.INVISIBLE);
|
||||||
|
mSweepDataLimit.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChartColor(int stroke, int fill, int disabled) {
|
||||||
|
mSeries.setChartColor(stroke, fill, disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setListener(DataUsageChartListener listener) {
|
public void setListener(DataUsageChartListener listener) {
|
||||||
|
Reference in New Issue
Block a user