// Copyright 2009 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package org.npr.android.util; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.provider.BaseColumns; import android.util.Log; import java.util.Arrays; public class PlaylistProvider extends ContentProvider { public static final Uri CONTENT_URI = Uri .parse("content://org.npr.android.util.Playlist"); private static final String DATABASE_NAME = "playlist.db"; private static final int DATABASE_VERSION = 4; protected static final String TABLE_NAME = "items"; private static final String LOG_TAG = PlaylistProvider.class.getName(); private PlaylistHelper helper; /** * For testing purposes, allows to override the existing helper so we don't * touch the actual filesystem. * * @param helper A PlaylistHelper stub for testing */ protected void setHelper(PlaylistHelper helper) { this.helper = helper; } /** * Useful for testing. * * @param helper A PlaylistHelper stub for testing * @return The max play order, or -1 if there are no entries in the playlist */ private static int getMax(PlaylistHelper helper) { SQLiteDatabase db = helper.getReadableDatabase(); if (DatabaseUtils.queryNumEntries(db, TABLE_NAME) == 0) { return -1; } return (int) DatabaseUtils.longForQuery(db, "select max(play_order) from " + TABLE_NAME, null); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); String realSelection = getSelectionFromId(uri, selection); return db.delete(TABLE_NAME, realSelection, selectionArgs); } @Override public String getType(Uri arg0) { throw new UnsupportedOperationException(); } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = helper.getWritableDatabase(); if (!values.containsKey(Items.PLAY_ORDER)) { values.put(Items.PLAY_ORDER, getMax(helper) + 1); } long id = db.insert(TABLE_NAME, Items.NAME, values); return ContentUris.withAppendedId(uri, id); } @Override public boolean onCreate() { helper = new PlaylistHelper(getContext()); // Always try to upgrade, due to upgrade problems on some devices helper.onUpgrade(helper.getWritableDatabase(), 3, 4); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = helper.getWritableDatabase(); String realSelection = getSelectionFromId(uri, selection); Cursor result = db.query(TABLE_NAME, projection, realSelection, selectionArgs, null /* no group by */, null /* no having */, sortOrder); Log.d(LOG_TAG, uri.toString() + ";" + realSelection + ";" + Arrays.toString(selectionArgs)); return result; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); String realSelection = getSelectionFromId(uri, selection); Log.d(LOG_TAG, "update where " + realSelection); return db.update(TABLE_NAME, values, realSelection, selectionArgs); } private String getSelectionFromId(Uri uri, String selection) { long id = ContentUris.parseId(uri); String realSelection = selection == null ? "" : selection + " and "; if (id != -1) { realSelection += Items._ID + " = " + id; return realSelection; } return selection; } public static class Items implements BaseColumns { public static final String NAME = "name"; public static final String URL = "url"; public static final String PLAY_ORDER = "play_order"; public static final String IS_READ = "is_read"; public static final String STORY_ID = "story_id"; public static final String DURATION = "duration"; public static final String[] COLUMNS = {NAME, URL, PLAY_ORDER, IS_READ, STORY_ID, DURATION}; public static final String[] ALL_COLUMNS = {BaseColumns._ID, NAME, URL, PLAY_ORDER, IS_READ, STORY_ID, DURATION}; // This class cannot be instantiated private Items() { } } protected static class PlaylistHelper extends SQLiteOpenHelper { private static final String LOG_TAG = PlaylistHelper.class.getName(); PlaylistHelper(Context context) { super(context, DATABASE_NAME, null /* no cursor factory */, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + Items._ID + " INTEGER PRIMARY KEY," + Items.NAME + " TEXT," + Items.URL + " VARCHAR," + Items.IS_READ + " BOOLEAN," + Items.PLAY_ORDER + " INTEGER," + Items.STORY_ID + " TEXT," + Items.DURATION + " TEXT" + ");"); } @SuppressWarnings("unused") private void dropTable(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // Check if these new columns exist, and add if they don't try { db.query(TABLE_NAME, new String[] {Items.STORY_ID}, null, null, null, null, null); } catch (SQLException e) { // Column doesn't exist - so add it Log.e(LOG_TAG, "Database update - adding StoryId", e); try { db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + Items.STORY_ID + " TEXT DEFAULT NULL;"); } catch (SQLException ex) { Log.e(LOG_TAG, "", ex); } } try { db.query(TABLE_NAME, new String[] {Items.DURATION}, null, null, null, null, null); } catch (SQLException e) { // Column doesn't exist - so add it Log.e(PlaylistHelper.class.getName(), "Database update - adding Duration", e); try { db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + Items.DURATION + " TEXT DEFAULT NULL;"); } catch (SQLException ex) { Log.e(LOG_TAG, "", ex); } } } } }