diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2017-04-16 20:10:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-16 20:10:16 +0200 |
commit | 4a37d16e433843ac18c53b5bc27676f2073d7b4c (patch) | |
tree | 0004e1a1dec3aaff70b427daeae27ab3e8aa99eb | |
parent | 9542ef156989cefe9534f414f034195f8b717b8f (diff) | |
parent | 8f226803cbfeaee628ca5b745bab03a7293c84d1 (diff) | |
download | AntennaPod-4a37d16e433843ac18c53b5bc27676f2073d7b4c.zip |
Merge pull request #2294 from ByteHamster/stats-duration
Allow choosing between getDuration and getPlayedDuration
6 files changed, 185 insertions, 29 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java index 9bb8f8856..b2ff43c43 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java @@ -1,14 +1,18 @@ package de.danoeh.antennapod.activity; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.ProgressBar; +import android.widget.RadioButton; import android.widget.TextView; import de.danoeh.antennapod.R; @@ -28,12 +32,16 @@ public class StatisticsActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { private static final String TAG = StatisticsActivity.class.getSimpleName(); + private static final String PREF_NAME = "StatisticsActivityPrefs"; + private static final String PREF_COUNT_ALL = "countAll"; private Subscription subscription; private TextView totalTimeTextView; private ListView feedStatisticsList; private ProgressBar progressBar; private StatisticsListAdapter listAdapter; + private boolean countAll = false; + private SharedPreferences prefs; @Override protected void onCreate(Bundle savedInstanceState) { @@ -42,10 +50,14 @@ public class StatisticsActivity extends AppCompatActivity getSupportActionBar().setDisplayShowHomeEnabled(true); setContentView(R.layout.statistics_activity); + prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE); + countAll = prefs.getBoolean(PREF_COUNT_ALL, false); + totalTimeTextView = (TextView) findViewById(R.id.total_time); feedStatisticsList = (ListView) findViewById(R.id.statistics_list); progressBar = (ProgressBar) findViewById(R.id.progressBar); listAdapter = new StatisticsListAdapter(this); + listAdapter.setCountAll(countAll); feedStatisticsList.setAdapter(listAdapter); feedStatisticsList.setOnItemClickListener(this); } @@ -53,10 +65,15 @@ public class StatisticsActivity extends AppCompatActivity @Override public void onResume() { super.onResume(); - progressBar.setVisibility(View.VISIBLE); - totalTimeTextView.setVisibility(View.GONE); - feedStatisticsList.setVisibility(View.GONE); - loadStats(); + refreshStatistics(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.statistics, menu); + return true; } @Override @@ -64,22 +81,54 @@ public class StatisticsActivity extends AppCompatActivity if (item.getItemId() == android.R.id.home) { finish(); return true; + } else if (item.getItemId() == R.id.statistics_mode) { + selectStatisticsMode(); + return true; } else { return super.onOptionsItemSelected(item); } } - private void loadStats() { - if(subscription != null) { + private void selectStatisticsMode() { + View contentView = View.inflate(this, R.layout.statistics_mode_select_dialog, null); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setView(contentView); + builder.setTitle(R.string.statistics_mode); + + if (countAll) { + ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true); + } else { + ((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true); + } + + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { + countAll = ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).isChecked(); + listAdapter.setCountAll(countAll); + prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply(); + refreshStatistics(); + }); + + builder.show(); + } + + private void refreshStatistics() { + progressBar.setVisibility(View.VISIBLE); + totalTimeTextView.setVisibility(View.GONE); + feedStatisticsList.setVisibility(View.GONE); + loadStatistics(); + } + + private void loadStatistics() { + if (subscription != null) { subscription.unsubscribe(); } - subscription = Observable.fromCallable(() -> DBReader.getStatistics()) + subscription = Observable.fromCallable(() -> DBReader.getStatistics(countAll)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { if (result != null) { totalTimeTextView.setText(Converter - .shortLocalizedDuration(this, result.totalTime)); + .shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime)); listAdapter.update(result.feedTime); progressBar.setVisibility(View.GONE); totalTimeTextView.setVisibility(View.VISIBLE); @@ -95,9 +144,10 @@ public class StatisticsActivity extends AppCompatActivity AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle(stats.feed.getTitle()); dialog.setMessage(getString(R.string.statistics_details_dialog, - stats.episodesStarted, + countAll ? stats.episodesStartedIncludingMarked : stats.episodesStarted, stats.episodes, - Converter.shortLocalizedDuration(this, stats.timePlayed), + Converter.shortLocalizedDuration(this, countAll ? + stats.timePlayedCountAll : stats.timePlayed), Converter.shortLocalizedDuration(this, stats.time))); dialog.setPositiveButton(android.R.string.ok, null); dialog.show(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java index fe891281b..c060083a6 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java @@ -25,11 +25,15 @@ import de.danoeh.antennapod.core.util.Converter; public class StatisticsListAdapter extends BaseAdapter { private Context context; List<DBReader.StatisticsItem> feedTime = new ArrayList<>(); + private boolean countAll = true; public StatisticsListAdapter(Context context) { this.context = context; } + public void setCountAll(boolean countAll) { + this.countAll = countAll; + } @Override public int getCount() { @@ -77,7 +81,8 @@ public class StatisticsListAdapter extends BaseAdapter { holder.title.setText(feed.getTitle()); holder.time.setText(Converter.shortLocalizedDuration(context, - feedTime.get(position).timePlayed)); + countAll ? feedTime.get(position).timePlayedCountAll + : feedTime.get(position).timePlayed)); return convertView; } diff --git a/app/src/main/res/layout/statistics_mode_select_dialog.xml b/app/src/main/res/layout/statistics_mode_select_dialog.xml new file mode 100644 index 000000000..8f8e1e657 --- /dev/null +++ b/app/src/main/res/layout/statistics_mode_select_dialog.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:text="@string/statistics_speed_not_counted" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp"/> + + <RadioButton + android:id="@+id/statistics_mode_normal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/statistics_mode_normal"/> + + <RadioButton + android:id="@+id/statistics_mode_count_all" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/statistics_mode_count_all"/> +</RadioGroup> diff --git a/app/src/main/res/menu/statistics.xml b/app/src/main/res/menu/statistics.xml new file mode 100644 index 000000000..6ecc70707 --- /dev/null +++ b/app/src/main/res/menu/statistics.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res-auto"> + + <item + android:id="@+id/statistics_mode" + android:icon="?attr/ic_filter" + android:title="@string/statistics_mode" + custom:showAsAction="never"> + </item> + +</menu> diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 7bda08b7a..8ed6718c0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -927,64 +927,107 @@ public final class DBReader { /** * Searches the DB for statistics * + * @param sortByCountAll If true, the statistic items will be sorted according to the + * countAll calculation time * @return The StatisticsInfo object */ - public static StatisticsData getStatistics() { + public static StatisticsData getStatistics(boolean sortByCountAll) { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); + long totalTimeCountAll = 0; long totalTime = 0; List<StatisticsItem> feedTime = new ArrayList<>(); List<Feed> feeds = getFeedList(); for (Feed feed : feeds) { + long feedPlayedTimeCountAll = 0; long feedPlayedTime = 0; long feedTotalTime = 0; long episodes = 0; long episodesStarted = 0; + long episodesStartedIncludingMarked = 0; List<FeedItem> items = getFeed(feed.getId()).getItems(); - for(FeedItem item : items) { + for (FeedItem item : items) { FeedMedia media = item.getMedia(); - if(media == null) { + if (media == null) { continue; } // played duration used to be reset when the item is added to the playback history - if(media.getPlaybackCompletionDate() != null) { + if (media.getPlaybackCompletionDate() != null) { feedPlayedTime += media.getDuration() / 1000; } feedPlayedTime += media.getPlayedDuration() / 1000; + + if (item.isPlayed()) { + feedPlayedTimeCountAll += media.getDuration() / 1000; + } else { + feedPlayedTimeCountAll += media.getPosition() / 1000; + } + if (media.getPlaybackCompletionDate() != null || media.getPlayedDuration() > 0) { episodesStarted++; } + + if (item.isPlayed() || media.getPosition() != 0) { + episodesStartedIncludingMarked++; + } + feedTotalTime += media.getDuration() / 1000; episodes++; } feedTime.add(new StatisticsItem( - feed, feedTotalTime, feedPlayedTime, episodes, episodesStarted)); + feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes, + episodesStarted, episodesStartedIncludingMarked)); totalTime += feedPlayedTime; + totalTimeCountAll += feedPlayedTimeCountAll; } - Collections.sort(feedTime, (item1, item2) -> { - if(item1.timePlayed > item2.timePlayed) { - return -1; - } else if(item1.timePlayed < item2.timePlayed) { - return 1; - } else { - return 0; - } - }); + if (sortByCountAll) { + Collections.sort(feedTime, (item1, item2) -> + compareLong(item1.timePlayedCountAll, item2.timePlayedCountAll)); + } else { + Collections.sort(feedTime, (item1, item2) -> + compareLong(item1.timePlayed, item2.timePlayed)); + } adapter.close(); - return new StatisticsData(totalTime, feedTime); + return new StatisticsData(totalTime, totalTimeCountAll, feedTime); + } + + /** + * Compares two {@code long} values. Long.compare() is not available before API 19 + * + * @return 0 if long1 = long2, less than 0 if long1 < long2, + * and greater than 0 if long1 > long2. + */ + private static int compareLong(long long1, long long2) { + if (long1 > long2) { + return -1; + } else if (long1 < long2) { + return 1; + } else { + return 0; + } } public static class StatisticsData { + /** + * Simply sums up time of podcasts that are marked as played + */ + public long totalTimeCountAll; + + /** + * Respects speed, listening twice, ... + */ public long totalTime; + public List<StatisticsItem> feedTime; - public StatisticsData(long totalTime, List<StatisticsItem> feedTime) { + public StatisticsData(long totalTime, long totalTimeCountAll, List<StatisticsItem> feedTime) { this.totalTime = totalTime; + this.totalTimeCountAll = totalTimeCountAll; this.feedTime = feedTime; } } @@ -992,17 +1035,34 @@ public final class DBReader { public static class StatisticsItem { public Feed feed; public long time; + + /** + * Respects speed, listening twice, ... + */ public long timePlayed; + /** + * Simply sums up time of podcasts that are marked as played + */ + public long timePlayedCountAll; public long episodes; + /** + * Episodes that are actually played + */ public long episodesStarted; + /** + * All episodes that are marked as played (or have position != 0) + */ + public long episodesStartedIncludingMarked; - public StatisticsItem(Feed feed, long time, long timePlayed, - long episodes, long episodesStarted) { + public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll, + long episodes, long episodesStarted, long episodesStartedIncludingMarked) { this.feed = feed; this.time = time; this.timePlayed = timePlayed; + this.timePlayedCountAll = timePlayedCountAll; this.episodes = episodes; this.episodesStarted = episodesStarted; + this.episodesStartedIncludingMarked = episodesStartedIncludingMarked; } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 974c5a7f8..b82a03801 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -31,6 +31,10 @@ <!-- Statistics fragment --> <string name="total_time_listened_to_podcasts">Total time of podcasts played:</string> <string name="statistics_details_dialog">%1$d out of %2$d episodes started.\n\nPlayed %3$s out of %4$s.</string> + <string name="statistics_mode">Statistics mode</string> + <string name="statistics_mode_normal">Calculate duration that was actually played. Playing twice is counted twice, while marking as played is not counted</string> + <string name="statistics_mode_count_all">Sum up all podcasts marked as played</string> + <string name="statistics_speed_not_counted">Notice: Playback speed is never taken into account.</string> <!-- Main activity --> <string name="drawer_open">Open menu</string> |