diff options
author | Xavier Gouchet <xavier.gouchet@gmail.com> | 2019-10-08 09:43:16 +0200 |
---|---|---|
committer | Xavier Gouchet <xavier.gouchet@gmail.com> | 2019-10-14 09:14:00 +0200 |
commit | f9b413332f82873aab43066e19170dddcefa8322 (patch) | |
tree | 58a02dad9e358ac4e1332bd567a4f6e99f120391 | |
parent | fa0fbc2bc5ba7c9c954c5ef93fb8b1d9adf79224 (diff) | |
download | AntennaPod-f9b413332f82873aab43066e19170dddcefa8322.zip |
Reset playback statistics
Fixes #1867
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java | 52 | ||||
-rw-r--r-- | app/src/main/res/menu/statistics.xml | 7 | ||||
-rw-r--r-- | core/src/main/java/de/danoeh/antennapod/core/event/StatisticsEvent.java | 14 | ||||
-rw-r--r-- | core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 89 | ||||
-rw-r--r-- | core/src/main/res/drawable-anydpi/ic_reset_stats.xml | 11 | ||||
-rw-r--r-- | core/src/main/res/drawable-hdpi/ic_reset_stats.png | bin | 0 -> 279 bytes | |||
-rw-r--r-- | core/src/main/res/drawable-mdpi/ic_reset_stats.png | bin | 0 -> 192 bytes | |||
-rw-r--r-- | core/src/main/res/drawable-xhdpi/ic_reset_stats.png | bin | 0 -> 294 bytes | |||
-rw-r--r-- | core/src/main/res/drawable-xxhdpi/ic_reset_stats.png | bin | 0 -> 419 bytes | |||
-rw-r--r-- | core/src/main/res/values/strings.xml | 1 |
10 files changed, 139 insertions, 35 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java index 2b5310837..2e6a3b5d5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java @@ -3,12 +3,6 @@ package de.danoeh.antennapod.fragment.preferences; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.appcompat.app.AlertDialog; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -18,10 +12,23 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.RadioButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.adapter.StatisticsListAdapter; +import de.danoeh.antennapod.core.event.StatisticsEvent; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBWriter; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -52,7 +59,9 @@ public class StatisticsFragment extends Fragment { @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View root = inflater.inflate(R.layout.statistics_activity, container, false); feedStatisticsList = root.findViewById(R.id.statistics_list); progressBar = root.findViewById(R.id.progressBar); @@ -63,6 +72,11 @@ public class StatisticsFragment extends Fragment { return root; } + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + EventBus.getDefault().register(this); + } + @Override public void onStart() { super.onStart(); @@ -70,6 +84,14 @@ public class StatisticsFragment extends Fragment { refreshStatistics(); } + @Override public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + if (disposable != null) { + disposable.dispose(); + } + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.statistics, menu); @@ -81,9 +103,19 @@ public class StatisticsFragment extends Fragment { selectStatisticsMode(); return true; } + if (item.getItemId() == R.id.statistics_reset) { + resetStatistics(); + return true; + } return super.onOptionsItemSelected(item); } + @Subscribe + public void onEvent(StatisticsEvent event) { + Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); + refreshStatistics(); + } + private void selectStatisticsMode() { View contentView = View.inflate(getContext(), R.layout.statistics_mode_select_dialog, null); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); @@ -106,6 +138,12 @@ public class StatisticsFragment extends Fragment { builder.show(); } + private void resetStatistics() { + progressBar.setVisibility(View.VISIBLE); + feedStatisticsList.setVisibility(View.GONE); + DBWriter.resetStatistics(); + } + private void refreshStatistics() { progressBar.setVisibility(View.VISIBLE); feedStatisticsList.setVisibility(View.GONE); diff --git a/app/src/main/res/menu/statistics.xml b/app/src/main/res/menu/statistics.xml index 6ecc70707..c1a545983 100644 --- a/app/src/main/res/menu/statistics.xml +++ b/app/src/main/res/menu/statistics.xml @@ -3,6 +3,13 @@ xmlns:custom="http://schemas.android.com/apk/res-auto"> <item + android:id="@+id/statistics_reset" + android:icon="@drawable/ic_reset_stats" + android:title="@string/statistics_reset_data" + custom:showAsAction="ifRoom" + /> + + <item android:id="@+id/statistics_mode" android:icon="?attr/ic_filter" android:title="@string/statistics_mode" diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/StatisticsEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/StatisticsEvent.java new file mode 100644 index 000000000..15b44c2af --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/StatisticsEvent.java @@ -0,0 +1,14 @@ +package de.danoeh.antennapod.core.event; + +public class StatisticsEvent { + + public enum Action { + STATISTICS_UPDATED + } + + public final Action action; + + public StatisticsEvent(Action action) { + this.action = action; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 11d90e57c..815eeeb50 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -2,9 +2,10 @@ package de.danoeh.antennapod.core.storage; import android.app.backup.BackupManager; import android.content.Context; -import androidx.annotation.NonNull; import android.util.Log; +import androidx.annotation.NonNull; + import org.greenrobot.eventbus.EventBus; import java.io.File; @@ -23,6 +24,7 @@ import de.danoeh.antennapod.core.event.FavoritesEvent; import de.danoeh.antennapod.core.event.FeedItemEvent; import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.QueueEvent; +import de.danoeh.antennapod.core.event.StatisticsEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedEvent; @@ -86,7 +88,8 @@ public class DBWriter { }); } - private static boolean deleteFeedMediaSynchronous(@NonNull Context context, @NonNull FeedMedia media) { + private static boolean deleteFeedMediaSynchronous( + @NonNull Context context, @NonNull FeedMedia media) { Log.i(TAG, String.format("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s", media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded()))); if (media.isDownloaded()) { @@ -111,7 +114,7 @@ public class DBWriter { } // Gpodder: queue delete action for synchronization - if(GpodnetPreferences.loggedIn()) { + if (GpodnetPreferences.loggedIn()) { FeedItem item = media.getItem(); GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.DELETE) .currentDeviceId() @@ -159,7 +162,7 @@ public class DBWriter { adapter.open(); if (removed.size() > 0) { adapter.setQueue(queue); - for(FeedItem item : removed) { + for (FeedItem item : removed) { EventBus.getDefault().post(QueueEvent.irreversibleRemoved(item)); } } @@ -184,7 +187,6 @@ public class DBWriter { /** * Deletes the entire playback history. - * */ public static Future<?> clearPlaybackHistory() { return dbExec.submit(() -> { @@ -215,7 +217,7 @@ public class DBWriter { * its playback completion date is set to a non-null value. This method will set the playback completion date to the * current date regardless of the current value. * - * @param media FeedMedia that should be added to the playback history. + * @param media FeedMedia that should be added to the playback history. */ public static Future<?> addItemToPlaybackHistory(final FeedMedia media) { return dbExec.submit(() -> { @@ -234,7 +236,7 @@ public class DBWriter { /** * Adds a Download status object to the download log. * - * @param status The DownloadStatus object. + * @param status The DownloadStatus object. */ public static Future<?> addDownloadStatus(final DownloadStatus status) { return dbExec.submit(() -> { @@ -304,9 +306,9 @@ public class DBWriter { * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. * - * @param context A context that is used for opening a database connection. + * @param context A context that is used for opening a database connection. * @param performAutoDownload true if an auto-download process should be started after the operation. - * @param itemIds IDs of the FeedItem objects that should be added to the queue. + * @param itemIds IDs of the FeedItem objects that should be added to the queue. */ public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload, final long... itemIds) { @@ -394,7 +396,6 @@ public class DBWriter { /** * Removes all FeedItem objects from the queue. - * */ public static Future<?> clearQueue() { return dbExec.submit(() -> { @@ -409,7 +410,8 @@ public class DBWriter { /** * Removes a FeedItem object from the queue. - * @param context A context that is used for opening a database connection. + * + * @param context A context that is used for opening a database connection. * @param performAutoDownload true if an auto-download process should be started after the operation. * @param item FeedItem that should be removed. */ @@ -497,14 +499,15 @@ public class DBWriter { /** * Moves the specified item to the top of the queue. - * @param itemId The item to move to the top of the queue + * + * @param itemId The item to move to the top of the queue * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to */ public static Future<?> moveQueueItemToTop(final long itemId, final boolean broadcastUpdate) { return dbExec.submit(() -> { LongList queueIdList = DBReader.getQueueIDList(); int index = queueIdList.indexOf(itemId); - if (index >=0) { + if (index >= 0) { moveQueueItemHelper(index, 0, broadcastUpdate); } else { Log.e(TAG, "moveQueueItemToTop: item not found"); @@ -514,7 +517,8 @@ public class DBWriter { /** * Moves the specified item to the bottom of the queue. - * @param itemId The item to move to the bottom of the queue + * + * @param itemId The item to move to the bottom of the queue * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to */ public static Future<?> moveQueueItemToBottom(final long itemId, @@ -524,7 +528,7 @@ public class DBWriter { int index = queueIdList.indexOf(itemId); if (index >= 0) { moveQueueItemHelper(index, queueIdList.size() - 1, - broadcastUpdate); + broadcastUpdate); } else { Log.e(TAG, "moveQueueItemToBottom: item not found"); } @@ -605,7 +609,7 @@ public class DBWriter { adapter.open(); adapter.setFeedItemRead(played, itemIds); adapter.close(); - if(broadcastUpdate) { + if (broadcastUpdate) { EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); @@ -614,7 +618,8 @@ public class DBWriter { /** * Sets the 'read'-attribute of a FeedItem to the specified value. - * @param item The FeedItem object + * + * @param item The FeedItem object * @param played New value of the 'read'-attribute one of FeedItem.PLAYED, * FeedItem.NEW, FeedItem.UNPLAYED * @param resetMediaPosition true if this method should also reset the position of the FeedItem's FeedMedia object. @@ -644,7 +649,7 @@ public class DBWriter { /** * Sets the 'read'-attribute of all NEW FeedItems of a specific Feed to UNPLAYED. * - * @param feedId ID of the Feed. + * @param feedId ID of the Feed. */ public static Future<?> removeFeedNewFlag(final long feedId) { return dbExec.submit(() -> { @@ -660,7 +665,7 @@ public class DBWriter { /** * Sets the 'read'-attribute of all FeedItems of a specific Feed to PLAYED. * - * @param feedId ID of the Feed. + * @param feedId ID of the Feed. */ public static Future<?> markFeedRead(final long feedId) { return dbExec.submit(() -> { @@ -732,7 +737,7 @@ public class DBWriter { * Saves a FeedMedia object in the database. This method will save all attributes of the FeedMedia object. The * contents of FeedComponent-attributes (e.g. the FeedMedia's 'item'-attribute) will not be saved. * - * @param media The FeedMedia object. + * @param media The FeedMedia object. */ public static Future<?> setFeedMedia(final FeedMedia media) { return dbExec.submit(() -> { @@ -746,7 +751,7 @@ public class DBWriter { /** * Saves the 'position', 'duration' and 'last played time' attributes of a FeedMedia object * - * @param media The FeedMedia object. + * @param media The FeedMedia object. */ public static Future<?> setFeedMediaPlaybackInformation(final FeedMedia media) { return dbExec.submit(() -> { @@ -761,7 +766,7 @@ public class DBWriter { * Saves a FeedItem object in the database. This method will save all attributes of the FeedItem object including * the content of FeedComponent-attributes. * - * @param item The FeedItem object. + * @param item The FeedItem object. */ public static Future<?> setFeedItem(final FeedItem item) { return dbExec.submit(() -> { @@ -777,7 +782,7 @@ public class DBWriter { * Updates download URL of a feed */ public static Future<?> updateFeedDownloadURL(final String original, final String updated) { - Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated +")"); + Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated + ")"); return dbExec.submit(() -> { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); @@ -802,11 +807,11 @@ public class DBWriter { } private static boolean itemListContains(List<FeedItem> items, long itemId) { - return indexInItemList(items, itemId) >= 0; + return indexInItemList(items, itemId) >= 0; } private static int indexInItemList(List<FeedItem> items, long itemId) { - for (int i = 0; i < items.size(); i ++) { + for (int i = 0; i < items.size(); i++) { FeedItem item = items.get(i); if (item.getId() == itemId) { return i; @@ -870,7 +875,7 @@ public class DBWriter { /** * Sets the 'auto_download'-attribute of specific FeedItem. * - * @param feedItem FeedItem. + * @param feedItem FeedItem. * @param autoDownload true enables auto download, false disables it */ public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem, @@ -888,7 +893,7 @@ public class DBWriter { return dbExec.submit(() -> { int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1; long autoDownload; - if(!feedItem.getAutoDownload() || failedAttempts >= 10) { + if (!feedItem.getAutoDownload() || failedAttempts >= 10) { autoDownload = 0; // giving up, disable auto download feedItem.setAutoDownload(false); } else { @@ -924,7 +929,8 @@ public class DBWriter { /** * Set filter of the feed - * @param feedId The feed's ID + * + * @param feedId The feed's ID * @param filterValues Values that represent properties to filter by */ public static Future<?> setFeedItemsFilter(final long feedId, @@ -939,4 +945,31 @@ public class DBWriter { }); } + + /** + * Reset the statistics in DB + */ + @NonNull + public static Future<?> resetStatistics() { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + + List<Feed> feeds = DBReader.getFeedList(); + for (Feed feed : feeds) { + List<FeedItem> items = DBReader.getFeed(feed.getId()).getItems(); + for (FeedItem item : items) { + FeedMedia media = item.getMedia(); + if (media == null) { + continue; + } + + media.setPlayedDuration(0); + adapter.setFeedMediaPlaybackInformation(media); + } + } + adapter.close(); + EventBus.getDefault().post(new StatisticsEvent(StatisticsEvent.Action.STATISTICS_UPDATED)); + }); + } } diff --git a/core/src/main/res/drawable-anydpi/ic_reset_stats.xml b/core/src/main/res/drawable-anydpi/ic_reset_stats.xml new file mode 100644 index 000000000..afc333088 --- /dev/null +++ b/core/src/main/res/drawable-anydpi/ic_reset_stats.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#000000" + android:alpha="0.8"> + <path + android:fillColor="#FF000000" + android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/> +</vector> diff --git a/core/src/main/res/drawable-hdpi/ic_reset_stats.png b/core/src/main/res/drawable-hdpi/ic_reset_stats.png Binary files differnew file mode 100644 index 000000000..11fc340de --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_reset_stats.png diff --git a/core/src/main/res/drawable-mdpi/ic_reset_stats.png b/core/src/main/res/drawable-mdpi/ic_reset_stats.png Binary files differnew file mode 100644 index 000000000..1e0c48d84 --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_reset_stats.png diff --git a/core/src/main/res/drawable-xhdpi/ic_reset_stats.png b/core/src/main/res/drawable-xhdpi/ic_reset_stats.png Binary files differnew file mode 100644 index 000000000..9c72f9256 --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_reset_stats.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_reset_stats.png b/core/src/main/res/drawable-xxhdpi/ic_reset_stats.png Binary files differnew file mode 100644 index 000000000..7469e76e9 --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_reset_stats.png diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0d61e30cd..4442c2e13 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -37,6 +37,7 @@ <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> + <string name="statistics_reset_data">Reset statistics data.</string> <!-- Main activity --> <string name="drawer_open">Open menu</string> |