All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.easimart.provider.DbProvider Maven / Gradle / Ivy

package co.easimart.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;

/**
 * Provides access to a the most recent artwork
 */
public class DbProvider extends ContentProvider {
    private static final String TAG = DbProvider.class.getSimpleName();
    /**
     * Shared Preference key for the current artwork location used in openFile
     */
    private static final String CURRENT_ARTWORK_LOCATION = "CURRENT_ARTWORK_LOCATION";
    /**
     * The incoming URI matches the ARTWORK URI pattern
     */
    private static final int ARTWORK = 1;
    /**
     * The database that the provider uses as its underlying data store
     */
    private static final String DATABASE_NAME = "easimart.db";
    /**
     * The database version
     */
    private static final int DATABASE_VERSION = 2;
    /**
     * A UriMatcher instance
     */
    private static final UriMatcher uriMatcher = DbProvider.buildUriMatcher();
    /**
     * An identity all column projection mapping
     */
    private final HashMap allColumnProjectionMap = DbProvider.buildAllColumnProjectionMap();
    /**
     * Handle to a new DatabaseHelper.
     */
    private DatabaseHelper databaseHelper;

    /**
     * Save the current artwork's local location so that third parties can use openFile to retrieve the already
     * downloaded artwork rather than re-download it
     *
     * @param context        Any valid Context
     * @param currentArtwork File pointing to the current artwork
     */
    public static boolean saveCurrentArtworkLocation(Context context, File currentArtwork) {
        if (currentArtwork == null || !currentArtwork.exists()) {
            Log.w(TAG, "File " + currentArtwork + " is not valid");
            return false;
        }
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        sharedPreferences.edit().putString(CURRENT_ARTWORK_LOCATION, currentArtwork.getAbsolutePath()).commit();
        return true;
    }

