Skip to content

Commit

Permalink
Merge pull request AntennaPod#2294 from ByteHamster/stats-duration
Browse files Browse the repository at this point in the history
Allow choosing between getDuration and getPlayedDuration
  • Loading branch information
mfietz authored Apr 16, 2017
2 parents 9542ef1 + 8f22680 commit 4a37d16
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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) {
Expand All @@ -42,44 +50,85 @@ protected void onCreate(Bundle savedInstanceState) {
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);
}

@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
public boolean onOptionsItemSelected(MenuItem item) {
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);
Expand All @@ -95,9 +144,10 @@ public void onItemClick(AdapterView<?> parent, View view, int position, long id)
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
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() {
Expand Down Expand Up @@ -77,7 +81,8 @@ public View getView(int position, View convertView, ViewGroup parent) {

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

Expand Down
25 changes: 25 additions & 0 deletions app/src/main/res/layout/statistics_mode_select_dialog.xml
Original file line number Diff line number Diff line change
@@ -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>
12 changes: 12 additions & 0 deletions app/src/main/res/menu/statistics.xml
Original file line number Diff line number Diff line change
@@ -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>
96 changes: 78 additions & 18 deletions core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -927,82 +927,142 @@ public static FeedMedia getFeedMedia(final long mediaId) {
/**
* 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;
}
}

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

Expand Down
4 changes: 4 additions & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down

0 comments on commit 4a37d16

Please sign in to comment.