/* * Copyright (C) 2017 Team Gateship-One * (Hendrik Borghorst & Frederik Luetkes) * * The AUTHORS.md file contains a detailed contributors list: * <https://github.com/gateship-one/odyssey/blob/master/AUTHORS.md> * * 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 org.gateshipone.odyssey.artworkdatabase; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import org.gateshipone.odyssey.BuildConfig; import org.gateshipone.odyssey.models.AlbumModel; import org.gateshipone.odyssey.models.ArtistModel; import org.gateshipone.odyssey.utils.MusicLibraryHelper; public class ArtworkDatabaseManager extends SQLiteOpenHelper { /** * The name of the database */ private static final String DATABASE_NAME = "OdysseyArtworkDB"; /** * The version of the database */ private static final int DATABASE_VERSION = BuildConfig.VERSION_CODE; private static ArtworkDatabaseManager mInstance; private ArtworkDatabaseManager(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } public static synchronized ArtworkDatabaseManager getInstance(Context context) { if (null == mInstance) { mInstance = new ArtworkDatabaseManager(context); } return mInstance; } /** * Creates the database tables if they are not already existing * * @param db */ @Override public void onCreate(SQLiteDatabase db) { AlbumArtTable.createTable(db); ArtistArtTable.createTable(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //FIXME } /** * Tries to fetch an image for the album with the given id (android album id). * * @param id Android MediaColumns album_id. * @return The byte[] containing the raw image file. This can be decoded with BitmapFactory. * @throws ImageNotFoundException If the image is not in the database and it was not searched for before. */ public synchronized byte[] getAlbumImage(long id) throws ImageNotFoundException { SQLiteDatabase database = getReadableDatabase(); String selection = AlbumArtTable.COLUMN_ALBUM_ID + "=?"; Cursor requestCursor = database.query(AlbumArtTable.TABLE_NAME, new String[]{AlbumArtTable.COLUMN_ALBUM_ID, AlbumArtTable.COLUMN_IMAGE_DATA, AlbumArtTable.COLUMN_IMAGE_NOT_FOUND}, selection, new String[]{String.valueOf(id)}, null, null, null); // Check if an image was found if (requestCursor.moveToFirst()) { // If the not_found flag is set then return null here, to indicate that the image is not here but was searched for before. if (requestCursor.getInt(requestCursor.getColumnIndex(AlbumArtTable.COLUMN_IMAGE_NOT_FOUND)) == 1) { return null; } byte[] imageData = requestCursor.getBlob(requestCursor.getColumnIndex(AlbumArtTable.COLUMN_IMAGE_DATA)); requestCursor.close(); database.close(); return imageData; } // If we reach this, no entry was found for the given request. Throw an exception requestCursor.close(); database.close(); throw new ImageNotFoundException(); } /** * Tries to fetch an image for the artist with the given id (android artist id). * * @param id Android MediaColumns artist_id. * @return The byte[] containing the raw image file. This can be decoded with BitmapFactory. * @throws ImageNotFoundException If the image is not in the database and it was not searched for before. */ public synchronized byte[] getArtistImage(long id) throws ImageNotFoundException { SQLiteDatabase database = getReadableDatabase(); String selection = ArtistArtTable.COLUMN_ARTIST_ID + "=?"; Cursor requestCursor = database.query(ArtistArtTable.TABLE_NAME, new String[]{ArtistArtTable.COLUMN_ARTIST_ID, ArtistArtTable.COLUMN_IMAGE_DATA, ArtistArtTable.COLUMN_IMAGE_NOT_FOUND}, selection, new String[]{String.valueOf(id)}, null, null, null); // Check if an image was found if (requestCursor.moveToFirst()) { // If the not_found flag is set then return null here, to indicate that the image is not here but was searched for before. if (requestCursor.getInt(requestCursor.getColumnIndex(ArtistArtTable.COLUMN_IMAGE_NOT_FOUND)) == 1) { return null; } byte[] imageData = requestCursor.getBlob(requestCursor.getColumnIndex(ArtistArtTable.COLUMN_IMAGE_DATA)); requestCursor.close(); database.close(); return imageData; } // If we reach this, no entry was found for the given request. Throw an exception requestCursor.close(); database.close(); throw new ImageNotFoundException(); } /** * Tries to fetch an image for the album with the given name. This is useful if artist_id is not set * * @param artistName The name of the artist to search for. * @return The byte[] containing the raw image file. This can be decoded with BitmapFactory. * @throws ImageNotFoundException If the image is not in the database and it was not searched for before. */ public synchronized byte[] getArtistImage(String artistName) throws ImageNotFoundException { SQLiteDatabase database = getReadableDatabase(); String selection = ArtistArtTable.COLUMN_ARTIST_NAME + "=?"; Cursor requestCursor = database.query(ArtistArtTable.TABLE_NAME, new String[]{ArtistArtTable.COLUMN_ARTIST_NAME, ArtistArtTable.COLUMN_IMAGE_DATA, ArtistArtTable.COLUMN_IMAGE_NOT_FOUND}, selection, new String[]{artistName}, null, null, null); // Check if an image was found if (requestCursor.moveToFirst()) { // If the not_found flag is set then return null here, to indicate that the image is not here but was searched for before. if (requestCursor.getInt(requestCursor.getColumnIndex(ArtistArtTable.COLUMN_IMAGE_NOT_FOUND)) == 1) { return null; } byte[] imageData = requestCursor.getBlob(requestCursor.getColumnIndex(ArtistArtTable.COLUMN_IMAGE_DATA)); requestCursor.close(); database.close(); return imageData; } // If we reach this, no entry was found for the given request. Throw an exception requestCursor.close(); database.close(); throw new ImageNotFoundException(); } /** * Inserts the given byte[] image to the artists table. * * @param artist Artist for the associated image byte[]. * @param image byte[] containing the raw image that was downloaded. This can be null in which case * the database entry will have the not_found flag set. */ public synchronized void insertArtistImage(ArtistModel artist, byte[] image, Context context) { SQLiteDatabase database = getWritableDatabase(); long artistID = artist.getArtistID(); if (artistID == -1) { // Try to get the artistID manually because it seems to be missing artistID = MusicLibraryHelper.getArtistIDFromName(artist.getArtistName(), context); } ContentValues values = new ContentValues(); values.put(ArtistArtTable.COLUMN_ARTIST_ID, artistID); values.put(ArtistArtTable.COLUMN_ARTIST_MBID, artist.getMBID()); values.put(ArtistArtTable.COLUMN_ARTIST_NAME, artist.getArtistName()); values.put(ArtistArtTable.COLUMN_IMAGE_DATA, image); // If null was given as byte[] set the not_found flag for this entry. values.put(ArtistArtTable.COLUMN_IMAGE_NOT_FOUND, image == null ? 1 : 0); database.replace(ArtistArtTable.TABLE_NAME, "", values); database.close(); } /** * Tries to fetch an image for the album with the given name. This can result in wrong results for e.g. "Greatest Hits" * * @param albumName The name of the album to search for. * @return The byte[] containing the raw image file. This can be decoded with BitmapFactory. * @throws ImageNotFoundException If the image is not in the database and it was not searched for before. */ public synchronized byte[] getAlbumImage(String albumName) throws ImageNotFoundException { SQLiteDatabase database = getReadableDatabase(); String selection = AlbumArtTable.COLUMN_ALBUM_NAME + "=?"; Cursor requestCursor = database.query(AlbumArtTable.TABLE_NAME, new String[]{AlbumArtTable.COLUMN_ALBUM_NAME, AlbumArtTable.COLUMN_IMAGE_DATA, AlbumArtTable.COLUMN_IMAGE_NOT_FOUND}, selection, new String[]{albumName}, null, null, null); // Check if an image was found if (requestCursor.moveToFirst()) { // If the not_found flag is set then return null here, to indicate that the image is not here but was searched for before. if (requestCursor.getInt(requestCursor.getColumnIndex(AlbumArtTable.COLUMN_IMAGE_NOT_FOUND)) == 1) { return null; } byte[] imageData = requestCursor.getBlob(requestCursor.getColumnIndex(AlbumArtTable.COLUMN_IMAGE_DATA)); requestCursor.close(); database.close(); return imageData; } // If we reach this, no entry was found for the given request. Throw an exception requestCursor.close(); database.close(); throw new ImageNotFoundException(); } /** * Inserts the given byte[] image to the albums table. * * @param album Album for the associated image byte[]. * @param image byte[] containing the raw image that was downloaded. This can be null in which case * the database entry will have the not_found flag set. */ public synchronized void insertAlbumImage(AlbumModel album, byte[] image) { SQLiteDatabase database = getWritableDatabase(); String albumID = String.valueOf(album.getAlbumID()); ContentValues values = new ContentValues(); values.put(AlbumArtTable.COLUMN_ALBUM_ID, albumID); values.put(AlbumArtTable.COLUMN_ALBUM_MBID, album.getMBID()); values.put(AlbumArtTable.COLUMN_ALBUM_NAME, album.getAlbumName()); values.put(AlbumArtTable.COLUMN_ARTIST_NAME, album.getArtistName()); values.put(AlbumArtTable.COLUMN_IMAGE_DATA, image); // If null was given as byte[] set the not_found flag for this entry. values.put(AlbumArtTable.COLUMN_IMAGE_NOT_FOUND, image == null ? 1 : 0); database.replace(AlbumArtTable.TABLE_NAME, "", values); database.close(); } /** * Removes all lines from the artists table */ public synchronized void clearArtistImages() { SQLiteDatabase database = getWritableDatabase(); database.delete(ArtistArtTable.TABLE_NAME, null, null); database.close(); } /** * Removes all lines from the albums table */ public synchronized void clearAlbumImages() { SQLiteDatabase database = getWritableDatabase(); database.delete(AlbumArtTable.TABLE_NAME, null, null); database.close(); } public synchronized void clearBlockedArtistImages() { SQLiteDatabase database = getWritableDatabase(); String where = ArtistArtTable.COLUMN_IMAGE_NOT_FOUND + "=?"; String whereArgs[] = {"1"}; database.delete(ArtistArtTable.TABLE_NAME, where, whereArgs); database.close(); } public synchronized void clearBlockedAlbumImages() { SQLiteDatabase database = getWritableDatabase(); String where = AlbumArtTable.COLUMN_IMAGE_NOT_FOUND + "=?"; String whereArgs[] = {"1"}; database.delete(AlbumArtTable.TABLE_NAME, where, whereArgs); database.close(); } public synchronized void removeArtistImage(ArtistModel artist) { SQLiteDatabase database = getWritableDatabase(); String where = ArtistArtTable.COLUMN_ARTIST_ID + "=? OR " +ArtistArtTable.COLUMN_ARTIST_NAME + "=?"; String whereArgs[] = {String.valueOf(artist.getArtistID()), artist.getArtistName()}; database.delete(ArtistArtTable.TABLE_NAME, where, whereArgs); database.close(); } public synchronized void removeAlbumImage(AlbumModel album) { SQLiteDatabase database = getWritableDatabase(); String where = AlbumArtTable.COLUMN_ALBUM_ID+ "=?"; String whereArgs[] = {String.valueOf(album.getAlbumID())}; database.delete(AlbumArtTable.TABLE_NAME, where, whereArgs); database.close(); } }