Nav drawer subscriptions context menu

This commit is contained in:
Martin Fietz 2015-06-30 00:18:24 +02:00
parent 5643933a51
commit 936ecc2b8e
15 changed files with 465 additions and 501 deletions

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@ -13,6 +14,8 @@ import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@ -31,6 +34,8 @@ import org.apache.commons.lang3.StringUtils;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.ChapterListAdapter;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
@ -39,6 +44,7 @@ import de.danoeh.antennapod.core.feed.SimpleChapter;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
@ -430,6 +436,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
drawerLayout.closeDrawer(navDrawer);
}
});
registerForContextMenu(navList);
drawerToggle.syncState();
findViewById(R.id.nav_settings).setOnClickListener(new View.OnClickListener() {
@ -634,6 +641,65 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if(v.getId() != R.id.nav_list) {
return;
}
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
int position = adapterInfo.position;
if(position < navAdapter.getSubscriptionOffset()) {
return;
}
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.nav_feed_context, menu);
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
menu.setHeaderTitle(feed.getTitle());
// episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
if(menuInfo.targetView.getParent() instanceof ListView == false
|| ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
return false;
}
int position = menuInfo.position;
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
switch(item.getItemId()) {
case R.id.mark_all_seen_item:
DBWriter.markFeedSeen(this, feed.getId());
return true;
case R.id.mark_all_read_item:
DBWriter.markFeedRead(this, feed.getId());
return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(this, feed) {
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
};
ConfirmationDialog conDialog = new ConfirmationDialog(this,
R.string.remove_feed_label,
R.string.feed_delete_confirmation_msg) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
dialog.dismiss();
remover.executeAsync();
}
};
conDialog.createNewDialog().show();
return true;
default:
return super.onContextItemSelected(item);
}
}
private DBReader.NavDrawerData navDrawerData;
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
@ -708,8 +774,8 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
@Override
public int getNumberOfUnreadFeedItems(long feedId) {
return (navDrawerData != null) ? navDrawerData.numUnreadFeedItems.get(feedId) : 0;
public int getFeedCounter(long feedId) {
return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
};
}

View File

@ -20,6 +20,8 @@ import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
@ -32,12 +34,15 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.QueueEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.AllEpisodesFragment;
@ -140,6 +145,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
navList.setAdapter(navAdapter);
navList.setOnItemClickListener(navListClickListener);
navList.setOnItemLongClickListener(newListLongClickListener);
registerForContextMenu(navList);
navAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
@ -493,6 +499,64 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if(v.getId() != R.id.nav_list) {
return;
}
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
int position = adapterInfo.position;
if(position < navAdapter.getSubscriptionOffset()) {
return;
}
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.nav_feed_context, menu);
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
menu.setHeaderTitle(feed.getTitle());
// episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
if(menuInfo.targetView.getParent() instanceof ListView == false
|| ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
return false;
}
int position = menuInfo.position;
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
switch(item.getItemId()) {
case R.id.mark_all_seen_item:
DBWriter.markFeedSeen(this, feed.getId());
return true;
case R.id.mark_all_read_item:
DBWriter.markFeedRead(this, feed.getId());
return true;
case R.id.remove_item:
final FeedRemover remover = new FeedRemover(this, feed) {
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
};
ConfirmationDialog conDialog = new ConfirmationDialog(this,
R.string.remove_feed_label,
R.string.feed_delete_confirmation_msg) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
dialog.dismiss();
remover.executeAsync();
}
};
conDialog.createNewDialog().show();
return true;
default:
return super.onContextItemSelected(item);
}
}
private DBReader.NavDrawerData navDrawerData;
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
private int selectedNavListIndex = 0;
@ -532,8 +596,8 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
}
@Override
public int getNumberOfUnreadFeedItems(long feedId) {
return (navDrawerData != null) ? navDrawerData.numUnreadFeedItems.get(feedId) : 0;
public int getFeedCounter(long feedId) {
return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
};

View File

@ -276,10 +276,10 @@ public class NavListAdapter extends BaseAdapter
p.addRule(RelativeLayout.LEFT_OF, R.id.txtvCount);
holder.failure.setVisibility(View.GONE);
}
int feedUnreadItems = itemAccess.getNumberOfUnreadFeedItems(feed.getId());
if(feedUnreadItems > 0) {
int counter = itemAccess.getFeedCounter(feed.getId());
if(counter > 0) {
holder.count.setVisibility(View.VISIBLE);
holder.count.setText(String.valueOf(feedUnreadItems));
holder.count.setText(String.valueOf(counter));
holder.count.setTypeface(holder.title.getTypeface());
} else {
holder.count.setVisibility(View.GONE);
@ -306,7 +306,7 @@ public class NavListAdapter extends BaseAdapter
int getSelectedItemIndex();
int getQueueSize();
int getNumberOfNewItems();
int getNumberOfUnreadFeedItems(long feedId);
int getFeedCounter(long feedId);
}
}

View File

@ -14,7 +14,6 @@ public class ClientConfigurator {
ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl();
ClientConfig.gpodnetCallbacks = new GpodnetCallbacksImpl();
ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl();
ClientConfig.storageCallbacks = new StorageCallbacksImpl();
ClientConfig.flattrCallbacks = new FlattrCallbacksImpl();
ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl();
}

View File

@ -1,206 +0,0 @@
package de.danoeh.antennapod.config;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.MediaMetadataRetriever;
import android.util.Log;
import de.danoeh.antennapod.core.StorageCallbacks;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
public class StorageCallbacksImpl implements StorageCallbacks {
@Override
public int getDatabaseVersion() {
return 17;
}
@Override
public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ newVersion + ".");
if (oldVersion <= 1) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ PodDBAdapter.KEY_TYPE + " TEXT");
}
if (oldVersion <= 2) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + PodDBAdapter.KEY_LINK + " TEXT");
}
if (oldVersion <= 3) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + PodDBAdapter.KEY_ITEM_IDENTIFIER + " TEXT");
}
if (oldVersion <= 4) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ PodDBAdapter.KEY_FEED_IDENTIFIER + " TEXT");
}
if (oldVersion <= 5) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + PodDBAdapter.KEY_REASON_DETAILED + " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE + " TEXT");
}
if (oldVersion <= 6) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + PodDBAdapter.KEY_CHAPTER_TYPE + " INTEGER");
}
if (oldVersion <= 7) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE
+ " INTEGER");
}
if (oldVersion <= 8) {
final int KEY_ID_POSITION = 0;
final int KEY_MEDIA_POSITION = 1;
// Add feeditem column to feedmedia table
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_FEEDITEM
+ " INTEGER");
Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
new String[]{PodDBAdapter.KEY_ID, PodDBAdapter.KEY_MEDIA}, "? > 0",
new String[]{PodDBAdapter.KEY_MEDIA}, null, null, null);
if (feeditemCursor.moveToFirst()) {
db.beginTransaction();
ContentValues contentValues = new ContentValues();
do {
long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
contentValues.put(PodDBAdapter.KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, PodDBAdapter.KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
contentValues.clear();
} while (feeditemCursor.moveToNext());
db.setTransactionSuccessful();
db.endTransaction();
}
feeditemCursor.close();
}
if (oldVersion <= 9) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD
+ " INTEGER DEFAULT 1");
}
if (oldVersion <= 10) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_FLATTR_STATUS
+ " INTEGER");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + PodDBAdapter.KEY_FLATTR_STATUS
+ " INTEGER");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_PLAYED_DURATION
+ " INTEGER");
}
if (oldVersion <= 11) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_USERNAME
+ " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD
+ " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + PodDBAdapter.KEY_IMAGE
+ " INTEGER");
}
if (oldVersion <= 12) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT");
}
if (oldVersion <= 13) {
// remove duplicate rows in "Chapters" table that were created because of a bug.
db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
"(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
PodDBAdapter.KEY_ID,
PodDBAdapter.KEY_ID,
PodDBAdapter.KEY_ID,
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
PodDBAdapter.KEY_TITLE,
PodDBAdapter.KEY_START,
PodDBAdapter.KEY_FEEDITEM,
PodDBAdapter.KEY_LINK,
PodDBAdapter.KEY_CHAPTER_TYPE));
}
if(oldVersion <= 14) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD + " INTEGER");
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " SET " + PodDBAdapter.KEY_AUTO_DOWNLOAD + " = "
+ "(SELECT " + PodDBAdapter.KEY_AUTO_DOWNLOAD
+ " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
+ " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_ID
+ " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_FEED + ")");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_HIDE + " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
// create indexes
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
}
if(oldVersion <= 15) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
+ " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=0");
Cursor c = db.rawQuery("SELECT " + PodDBAdapter.KEY_FILE_URL
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=1 "
+ " AND " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
if(c.moveToFirst()) {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
do {
String fileUrl = c.getString(0);
try {
mmr.setDataSource(fileUrl);
byte[] image = mmr.getEmbeddedPicture();
if (image != null) {
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=1"
+ " WHERE " + PodDBAdapter.KEY_FILE_URL + "='"+ fileUrl + "'");
} else {
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
+ " WHERE " + PodDBAdapter.KEY_FILE_URL + "='"+ fileUrl + "'");
}
} catch(Exception e) {
e.printStackTrace();
}
} while(c.moveToNext());
}
c.close();
}
if(oldVersion <= 17) {
String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "="
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_FEEDITEM
+ " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "="
+ PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_FEEDITEM
+ " WHERE "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ + " = 0 AND " // unplayed
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOADED + " = 0 AND " // undownloaded
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION + " = 0 AND " // not partially played
+ PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_ID + " IS NULL"; // not in queue
String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " SET " + PodDBAdapter.KEY_READ + "=" + FeedItem.NEW
+ " WHERE " + PodDBAdapter.KEY_ID + " IN (" + selectNew + ")";
Log.d("Migration", "SQL: " + sql);
db.execSQL(sql);
}
}
}

View File

@ -5,8 +5,6 @@ import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -316,7 +314,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkPlayed(boolean isPlayed) {
for (FeedItem episode : episodes) {
if(episode.isRead() == isPlayed) {
if(episode.isPlayed() == isPlayed) {
if(!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/mark_all_seen_item"
android:menuCategory="container"
android:title="@string/mark_all_seen_label" />
<item
android:id="@+id/mark_all_read_item"
android:menuCategory="container"
android:title="@string/mark_all_read_label" />
<item
android:id="@+id/remove_item"
android:menuCategory="container"
android:title="@string/remove_feed_label" />
</menu>

View File

@ -21,7 +21,5 @@ public class ClientConfig {
public static FlattrCallbacks flattrCallbacks;
public static StorageCallbacks storageCallbacks;
public static DBTasksCallbacks dbTasksCallbacks;
}

View File

@ -1,27 +0,0 @@
package de.danoeh.antennapod.core;
import android.database.sqlite.SQLiteDatabase;
/**
* Callbacks for the classes in the storage package of the core module.
*/
public interface StorageCallbacks {
/**
* Returns the current version of the database.
*
* @return The non-negative version number of the database.
*/
public int getDatabaseVersion();
/**
* Upgrades the given database from an old version to a newer version.
*
* @param db The database that is supposed to be upgraded.
* @param oldVersion The old version of the database.
* @param newVersion The version that the database is supposed to be upgraded to.
*/
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
}

View File

@ -177,10 +177,21 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
public boolean hasNewItems() {
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.UNREAD) {
if (item.getMedia() != null) {
return true;
}
if (item.isNew()) {
return true;
}
}
return false;
}
/**
* Returns true if at least one item in the itemlist is unread.
*
*/
public boolean hasUnplayedItems() {
for (FeedItem item : items) {
if (false == item.isNew() && false == item.isPlayed()) {
return true;
}
}
return false;

View File

@ -1,139 +0,0 @@
package de.danoeh.antennapod.core.storage;
import android.content.Context;
import android.util.Log;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import de.danoeh.antennapod.core.feed.FeedItem;
/**
* Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps.
*/
public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
private static final String TAG = "APSPCleanupAlgorithm";
final int numberOfNewAutomaticallyDownloadedEpisodes;
public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
}
/**
* Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first.
* The episode that is currently playing as well as the n most recent episodes (the exact value is determined
* by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted.
*
* @param context
* @param episodeSize The maximum amount of space that should be freed by this method
* @return The number of episodes that have been deleted
*/
@Override
public int performCleanup(Context context, Integer episodeSize) {
Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize));
if (episodeSize <= 0) {
return 0;
}
List<FeedItem> candidates = getAutoCleanupCandidates(context);
List<FeedItem> deleteList = new ArrayList<FeedItem>();
long deletedEpisodesSize = 0;
Collections.sort(candidates, new Comparator<FeedItem>() {
@Override
public int compare(FeedItem lhs, FeedItem rhs) {
File lFile = new File(lhs.getMedia().getFile_url());
File rFile = new File(rhs.getMedia().getFile_url());
if (!lFile.exists() || !rFile.exists()) {
return 0;
}
if (FileUtils.isFileOlder(lFile, rFile)) {
return -1;
} else {
return 1;
}
}
});
// listened episodes will be deleted first
Iterator<FeedItem> it = candidates.iterator();
if (it.hasNext()) {
for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) {
it.remove();
deleteList.add(i);
deletedEpisodesSize += i.getMedia().getSize();
}
}
}
// delete unlistened old episodes if necessary
it = candidates.iterator();
if (it.hasNext()) {
for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
if (!i.getMedia().isPlaying()) {
it.remove();
deleteList.add(i);
deletedEpisodesSize += i.getMedia().getSize();
}
}
}
for (FeedItem item : deleteList) {
try {
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory",
episodeSize, deleteList.size(), deletedEpisodesSize));
return deleteList.size();
}
@Override
public Integer getDefaultCleanupParameter(Context context) {
return 0;
}
@Override
public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
int episodeSize = 0;
for (FeedItem item : items) {
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
episodeSize += item.getMedia().getSize();
}
}
return episodeSize;
}
/**
* Returns list of FeedItems that have been downloaded, but are not one of the
* [numberOfNewAutomaticallyDownloadedEpisodes] most recent items.
*/
private List<FeedItem> getAutoCleanupCandidates(Context context) {
List<FeedItem> downloaded = new ArrayList<FeedItem>(DBReader.getDownloadedItems(context));
List<FeedItem> recent = new ArrayList<FeedItem>(DBReader.getRecentlyPublishedEpisodes(context,
numberOfNewAutomaticallyDownloadedEpisodes));
for (FeedItem r : recent) {
if (r.hasMedia() && r.getMedia().isDownloaded()) {
for (int i = 0; i < downloaded.size(); i++) {
if (downloaded.get(i).getId() == r.getId()) {
downloaded.remove(i);
break;
}
}
}
}
return downloaded;
}
}

View File

@ -1,72 +0,0 @@
package de.danoeh.antennapod.core.storage;
import android.content.Context;
import android.util.Log;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.NetworkUtils;
/**
* Implements the automatic download algorithm used by AntennaPodSP apps.
*/
public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm {
private static final String TAG = "APSPDownloadAlgorithm";
private final int numberOfNewAutomaticallyDownloadedEpisodes;
public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
}
/**
* Downloads the most recent episodes automatically. The exact number of
* episodes that will be downloaded can be set in the AppPreferences.
*
* @param context Used for accessing the DB.
* @return A Runnable that will be submitted to an ExecutorService.
*/
@Override
public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) {
return new Runnable() {
@Override
public void run() {
if (BuildConfig.DEBUG)
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
if (NetworkUtils.autodownloadNetworkAvailable(context)
&& UserPreferences.isEnableAutodownload()) {
Arrays.sort(mediaIds);
List<FeedItem> itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context,
numberOfNewAutomaticallyDownloadedEpisodes);
Iterator<FeedItem> it = itemsToDownload.iterator();
for (FeedItem item = it.next(); it.hasNext(); item = it.next()) {
if (!item.hasMedia()
|| item.getMedia().isDownloaded()
|| Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) {
it.remove();
}
}
if (BuildConfig.DEBUG)
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
+ " items for automatic download");
if (!itemsToDownload.isEmpty()) {
try {
DBTasks.downloadFeedItems(false, context,
itemsToDownload.toArray(new FeedItem[itemsToDownload
.size()]));
} catch (DownloadRequestException e) {
e.printStackTrace();
}
}
}
}
};
}
}

View File

@ -22,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.ID3Chapter;
import de.danoeh.antennapod.core.feed.SimpleChapter;
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.LongIntMap;
@ -1139,27 +1140,42 @@ public final class DBReader {
for(int i=0; i < feeds.size(); i++) {
feedIds[i] = feeds.get(i).getId();
}
final LongIntMap numUnreadFeedItems = adapter.getNumberOfUnreadFeedItems(feedIds);
Collections.sort(feeds, new Comparator<Feed>() {
@Override
public int compare(Feed lhs, Feed rhs) {
long numUnreadLhs = numUnreadFeedItems.get(lhs.getId());
Log.d(TAG, "feed with id " + lhs.getId() + " has " + numUnreadLhs + " unread items");
long numUnreadRhs = numUnreadFeedItems.get(rhs.getId());
Log.d(TAG, "feed with id " + rhs.getId() + " has " + numUnreadRhs + " unread items");
if(numUnreadLhs > numUnreadRhs) {
// reverse natural order: podcast with most unplayed episodes first
return -1;
} else if(numUnreadLhs == numUnreadRhs) {
return lhs.getTitle().compareTo(rhs.getTitle());
} else {
return 1;
final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
Comparator<Feed> comparator;
int feedOrder = UserPreferences.getFeedOrder();
if(feedOrder == UserPreferences.ORDER_UNPLAYED_EPISODES) {
comparator = new Comparator<Feed>() {
@Override
public int compare(Feed lhs, Feed rhs) {
long counterLhs = feedCounters.get(lhs.getId());
long counterRhs = feedCounters.get(rhs.getId());
if(counterLhs > counterRhs) {
// reverse natural order: podcast with most unplayed episodes first
return -1;
} else if(counterLhs == counterRhs) {
return lhs.getTitle().compareTo(rhs.getTitle());
} else {
return 1;
}
}
}
});
};
} else {
comparator = new Comparator<Feed>() {
@Override
public int compare(Feed lhs, Feed rhs) {
if(lhs.getTitle() == null) {
return 1;
}
return lhs.getTitle().compareTo(rhs.getTitle());
}
};
}
Collections.sort(feeds, comparator);
int queueSize = adapter.getQueueSize();
int numNewItems = adapter.getNumberOfNewItems();
NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numUnreadFeedItems);
NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters);
adapter.close();
return result;
}
@ -1168,14 +1184,16 @@ public final class DBReader {
public List<Feed> feeds;
public int queueSize;
public int numNewItems;
public LongIntMap numUnreadFeedItems;
public LongIntMap feedCounters;
public NavDrawerData(List<Feed> feeds, int queueSize, int numNewItems,
LongIntMap numUnreadFeedItems) {
public NavDrawerData(List<Feed> feeds,
int queueSize,
int numNewItems,
LongIntMap feedIndicatorValues) {
this.feeds = feeds;
this.queueSize = queueSize;
this.numNewItems = numNewItems;
this.numUnreadFeedItems = numUnreadFeedItems;
this.feedCounters = feedIndicatorValues;
}
}
}

View File

@ -409,8 +409,8 @@ public class DBWriter {
if (item != null) {
// add item to either front ot back of queue
boolean addToFront = UserPreferences.enqueueAtFront();
if(addToFront){
queue.add(0+i, item);
if (addToFront) {
queue.add(0 + i, item);
} else {
queue.add(item);
}
@ -610,7 +610,8 @@ public class DBWriter {
public void run() {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setFeedItemRead(read, itemIds);
int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED;
adapter.setFeedItemRead(played, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
@ -650,6 +651,35 @@ public class DBWriter {
});
}
/**
* Sets the 'read'-attribute of all FeedItems of a specific Feed to true.
*
* @param context A context that is used for opening a database connection.
* @param feedId ID of the Feed.
*/
public static Future<?> markFeedSeen(final Context context, final long feedId) {
return dbExec.submit(new Runnable() {
@Override
public void run() {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId);
long[] ids = new long[itemCursor.getCount()];
itemCursor.moveToFirst();
for (int i = 0; i < ids.length; i++) {
ids[i] = itemCursor.getLong(0);
itemCursor.moveToNext();
}
itemCursor.close();
adapter.setFeedItemRead(FeedItem.UNPLAYED, ids);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
}
/**
* Sets the 'read'-attribute of all FeedItems of a specific Feed to true.
*
@ -677,7 +707,6 @@ public class DBWriter {
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
}
/**

View File

@ -9,6 +9,7 @@ import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.media.MediaMetadataRetriever;
import android.text.TextUtils;
import android.util.Log;
@ -18,7 +19,6 @@ import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.Chapter;
@ -28,13 +28,12 @@ import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import de.greenrobot.event.EventBus;
;
// TODO Remove media column from feeditem table
/**
@ -369,8 +368,7 @@ public class PodDBAdapter {
private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) {
if (dbHelperSingleton == null) {
dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null,
ClientConfig.storageCallbacks.getDatabaseVersion());
dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null);
}
return dbHelperSingleton;
}
@ -1113,6 +1111,20 @@ public class PodDBAdapter {
return db.rawQuery(query, null);
}
/**
* Returns a cursor which contains all items of a feed that are considered new.
* The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
*/
public final Cursor getNewItemsIdsCursor(long feedId) {
final String query = "SELECT " + KEY_ID
+ " FROM " + TABLE_NAME_FEED_ITEMS
+ " WHERE " + KEY_FEED + "=" + feedId
+ " AND " + KEY_READ + "=" + FeedItem.NEW
+ " ORDER BY " + KEY_PUBDATE + " DESC";
Cursor c = db.rawQuery(query, null);
return c;
}
/**
* Returns a cursor which contains all feed items that are considered new.
* The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
@ -1282,7 +1294,20 @@ public class PodDBAdapter {
return result;
}
public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) {
public final LongIntMap getFeedCounters(long... feedIds) {
int indicator = UserPreferences.getFeedIndicator();
String whereRead;
if(indicator == UserPreferences.SHOW_NEW_UNPLAYED_SUM) {
whereRead = "(" + KEY_READ + "=" + FeedItem.NEW
+ " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")";
} else if(indicator == UserPreferences.SHOW_NEW) {
whereRead = KEY_READ + "=" + FeedItem.NEW;
} else if(indicator == UserPreferences.SHOW_UNPLAYED) {
whereRead = KEY_READ + "=" + FeedItem.UNPLAYED;
} else {
return new LongIntMap(0);
}
// work around TextUtils.join wanting only boxed items
// and StringUtils.join() causing NoSuchMethodErrors on MIUI
StringBuilder builder = new StringBuilder();
@ -1298,9 +1323,8 @@ public class PodDBAdapter {
final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count "
+ " FROM " + TABLE_NAME_FEED_ITEMS
+ " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") "
+ " AND (" + KEY_READ + "=" + FeedItem.NEW
+ " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"
+ " GROUP BY " + KEY_FEED;
+ " AND " + whereRead + " GROUP BY " + KEY_FEED;
Cursor c = db.rawQuery(query, null);
LongIntMap result = new LongIntMap(c.getCount());
if (c.moveToFirst()) {
@ -1454,6 +1478,8 @@ public class PodDBAdapter {
*/
private static class PodDBHelper extends SQLiteOpenHelper {
private final static int VERSION = 17;
private Context context;
/**
@ -1462,11 +1488,10 @@ public class PodDBAdapter {
* @param context Context to use
* @param name Name of the database
* @param factory to use for creating cursor objects
* @param version number of the database
*/
public PodDBHelper(final Context context, final String name,
final CursorFactory factory, final int version) {
super(context, name, factory, version);
final CursorFactory factory) {
super(context, name, factory, VERSION);
this.context = context;
}
@ -1492,7 +1517,188 @@ public class PodDBAdapter {
public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
final int newVersion) {
EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database)));
ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion);
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ newVersion + ".");
if (oldVersion <= 1) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ KEY_TYPE + " TEXT");
}
if (oldVersion <= 2) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + KEY_LINK + " TEXT");
}
if (oldVersion <= 3) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT");
}
if (oldVersion <= 4) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ KEY_FEED_IDENTIFIER + " TEXT");
}
if (oldVersion <= 5) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
}
if (oldVersion <= 6) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER");
}
if (oldVersion <= 7) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE
+ " INTEGER");
}
if (oldVersion <= 8) {
final int KEY_ID_POSITION = 0;
final int KEY_MEDIA_POSITION = 1;
// Add feeditem column to feedmedia table
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + KEY_FEEDITEM
+ " INTEGER");
Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
new String[]{KEY_ID, KEY_MEDIA}, "? > 0",
new String[]{KEY_MEDIA}, null, null, null);
if (feeditemCursor.moveToFirst()) {
db.beginTransaction();
ContentValues contentValues = new ContentValues();
do {
long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
contentValues.clear();
} while (feeditemCursor.moveToNext());
db.setTransactionSuccessful();
db.endTransaction();
}
feeditemCursor.close();
}
if (oldVersion <= 9) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_AUTO_DOWNLOAD
+ " INTEGER DEFAULT 1");
}
if (oldVersion <= 10) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_FLATTR_STATUS
+ " INTEGER");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + KEY_FLATTR_STATUS
+ " INTEGER");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + KEY_PLAYED_DURATION
+ " INTEGER");
}
if (oldVersion <= 11) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_USERNAME
+ " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_PASSWORD
+ " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + KEY_IMAGE
+ " INTEGER");
}
if (oldVersion <= 12) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_NEXT_PAGE_LINK + " TEXT");
}
if (oldVersion <= 13) {
// remove duplicate rows in "Chapters" table that were created because of a bug.
db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
"(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
KEY_ID,
KEY_ID,
KEY_ID,
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
KEY_TITLE,
KEY_START,
KEY_FEEDITEM,
KEY_LINK,
KEY_CHAPTER_TYPE));
}
if(oldVersion <= 14) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER");
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " SET " + KEY_AUTO_DOWNLOAD + " = "
+ "(SELECT " + KEY_AUTO_DOWNLOAD
+ " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
+ " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID
+ " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_HIDE + " TEXT");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
// create indexes
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
}
if(oldVersion <= 15) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ " WHERE " + KEY_DOWNLOADED + "=0");
Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " WHERE " + KEY_DOWNLOADED + "=1 "
+ " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
if(c.moveToFirst()) {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
do {
String fileUrl = c.getString(0);
try {
mmr.setDataSource(fileUrl);
byte[] image = mmr.getEmbeddedPicture();
if (image != null) {
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1"
+ " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
} else {
db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
}
} catch(Exception e) {
e.printStackTrace();
}
} while(c.moveToNext());
}
c.close();
}
if(oldVersion <= 16) {
String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID
+ " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
+ " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
+ " WHERE "
+ PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
+ PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
+ PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ " SET " + KEY_READ + "=" + FeedItem.NEW
+ " WHERE " + KEY_ID + " IN (" + selectNew + ")";
Log.d("Migration", "SQL: " + sql);
db.execSQL(sql);
}
EventBus.getDefault().post(ProgressEvent.end());
}
}