Android: Store folders to scan in SharedPreferences instead of SQLite
Needed in order for the next commit to get rid of the SQLite database.
This commit is contained in:
parent
5f29e891d3
commit
daee5a4b43
|
@ -2,9 +2,11 @@ package org.dolphinemu.dolphinemu.model;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||||
|
@ -37,8 +39,6 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
public static final int GAME_COLUMN_COMPANY = 7;
|
public static final int GAME_COLUMN_COMPANY = 7;
|
||||||
public static final int GAME_COLUMN_SCREENSHOT_PATH = 8;
|
public static final int GAME_COLUMN_SCREENSHOT_PATH = 8;
|
||||||
|
|
||||||
public static final int FOLDER_COLUMN_PATH = 1;
|
|
||||||
|
|
||||||
public static final String KEY_DB_ID = "_id";
|
public static final String KEY_DB_ID = "_id";
|
||||||
|
|
||||||
public static final String KEY_GAME_PATH = "path";
|
public static final String KEY_GAME_PATH = "path";
|
||||||
|
@ -49,18 +49,12 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
public static final String KEY_GAME_ID = "game_id";
|
public static final String KEY_GAME_ID = "game_id";
|
||||||
public static final String KEY_GAME_COMPANY = "company";
|
public static final String KEY_GAME_COMPANY = "company";
|
||||||
public static final String KEY_GAME_SCREENSHOT_PATH = "screenshot_path";
|
public static final String KEY_GAME_SCREENSHOT_PATH = "screenshot_path";
|
||||||
|
|
||||||
public static final String KEY_FOLDER_PATH = "path";
|
|
||||||
|
|
||||||
public static final String TABLE_NAME_FOLDERS = "folders";
|
|
||||||
public static final String TABLE_NAME_GAMES = "games";
|
public static final String TABLE_NAME_GAMES = "games";
|
||||||
|
|
||||||
private static final String TYPE_PRIMARY = " INTEGER PRIMARY KEY";
|
private static final String TYPE_PRIMARY = " INTEGER PRIMARY KEY";
|
||||||
private static final String TYPE_INTEGER = " INTEGER";
|
private static final String TYPE_INTEGER = " INTEGER";
|
||||||
private static final String TYPE_STRING = " TEXT";
|
private static final String TYPE_STRING = " TEXT";
|
||||||
|
|
||||||
private static final String CONSTRAINT_UNIQUE = " UNIQUE";
|
|
||||||
|
|
||||||
private static final String SEPARATOR = ", ";
|
private static final String SEPARATOR = ", ";
|
||||||
|
|
||||||
private static final String SQL_CREATE_GAMES = "CREATE TABLE " + TABLE_NAME_GAMES + "("
|
private static final String SQL_CREATE_GAMES = "CREATE TABLE " + TABLE_NAME_GAMES + "("
|
||||||
|
@ -74,17 +68,19 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
+ KEY_GAME_COMPANY + TYPE_STRING + SEPARATOR
|
+ KEY_GAME_COMPANY + TYPE_STRING + SEPARATOR
|
||||||
+ KEY_GAME_SCREENSHOT_PATH + TYPE_STRING + ")";
|
+ KEY_GAME_SCREENSHOT_PATH + TYPE_STRING + ")";
|
||||||
|
|
||||||
private static final String SQL_CREATE_FOLDERS = "CREATE TABLE " + TABLE_NAME_FOLDERS + "("
|
|
||||||
+ KEY_DB_ID + TYPE_PRIMARY + SEPARATOR
|
|
||||||
+ KEY_FOLDER_PATH + TYPE_STRING + CONSTRAINT_UNIQUE + ")";
|
|
||||||
|
|
||||||
private static final String SQL_DELETE_FOLDERS = "DROP TABLE IF EXISTS " + TABLE_NAME_FOLDERS;
|
|
||||||
private static final String SQL_DELETE_GAMES = "DROP TABLE IF EXISTS " + TABLE_NAME_GAMES;
|
private static final String SQL_DELETE_GAMES = "DROP TABLE IF EXISTS " + TABLE_NAME_GAMES;
|
||||||
|
|
||||||
|
private static final String GAME_FOLDER_PATHS_PREFERENCE = "gameFolderPaths";
|
||||||
|
|
||||||
|
private static final Set<String> EMPTY_SET = new HashSet<>();
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
public GameDatabase(Context context)
|
public GameDatabase(Context context)
|
||||||
{
|
{
|
||||||
// Superclass constructor builds a database or uses an existing one.
|
// Superclass constructor builds a database or uses an existing one.
|
||||||
super(context, "games.db", null, DB_VERSION);
|
super(context, "games.db", null, DB_VERSION);
|
||||||
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,16 +89,12 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
Log.debug("[GameDatabase] GameDatabase - Creating database...");
|
Log.debug("[GameDatabase] GameDatabase - Creating database...");
|
||||||
|
|
||||||
execSqlAndLog(database, SQL_CREATE_GAMES);
|
execSqlAndLog(database, SQL_CREATE_GAMES);
|
||||||
execSqlAndLog(database, SQL_CREATE_FOLDERS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDowngrade(SQLiteDatabase database, int oldVersion, int newVersion)
|
public void onDowngrade(SQLiteDatabase database, int oldVersion, int newVersion)
|
||||||
{
|
{
|
||||||
Log.verbose("[GameDatabase] Downgrades not supporting, clearing databases..");
|
Log.verbose("[GameDatabase] Downgrades not supporting, clearing databases..");
|
||||||
execSqlAndLog(database, SQL_DELETE_FOLDERS);
|
|
||||||
execSqlAndLog(database, SQL_CREATE_FOLDERS);
|
|
||||||
|
|
||||||
execSqlAndLog(database, SQL_DELETE_GAMES);
|
execSqlAndLog(database, SQL_DELETE_GAMES);
|
||||||
execSqlAndLog(database, SQL_CREATE_GAMES);
|
execSqlAndLog(database, SQL_CREATE_GAMES);
|
||||||
}
|
}
|
||||||
|
@ -120,6 +112,19 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
scanLibrary(database);
|
scanLibrary(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addGameFolder(String path)
|
||||||
|
{
|
||||||
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||||
|
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||||
|
Set<String> newFolderPaths = new HashSet<>(folderPaths);
|
||||||
|
newFolderPaths.add(path);
|
||||||
|
SharedPreferences.Editor editor = preferences.edit();
|
||||||
|
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
scanLibrary(getWritableDatabase());
|
||||||
|
}
|
||||||
|
|
||||||
public void scanLibrary(SQLiteDatabase database)
|
public void scanLibrary(SQLiteDatabase database)
|
||||||
{
|
{
|
||||||
// Before scanning known folders, go through the game table and remove any entries for which the file itself is missing.
|
// Before scanning known folders, go through the game table and remove any entries for which the file itself is missing.
|
||||||
|
@ -148,28 +153,17 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get a cursor listing all the folders the user has added to the library.
|
|
||||||
Cursor folderCursor = database.query(TABLE_NAME_FOLDERS,
|
|
||||||
null, // Get all columns.
|
|
||||||
null, // Get all rows.
|
|
||||||
null,
|
|
||||||
null, // No grouping.
|
|
||||||
null,
|
|
||||||
null); // Order of folders is irrelevant.
|
|
||||||
|
|
||||||
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(
|
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(
|
||||||
".ciso", ".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".tgc", ".wad", ".wbfs"));
|
".ciso", ".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".tgc", ".wad", ".wbfs"));
|
||||||
|
|
||||||
// Possibly overly defensive, but ensures that moveToNext() does not skip a row.
|
|
||||||
folderCursor.moveToPosition(-1);
|
|
||||||
|
|
||||||
// Iterate through all results of the DB query (i.e. all folders in the library.)
|
// Iterate through all results of the DB query (i.e. all folders in the library.)
|
||||||
while (folderCursor.moveToNext())
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||||
|
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||||
|
Set<String> newFolderPaths = new HashSet<>();
|
||||||
|
for (String folderPath : folderPaths)
|
||||||
{
|
{
|
||||||
|
|
||||||
String folderPath = folderCursor.getString(FOLDER_COLUMN_PATH);
|
|
||||||
File folder = new File(folderPath);
|
File folder = new File(folderPath);
|
||||||
|
boolean deleteFolder = false;
|
||||||
|
|
||||||
Log.info("[GameDatabase] Reading files from library folder: " + folderPath);
|
Log.info("[GameDatabase] Reading files from library folder: " + folderPath);
|
||||||
|
|
||||||
|
@ -245,19 +239,29 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
else if (!folder.exists())
|
else if (!folder.exists())
|
||||||
{
|
{
|
||||||
Log.error("[GameDatabase] Folder no longer exists. Removing from the library: " + folderPath);
|
Log.error("[GameDatabase] Folder no longer exists. Removing from the library: " + folderPath);
|
||||||
database.delete(TABLE_NAME_FOLDERS,
|
deleteFolder = true;
|
||||||
KEY_DB_ID + " = ?",
|
|
||||||
new String[]{Long.toString(folderCursor.getLong(COLUMN_DB_ID))});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.error("[GameDatabase] Folder contains no games: " + folderPath);
|
Log.error("[GameDatabase] Folder contains no games: " + folderPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!deleteFolder)
|
||||||
|
{
|
||||||
|
newFolderPaths.add(folderPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileCursor.close();
|
fileCursor.close();
|
||||||
folderCursor.close();
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
if (folderPaths.size() != newFolderPaths.size())
|
||||||
|
{
|
||||||
|
// One or more folders are being deleted
|
||||||
|
SharedPreferences.Editor editor = preferences.edit();
|
||||||
|
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Cursor> getGamesForPlatform(final Platform platform)
|
public Observable<Cursor> getGamesForPlatform(final Platform platform)
|
||||||
|
|
|
@ -19,7 +19,6 @@ public final class GameProvider extends ContentProvider
|
||||||
public static final String REFRESH_LIBRARY = "refresh";
|
public static final String REFRESH_LIBRARY = "refresh";
|
||||||
|
|
||||||
public static final String AUTHORITY = "content://" + BuildConfig.APPLICATION_ID + ".provider";
|
public static final String AUTHORITY = "content://" + BuildConfig.APPLICATION_ID + ".provider";
|
||||||
public static final Uri URI_FOLDER = Uri.parse(AUTHORITY + "/" + GameDatabase.TABLE_NAME_FOLDERS + "/");
|
|
||||||
public static final Uri URI_GAME = Uri.parse(AUTHORITY + "/" + GameDatabase.TABLE_NAME_GAMES + "/");
|
public static final Uri URI_GAME = Uri.parse(AUTHORITY + "/" + GameDatabase.TABLE_NAME_GAMES + "/");
|
||||||
public static final Uri URI_REFRESH = Uri.parse(AUTHORITY + "/" + REFRESH_LIBRARY + "/");
|
public static final Uri URI_REFRESH = Uri.parse(AUTHORITY + "/" + REFRESH_LIBRARY + "/");
|
||||||
|
|
||||||
|
@ -72,11 +71,7 @@ public final class GameProvider extends ContentProvider
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastSegment.equals(GameDatabase.TABLE_NAME_FOLDERS))
|
if (lastSegment.equals(GameDatabase.TABLE_NAME_GAMES))
|
||||||
{
|
|
||||||
return MIME_TYPE_FOLDER;
|
|
||||||
}
|
|
||||||
else if (lastSegment.equals(GameDatabase.TABLE_NAME_GAMES))
|
|
||||||
{
|
{
|
||||||
return MIME_TYPE_GAME;
|
return MIME_TYPE_GAME;
|
||||||
}
|
}
|
||||||
|
@ -109,12 +104,6 @@ public final class GameProvider extends ContentProvider
|
||||||
// If insertion was successful...
|
// If insertion was successful...
|
||||||
if (id > 0)
|
if (id > 0)
|
||||||
{
|
{
|
||||||
// If we just added a folder, add its contents to the game list.
|
|
||||||
if (table.equals(GameDatabase.TABLE_NAME_FOLDERS))
|
|
||||||
{
|
|
||||||
mDbHelper.scanLibrary(database);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the UI that its contents should be refreshed.
|
// Notify the UI that its contents should be refreshed.
|
||||||
getContext().getContentResolver().notifyChange(uri, null);
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
uri = Uri.withAppendedPath(uri, Long.toString(id));
|
uri = Uri.withAppendedPath(uri, Long.toString(id));
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package org.dolphinemu.dolphinemu.utils;
|
package org.dolphinemu.dolphinemu.utils;
|
||||||
|
|
||||||
import android.content.AsyncQueryHandler;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.DolphinApplication;
|
||||||
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
import org.dolphinemu.dolphinemu.model.GameProvider;
|
|
||||||
|
|
||||||
public class AddDirectoryHelper
|
public class AddDirectoryHelper
|
||||||
{
|
{
|
||||||
|
@ -24,21 +22,23 @@ public class AddDirectoryHelper
|
||||||
|
|
||||||
public void addDirectory(String dir, AddDirectoryListener addDirectoryListener)
|
public void addDirectory(String dir, AddDirectoryListener addDirectoryListener)
|
||||||
{
|
{
|
||||||
AsyncQueryHandler handler = new AsyncQueryHandler(mContext.getContentResolver())
|
new AsyncTask<String, Void, Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void onInsertComplete(int token, Object cookie, Uri uri)
|
protected Void doInBackground(String... params)
|
||||||
{
|
{
|
||||||
addDirectoryListener.onDirectoryAdded();
|
for (String path : params)
|
||||||
}
|
{
|
||||||
};
|
DolphinApplication.databaseHelper.addGameFolder(path);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
ContentValues file = new ContentValues();
|
@Override
|
||||||
file.put(GameDatabase.KEY_FOLDER_PATH, dir);
|
protected void onPostExecute(Void result)
|
||||||
|
{
|
||||||
handler.startInsert(0, // We don't need to identify this call to the handler
|
addDirectoryListener.onDirectoryAdded();
|
||||||
null, // We don't need to pass additional data to the handler
|
}
|
||||||
GameProvider.URI_FOLDER, // Tell the GameProvider we are adding a folder
|
}.execute(dir);
|
||||||
file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue