Finished MovieProvider and corresponding tests
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -37,7 +37,7 @@
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.test.AndroidTestCase;
|
||||
@@ -14,18 +15,23 @@ public class TestDb extends AndroidTestCase {
|
||||
|
||||
public static final String LOG_TAG = TestDb.class.getSimpleName();
|
||||
|
||||
// Since we want each test to start with a clean slate
|
||||
void deleteTheDatabase() {
|
||||
mContext.deleteDatabase(MovieDbHelper.DB_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
deleteTheDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() {
|
||||
deleteTheDatabase();
|
||||
}
|
||||
|
||||
public void testCreateDb() throws Throwable {
|
||||
Log.d(LOG_TAG, "Test: testCreateDb()");
|
||||
final HashSet<String> tableNameHashSet = new HashSet<String>();
|
||||
final HashSet<String> tableNameHashSet = new HashSet<>();
|
||||
tableNameHashSet.add(MovieContract.MovieEntry.TABLE_NAME);
|
||||
|
||||
mContext.deleteDatabase(MovieDbHelper.DB_NAME);
|
||||
@@ -45,7 +51,7 @@ public class TestDb extends AndroidTestCase {
|
||||
} while( c.moveToNext() );
|
||||
|
||||
// if this fails, it means that your database doesn't contain both the location entry
|
||||
// and weather entry tables
|
||||
// and Movie entry tables
|
||||
assertTrue("Error: Your database was created without the Movie Table",
|
||||
tableNameHashSet.isEmpty());
|
||||
|
||||
@@ -57,7 +63,7 @@ public class TestDb extends AndroidTestCase {
|
||||
c.moveToFirst());
|
||||
|
||||
// Build a HashSet of all of the column names we want to look for
|
||||
final HashSet<String> movieColumnHashSet = new HashSet<String>();
|
||||
final HashSet<String> movieColumnHashSet = new HashSet<>();
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry._ID);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_TMDB_ID);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_TITLE);
|
||||
@@ -66,6 +72,7 @@ public class TestDb extends AndroidTestCase {
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_RELEASE);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_RUNTIME);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_RATING);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_FAVORITE);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_VOTE_CNT);
|
||||
movieColumnHashSet.add(MovieContract.MovieEntry.COLUMN_GENRES);
|
||||
|
||||
@@ -82,8 +89,28 @@ public class TestDb extends AndroidTestCase {
|
||||
db.close();
|
||||
}
|
||||
|
||||
//TODO: Add Test for Movie Table
|
||||
//TODO: Add Test for Popular Table
|
||||
//TODO: Add Test for Rating Table
|
||||
//TODO: Add Test for Favorites Table
|
||||
public void testMovieTable() {
|
||||
Log.d(LOG_TAG, "TEST: TestDb.testMovieTable()");
|
||||
MovieDbHelper dbHelper = new MovieDbHelper(mContext);
|
||||
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
String filePath = TestUtilities.storeTestImage(mContext);
|
||||
ContentValues testValues = TestUtilities.createFightClubMovieValues(filePath);
|
||||
assertTrue(db.insert(MovieContract.MovieEntry.TABLE_NAME, null, testValues) != -1);
|
||||
Cursor cursor = db.query(MovieContract.MovieEntry.TABLE_NAME,
|
||||
null, null, null, null, null, null);
|
||||
assertTrue("Error: No Movies Returned From Query!", cursor.moveToFirst());
|
||||
TestUtilities.validateCurrentRecord("Error: Movie Not Validated!", cursor, testValues);
|
||||
|
||||
//Test bitmap
|
||||
String f =cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.COLUMN_IMG_PATH));
|
||||
assertTrue(f.equals(filePath));
|
||||
assertTrue(TestUtilities.getTestImage(mContext).sameAs(FileUtils.getImage(f)));
|
||||
|
||||
assertFalse( "Error: More than one record!", cursor.moveToNext());
|
||||
cursor.close();
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
import com.example.android.popularmovies.R;
|
||||
|
||||
/**
|
||||
* Created by Aaron Helton on 2/15/2016
|
||||
*/
|
||||
public class TestFileUtils extends AndroidTestCase
|
||||
{
|
||||
private static final String LOG_TAG = TestFileUtils.class.getSimpleName();
|
||||
private Bitmap bm;
|
||||
private String filePath;
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
bm = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
|
||||
}
|
||||
public void testStoreAndGetImage()
|
||||
{
|
||||
Log.d(LOG_TAG, "Test: TestFileUtils.testStoreAndGetImage()");
|
||||
String filePath = FileUtils.storeImage(mContext, bm, "ic_launcher");
|
||||
|
||||
assertNotNull("Improperly Returned Filepath!", filePath);
|
||||
assertFalse("Filepath is Empty!", filePath.isEmpty());
|
||||
assertTrue("Default PNG Encoding Not Applied!", filePath.contains(".png"));
|
||||
|
||||
Bitmap ret = FileUtils.getImage(filePath);
|
||||
assertNotNull("Returned Bitmap is Null!", ret);
|
||||
assertTrue("Bitmap Returned is not the Same!", bm.sameAs(ret));
|
||||
|
||||
String filePath2 = FileUtils.storeImage(mContext, bm, "someImage");
|
||||
|
||||
filePath = FileUtils.storeImage(null, bm, "ic_launcher");
|
||||
assertNull(filePath);
|
||||
filePath = FileUtils.storeImage(mContext, bm, null);
|
||||
assertNull(filePath);
|
||||
filePath = FileUtils.storeImage(mContext, bm, "");
|
||||
assertNull(filePath);
|
||||
|
||||
filePath = FileUtils.storeImage(mContext, bm, "ic_launcher.jpg");
|
||||
String ext = FileUtils.getExtension(filePath);
|
||||
assertNotNull(ext);
|
||||
assertTrue(ext.equals("jpg"));
|
||||
|
||||
ret = FileUtils.getImage(filePath);
|
||||
assertFalse("JPG Compression Should Make This False", bm.sameAs(ret));
|
||||
|
||||
filePath = FileUtils.storeImage(mContext, bm, "someFileName");
|
||||
assertTrue(FileUtils.getImage(filePath).sameAs(bm));
|
||||
}
|
||||
|
||||
public void testGetExtension()
|
||||
{
|
||||
Log.d(LOG_TAG, "TEST: TestFileUtils.testGetExtension()");
|
||||
final String TEST_EXTENSION = "someExtension";
|
||||
final String TEST_FILE_STEM = "test";
|
||||
|
||||
String fileName = TEST_FILE_STEM + "." + TEST_EXTENSION;
|
||||
assertTrue(TEST_EXTENSION.equals(FileUtils.getExtension(fileName)));
|
||||
assertNull(FileUtils.getExtension(TEST_FILE_STEM));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,507 +1,253 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
//
|
||||
//import android.content.ContentUris;
|
||||
//import android.content.ContentValues;
|
||||
//import android.database.Cursor;
|
||||
//import android.database.sqlite.SQLiteDatabase;
|
||||
//import android.net.Uri;
|
||||
//import android.os.Build;
|
||||
//import android.test.AndroidTestCase;
|
||||
//import android.util.Log;
|
||||
//
|
||||
//import android.content.ContentUris;
|
||||
//import android.content.ContentValues;
|
||||
//import android.database.Cursor;
|
||||
//import android.database.sqlite.SQLiteDatabase;
|
||||
//import android.net.Uri;
|
||||
//import android.os.Build;
|
||||
//import android.test.AndroidTestCase;
|
||||
//import android.util.Log;
|
||||
//
|
||||
//import com.example.android.sunshine.app.data.WeatherContract.LocationEntry;
|
||||
//import com.example.android.sunshine.app.data.WeatherContract.WeatherEntry;
|
||||
//
|
||||
///*
|
||||
// Note: This is not a complete set of tests of the Sunshine ContentProvider, but it does test
|
||||
// that at least the basic functionality has been implemented correctly.
|
||||
//
|
||||
// Students: Uncomment the tests in this class as you implement the functionality in your
|
||||
// ContentProvider to make sure that you've implemented things reasonably correctly.
|
||||
// */
|
||||
import android.util.Log;
|
||||
|
||||
import com.example.android.popularmovies.data.MovieContract.MovieEntry;
|
||||
|
||||
public class TestProvider extends AndroidTestCase {
|
||||
//
|
||||
// public static final String LOG_TAG = TestProvider.class.getSimpleName();
|
||||
//
|
||||
// /*
|
||||
// This helper function deletes all records from both database tables using the ContentProvider.
|
||||
// It also queries the ContentProvider to make sure that the database has been successfully
|
||||
// deleted, so it cannot be used until the Query and Delete functions have been written
|
||||
// in the ContentProvider.
|
||||
//
|
||||
// Students: Replace the calls to deleteAllRecordsFromDB with this one after you have written
|
||||
// the delete functionality in the ContentProvider.
|
||||
// */
|
||||
// public void deleteAllRecordsFromProvider() {
|
||||
// mContext.getContentResolver().delete(
|
||||
// WeatherEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
// mContext.getContentResolver().delete(
|
||||
// LocationEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
//
|
||||
// Cursor cursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
// assertEquals("Error: Records not deleted from Weather table during delete", 0, cursor.getCount());
|
||||
// cursor.close();
|
||||
//
|
||||
// cursor = mContext.getContentResolver().query(
|
||||
// LocationEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
// assertEquals("Error: Records not deleted from Location table during delete", 0, cursor.getCount());
|
||||
// cursor.close();
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// Student: Refactor this function to use the deleteAllRecordsFromProvider functionality once
|
||||
// you have implemented delete functionality there.
|
||||
// */
|
||||
// public void deleteAllRecords() {
|
||||
// deleteAllRecordsFromProvider();
|
||||
// }
|
||||
//
|
||||
// // Since we want each test to start with a clean slate, run deleteAllRecords
|
||||
// // in setUp (called by the test runner before each test).
|
||||
// @Override
|
||||
// protected void setUp() throws Exception {
|
||||
// super.setUp();
|
||||
// deleteAllRecords();
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// This test checks to make sure that the content provider is registered correctly.
|
||||
// Students: Uncomment this test to make sure you've correctly registered the WeatherProvider.
|
||||
// */
|
||||
//// public void testProviderRegistry() {
|
||||
//// PackageManager pm = mContext.getPackageManager();
|
||||
////
|
||||
//// // We define the component name based on the package name from the context and the
|
||||
//// // WeatherProvider class.
|
||||
//// ComponentName componentName = new ComponentName(mContext.getPackageName(),
|
||||
//// WeatherProvider.class.getName());
|
||||
//// try {
|
||||
//// // Fetch the provider info using the component name from the PackageManager
|
||||
//// // This throws an exception if the provider isn't registered.
|
||||
//// ProviderInfo providerInfo = pm.getProviderInfo(componentName, 0);
|
||||
////
|
||||
//// // Make sure that the registered authority matches the authority from the Contract.
|
||||
//// assertEquals("Error: WeatherProvider registered with authority: " + providerInfo.authority +
|
||||
//// " instead of authority: " + WeatherContract.CONTENT_AUTHORITY,
|
||||
//// providerInfo.authority, WeatherContract.CONTENT_AUTHORITY);
|
||||
//// } catch (PackageManager.NameNotFoundException e) {
|
||||
//// // I guess the provider isn't registered correctly.
|
||||
//// assertTrue("Error: WeatherProvider not registered at " + mContext.getPackageName(),
|
||||
//// false);
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
// /*
|
||||
// This test doesn't touch the database. It verifies that the ContentProvider returns
|
||||
// the correct type for each type of URI that it can handle.
|
||||
// Students: Uncomment this test to verify that your implementation of GetType is
|
||||
// functioning correctly.
|
||||
// */
|
||||
// public void testGetType() {
|
||||
// // content://com.example.android.sunshine.app/weather/
|
||||
// String type = mContext.getContentResolver().getType(WeatherEntry.CONTENT_URI);
|
||||
// // vnd.android.cursor.dir/com.example.android.sunshine.app/weather
|
||||
// assertEquals("Error: the WeatherEntry CONTENT_URI should return WeatherEntry.CONTENT_TYPE",
|
||||
// WeatherEntry.CONTENT_TYPE, type);
|
||||
//
|
||||
// String testLocation = "94074";
|
||||
// // content://com.example.android.sunshine.app/weather/94074
|
||||
// type = mContext.getContentResolver().getType(
|
||||
// WeatherEntry.buildWeatherLocation(testLocation));
|
||||
// // vnd.android.cursor.dir/com.example.android.sunshine.app/weather
|
||||
// assertEquals("Error: the WeatherEntry CONTENT_URI with location should return WeatherEntry.CONTENT_TYPE",
|
||||
// WeatherEntry.CONTENT_TYPE, type);
|
||||
//
|
||||
// long testDate = 1419120000L; // December 21st, 2014
|
||||
// // content://com.example.android.sunshine.app/weather/94074/20140612
|
||||
// type = mContext.getContentResolver().getType(
|
||||
// WeatherEntry.buildWeatherLocationWithDate(testLocation, testDate));
|
||||
// // vnd.android.cursor.item/com.example.android.sunshine.app/weather/1419120000
|
||||
// assertEquals("Error: the WeatherEntry CONTENT_URI with location and date should return WeatherEntry.CONTENT_ITEM_TYPE",
|
||||
// WeatherEntry.CONTENT_ITEM_TYPE, type);
|
||||
//
|
||||
// // content://com.example.android.sunshine.app/location/
|
||||
// type = mContext.getContentResolver().getType(LocationEntry.CONTENT_URI);
|
||||
// // vnd.android.cursor.dir/com.example.android.sunshine.app/location
|
||||
// assertEquals("Error: the LocationEntry CONTENT_URI should return LocationEntry.CONTENT_TYPE",
|
||||
// LocationEntry.CONTENT_TYPE, type);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /*
|
||||
// This test uses the database directly to insert and then uses the ContentProvider to
|
||||
// read out the data. Uncomment this test to see if the basic weather query functionality
|
||||
// given in the ContentProvider is working correctly.
|
||||
// */
|
||||
// public void testBasicWeatherQuery() {
|
||||
// // insert our test records into the database
|
||||
// WeatherDbHelper dbHelper = new WeatherDbHelper(mContext);
|
||||
// SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
//
|
||||
// ContentValues testValues = TestUtilities.createNorthPoleLocationValues();
|
||||
// long locationRowId = TestUtilities.insertNorthPoleLocationValues(mContext);
|
||||
//
|
||||
// // Fantastic. Now that we have a location, add some weather!
|
||||
// ContentValues weatherValues = TestUtilities.createWeatherValues(locationRowId);
|
||||
//
|
||||
// long weatherRowId = db.insert(WeatherEntry.TABLE_NAME, null, weatherValues);
|
||||
// assertTrue("Unable to Insert WeatherEntry into the Database", weatherRowId != -1);
|
||||
//
|
||||
// db.close();
|
||||
//
|
||||
// // Test the basic content provider query
|
||||
// Cursor weatherCursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
//
|
||||
// // Make sure we get the correct cursor out of the database
|
||||
// TestUtilities.validateCursor("testBasicWeatherQuery", weatherCursor, weatherValues);
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// This test uses the database directly to insert and then uses the ContentProvider to
|
||||
// read out the data. Uncomment this test to see if your location queries are
|
||||
// performing correctly.
|
||||
// */
|
||||
// public void testBasicLocationQueries() {
|
||||
// // insert our test records into the database
|
||||
// WeatherDbHelper dbHelper = new WeatherDbHelper(mContext);
|
||||
// SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
//
|
||||
// ContentValues testValues = TestUtilities.createNorthPoleLocationValues();
|
||||
// long locationRowId = TestUtilities.insertNorthPoleLocationValues(mContext);
|
||||
//
|
||||
// // Test the basic content provider query
|
||||
// Cursor locationCursor = mContext.getContentResolver().query(
|
||||
// LocationEntry.CONTENT_URI,
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
//
|
||||
// // Make sure we get the correct cursor out of the database
|
||||
// TestUtilities.validateCursor("testBasicLocationQueries, location query", locationCursor, testValues);
|
||||
//
|
||||
// // Has the NotificationUri been set correctly? --- we can only test this easily against API
|
||||
// // level 19 or greater because getNotificationUri was added in API level 19.
|
||||
// if ( Build.VERSION.SDK_INT >= 19 ) {
|
||||
// assertEquals("Error: Location Query did not properly set NotificationUri",
|
||||
// locationCursor.getNotificationUri(), LocationEntry.CONTENT_URI);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// This test uses the provider to insert and then update the data. Uncomment this test to
|
||||
// see if your update location is functioning correctly.
|
||||
// */
|
||||
// public void testUpdateLocation() {
|
||||
// // Create a new map of values, where column names are the keys
|
||||
// ContentValues values = TestUtilities.createNorthPoleLocationValues();
|
||||
//
|
||||
// Uri locationUri = mContext.getContentResolver().
|
||||
// insert(LocationEntry.CONTENT_URI, values);
|
||||
// long locationRowId = ContentUris.parseId(locationUri);
|
||||
//
|
||||
// // Verify we got a row back.
|
||||
// assertTrue(locationRowId != -1);
|
||||
// Log.d(LOG_TAG, "New row id: " + locationRowId);
|
||||
//
|
||||
// ContentValues updatedValues = new ContentValues(values);
|
||||
// updatedValues.put(LocationEntry._ID, locationRowId);
|
||||
// updatedValues.put(LocationEntry.COLUMN_CITY_NAME, "Santa's Village");
|
||||
//
|
||||
// // Create a cursor with observer to make sure that the content provider is notifying
|
||||
// // the observers as expected
|
||||
// Cursor locationCursor = mContext.getContentResolver().query(LocationEntry.CONTENT_URI, null, null, null, null);
|
||||
//
|
||||
// TestUtilities.TestContentObserver tco = TestUtilities.getTestContentObserver();
|
||||
// locationCursor.registerContentObserver(tco);
|
||||
//
|
||||
// int count = mContext.getContentResolver().update(
|
||||
// LocationEntry.CONTENT_URI, updatedValues, LocationEntry._ID + "= ?",
|
||||
// new String[] { Long.toString(locationRowId)});
|
||||
// assertEquals(count, 1);
|
||||
//
|
||||
// // Test to make sure our observer is called. If not, we throw an assertion.
|
||||
// //
|
||||
// // Students: If your code is failing here, it means that your content provider
|
||||
// // isn't calling getContext().getContentResolver().notifyChange(uri, null);
|
||||
// tco.waitForNotificationOrFail();
|
||||
//
|
||||
// locationCursor.unregisterContentObserver(tco);
|
||||
// locationCursor.close();
|
||||
//
|
||||
// // A cursor is your primary interface to the query results.
|
||||
// Cursor cursor = mContext.getContentResolver().query(
|
||||
// LocationEntry.CONTENT_URI,
|
||||
// null, // projection
|
||||
// LocationEntry._ID + " = " + locationRowId,
|
||||
// null, // Values for the "where" clause
|
||||
// null // sort order
|
||||
// );
|
||||
//
|
||||
// TestUtilities.validateCursor("testUpdateLocation. Error validating location entry update.",
|
||||
// cursor, updatedValues);
|
||||
//
|
||||
// cursor.close();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Make sure we can still delete after adding/updating stuff
|
||||
// //
|
||||
// // Student: Uncomment this test after you have completed writing the insert functionality
|
||||
// // in your provider. It relies on insertions with testInsertReadProvider, so insert and
|
||||
// // query functionality must also be complete before this test can be used.
|
||||
// public void testInsertReadProvider() {
|
||||
// ContentValues testValues = TestUtilities.createNorthPoleLocationValues();
|
||||
//
|
||||
// // Register a content observer for our insert. This time, directly with the content resolver
|
||||
// TestUtilities.TestContentObserver tco = TestUtilities.getTestContentObserver();
|
||||
// mContext.getContentResolver().registerContentObserver(LocationEntry.CONTENT_URI, true, tco);
|
||||
// Uri locationUri = mContext.getContentResolver().insert(LocationEntry.CONTENT_URI, testValues);
|
||||
//
|
||||
// // Did our content observer get called? Students: If this fails, your insert location
|
||||
// // isn't calling getContext().getContentResolver().notifyChange(uri, null);
|
||||
// tco.waitForNotificationOrFail();
|
||||
// mContext.getContentResolver().unregisterContentObserver(tco);
|
||||
//
|
||||
// long locationRowId = ContentUris.parseId(locationUri);
|
||||
//
|
||||
// // Verify we got a row back.
|
||||
// assertTrue(locationRowId != -1);
|
||||
//
|
||||
// // Data's inserted. IN THEORY. Now pull some out to stare at it and verify it made
|
||||
// // the round trip.
|
||||
//
|
||||
// // A cursor is your primary interface to the query results.
|
||||
// Cursor cursor = mContext.getContentResolver().query(
|
||||
// LocationEntry.CONTENT_URI,
|
||||
// null, // leaving "columns" null just returns all the columns.
|
||||
// null, // cols for "where" clause
|
||||
// null, // values for "where" clause
|
||||
// null // sort order
|
||||
// );
|
||||
//
|
||||
// TestUtilities.validateCursor("testInsertReadProvider. Error validating LocationEntry.",
|
||||
// cursor, testValues);
|
||||
//
|
||||
// // Fantastic. Now that we have a location, add some weather!
|
||||
// ContentValues weatherValues = TestUtilities.createWeatherValues(locationRowId);
|
||||
// // The TestContentObserver is a one-shot class
|
||||
// tco = TestUtilities.getTestContentObserver();
|
||||
//
|
||||
// mContext.getContentResolver().registerContentObserver(WeatherEntry.CONTENT_URI, true, tco);
|
||||
//
|
||||
// Uri weatherInsertUri = mContext.getContentResolver()
|
||||
// .insert(WeatherEntry.CONTENT_URI, weatherValues);
|
||||
// assertTrue(weatherInsertUri != null);
|
||||
//
|
||||
// // Did our content observer get called? Students: If this fails, your insert weather
|
||||
// // in your ContentProvider isn't calling
|
||||
// // getContext().getContentResolver().notifyChange(uri, null);
|
||||
// tco.waitForNotificationOrFail();
|
||||
// mContext.getContentResolver().unregisterContentObserver(tco);
|
||||
//
|
||||
// // A cursor is your primary interface to the query results.
|
||||
// Cursor weatherCursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.CONTENT_URI, // Table to Query
|
||||
// null, // leaving "columns" null just returns all the columns.
|
||||
// null, // cols for "where" clause
|
||||
// null, // values for "where" clause
|
||||
// null // columns to group by
|
||||
// );
|
||||
//
|
||||
// TestUtilities.validateCursor("testInsertReadProvider. Error validating WeatherEntry insert.",
|
||||
// weatherCursor, weatherValues);
|
||||
//
|
||||
// // Add the location values in with the weather data so that we can make
|
||||
// // sure that the join worked and we actually get all the values back
|
||||
// weatherValues.putAll(testValues);
|
||||
//
|
||||
// // Get the joined Weather and Location data
|
||||
// weatherCursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.buildWeatherLocation(TestUtilities.TEST_LOCATION),
|
||||
// null, // leaving "columns" null just returns all the columns.
|
||||
// null, // cols for "where" clause
|
||||
// null, // values for "where" clause
|
||||
// null // sort order
|
||||
// );
|
||||
// TestUtilities.validateCursor("testInsertReadProvider. Error validating joined Weather and Location Data.",
|
||||
// weatherCursor, weatherValues);
|
||||
//
|
||||
// // Get the joined Weather and Location data with a start date
|
||||
// weatherCursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.buildWeatherLocationWithStartDate(
|
||||
// TestUtilities.TEST_LOCATION, TestUtilities.TEST_DATE),
|
||||
// null, // leaving "columns" null just returns all the columns.
|
||||
// null, // cols for "where" clause
|
||||
// null, // values for "where" clause
|
||||
// null // sort order
|
||||
// );
|
||||
// TestUtilities.validateCursor("testInsertReadProvider. Error validating joined Weather and Location Data with start date.",
|
||||
// weatherCursor, weatherValues);
|
||||
//
|
||||
// // Get the joined Weather data for a specific date
|
||||
// weatherCursor = mContext.getContentResolver().query(
|
||||
// WeatherEntry.buildWeatherLocationWithDate(TestUtilities.TEST_LOCATION, TestUtilities.TEST_DATE),
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
// TestUtilities.validateCursor("testInsertReadProvider. Error validating joined Weather and Location data for a specific date.",
|
||||
// weatherCursor, weatherValues);
|
||||
// }
|
||||
//
|
||||
// // Make sure we can still delete after adding/updating stuff
|
||||
// //
|
||||
// // Student: Uncomment this test after you have completed writing the delete functionality
|
||||
// // in your provider. It relies on insertions with testInsertReadProvider, so insert and
|
||||
// // query functionality must also be complete before this test can be used.
|
||||
// public void testDeleteRecords() {
|
||||
// testInsertReadProvider();
|
||||
//
|
||||
// // Register a content observer for our location delete.
|
||||
// TestUtilities.TestContentObserver locationObserver = TestUtilities.getTestContentObserver();
|
||||
// mContext.getContentResolver().registerContentObserver(LocationEntry.CONTENT_URI, true, locationObserver);
|
||||
//
|
||||
// // Register a content observer for our weather delete.
|
||||
// TestUtilities.TestContentObserver weatherObserver = TestUtilities.getTestContentObserver();
|
||||
// mContext.getContentResolver().registerContentObserver(WeatherEntry.CONTENT_URI, true, weatherObserver);
|
||||
//
|
||||
// deleteAllRecordsFromProvider();
|
||||
//
|
||||
// // Students: If either of these fail, you most-likely are not calling the
|
||||
// // getContext().getContentResolver().notifyChange(uri, null); in the ContentProvider
|
||||
// // delete. (only if the insertReadProvider is succeeding)
|
||||
// locationObserver.waitForNotificationOrFail();
|
||||
// weatherObserver.waitForNotificationOrFail();
|
||||
//
|
||||
// mContext.getContentResolver().unregisterContentObserver(locationObserver);
|
||||
// mContext.getContentResolver().unregisterContentObserver(weatherObserver);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// static private final int BULK_INSERT_RECORDS_TO_INSERT = 10;
|
||||
// static ContentValues[] createBulkInsertWeatherValues(long locationRowId) {
|
||||
// long currentTestDate = TestUtilities.TEST_DATE;
|
||||
// long millisecondsInADay = 1000*60*60*24;
|
||||
// ContentValues[] returnContentValues = new ContentValues[BULK_INSERT_RECORDS_TO_INSERT];
|
||||
//
|
||||
// for ( int i = 0; i < BULK_INSERT_RECORDS_TO_INSERT; i++, currentTestDate+= millisecondsInADay ) {
|
||||
// ContentValues weatherValues = new ContentValues();
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_LOC_KEY, locationRowId);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DATE, currentTestDate);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DEGREES, 1.1);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_HUMIDITY, 1.2 + 0.01 * (float) i);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_PRESSURE, 1.3 - 0.01 * (float) i);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, 75 + i);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, 65 - i);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, "Asteroids");
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WIND_SPEED, 5.5 + 0.2 * (float) i);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, 321);
|
||||
// returnContentValues[i] = weatherValues;
|
||||
// }
|
||||
// return returnContentValues;
|
||||
// }
|
||||
//
|
||||
// // Student: Uncomment this test after you have completed writing the BulkInsert functionality
|
||||
// // in your provider. Note that this test will work with the built-in (default) provider
|
||||
// // implementation, which just inserts records one-at-a-time, so really do implement the
|
||||
// // BulkInsert ContentProvider function.
|
||||
//// public void testBulkInsert() {
|
||||
//// // first, let's create a location value
|
||||
//// ContentValues testValues = TestUtilities.createNorthPoleLocationValues();
|
||||
//// Uri locationUri = mContext.getContentResolver().insert(LocationEntry.CONTENT_URI, testValues);
|
||||
//// long locationRowId = ContentUris.parseId(locationUri);
|
||||
////
|
||||
//// // Verify we got a row back.
|
||||
//// assertTrue(locationRowId != -1);
|
||||
////
|
||||
//// // Data's inserted. IN THEORY. Now pull some out to stare at it and verify it made
|
||||
//// // the round trip.
|
||||
////
|
||||
//// // A cursor is your primary interface to the query results.
|
||||
//// Cursor cursor = mContext.getContentResolver().query(
|
||||
//// LocationEntry.CONTENT_URI,
|
||||
//// null, // leaving "columns" null just returns all the columns.
|
||||
//// null, // cols for "where" clause
|
||||
//// null, // values for "where" clause
|
||||
//// null // sort order
|
||||
//// );
|
||||
////
|
||||
//// TestUtilities.validateCursor("testBulkInsert. Error validating LocationEntry.",
|
||||
//// cursor, testValues);
|
||||
////
|
||||
//// // Now we can bulkInsert some weather. In fact, we only implement BulkInsert for weather
|
||||
//// // entries. With ContentProviders, you really only have to implement the features you
|
||||
//// // use, after all.
|
||||
//// ContentValues[] bulkInsertContentValues = createBulkInsertWeatherValues(locationRowId);
|
||||
////
|
||||
//// // Register a content observer for our bulk insert.
|
||||
//// TestUtilities.TestContentObserver weatherObserver = TestUtilities.getTestContentObserver();
|
||||
//// mContext.getContentResolver().registerContentObserver(WeatherEntry.CONTENT_URI, true, weatherObserver);
|
||||
////
|
||||
//// int insertCount = mContext.getContentResolver().bulkInsert(WeatherEntry.CONTENT_URI, bulkInsertContentValues);
|
||||
////
|
||||
//// // Students: If this fails, it means that you most-likely are not calling the
|
||||
//// // getContext().getContentResolver().notifyChange(uri, null); in your BulkInsert
|
||||
//// // ContentProvider method.
|
||||
//// weatherObserver.waitForNotificationOrFail();
|
||||
//// mContext.getContentResolver().unregisterContentObserver(weatherObserver);
|
||||
////
|
||||
//// assertEquals(insertCount, BULK_INSERT_RECORDS_TO_INSERT);
|
||||
////
|
||||
//// // A cursor is your primary interface to the query results.
|
||||
//// cursor = mContext.getContentResolver().query(
|
||||
//// WeatherEntry.CONTENT_URI,
|
||||
//// null, // leaving "columns" null just returns all the columns.
|
||||
//// null, // cols for "where" clause
|
||||
//// null, // values for "where" clause
|
||||
//// WeatherEntry.COLUMN_DATE + " ASC" // sort order == by DATE ASCENDING
|
||||
//// );
|
||||
////
|
||||
//// // we should have as many records in the database as we've inserted
|
||||
//// assertEquals(cursor.getCount(), BULK_INSERT_RECORDS_TO_INSERT);
|
||||
////
|
||||
//// // and let's make sure they match the ones we created
|
||||
//// cursor.moveToFirst();
|
||||
//// for ( int i = 0; i < BULK_INSERT_RECORDS_TO_INSERT; i++, cursor.moveToNext() ) {
|
||||
//// TestUtilities.validateCurrentRecord("testBulkInsert. Error validating WeatherEntry " + i,
|
||||
//// cursor, bulkInsertContentValues[i]);
|
||||
//// }
|
||||
//// cursor.close();
|
||||
//// }
|
||||
|
||||
public static final String LOG_TAG = TestProvider.class.getSimpleName();
|
||||
|
||||
public void deleteAllRecords() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.deleteAllRecords()");
|
||||
mContext.getContentResolver().delete(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
Cursor cursor = mContext.getContentResolver().query(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
assertNotNull(cursor);
|
||||
if(cursor.moveToFirst())
|
||||
{
|
||||
int columns = cursor.getColumnCount();
|
||||
Log.e(LOG_TAG, "DETECTED VALUES:\n");
|
||||
for(int i = 0; i < columns; i++)
|
||||
{
|
||||
Log.e(LOG_TAG, cursor.getColumnName(i) + ": ");
|
||||
}
|
||||
Log.e(LOG_TAG, "SUSPECT FAVORITE? " + cursor.getInt(cursor.getColumnIndex(MovieEntry.COLUMN_FAVORITE)));
|
||||
}
|
||||
assertEquals("Error: Movie Records Not Deleted!", 0, cursor.getCount());
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
deleteAllRecords();
|
||||
}
|
||||
|
||||
/*
|
||||
This test checks to make sure that the content provider is registered correctly.
|
||||
Students: Uncomment this test to make sure you've correctly registered the MovieProvider.
|
||||
*/
|
||||
public void testProviderRegistry() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.testProviderRegistry()");
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
ComponentName componentName =
|
||||
new ComponentName(mContext.getPackageName(), MovieProvider.class.getName());
|
||||
try {
|
||||
ProviderInfo providerInfo = pm.getProviderInfo(componentName, 0);
|
||||
assertEquals("Error: MovieProvider registered with authority: " + providerInfo.authority +
|
||||
" instead of authority: " + MovieContract.CONTENT_AUTHORITY,
|
||||
providerInfo.authority, MovieContract.CONTENT_AUTHORITY);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
assertTrue("Error: MovieProvider not registered at " + mContext.getPackageName(),false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetType() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.testGetType()");
|
||||
String type = mContext.getContentResolver().getType(MovieEntry.CONTENT_URI);
|
||||
assertEquals("Error: the MovieEntry CONTENT_URI should return MovieEntry.CONTENT_TYPE",
|
||||
MovieEntry.CONTENT_TYPE, type);
|
||||
|
||||
long testId = 550;
|
||||
type = mContext.getContentResolver().getType(MovieEntry.buildMovieUriWithId(testId));
|
||||
|
||||
assertEquals("Error: the MovieEntry CONTENT_URI WITH ID " +
|
||||
"should return MovieEntry.CONTENT_ITEM_TYPE", MovieEntry.CONTENT_ITEM_TYPE, type);
|
||||
}
|
||||
|
||||
public void testBasicMovieQuery() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.testBasicMovieQuery()");
|
||||
MovieDbHelper dbHelper = new MovieDbHelper(mContext);
|
||||
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
String filePath = TestUtilities.storeTestImage(mContext);
|
||||
ContentValues MovieValues = TestUtilities.createFightClubMovieValues(filePath);
|
||||
long MovieRowId = db.insert(MovieEntry.TABLE_NAME, null, MovieValues);
|
||||
assertTrue("Unable to Insert MovieEntry into the Database", MovieRowId != -1);
|
||||
db.close();
|
||||
|
||||
Cursor MovieCursor = mContext.getContentResolver().query(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
TestUtilities.validateCursor("testBasicMovieQuery", MovieCursor, MovieValues);
|
||||
}
|
||||
|
||||
public void testUpdateMovie() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.testUpdateMovie()");
|
||||
String filePath = TestUtilities.storeTestImage(mContext);
|
||||
ContentValues values = TestUtilities.createFightClubMovieValues(filePath);
|
||||
|
||||
Uri movieUri = mContext.getContentResolver().insert(MovieEntry.CONTENT_URI, values);
|
||||
long movieTMDBId = ContentUris.parseId(movieUri);
|
||||
|
||||
Log.d(LOG_TAG, "Movie ID: " + movieTMDBId);
|
||||
|
||||
ContentValues updatedValues = new ContentValues(values);
|
||||
updatedValues.put(MovieEntry.COLUMN_POPULARITY, 25.3);
|
||||
|
||||
// Create a cursor with observer to make sure that the content provider is notifying
|
||||
// the observers as expected
|
||||
Cursor movieCursor = mContext.getContentResolver().query(MovieEntry.CONTENT_URI,
|
||||
null, null, null, null);
|
||||
assertNotNull(movieCursor);
|
||||
TestUtilities.TestContentObserver tco = TestUtilities.getTestContentObserver();
|
||||
movieCursor.registerContentObserver(tco);
|
||||
|
||||
int count = mContext.getContentResolver().update(
|
||||
MovieEntry.CONTENT_URI, updatedValues, MovieEntry.COLUMN_TMDB_ID + " = ?",
|
||||
new String[] { Long.toString(movieTMDBId)});
|
||||
assertEquals(1, count);
|
||||
|
||||
tco.waitForNotificationOrFail();
|
||||
movieCursor.unregisterContentObserver(tco);
|
||||
movieCursor.close();
|
||||
|
||||
Cursor cursor = mContext.getContentResolver().query(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null, // projection
|
||||
MovieEntry.COLUMN_TMDB_ID + " = " + movieTMDBId,
|
||||
null, // Values for the "where" clause
|
||||
null // sort order
|
||||
);
|
||||
assertNotNull(cursor);
|
||||
TestUtilities.validateCursor("testUpdateLocation. Error validating location entry update.",
|
||||
cursor, updatedValues);
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
public void testInsertReadProvider() {
|
||||
Log.d(LOG_TAG, "TEST: TestProvider.testInsertReadProvider()");
|
||||
String filePath = TestUtilities.storeTestImage(mContext);
|
||||
ContentValues testValues = TestUtilities.createFightClubMovieValues(filePath);
|
||||
|
||||
TestUtilities.TestContentObserver tco = TestUtilities.getTestContentObserver();
|
||||
mContext.getContentResolver().registerContentObserver(MovieEntry.CONTENT_URI, true, tco);
|
||||
Uri movieUri = mContext.getContentResolver().insert(MovieEntry.CONTENT_URI, testValues);
|
||||
|
||||
tco.waitForNotificationOrFail();
|
||||
mContext.getContentResolver().unregisterContentObserver(tco);
|
||||
|
||||
long movieRowId = ContentUris.parseId(movieUri);
|
||||
|
||||
assertTrue(movieRowId != -1);
|
||||
|
||||
Cursor cursor = mContext.getContentResolver().query(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
TestUtilities.validateCursor("testInsertReadProvider. Error validating MovieEntry.",
|
||||
cursor, testValues);
|
||||
}
|
||||
|
||||
public void testDeleteRecords() {
|
||||
testInsertReadProvider();
|
||||
|
||||
TestUtilities.TestContentObserver MovieObserver = TestUtilities.getTestContentObserver();
|
||||
mContext.getContentResolver().registerContentObserver(MovieEntry.CONTENT_URI, true, MovieObserver);
|
||||
|
||||
deleteAllRecords();
|
||||
|
||||
MovieObserver.waitForNotificationOrFail();
|
||||
|
||||
mContext.getContentResolver().unregisterContentObserver(MovieObserver);
|
||||
}
|
||||
|
||||
|
||||
static private final int BULK_INSERT_RECORDS_TO_INSERT = 10;
|
||||
static ContentValues[] createBulkInsertMovieValues(Context context) {
|
||||
String movie = TestUtilities.storeTestImage(context);
|
||||
ContentValues[] returnContentValues = new ContentValues[BULK_INSERT_RECORDS_TO_INSERT];
|
||||
long startID = 1;
|
||||
for ( int i = 0; i < BULK_INSERT_RECORDS_TO_INSERT; i++) {
|
||||
ContentValues MovieValues = new ContentValues();
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_TMDB_ID, startID++);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_TITLE, "Game Grumps: The Movie");
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_DESC, "Two men, one game, 10 minutes");
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_POPULARITY, 9001);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_IMG_PATH, movie);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_FAVORITE, 1);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_RELEASE, "2012-07-18");
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_RUNTIME, 18);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_VOTE_CNT, 3047171);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_RATING, 11.2);
|
||||
MovieValues.put(MovieContract.MovieEntry.COLUMN_GENRES, "Comedy_Romance_Drama");
|
||||
returnContentValues[i] = MovieValues;
|
||||
}
|
||||
return returnContentValues;
|
||||
}
|
||||
|
||||
public void testBulkInsert() {
|
||||
ContentValues[] bulkInsertContentValues = createBulkInsertMovieValues(mContext);
|
||||
|
||||
// Register a content observer for our bulk insert.
|
||||
TestUtilities.TestContentObserver movieObserver = TestUtilities.getTestContentObserver();
|
||||
mContext.getContentResolver()
|
||||
.registerContentObserver(MovieEntry.CONTENT_URI, true, movieObserver);
|
||||
|
||||
int insertCount = mContext.getContentResolver().bulkInsert(MovieEntry.CONTENT_URI,
|
||||
bulkInsertContentValues);
|
||||
|
||||
movieObserver.waitForNotificationOrFail();
|
||||
mContext.getContentResolver().unregisterContentObserver(movieObserver);
|
||||
|
||||
assertEquals(insertCount, BULK_INSERT_RECORDS_TO_INSERT);
|
||||
|
||||
Cursor cursor = mContext.getContentResolver().query(
|
||||
MovieEntry.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
assertNotNull(cursor);
|
||||
assertEquals(cursor.getCount(), BULK_INSERT_RECORDS_TO_INSERT);
|
||||
|
||||
cursor.moveToFirst();
|
||||
for ( int i = 0; i < BULK_INSERT_RECORDS_TO_INSERT; i++, cursor.moveToNext() ) {
|
||||
TestUtilities.validateCurrentRecord("testBulkInsert. Error validating MovieEntry " + i,
|
||||
cursor, bulkInsertContentValues[i]);
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,41 +15,24 @@
|
||||
*/
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.content.UriMatcher;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
/*
|
||||
Uncomment this class when you are ready to test your UriMatcher. Note that this class utilizes
|
||||
constants that are declared with package protection inside of the UriMatcher, which is why
|
||||
the test must be in the same data package as the Android app code. Doing the test this way is
|
||||
a nice compromise between data hiding and testability.
|
||||
*/
|
||||
public class TestUriMatcher extends AndroidTestCase {
|
||||
// private static final String LOCATION_QUERY = "London, UK";
|
||||
// private static final long TEST_DATE = 1419033600L; // December 20th, 2014
|
||||
// private static final long TEST_LOCATION_ID = 10L;
|
||||
//
|
||||
// // content://com.example.android.sunshine.app/weather"
|
||||
// private static final Uri TEST_WEATHER_DIR = WeatherContract.WeatherEntry.CONTENT_URI;
|
||||
// private static final Uri TEST_WEATHER_WITH_LOCATION_DIR = WeatherContract.WeatherEntry.buildWeatherLocation(LOCATION_QUERY);
|
||||
// private static final Uri TEST_WEATHER_WITH_LOCATION_AND_DATE_DIR = WeatherContract.WeatherEntry.buildWeatherLocationWithDate(LOCATION_QUERY, TEST_DATE);
|
||||
// // content://com.example.android.sunshine.app/location"
|
||||
// private static final Uri TEST_LOCATION_DIR = WeatherContract.LocationEntry.CONTENT_URI;
|
||||
//
|
||||
// /*
|
||||
// Students: This function tests that your UriMatcher returns the correct integer value
|
||||
// for each of the Uri types that our ContentProvider can handle. Uncomment this when you are
|
||||
// ready to test your UriMatcher.
|
||||
// */
|
||||
// public void testUriMatcher() {
|
||||
// UriMatcher testMatcher = WeatherProvider.buildUriMatcher();
|
||||
//
|
||||
// assertEquals("Error: The WEATHER URI was matched incorrectly.",
|
||||
// testMatcher.match(TEST_WEATHER_DIR), WeatherProvider.WEATHER);
|
||||
// assertEquals("Error: The WEATHER WITH LOCATION URI was matched incorrectly.",
|
||||
// testMatcher.match(TEST_WEATHER_WITH_LOCATION_DIR), WeatherProvider.WEATHER_WITH_LOCATION);
|
||||
// assertEquals("Error: The WEATHER WITH LOCATION AND DATE URI was matched incorrectly.",
|
||||
// testMatcher.match(TEST_WEATHER_WITH_LOCATION_AND_DATE_DIR), WeatherProvider.WEATHER_WITH_LOCATION_AND_DATE);
|
||||
// assertEquals("Error: The LOCATION URI was matched incorrectly.",
|
||||
// testMatcher.match(TEST_LOCATION_DIR), WeatherProvider.LOCATION);
|
||||
// }
|
||||
private static final String LOG_TAG = TestUriMatcher.class.getSimpleName();
|
||||
private static final long MOVIE_ID = 550;
|
||||
private static final Uri TEST_MOVIE_DIR = MovieContract.MovieEntry.CONTENT_URI;
|
||||
private static final Uri TEST_MOVIE_WITH_ID_DIR = MovieContract.MovieEntry.buildMovieUriWithId(MOVIE_ID);
|
||||
|
||||
public void testUriMatcher() {
|
||||
Log.d(LOG_TAG, "TEST: TestUriMatcher.testUriMatcher()");
|
||||
UriMatcher testMatcher = MovieProvider.buildUriMatcher();
|
||||
|
||||
assertEquals("Error: The MOVIES URI was matched incorrectly.",
|
||||
testMatcher.match(TEST_MOVIE_DIR), MovieProvider.MOVIES);
|
||||
assertEquals("Error: The MOVIE WITH ID URI was matched incorrectly.",
|
||||
testMatcher.match(TEST_MOVIE_WITH_ID_DIR), MovieProvider.MOVIE_WITH_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +1,117 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/*
|
||||
Students: These are functions and some test data to make it easier to test your database and
|
||||
Content Provider. Note that you'll want your WeatherContract class to exactly match the one
|
||||
in our solution to use these as-given.
|
||||
*/
|
||||
import com.example.android.popularmovies.R;
|
||||
import com.example.android.popularmovies.utils.PollingCheck;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class TestUtilities extends AndroidTestCase {
|
||||
// static final String TEST_LOCATION = "99705";
|
||||
// static final long TEST_DATE = 1419033600L; // December 20th, 2014
|
||||
//
|
||||
// static void validateCursor(String error, Cursor valueCursor, ContentValues expectedValues) {
|
||||
// assertTrue("Empty cursor returned. " + error, valueCursor.moveToFirst());
|
||||
// validateCurrentRecord(error, valueCursor, expectedValues);
|
||||
// valueCursor.close();
|
||||
// }
|
||||
//
|
||||
// static void validateCurrentRecord(String error, Cursor valueCursor, ContentValues expectedValues) {
|
||||
// Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();
|
||||
// for (Map.Entry<String, Object> entry : valueSet) {
|
||||
// String columnName = entry.getKey();
|
||||
// int idx = valueCursor.getColumnIndex(columnName);
|
||||
// assertFalse("Column '" + columnName + "' not found. " + error, idx == -1);
|
||||
// String expectedValue = entry.getValue().toString();
|
||||
// assertEquals("Value '" + entry.getValue().toString() +
|
||||
// "' did not match the expected value '" +
|
||||
// expectedValue + "'. " + error, expectedValue, valueCursor.getString(idx));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// Students: Use this to create some default weather values for your database tests.
|
||||
// */
|
||||
// static ContentValues createWeatherValues(long locationRowId) {
|
||||
// ContentValues weatherValues = new ContentValues();
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_LOC_KEY, locationRowId);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DATE, TEST_DATE);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DEGREES, 1.1);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_HUMIDITY, 1.2);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_PRESSURE, 1.3);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, 75);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, 65);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, "Asteroids");
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WIND_SPEED, 5.5);
|
||||
// weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, 321);
|
||||
//
|
||||
// return weatherValues;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// Students: You can uncomment this helper function once you have finished creating the
|
||||
// LocationEntry part of the WeatherContract.
|
||||
// */
|
||||
// static ContentValues createNorthPoleLocationValues() {
|
||||
// // Create a new map of values, where column names are the keys
|
||||
// ContentValues testValues = new ContentValues();
|
||||
// testValues.put(WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING, TEST_LOCATION);
|
||||
// testValues.put(WeatherContract.LocationEntry.COLUMN_CITY_NAME, "North Pole");
|
||||
// testValues.put(WeatherContract.LocationEntry.COLUMN_COORD_LAT, 64.7488);
|
||||
// testValues.put(WeatherContract.LocationEntry.COLUMN_COORD_LONG, -147.353);
|
||||
//
|
||||
// return testValues;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// Students: You can uncomment this function once you have finished creating the
|
||||
// LocationEntry part of the WeatherContract as well as the WeatherDbHelper.
|
||||
// */
|
||||
// static long insertNorthPoleLocationValues(Context context) {
|
||||
// // insert our test records into the database
|
||||
// WeatherDbHelper dbHelper = new WeatherDbHelper(context);
|
||||
// SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
// ContentValues testValues = TestUtilities.createNorthPoleLocationValues();
|
||||
//
|
||||
// long locationRowId;
|
||||
// locationRowId = db.insert(WeatherContract.LocationEntry.TABLE_NAME, null, testValues);
|
||||
//
|
||||
// // Verify we got a row back.
|
||||
// assertTrue("Error: Failure to insert North Pole Location Values", locationRowId != -1);
|
||||
//
|
||||
// return locationRowId;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// Students: The functions we provide inside of TestProvider use this utility class to test
|
||||
// the ContentObserver callbacks using the PollingCheck class that we grabbed from the Android
|
||||
// CTS tests.
|
||||
//
|
||||
// Note that this only tests that the onChange function is called; it does not test that the
|
||||
// correct Uri is returned.
|
||||
// */
|
||||
// static class TestContentObserver extends ContentObserver {
|
||||
// final HandlerThread mHT;
|
||||
// boolean mContentChanged;
|
||||
//
|
||||
// static TestContentObserver getTestContentObserver() {
|
||||
// HandlerThread ht = new HandlerThread("ContentObserverThread");
|
||||
// ht.start();
|
||||
// return new TestContentObserver(ht);
|
||||
// }
|
||||
//
|
||||
// private TestContentObserver(HandlerThread ht) {
|
||||
// super(new Handler(ht.getLooper()));
|
||||
// mHT = ht;
|
||||
// }
|
||||
//
|
||||
// // On earlier versions of Android, this onChange method is called
|
||||
// @Override
|
||||
// public void onChange(boolean selfChange) {
|
||||
// onChange(selfChange, null);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onChange(boolean selfChange, Uri uri) {
|
||||
// mContentChanged = true;
|
||||
// }
|
||||
//
|
||||
// public void waitForNotificationOrFail() {
|
||||
// // Note: The PollingCheck class is taken from the Android CTS (Compatibility Test Suite).
|
||||
// // It's useful to look at the Android CTS source for ideas on how to test your Android
|
||||
// // applications. The reason that PollingCheck works is that, by default, the JUnit
|
||||
// // testing framework is not running on the main Android application thread.
|
||||
// new PollingCheck(5000) {
|
||||
// @Override
|
||||
// protected boolean check() {
|
||||
// return mContentChanged;
|
||||
// }
|
||||
// }.run();
|
||||
// mHT.quit();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static TestContentObserver getTestContentObserver() {
|
||||
// return TestContentObserver.getTestContentObserver();
|
||||
// }
|
||||
|
||||
static String storeTestImage(Context context) {
|
||||
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
|
||||
return FileUtils.storeImage(context, bm, "FightClub.png");
|
||||
}
|
||||
|
||||
static Bitmap getTestImage(Context context) {
|
||||
return BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
|
||||
}
|
||||
|
||||
static void validateCursor(String error, Cursor valueCursor, ContentValues expectedValues) {
|
||||
assertTrue("Empty cursor returned. " + error, valueCursor.moveToFirst());
|
||||
validateCurrentRecord(error, valueCursor, expectedValues);
|
||||
valueCursor.close();
|
||||
}
|
||||
|
||||
static void validateCurrentRecord(String error, Cursor valueCursor,ContentValues expectedValues)
|
||||
{
|
||||
Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();
|
||||
for (Map.Entry<String, Object> entry : valueSet) {
|
||||
String columnName = entry.getKey();
|
||||
int idx = valueCursor.getColumnIndex(columnName);
|
||||
assertFalse("Column '" + columnName + "' not found. " + error, idx == -1);
|
||||
String expectedValue = entry.getValue().toString();
|
||||
assertEquals("Value '" + entry.getValue().toString() +
|
||||
"' did not match the expected value '" +
|
||||
expectedValue + "'. " + error, expectedValue, valueCursor.getString(idx));
|
||||
}
|
||||
}
|
||||
|
||||
public static ContentValues createFightClubMovieValues(String imgPath) {
|
||||
ContentValues testValues = new ContentValues();
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_TMDB_ID, 550);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_TITLE,"Fight Club");
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_DESC, "A ticking-time-bomb insomniac and a"+
|
||||
" slippery soap salesman channel primal male aggression into a shocking new form " +
|
||||
"of therapy. Their concept catches on, with underground \"fight clubs\" forming " +
|
||||
"in every town, until an eccentric gets in the way and ignites an out-of-control " +
|
||||
"spiral toward oblivion.");
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_POPULARITY, 2.5);
|
||||
//Can't use real double because of comparison problems.
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_IMG_PATH, imgPath);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_RELEASE, "1999-10-14");
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_RUNTIME, 139);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_FAVORITE, 1);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_VOTE_CNT, 3185);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_RATING, 7.7);
|
||||
testValues.put(MovieContract.MovieEntry.COLUMN_GENRES, "Drama");
|
||||
|
||||
return testValues;
|
||||
}
|
||||
|
||||
static class TestContentObserver extends ContentObserver {
|
||||
final HandlerThread mHT;
|
||||
boolean mContentChanged;
|
||||
|
||||
static TestContentObserver getTestContentObserver() {
|
||||
HandlerThread ht = new HandlerThread("ContentObserverThread");
|
||||
ht.start();
|
||||
return new TestContentObserver(ht);
|
||||
}
|
||||
|
||||
private TestContentObserver(HandlerThread ht) {
|
||||
super(new Handler(ht.getLooper()));
|
||||
mHT = ht;
|
||||
}
|
||||
|
||||
// On earlier versions of Android, this onChange method is called
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
onChange(selfChange, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
mContentChanged = true;
|
||||
}
|
||||
|
||||
public void waitForNotificationOrFail() {
|
||||
// Note: The PollingCheck class is taken from the Android CTS (Compatibility Test Suite).
|
||||
// It's useful to look at the Android CTS source for ideas on how to test your Android
|
||||
// applications. The reason that PollingCheck works is that, by default, the JUnit
|
||||
// testing framework is not running on the main Android application thread.
|
||||
new PollingCheck(5000) {
|
||||
@Override
|
||||
protected boolean check() {
|
||||
return mContentChanged;
|
||||
}
|
||||
}.run();
|
||||
mHT.quit();
|
||||
}
|
||||
}
|
||||
|
||||
static TestContentObserver getTestContentObserver() {
|
||||
return TestContentObserver.getTestContentObserver();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
package="com.example.android.popularmovies">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@@ -31,6 +30,9 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.example.android.popularmovies.MainActivity"/>
|
||||
</activity>
|
||||
<provider
|
||||
android:authorities="com.example.android.popularmovies"
|
||||
android:name=".data.MovieProvider"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -73,7 +73,6 @@ public class Movie implements Comparable<Movie>
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Implementation tied explicitly to Picasso. Check out other libraries!
|
||||
public static Bitmap getPoster(Context context, String posterPath) throws IOException
|
||||
{
|
||||
if(context == null || posterPath == null || posterPath.isEmpty())
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Aaron Helton on 2/15/2016
|
||||
*/
|
||||
public final class FileUtils
|
||||
{
|
||||
private static final String LOG_TAG = FileUtils.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Stores an image in the internal cache directory.
|
||||
* @param context the context for storing the file
|
||||
* @param image the image to be stored
|
||||
* @param fileName the name of the file to be stored
|
||||
* @return the filepath for the stored image. Null if the save was unsuccessful.
|
||||
*/
|
||||
public static String storeImage(Context context, Bitmap image, String fileName)
|
||||
{
|
||||
//Sanity checks
|
||||
if(image == null || fileName == null || fileName.isEmpty() || context == null)
|
||||
return null;
|
||||
|
||||
File pictureFile;
|
||||
String extension = getExtension(fileName);
|
||||
if(extension == null) {
|
||||
extension = "png";
|
||||
pictureFile = new File(context.getFilesDir(), fileName + "." + extension);
|
||||
}
|
||||
else {
|
||||
pictureFile = new File(context.getFilesDir(), fileName);
|
||||
}
|
||||
|
||||
Bitmap.CompressFormat format;
|
||||
switch(extension.toLowerCase()) {
|
||||
case "png":
|
||||
format = Bitmap.CompressFormat.PNG; break;
|
||||
case "jpg":case "jpeg":
|
||||
format = Bitmap.CompressFormat.JPEG; break;
|
||||
case "webp":
|
||||
format = Bitmap.CompressFormat.WEBP; break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported Format: "
|
||||
+ extension.toUpperCase());
|
||||
}
|
||||
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(pictureFile);
|
||||
image.compress(format, 90, fos);
|
||||
fos.close();
|
||||
return pictureFile.getAbsolutePath();
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.d(LOG_TAG, "File not found: " + e.getMessage());
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
Log.d(LOG_TAG, "Error accessing file: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap getImage(String file)
|
||||
{
|
||||
return BitmapFactory.decodeFile(file);
|
||||
}
|
||||
|
||||
public static String getExtension(String fileName)
|
||||
{
|
||||
int dotIndex = fileName.lastIndexOf(".");
|
||||
if(dotIndex == -1) {
|
||||
return null;
|
||||
} else {
|
||||
return fileName.substring(dotIndex+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,15 +29,22 @@ public class MovieContract {
|
||||
public static final String COLUMN_TMDB_ID = "tmdb_id";
|
||||
public static final String COLUMN_TITLE = "title";
|
||||
public static final String COLUMN_DESC = "overview";
|
||||
public static final String COLUMN_POPULARITY = "popularity";
|
||||
public static final String COLUMN_IMG_PATH = "img_path";
|
||||
public static final String COLUMN_FAVORITE = "favorite";
|
||||
public static final String COLUMN_RELEASE = "release_date";
|
||||
public static final String COLUMN_RUNTIME = "runtime";
|
||||
public static final String COLUMN_VOTE_CNT = "vote_count";
|
||||
public static final String COLUMN_RATING = "rating";
|
||||
public static final String COLUMN_GENRES = "genres";
|
||||
|
||||
public static final Uri buildMovieUri(long tmdb_id) {
|
||||
public static Uri buildMovieUriWithId(long tmdb_id) {
|
||||
return ContentUris.withAppendedId(CONTENT_URI, tmdb_id);
|
||||
}
|
||||
|
||||
public static long getMovieIdFromUri(Uri uri)
|
||||
{
|
||||
return Long.parseLong(uri.getPathSegments().get(uri.getPathSegments().size()-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,22 +17,23 @@ public class MovieDbHelper extends SQLiteOpenHelper {
|
||||
super(context, DB_NAME, null, DB_VER);
|
||||
}
|
||||
|
||||
//TODO: Create the Favorites, Rating, and Popular Tables
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase sqLiteDatabase) {
|
||||
final String SQL_CREATE_FAVORITES_TABLE = "CREATE TABLE " + MovieEntry.TABLE_NAME + " (" +
|
||||
final String SQL_CREATE_MOVIES_TABLE = "CREATE TABLE " + MovieEntry.TABLE_NAME + " (" +
|
||||
MovieEntry._ID + " INTEGER PRIMARY KEY," +
|
||||
MovieEntry.COLUMN_TMDB_ID + " INTEGER UNIQUE NOT NULL," +
|
||||
MovieEntry.COLUMN_TITLE + " TEXT NOT NULL," +
|
||||
MovieEntry.COLUMN_DESC + " TEXT NOT NULL," +
|
||||
MovieEntry.COLUMN_POPULARITY + " REAL NOT NULL," +
|
||||
MovieEntry.COLUMN_IMG_PATH + " TEXT NOT NULL," +
|
||||
MovieEntry.COLUMN_RELEASE + " TEXT NOT NULL," +
|
||||
MovieEntry.COLUMN_RUNTIME + " INTEGER NOT NULL," +
|
||||
MovieEntry.COLUMN_FAVORITE + " INTEGER NOT NULL DEFAULT 0," +
|
||||
MovieEntry.COLUMN_VOTE_CNT + " INTEGER NOT NULL," +
|
||||
MovieEntry.COLUMN_RATING + " REAL NOT NULL," +
|
||||
MovieEntry.COLUMN_GENRES + " TEXT NOT NULL" +
|
||||
" );";
|
||||
sqLiteDatabase.execSQL(SQL_CREATE_FAVORITES_TABLE);
|
||||
sqLiteDatabase.execSQL(SQL_CREATE_MOVIES_TABLE);
|
||||
}
|
||||
|
||||
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
package com.example.android.popularmovies.data;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by Aaron Helton on 2/16/2016
|
||||
*/
|
||||
public class MovieProvider extends ContentProvider
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private static final String LOG_TAG = MovieProvider.class.getSimpleName();
|
||||
|
||||
private static final UriMatcher sUriMatcher = buildUriMatcher();
|
||||
private MovieDbHelper mOpenHelper;
|
||||
|
||||
public static final int MOVIES = 100;
|
||||
public static final int MOVIE_WITH_ID = 101;
|
||||
|
||||
public static UriMatcher buildUriMatcher() {
|
||||
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
final String authority = MovieContract.CONTENT_AUTHORITY;
|
||||
|
||||
matcher.addURI(authority, MovieContract.PATH_MOVIES, MOVIES);
|
||||
matcher.addURI(authority, MovieContract.PATH_MOVIES + "/#", MOVIE_WITH_ID);
|
||||
return matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
mOpenHelper = new MovieDbHelper(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri)
|
||||
{
|
||||
final int match = sUriMatcher.match(uri);
|
||||
|
||||
switch(match) {
|
||||
case MOVIES:
|
||||
return MovieContract.MovieEntry.CONTENT_TYPE;
|
||||
case MOVIE_WITH_ID:
|
||||
return MovieContract.MovieEntry.CONTENT_ITEM_TYPE;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown Uri: " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, String[] projection, String selection,
|
||||
String[] selectionArgs, String sortOrder)
|
||||
{
|
||||
Cursor retCursor;
|
||||
switch(sUriMatcher.match(uri)) {
|
||||
case MOVIES:
|
||||
retCursor = mOpenHelper.getReadableDatabase().query(
|
||||
MovieContract.MovieEntry.TABLE_NAME,
|
||||
projection, selection, selectionArgs, null, null, sortOrder);
|
||||
break;
|
||||
case MOVIE_WITH_ID:
|
||||
retCursor = getMovieById(uri, projection);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI: " + uri);
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return retCursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs)
|
||||
{
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
|
||||
final int match = sUriMatcher.match(uri);
|
||||
int rowsModified;
|
||||
switch(match) {
|
||||
case MOVIES: {
|
||||
rowsModified = db.update(MovieContract.MovieEntry.TABLE_NAME, values,
|
||||
selection, selectionArgs);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new UnsupportedOperationException("Invalid URI: " + uri);
|
||||
}
|
||||
}
|
||||
if(rowsModified > 0)
|
||||
//noinspection ConstantConditions
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
db.close();
|
||||
return rowsModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
final int match = sUriMatcher.match(uri);
|
||||
Uri returnUri;
|
||||
switch(match)
|
||||
{
|
||||
case MOVIES: {
|
||||
long id = values.getAsInteger(MovieContract.MovieEntry.COLUMN_TMDB_ID);
|
||||
long rowId = db.insert(MovieContract.MovieEntry.TABLE_NAME, null, values);
|
||||
if(rowId > 0)
|
||||
returnUri = MovieContract.MovieEntry.buildMovieUriWithId(id);
|
||||
else
|
||||
throw new SQLException("Failed to insert row into " + uri);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI: " + uri);
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
db.close();
|
||||
return returnUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
final int match = sUriMatcher.match(uri);
|
||||
if(selection == null)
|
||||
selection = "1";
|
||||
int rowsModified;
|
||||
switch(match) {
|
||||
case MOVIES: {
|
||||
rowsModified = db.delete(MovieContract.MovieEntry.TABLE_NAME,
|
||||
selection, selectionArgs);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Invalid URI: " + uri);
|
||||
}
|
||||
if(rowsModified > 0)
|
||||
//noinspection ConstantConditions
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
db.close();
|
||||
return rowsModified;
|
||||
}
|
||||
|
||||
private Cursor getMovieById(Uri uri, String[] projection)
|
||||
{
|
||||
long id = MovieContract.MovieEntry.getMovieIdFromUri(uri);
|
||||
return mOpenHelper.getReadableDatabase().query(
|
||||
MovieContract.MovieEntry.TABLE_NAME,
|
||||
projection,
|
||||
MovieContract.MovieEntry.COLUMN_TMDB_ID + " = ?",
|
||||
new String[]{Long.toString(id)},
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
|
||||
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
final int match = sUriMatcher.match(uri);
|
||||
switch (match) {
|
||||
case MOVIES:
|
||||
db.beginTransaction();
|
||||
int returnCount = 0;
|
||||
try {
|
||||
for (ContentValues value : values) {
|
||||
long _id = db.insert(MovieContract.MovieEntry.TABLE_NAME, null, value);
|
||||
if (_id != -1) {
|
||||
returnCount++;
|
||||
}
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
db.close();
|
||||
return returnCount;
|
||||
default:
|
||||
int count = super.bulkInsert(uri, values);
|
||||
db.close();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(11)
|
||||
public void shutdown() {
|
||||
mOpenHelper.close();
|
||||
super.shutdown();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user