mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Support multiple DefaultDownloadIndex instances
PiperOrigin-RevId: 244226680
This commit is contained in:
parent
e9413b0d41
commit
0ccda60ab4
2 changed files with 47 additions and 36 deletions
|
|
@ -23,6 +23,7 @@ import android.database.sqlite.SQLiteException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.google.android.exoplayer2.database.DatabaseIOException;
|
import com.google.android.exoplayer2.database.DatabaseIOException;
|
||||||
import com.google.android.exoplayer2.database.DatabaseProvider;
|
import com.google.android.exoplayer2.database.DatabaseProvider;
|
||||||
import com.google.android.exoplayer2.database.VersionTable;
|
import com.google.android.exoplayer2.database.VersionTable;
|
||||||
|
|
@ -32,18 +33,11 @@ import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A {@link DownloadIndex} that uses SQLite to persist {@link Download Downloads}. */
|
||||||
* A {@link DownloadIndex} which uses SQLite to persist {@link Download}s.
|
|
||||||
*
|
|
||||||
* <p class="caution">Database access may take a long time, do not call methods of this class from
|
|
||||||
* the application main thread.
|
|
||||||
*/
|
|
||||||
public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
|
|
||||||
private static final String TABLE_NAME = DatabaseProvider.TABLE_PREFIX + "Downloads";
|
private static final String TABLE_PREFIX = DatabaseProvider.TABLE_PREFIX + "Downloads";
|
||||||
|
|
||||||
// TODO: Support multiple instances. Probably using the underlying cache UID.
|
|
||||||
@VisibleForTesting /* package */ static final String INSTANCE_UID = "singleton";
|
|
||||||
@VisibleForTesting /* package */ static final int TABLE_VERSION = 1;
|
@VisibleForTesting /* package */ static final int TABLE_VERSION = 1;
|
||||||
|
|
||||||
private static final String COLUMN_ID = "id";
|
private static final String COLUMN_ID = "id";
|
||||||
|
|
@ -108,11 +102,8 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
COLUMN_UPDATE_TIME_MS
|
COLUMN_UPDATE_TIME_MS
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String SQL_DROP_TABLE_IF_EXISTS = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
private static final String TABLE_SCHEMA =
|
||||||
private static final String SQL_CREATE_TABLE =
|
"("
|
||||||
"CREATE TABLE "
|
|
||||||
+ TABLE_NAME
|
|
||||||
+ " ("
|
|
||||||
+ COLUMN_ID
|
+ COLUMN_ID
|
||||||
+ " TEXT PRIMARY KEY NOT NULL,"
|
+ " TEXT PRIMARY KEY NOT NULL,"
|
||||||
+ COLUMN_TYPE
|
+ COLUMN_TYPE
|
||||||
|
|
@ -148,19 +139,42 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
|
|
||||||
private static final String TRUE = "1";
|
private static final String TRUE = "1";
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String tableName;
|
||||||
private final DatabaseProvider databaseProvider;
|
private final DatabaseProvider databaseProvider;
|
||||||
|
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DefaultDownloadIndex which stores the {@link Download}s on a SQLite database provided
|
* Creates an instance that stores the {@link Download Downloads} in an SQLite database provided
|
||||||
* by {@code databaseProvider}.
|
* by a {@link DatabaseProvider}.
|
||||||
*
|
*
|
||||||
* @param databaseProvider A DatabaseProvider which provides the database which will be used to
|
* <p>Equivalent to calling {@link #DefaultDownloadIndex(DatabaseProvider, String)} with {@code
|
||||||
* store DownloadStatus table.
|
* name=""}.
|
||||||
|
*
|
||||||
|
* <p>Applications that only have one download index may use this constructor. Applications that
|
||||||
|
* have multiple download indices should call {@link #DefaultDownloadIndex(DatabaseProvider,
|
||||||
|
* String)} to specify a unique name for each index.
|
||||||
|
*
|
||||||
|
* @param databaseProvider Provides the SQLite database in which downloads are persisted.
|
||||||
*/
|
*/
|
||||||
public DefaultDownloadIndex(DatabaseProvider databaseProvider) {
|
public DefaultDownloadIndex(DatabaseProvider databaseProvider) {
|
||||||
|
this(databaseProvider, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance that stores the {@link Download Downloads} in an SQLite database provided
|
||||||
|
* by a {@link DatabaseProvider}.
|
||||||
|
*
|
||||||
|
* @param databaseProvider Provides the SQLite database in which downloads are persisted.
|
||||||
|
* @param name The name of the index. This name is incorporated into the names of the SQLite
|
||||||
|
* tables in which downloads are persisted.
|
||||||
|
*/
|
||||||
|
public DefaultDownloadIndex(DatabaseProvider databaseProvider, String name) {
|
||||||
|
// TODO: Remove this backward compatibility hack for launch.
|
||||||
|
this.name = TextUtils.isEmpty(name) ? "singleton" : name;
|
||||||
this.databaseProvider = databaseProvider;
|
this.databaseProvider = databaseProvider;
|
||||||
|
tableName = TABLE_PREFIX + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -207,7 +221,7 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
values.put(COLUMN_UPDATE_TIME_MS, download.updateTimeMs);
|
values.put(COLUMN_UPDATE_TIME_MS, download.updateTimeMs);
|
||||||
try {
|
try {
|
||||||
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
||||||
writableDatabase.replaceOrThrow(TABLE_NAME, /* nullColumnHack= */ null, values);
|
writableDatabase.replaceOrThrow(tableName, /* nullColumnHack= */ null, values);
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
throw new DatabaseIOException(e);
|
throw new DatabaseIOException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +231,7 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
public void removeDownload(String id) throws DatabaseIOException {
|
public void removeDownload(String id) throws DatabaseIOException {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
try {
|
try {
|
||||||
databaseProvider.getWritableDatabase().delete(TABLE_NAME, WHERE_ID_EQUALS, new String[] {id});
|
databaseProvider.getWritableDatabase().delete(tableName, WHERE_ID_EQUALS, new String[] {id});
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
throw new DatabaseIOException(e);
|
throw new DatabaseIOException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +244,7 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(COLUMN_STOP_REASON, stopReason);
|
values.put(COLUMN_STOP_REASON, stopReason);
|
||||||
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
||||||
writableDatabase.update(TABLE_NAME, values, WHERE_STATE_TERMINAL, /* whereArgs= */ null);
|
writableDatabase.update(tableName, values, WHERE_STATE_TERMINAL, /* whereArgs= */ null);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DatabaseIOException(e);
|
throw new DatabaseIOException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +258,7 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
values.put(COLUMN_STOP_REASON, stopReason);
|
values.put(COLUMN_STOP_REASON, stopReason);
|
||||||
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
||||||
writableDatabase.update(
|
writableDatabase.update(
|
||||||
TABLE_NAME, values, WHERE_STATE_TERMINAL + " AND " + WHERE_ID_EQUALS, new String[] {id});
|
tableName, values, WHERE_STATE_TERMINAL + " AND " + WHERE_ID_EQUALS, new String[] {id});
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DatabaseIOException(e);
|
throw new DatabaseIOException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -256,16 +270,15 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
|
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
|
||||||
int version =
|
int version = VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, name);
|
||||||
VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID);
|
|
||||||
if (version == VersionTable.VERSION_UNSET || version > TABLE_VERSION) {
|
if (version == VersionTable.VERSION_UNSET || version > TABLE_VERSION) {
|
||||||
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
||||||
writableDatabase.beginTransaction();
|
writableDatabase.beginTransaction();
|
||||||
try {
|
try {
|
||||||
VersionTable.setVersion(
|
VersionTable.setVersion(
|
||||||
writableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID, TABLE_VERSION);
|
writableDatabase, VersionTable.FEATURE_OFFLINE, name, TABLE_VERSION);
|
||||||
writableDatabase.execSQL(SQL_DROP_TABLE_IF_EXISTS);
|
writableDatabase.execSQL("DROP TABLE IF EXISTS " + tableName);
|
||||||
writableDatabase.execSQL(SQL_CREATE_TABLE);
|
writableDatabase.execSQL("CREATE TABLE " + tableName + " " + TABLE_SCHEMA);
|
||||||
writableDatabase.setTransactionSuccessful();
|
writableDatabase.setTransactionSuccessful();
|
||||||
} finally {
|
} finally {
|
||||||
writableDatabase.endTransaction();
|
writableDatabase.endTransaction();
|
||||||
|
|
@ -287,7 +300,7 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
|
||||||
return databaseProvider
|
return databaseProvider
|
||||||
.getReadableDatabase()
|
.getReadableDatabase()
|
||||||
.query(
|
.query(
|
||||||
TABLE_NAME,
|
tableName,
|
||||||
COLUMNS,
|
COLUMNS,
|
||||||
selection,
|
selection,
|
||||||
selectionArgs,
|
selectionArgs,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.offline;
|
package com.google.android.exoplayer2.offline;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.offline.DefaultDownloadIndex.INSTANCE_UID;
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
@ -33,6 +32,8 @@ import org.junit.runner.RunWith;
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class DefaultDownloadIndexTest {
|
public class DefaultDownloadIndexTest {
|
||||||
|
|
||||||
|
private static final String EMPTY_NAME = "singleton";
|
||||||
|
|
||||||
private ExoDatabaseProvider databaseProvider;
|
private ExoDatabaseProvider databaseProvider;
|
||||||
private DefaultDownloadIndex downloadIndex;
|
private DefaultDownloadIndex downloadIndex;
|
||||||
|
|
||||||
|
|
@ -170,14 +171,12 @@ public class DefaultDownloadIndexTest {
|
||||||
@Test
|
@Test
|
||||||
public void putDownload_setsVersion() throws DatabaseIOException {
|
public void putDownload_setsVersion() throws DatabaseIOException {
|
||||||
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
|
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
|
||||||
assertThat(
|
assertThat(VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, EMPTY_NAME))
|
||||||
VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID))
|
|
||||||
.isEqualTo(VersionTable.VERSION_UNSET);
|
.isEqualTo(VersionTable.VERSION_UNSET);
|
||||||
|
|
||||||
downloadIndex.putDownload(new DownloadBuilder("id1").build());
|
downloadIndex.putDownload(new DownloadBuilder("id1").build());
|
||||||
|
|
||||||
assertThat(
|
assertThat(VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, EMPTY_NAME))
|
||||||
VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID))
|
|
||||||
.isEqualTo(DefaultDownloadIndex.TABLE_VERSION);
|
.isEqualTo(DefaultDownloadIndex.TABLE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,15 +190,14 @@ public class DefaultDownloadIndexTest {
|
||||||
|
|
||||||
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
|
||||||
VersionTable.setVersion(
|
VersionTable.setVersion(
|
||||||
writableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID, Integer.MAX_VALUE);
|
writableDatabase, VersionTable.FEATURE_OFFLINE, EMPTY_NAME, Integer.MAX_VALUE);
|
||||||
|
|
||||||
downloadIndex = new DefaultDownloadIndex(databaseProvider);
|
downloadIndex = new DefaultDownloadIndex(databaseProvider);
|
||||||
|
|
||||||
cursor = downloadIndex.getDownloads();
|
cursor = downloadIndex.getDownloads();
|
||||||
assertThat(cursor.getCount()).isEqualTo(0);
|
assertThat(cursor.getCount()).isEqualTo(0);
|
||||||
cursor.close();
|
cursor.close();
|
||||||
assertThat(
|
assertThat(VersionTable.getVersion(writableDatabase, VersionTable.FEATURE_OFFLINE, EMPTY_NAME))
|
||||||
VersionTable.getVersion(writableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID))
|
|
||||||
.isEqualTo(DefaultDownloadIndex.TABLE_VERSION);
|
.isEqualTo(DefaultDownloadIndex.TABLE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue