diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameDatabase.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameDatabase.java index 41181f4183..9c152d90ad 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameDatabase.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameDatabase.java @@ -2,9 +2,11 @@ package org.dolphinemu.dolphinemu.model; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.preference.PreferenceManager; import org.dolphinemu.dolphinemu.NativeLibrary; 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_SCREENSHOT_PATH = 8; - public static final int FOLDER_COLUMN_PATH = 1; - public static final String KEY_DB_ID = "_id"; 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_COMPANY = "company"; 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"; private static final String TYPE_PRIMARY = " INTEGER PRIMARY KEY"; private static final String TYPE_INTEGER = " INTEGER"; private static final String TYPE_STRING = " TEXT"; - private static final String CONSTRAINT_UNIQUE = " UNIQUE"; - private static final String SEPARATOR = ", "; 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_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 GAME_FOLDER_PATHS_PREFERENCE = "gameFolderPaths"; + + private static final Set EMPTY_SET = new HashSet<>(); + + private Context mContext; + public GameDatabase(Context context) { // Superclass constructor builds a database or uses an existing one. super(context, "games.db", null, DB_VERSION); + mContext = context; } @Override @@ -93,16 +89,12 @@ public final class GameDatabase extends SQLiteOpenHelper Log.debug("[GameDatabase] GameDatabase - Creating database..."); execSqlAndLog(database, SQL_CREATE_GAMES); - execSqlAndLog(database, SQL_CREATE_FOLDERS); } @Override public void onDowngrade(SQLiteDatabase database, int oldVersion, int newVersion) { 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_CREATE_GAMES); } @@ -120,6 +112,19 @@ public final class GameDatabase extends SQLiteOpenHelper scanLibrary(database); } + public void addGameFolder(String path) + { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext); + Set folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET); + Set 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) { // 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 allowedExtensions = new HashSet(Arrays.asList( ".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.) - while (folderCursor.moveToNext()) + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext); + Set folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET); + Set newFolderPaths = new HashSet<>(); + for (String folderPath : folderPaths) { - - String folderPath = folderCursor.getString(FOLDER_COLUMN_PATH); File folder = new File(folderPath); + boolean deleteFolder = false; Log.info("[GameDatabase] Reading files from library folder: " + folderPath); @@ -245,19 +239,29 @@ public final class GameDatabase extends SQLiteOpenHelper else if (!folder.exists()) { Log.error("[GameDatabase] Folder no longer exists. Removing from the library: " + folderPath); - database.delete(TABLE_NAME_FOLDERS, - KEY_DB_ID + " = ?", - new String[]{Long.toString(folderCursor.getLong(COLUMN_DB_ID))}); + deleteFolder = true; } else { Log.error("[GameDatabase] Folder contains no games: " + folderPath); } + + if (!deleteFolder) + { + newFolderPaths.add(folderPath); + } } fileCursor.close(); - folderCursor.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 getGamesForPlatform(final Platform platform) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameProvider.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameProvider.java index 61abb0ab00..ffb8e5b5ec 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameProvider.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameProvider.java @@ -19,7 +19,6 @@ public final class GameProvider extends ContentProvider public static final String REFRESH_LIBRARY = "refresh"; 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_REFRESH = Uri.parse(AUTHORITY + "/" + REFRESH_LIBRARY + "/"); @@ -72,11 +71,7 @@ public final class GameProvider extends ContentProvider return null; } - if (lastSegment.equals(GameDatabase.TABLE_NAME_FOLDERS)) - { - return MIME_TYPE_FOLDER; - } - else if (lastSegment.equals(GameDatabase.TABLE_NAME_GAMES)) + if (lastSegment.equals(GameDatabase.TABLE_NAME_GAMES)) { return MIME_TYPE_GAME; } @@ -109,12 +104,6 @@ public final class GameProvider extends ContentProvider // If insertion was successful... 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. getContext().getContentResolver().notifyChange(uri, null); uri = Uri.withAppendedPath(uri, Long.toString(id)); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java index 55feddb957..7678779707 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java @@ -1,12 +1,10 @@ package org.dolphinemu.dolphinemu.utils; -import android.content.AsyncQueryHandler; -import android.content.ContentValues; 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.GameProvider; public class AddDirectoryHelper { @@ -24,21 +22,23 @@ public class AddDirectoryHelper public void addDirectory(String dir, AddDirectoryListener addDirectoryListener) { - AsyncQueryHandler handler = new AsyncQueryHandler(mContext.getContentResolver()) + new AsyncTask() { @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(); - file.put(GameDatabase.KEY_FOLDER_PATH, dir); - - handler.startInsert(0, // We don't need to identify this call to the handler - null, // We don't need to pass additional data to the handler - GameProvider.URI_FOLDER, // Tell the GameProvider we are adding a folder - file); + @Override + protected void onPostExecute(Void result) + { + addDirectoryListener.onDirectoryAdded(); + } + }.execute(dir); } }