Allow choosing between getDuration and getPlayedDuration

This commit is contained in:
ByteHamster 2016-08-28 18:35:05 +02:00
parent 639ff81f8c
commit 416117515c
6 changed files with 180 additions and 31 deletions

View File

@ -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();
refreshStats();
}
@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.calculation_type) {
selectCalculationType();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void selectCalculationType() {
View contentView = View.inflate(this, R.layout.calculation_type, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(contentView);
builder.setTitle(R.string.calculation_type);
if (countAll) {
((RadioButton) contentView.findViewById(R.id.calculation_type_count_all)).setChecked(true);
} else {
((RadioButton) contentView.findViewById(R.id.calculation_type_normal)).setChecked(true);
}
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
countAll = ((RadioButton) contentView.findViewById(R.id.calculation_type_count_all)).isChecked();
listAdapter.setCountAll(countAll);
prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).commit();
refreshStats();
});
builder.show();
}
private void refreshStats() {
progressBar.setVisibility(View.VISIBLE);
totalTimeTextView.setVisibility(View.GONE);
feedStatisticsList.setVisibility(View.GONE);
loadStats();
}
private void loadStats() {
if(subscription != null) {
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();

View File

@ -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;
}

View File

@ -0,0 +1,19 @@
<?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">
<RadioButton
android:id="@+id/calculation_type_normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/calculation_type_normal" />
<RadioButton
android:id="@+id/calculation_type_count_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/calculation_type_count_all" />
</RadioGroup>

View File

@ -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/calculation_type"
android:icon="?attr/ic_filter"
android:title="@string/calculation_type"
custom:showAsAction="never">
</item>
</menu>

View File

@ -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 &lt; long2,
* and greater than 0 if long1 &gt; 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;
public long timePlayed;
public long episodes;
public long episodesStarted;
public StatisticsItem(Feed feed, long time, long timePlayed,
long episodes, long episodesStarted) {
/**
* 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 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;
}
}

View File

@ -31,6 +31,9 @@
<!-- 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="calculation_type">Calculation type</string>
<string name="calculation_type_normal">The time you actually played podcasts, respecting playback speed</string>
<string name="calculation_type_count_all">Sum up all played podcast durations, including those just marked as played</string>
<!-- Main activity -->
<string name="drawer_open">Open menu</string>