    /**
     * Creates and initializes a column project for all columns
     *
     * @return The all column projection map
     */
    private static HashMap buildAllColumnProjectionMap() {
        final HashMap allColumnProjectionMap = new HashMap<>();

        allColumnProjectionMap.put(BaseColumns._ID, BaseColumns._ID);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_IMAGE_URI, DbContract.Artwork.COLUMN_NAME_IMAGE_URI);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_TITLE, DbContract.Artwork.COLUMN_NAME_TITLE);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_BYLINE, DbContract.Artwork.COLUMN_NAME_BYLINE);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_ATTRIBUTION, DbContract.Artwork.COLUMN_NAME_ATTRIBUTION);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_TOKEN, DbContract.Artwork.COLUMN_NAME_TOKEN);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_VIEW_INTENT, DbContract.Artwork.COLUMN_NAME_VIEW_INTENT);

        allColumnProjectionMap.put(DbContract.Artwork.COLUMN_NAME_META_FONT, DbContract.Artwork.COLUMN_NAME_META_FONT);

        return allColumnProjectionMap;
    }

    /**
     * Creates and initializes the URI matcher
     *
     * @return the URI Matcher
     */
    private static UriMatcher buildUriMatcher() {
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI(DbContract.AUTHORITY, DbContract.Artwork.TABLE_NAME,
                DbProvider.ARTWORK);
        return matcher;
    }

    @Override
    public int delete(final Uri uri, final String where, final String[] whereArgs) {
        throw new UnsupportedOperationException("Deletes are not supported");
    }

    @Override
    public String getType(final Uri uri) {
        /**
         * Chooses the MIME type based on the incoming URI pattern
         */
        switch (DbProvider.uriMatcher.match(uri)) {
            case ARTWORK:
                // If the pattern is for artwork, returns the general content type.
                return DbContract.Artwork.CONTENT_TYPE;
            default:
                throw new IllegalArgumentException("Unknown URI " + uri);
        }
    }

    @Override
    public Uri insert(final Uri uri, final ContentValues values) {
        // Validates the incoming URI. Only the full provider URI is allowed for inserts.
        if (DbProvider.uriMatcher.match(uri) != DbProvider.ARTWORK)
            throw new IllegalArgumentException("Unknown URI " + uri);
        if (values == null) {
            throw new IllegalArgumentException("Invalid ContentValues: must not be null");
        }
        final SQLiteDatabase db = databaseHelper.getWritableDatabase();
        final int countUpdated = db.update(DbContract.Artwork.TABLE_NAME,
                values, BaseColumns._ID + "=1", null);
        if (countUpdated != 1) {
            long rowId = db.insert(DbContract.Artwork.TABLE_NAME,
                    DbContract.Artwork.COLUMN_NAME_IMAGE_URI, values);
            if (rowId <= 0) {
                throw new SQLException("Failed to insert row into " + uri);
            }
        }
        getContext().getContentResolver().notifyChange(DbContract.Artwork.CONTENT_URI, null);
        getContext().sendBroadcast(new Intent(DbContract.Artwork.ACTION_ARTWORK_CHANGED));
        return DbContract.Artwork.CONTENT_URI;
    }

    /**
     * Creates the underlying DatabaseHelper
     *
     * @see android.content.ContentProvider#onCreate()
     */
    @Override
    public boolean onCreate() {
        databaseHelper = new DatabaseHelper(getContext());
        return true;
    }

    @Override
    public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs,
                        final String sortOrder) {
        // Validates the incoming URI. Only the full provider URI is allowed for queries.
        if (DbProvider.uriMatcher.match(uri) != DbProvider.ARTWORK)
            throw new IllegalArgumentException("Unknown URI " + uri);
        final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(DbContract.Artwork.TABLE_NAME);
        qb.setProjectionMap(allColumnProjectionMap);
        final SQLiteDatabase db = databaseHelper.getReadableDatabase();
        final Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder, null);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }

    @Override
    public ParcelFileDescriptor openFile(final Uri uri, final String mode) throws FileNotFoundException {
        // Validates the incoming URI. Only the full provider URI is allowed for openFile
        if (DbProvider.uriMatcher.match(uri) != DbProvider.ARTWORK) {
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
        if (!"r".equals(mode)) {
            throw new IllegalArgumentException("Invalid mode for opening file: " + mode + ". Only 'r' is valid");
        }
        String currentArtworkLocation = PreferenceManager.getDefaultSharedPreferences(getContext())
                .getString(CURRENT_ARTWORK_LOCATION, null);
        if (currentArtworkLocation == null) {
            throw new FileNotFoundException("No artwork image is set");
        }
        File file = new File(currentArtworkLocation);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + currentArtworkLocation + " does not exist");
        }
        return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    }

    @Override
    public int update(final Uri uri, final ContentValues values, final String selection, final String[] selectionArgs) {
        throw new UnsupportedOperationException("Updates are not allowed: insert does an insert or update operation");
    }

    /**
     * This class helps open, create, and upgrade the database file.
     */
    static class DatabaseHelper extends SQLiteOpenHelper {
        /**
         * Creates a new DatabaseHelper
         *
         * @param context context of this database
         */
        DatabaseHelper(final Context context) {
            super(context, DbProvider.DATABASE_NAME, null, DbProvider.DATABASE_VERSION);
        }

        /**
         * Creates the underlying database with table name and column names taken from the DbContract class.
         */
        @Override
        public void onCreate(final SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + DbContract.Artwork.TABLE_NAME + " (" + BaseColumns._ID
                    + " INTEGER PRIMARY KEY AUTOINCREMENT," + DbContract.Artwork.COLUMN_NAME_IMAGE_URI
                    + " TEXT," + DbContract.Artwork.COLUMN_NAME_TITLE + " TEXT,"
                    + DbContract.Artwork.COLUMN_NAME_BYLINE + " TEXT,"
                    + DbContract.Artwork.COLUMN_NAME_ATTRIBUTION + " TEXT,"
                    + DbContract.Artwork.COLUMN_NAME_TOKEN + " TEXT,"
                    + DbContract.Artwork.COLUMN_NAME_META_FONT + " TEXT,"
                    + DbContract.Artwork.COLUMN_NAME_VIEW_INTENT + " TEXT);");
        }

        /**
         * Demonstrates that the provider must consider what happens when the underlying database is changed. Note that
         * this currently just destroys and recreates the database - should upgrade in place
         */
        @Override
        public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + DbContract.Artwork.TABLE_NAME);
            onCreate(db);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy