Allow choosing between getDuration and getPlayedDuration
This commit is contained in:
parent
639ff81f8c
commit
416117515c
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue