/* This file is part of the Android Clementine Remote. * Copyright (C) 2013, Andreas Muttscheller <asfa194@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.qspool.clementineremote.backend.library; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.preference.PreferenceManager; import java.io.File; import de.qspool.clementineremote.App; import de.qspool.clementineremote.SharedPreferencesKeys; public class LibraryDatabaseHelper { private final static String LIBRARY_DB_FILE_NAME = "library.db"; // Table names public final static String SONGS = "songs"; public final static String SONGS_FTS = "songs_fts"; public final static String SONGS_ARTIST = "songs_artist"; public final static String SONGS_ALBUM = "songs_album"; public final static String SONGS_TITLE = "songs_title"; private SQLiteDatabase db; public SQLiteDatabase openDatabase(int flags) { db = SQLiteDatabase.openDatabase(getLibraryDb().getAbsolutePath(), null, flags); return db; } public void closeDatabase() { if (db != null && db.isOpen()) { db.close(); } } public boolean checkConsistency() { boolean dbConsistent = true; // Check the consistency of the database if (databaseExists()) { try { openDatabase(SQLiteDatabase.OPEN_READWRITE); dbConsistent = databaseIntegrityOk(); closeDatabase(); } catch (SQLiteException e) { dbConsistent = false; } if (!dbConsistent) { getLibraryDb().delete(); } } return dbConsistent; } /** * Get the file path to the library database file. The file is stored on the * external storage in die android dir. Filename is library.db * * @return The path incl. filename to the database file */ public File getLibraryDb() { return new File(App.getApp().getExternalFilesDir(null), LIBRARY_DB_FILE_NAME); } /** * Check if the library file is from the currenly connected system. If not, we obviously cannot * add songs from this db to Clementine. So here we delete the wrong library file. * * @return true if a database file existed and the current Clementine connection has a different * ip that the ip from the library. False otherwise */ public boolean removeDatabaseIfFromOtherClementine() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(App.getApp()); String libraryClementine = prefs.getString(SharedPreferencesKeys.SP_LIBRARY_IP, ""); String currentClementine = prefs.getString(SharedPreferencesKeys.SP_KEY_IP, ""); if (libraryClementine.equals(currentClementine)) { return false; } else { // Save the current library ip SharedPreferences.Editor edit = prefs.edit(); edit.putString(SharedPreferencesKeys.SP_LIBRARY_IP, currentClementine); edit.apply(); // Delete the file if exists return getLibraryDb().delete(); } } /** * Optimize library table (table songs). We create a fts virtual table * songs_fts for full text search. The following indices will be created: * songs_artist (artist) songs_album (artist, album) songs_title (artist, * album, title) */ public void optimizeTable() { openDatabase(SQLiteDatabase.OPEN_READWRITE); // Remove unavailable songs db.execSQL("DELETE from SONGS where unavailable <> 0"); StringBuilder sb = new StringBuilder(); Cursor c = db.rawQuery("PRAGMA table_info(songs);", new String[]{}); if (c != null && c.moveToFirst()) { do { if (sb.length() != 0) { sb.append(", "); } sb.append(c.getString(1)); } while (c.moveToNext()); c.close(); } // FTS Table for search db.execSQL("CREATE VIRTUAL TABLE " + SONGS_FTS + " USING fts3(" + sb.toString() + ");"); db.execSQL("INSERT INTO " + SONGS_FTS + " SELECT * FROM songs"); // Indices for fragment db.execSQL("CREATE INDEX " + SONGS_ARTIST + " ON songs (artist);"); db.execSQL("CREATE INDEX " + SONGS_ALBUM + " ON songs (artist, album);"); db.execSQL("CREATE INDEX " + SONGS_TITLE + " ON songs (artist, album, title);"); closeDatabase(); } public boolean databaseExists() { return getLibraryDb().exists(); } private boolean databaseIntegrityOk() { boolean result; try { Cursor c = db.rawQuery("PRAGMA main.integrity_check(1)", null); c.moveToFirst(); result = c.getString(0).equalsIgnoreCase("ok"); c.close(); } catch (SQLiteException e) { result = false; } return result; } }