Samples: Fix bugs in Note Pad sample app.
Change-Id: I859cbc73eaaa77a9ff89484f33c7150d76a4e2c2
This commit is contained in:
@@ -115,6 +115,6 @@
|
|||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8"/>
|
<uses-sdk android:minSdkVersion="Froyo"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
||||||
|
|||||||
@@ -584,6 +584,7 @@ public class NotePadProvider extends ContentProvider implements PipeDataWriter<C
|
|||||||
|
|
||||||
// Opens the database object in "write" mode.
|
// Opens the database object in "write" mode.
|
||||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||||
|
String finalWhere;
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
@@ -604,34 +605,27 @@ public class NotePadProvider extends ContentProvider implements PipeDataWriter<C
|
|||||||
// incoming data, but modifies the where clause to restrict it to the
|
// incoming data, but modifies the where clause to restrict it to the
|
||||||
// particular note ID.
|
// particular note ID.
|
||||||
case NOTE_ID:
|
case NOTE_ID:
|
||||||
// From the incoming URI, get the note ID
|
/*
|
||||||
String noteId = uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION);
|
* Starts a final WHERE clause by restricting it to the
|
||||||
|
* desired note ID.
|
||||||
|
*/
|
||||||
|
finalWhere =
|
||||||
|
NotePad.Notes._ID + // The ID column name
|
||||||
|
" = " + // test for equality
|
||||||
|
uri.getPathSegments(). // the incoming note ID
|
||||||
|
get(NotePad.Notes.NOTE_ID_PATH_POSITION)
|
||||||
|
;
|
||||||
|
|
||||||
// If no where clause was passed in, uses the note ID column name
|
// If there were additional selection criteria, append them to the final
|
||||||
// for a column and the note ID for a value.
|
// WHERE clause
|
||||||
if (TextUtils.isEmpty(where)) {
|
if (where != null) {
|
||||||
where = NotePad.Notes._ID + " = ?";
|
finalWhere = finalWhere + " AND " + where;
|
||||||
whereArgs[0] = noteId;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If where clause columns were passed in, appends the note ID column name to
|
|
||||||
* the list of columns using a replaceable parameter. This works even if the
|
|
||||||
* other columns have actual values.
|
|
||||||
*/
|
|
||||||
// Appends the note ID column name as an AND condition using a replaceable
|
|
||||||
// parameter.
|
|
||||||
where = where + " AND " + NotePad.Notes._ID + " = ?";
|
|
||||||
|
|
||||||
// Appends the note ID value to the end of the where clause values.
|
|
||||||
whereArgs[whereArgs.length] = noteId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs the delete.
|
// Performs the delete.
|
||||||
count = db.delete(
|
count = db.delete(
|
||||||
NotePad.Notes.TABLE_NAME, // The database table name.
|
NotePad.Notes.TABLE_NAME, // The database table name.
|
||||||
where, // The incoming where clause column names.
|
finalWhere, // The final WHERE clause
|
||||||
whereArgs // The incoming where clause values.
|
whereArgs // The incoming where clause values.
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -677,6 +671,7 @@ public class NotePadProvider extends ContentProvider implements PipeDataWriter<C
|
|||||||
// Opens the database object in "write" mode.
|
// Opens the database object in "write" mode.
|
||||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||||
int count;
|
int count;
|
||||||
|
String finalWhere;
|
||||||
|
|
||||||
// Does the update based on the incoming URI pattern
|
// Does the update based on the incoming URI pattern
|
||||||
switch (sUriMatcher.match(uri)) {
|
switch (sUriMatcher.match(uri)) {
|
||||||
@@ -700,29 +695,29 @@ public class NotePadProvider extends ContentProvider implements PipeDataWriter<C
|
|||||||
// From the incoming URI, get the note ID
|
// From the incoming URI, get the note ID
|
||||||
String noteId = uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION);
|
String noteId = uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION);
|
||||||
|
|
||||||
// If no where clause was passed in, uses the note ID column name
|
/*
|
||||||
// for a column and the note ID for a value.
|
* Starts creating the final WHERE clause by restricting it to the incoming
|
||||||
if (TextUtils.isEmpty(where)) {
|
* note ID.
|
||||||
where = NotePad.Notes._ID + " = " + noteId;
|
*/
|
||||||
|
finalWhere =
|
||||||
// If where clause columns were passed in, appends the note ID to the where
|
NotePad.Notes._ID + // The ID column name
|
||||||
// clause
|
" = " + // test for equality
|
||||||
} else {
|
uri.getPathSegments(). // the incoming note ID
|
||||||
|
get(NotePad.Notes.NOTE_ID_PATH_POSITION)
|
||||||
/*
|
;
|
||||||
* Prepends the note ID column name to the search criteria. This handles two
|
|
||||||
* cases: a) whereArgs contains values b) whereArgs is null.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
where = NotePad.Notes._ID + " = " + noteId + " AND " + where;
|
|
||||||
|
|
||||||
|
// If there were additional selection criteria, append them to the final WHERE
|
||||||
|
// clause
|
||||||
|
if (where !=null) {
|
||||||
|
finalWhere = finalWhere + " AND " + where;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Does the update and returns the number of rows updated.
|
// Does the update and returns the number of rows updated.
|
||||||
count = db.update(
|
count = db.update(
|
||||||
NotePad.Notes.TABLE_NAME, // The database table name.
|
NotePad.Notes.TABLE_NAME, // The database table name.
|
||||||
values, // A map of column names and new values to use.
|
values, // A map of column names and new values to use.
|
||||||
where, // The where clause column names. May contain
|
finalWhere, // The final WHERE clause to use
|
||||||
// placeholders for whereArgs
|
// placeholders for whereArgs
|
||||||
whereArgs // The where clause column values to select on, or
|
whereArgs // The where clause column values to select on, or
|
||||||
// null if the values are in the where argument.
|
// null if the values are in the where argument.
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public class TitleEditor extends Activity implements View.OnClickListener {
|
|||||||
* the block will be momentary, but in a real app you should use
|
* the block will be momentary, but in a real app you should use
|
||||||
* android.content.AsyncQueryHandler or android.os.AsyncTask.
|
* android.content.AsyncQueryHandler or android.os.AsyncTask.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mCursor = managedQuery(
|
mCursor = managedQuery(
|
||||||
mUri, // The URI for the note that is to be retrieved.
|
mUri, // The URI for the note that is to be retrieved.
|
||||||
PROJECTION, // The columns to retrieve
|
PROJECTION, // The columns to retrieve
|
||||||
@@ -141,6 +142,7 @@ public class TitleEditor extends Activity implements View.OnClickListener {
|
|||||||
|
|
||||||
// Verifies that the query made in onCreate() actually worked. If it worked, then the
|
// Verifies that the query made in onCreate() actually worked. If it worked, then the
|
||||||
// Cursor object is not null. If it is *empty*, then mCursor.getCount() == 0.
|
// Cursor object is not null. If it is *empty*, then mCursor.getCount() == 0.
|
||||||
|
|
||||||
if (mCursor != null) {
|
if (mCursor != null) {
|
||||||
|
|
||||||
// Creates a values map for updating the provider.
|
// Creates a values map for updating the provider.
|
||||||
@@ -163,6 +165,7 @@ public class TitleEditor extends Activity implements View.OnClickListener {
|
|||||||
null, // No selection criteria is used, so no "where" columns are needed.
|
null, // No selection criteria is used, so no "where" columns are needed.
|
||||||
null // No "where" columns are used, so no "where" values are needed.
|
null // No "where" columns are used, so no "where" values are needed.
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,49 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Copyright (C) 2008 The Android Open Source Project
|
<!--
|
||||||
|
Copyright (C) 2007 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
<!--
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
To run this test package, install it and the NotesList application to a device or emulator and
|
||||||
package="com.example.android.notepad.tests">
|
then run
|
||||||
|
adb shell am instrument -w com.example.android.notepad.tests/android.test.InstrumentationTestRunner
|
||||||
<!-- We add an application tag here just so that we can indicate that
|
-->
|
||||||
this package needs to link against the android.test library,
|
<!--
|
||||||
which is needed when building test cases. -->
|
The Android package name differs from the package ID of the code. The code package ID
|
||||||
|
'com.example.android.notepad' allows the test code to use declarations from the application
|
||||||
|
under test, while the Android package name identifies this as a separate test package.
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.android.notepad.tests"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
<!--
|
||||||
|
The application element indicates that this package must be linked against the library
|
||||||
|
android.test.runner, which is not part of the normal link path. The library contains
|
||||||
|
code for test cases.
|
||||||
|
-->
|
||||||
<application>
|
<application>
|
||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
</application>
|
</application>
|
||||||
|
<!--
|
||||||
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
The instrumentation element tells Android to use instrumentation to run this package.
|
||||||
android:targetPackage="com.example.android.notepad"
|
The target Android package 'com.example.android.notepad' is loaded along with the
|
||||||
android:label="NotePad sample tests">
|
test package 'com.example.android.notepad.tests'. Android then starts the class
|
||||||
</instrumentation>
|
'android.test.InstrumentationTestRunner', which loads the test case classes in the package.
|
||||||
|
-->
|
||||||
|
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
||||||
|
android:targetPackage="com.example.android.notepad"
|
||||||
|
android:label="Tests for com.example.android.notepad"/>
|
||||||
|
<uses-sdk android:minSdkVersion="10"></uses-sdk>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.example.android.notepad;
|
package com.example.android.notepad;
|
||||||
|
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
|
|
||||||
import com.example.android.notepad.NotesList;
|
import com.example.android.notepad.NotesList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +29,7 @@ public class NotePadActivityTest extends ActivityInstrumentationTestCase2<NotesL
|
|||||||
* Creates an {@link ActivityInstrumentationTestCase2} for the {@link NotesList} activity.
|
* Creates an {@link ActivityInstrumentationTestCase2} for the {@link NotesList} activity.
|
||||||
*/
|
*/
|
||||||
public NotePadActivityTest() {
|
public NotePadActivityTest() {
|
||||||
super("com.example.android.notepad.test",NotesList.class);
|
super(NotesList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,12 +18,19 @@ package com.example.android.notepad;
|
|||||||
|
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.test.ProviderTestCase2;
|
import android.test.ProviderTestCase2;
|
||||||
import android.test.mock.MockContentResolver;
|
import android.test.mock.MockContentResolver;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
@@ -73,6 +80,18 @@ public class NotePadProviderTest extends ProviderTestCase2<NotePadProvider> {
|
|||||||
// Stores a timestamp value, set to an arbitrary starting point
|
// Stores a timestamp value, set to an arbitrary starting point
|
||||||
private final static long START_DATE = TEST_CALENDAR.getTimeInMillis();
|
private final static long START_DATE = TEST_CALENDAR.getTimeInMillis();
|
||||||
|
|
||||||
|
// Sets a MIME type filter, used to test provider methods that return more than one MIME type
|
||||||
|
// for a particular note. The filter will retrieve any MIME types supported for the content URI.
|
||||||
|
private final static String MIME_TYPES_ALL = "*/*";
|
||||||
|
|
||||||
|
// Sets a MIME type filter, used to test provider methods that return more than one MIME type
|
||||||
|
// for a particular note. The filter is nonsense, so it will not retrieve any MIME types.
|
||||||
|
private final static String MIME_TYPES_NONE = "qwer/qwer";
|
||||||
|
|
||||||
|
// Sets a MIME type filter for plain text, used to the provider's methods that only handle
|
||||||
|
// plain text
|
||||||
|
private final static String MIME_TYPE_TEXT = "text/plain";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor for the test case class.
|
* Constructor for the test case class.
|
||||||
* Calls the super constructor with the class name of the provider under test and the
|
* Calls the super constructor with the class name of the provider under test and the
|
||||||
@@ -82,7 +101,6 @@ public class NotePadProviderTest extends ProviderTestCase2<NotePadProvider> {
|
|||||||
super(NotePadProvider.class, NotePad.AUTHORITY);
|
super(NotePadProvider.class, NotePad.AUTHORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets up the test environment before each test method. Creates a mock content resolver,
|
* Sets up the test environment before each test method. Creates a mock content resolver,
|
||||||
* gets the provider under test, and creates a new database for the provider.
|
* gets the provider under test, and creates a new database for the provider.
|
||||||
@@ -162,6 +180,241 @@ public class NotePadProviderTest extends ProviderTestCase2<NotePadProvider> {
|
|||||||
mimeType = mMockResolver.getType(INVALID_URI);
|
mimeType = mMockResolver.getType(INVALID_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the provider's stream MIME types returned by getStreamTypes(). If the provider supports
|
||||||
|
* stream data for the URI, the MIME type is returned. Otherwise, the provider returns null.
|
||||||
|
*/
|
||||||
|
public void testGetStreamTypes() {
|
||||||
|
|
||||||
|
// Tests the notes table URI. This should return null, since the content provider does
|
||||||
|
// not provide a stream MIME type for multiple notes.
|
||||||
|
assertNull(mMockResolver.getStreamTypes(NotePad.Notes.CONTENT_URI, MIME_TYPES_ALL));
|
||||||
|
|
||||||
|
// Tests the live folders URI. This should return null, since the content provider does not
|
||||||
|
// provide a stream MIME type for multiple notes.
|
||||||
|
assertNull(mMockResolver.getStreamTypes(NotePad.Notes.LIVE_FOLDER_URI, MIME_TYPES_ALL));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the note id URI for a single note, using _ID value "1" which is a valid ID. Uses a
|
||||||
|
* valid MIME type filter that will return all the supported MIME types for a content URI.
|
||||||
|
* The result should be "text/plain".
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Constructs the note id URI
|
||||||
|
Uri testUri = Uri.withAppendedPath(NotePad.Notes.CONTENT_ID_URI_BASE, "1");
|
||||||
|
|
||||||
|
// Gets the MIME types for the URI, with the filter that selects all MIME types.
|
||||||
|
String mimeType[] = mMockResolver.getStreamTypes(testUri, MIME_TYPES_ALL);
|
||||||
|
|
||||||
|
// Tests that the result is not null and is equal to the expected value. Also tests that
|
||||||
|
// only one MIME type is returned.
|
||||||
|
assertNotNull(mimeType);
|
||||||
|
assertEquals(mimeType[0],"text/plain");
|
||||||
|
assertEquals(mimeType.length,1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests with the same URI but with a filter that should not return any URIs.
|
||||||
|
*/
|
||||||
|
mimeType = mMockResolver.getStreamTypes(testUri, MIME_TYPES_NONE);
|
||||||
|
assertNull(mimeType);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests with a URI that should not have any associated stream MIME types, but with a
|
||||||
|
* filter that returns all types. The result should still be null.
|
||||||
|
*/
|
||||||
|
mimeType = mMockResolver.getStreamTypes(NotePad.Notes.CONTENT_URI, MIME_TYPES_ALL);
|
||||||
|
assertNull(mimeType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the provider's public API for opening a read-only pipe of data for a note ID URI
|
||||||
|
* and MIME type filter matching "text/plain".
|
||||||
|
* This method throws a FileNotFoundException if the URI isn't for a note ID or the MIME type
|
||||||
|
* filter isn't "text/plain". It throws an IOException if it can't close a file descriptor.
|
||||||
|
*/
|
||||||
|
public void testOpenTypedAssetFile() throws FileNotFoundException, IOException {
|
||||||
|
|
||||||
|
// A URI to contain a note ID content URI.
|
||||||
|
Uri testNoteIdUri;
|
||||||
|
|
||||||
|
// A handle for the file descriptor returned by openTypedAssetFile().
|
||||||
|
AssetFileDescriptor testAssetDescriptor;
|
||||||
|
|
||||||
|
// Inserts data into the provider, so that the note ID URI will be recognized.
|
||||||
|
insertData();
|
||||||
|
|
||||||
|
// Constructs a URI with a note ID of 1. This matches the note ID URI pattern that
|
||||||
|
// openTypedAssetFile can handle.
|
||||||
|
testNoteIdUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_ID_URI_BASE, 1);
|
||||||
|
|
||||||
|
// Opens the pipe. The opts argument is for passing options from a caller to the provider,
|
||||||
|
// but the NotePadProvider does not use it.
|
||||||
|
testAssetDescriptor = mMockResolver.openTypedAssetFileDescriptor(
|
||||||
|
testNoteIdUri, // the URI for a single note. The pipe points to this
|
||||||
|
// note's data
|
||||||
|
MIME_TYPE_TEXT, // a MIME type of "text/plain"
|
||||||
|
null // the "opts" argument
|
||||||
|
);
|
||||||
|
|
||||||
|
// Gets the parcel file handle from the asset file handle.
|
||||||
|
ParcelFileDescriptor testParcelDescriptor = testAssetDescriptor.getParcelFileDescriptor();
|
||||||
|
|
||||||
|
// Gets the file handle from the asset file handle.
|
||||||
|
FileDescriptor testDescriptor = testAssetDescriptor.getFileDescriptor();
|
||||||
|
|
||||||
|
// Tests that the asset file handle is not null.
|
||||||
|
assertNotNull(testAssetDescriptor);
|
||||||
|
|
||||||
|
// Tests that the parcel file handle is not null.
|
||||||
|
assertNotNull(testParcelDescriptor);
|
||||||
|
|
||||||
|
// Tests that the file handle is not null.
|
||||||
|
assertNotNull(testDescriptor);
|
||||||
|
|
||||||
|
// Tests that the file handle is valid.
|
||||||
|
assertTrue(testDescriptor.valid());
|
||||||
|
|
||||||
|
// Closes the file handles.
|
||||||
|
testParcelDescriptor.close();
|
||||||
|
testAssetDescriptor.close();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes the URI to a notes URI for multiple notes, and re-test. This should fail, since
|
||||||
|
* the provider does not support this type of URI. A FileNotFound exception is expected,
|
||||||
|
* so call fail() if it does *not* occur.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
testAssetDescriptor = mMockResolver.openTypedAssetFileDescriptor(
|
||||||
|
NotePad.Notes.CONTENT_URI,
|
||||||
|
MIME_TYPE_TEXT,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
fail();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes back to the note ID URI, but changes the MIME type filter to one that is not
|
||||||
|
* supported by the provider. This should also fail, since the provider will only open a
|
||||||
|
* pipe for MIME type "text/plain". A FileNotFound exception is expected, so calls
|
||||||
|
* fail() if it does *not* occur.
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
testAssetDescriptor = mMockResolver.openTypedAssetFileDescriptor(
|
||||||
|
testNoteIdUri,
|
||||||
|
MIME_TYPES_NONE,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
fail();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the provider's method for actually returning writing data into a pipe. The method is
|
||||||
|
* writeDataToPipe, but this method is not called directly. Instead, a caller invokes
|
||||||
|
* openTypedAssetFile(). That method uses ContentProvider.openPipeHelper(), which has as one of
|
||||||
|
* its arguments a ContentProvider.PipeDataWriter object that must actually put the data into
|
||||||
|
* the pipe. PipeDataWriter is an interface, not a class, so it must be implemented.
|
||||||
|
*
|
||||||
|
* The NotePadProvider class itself implements the "ContentProvider.PipeDataWriter, which means
|
||||||
|
* that it supplies the interface's only method, writeDataToPipe(). In effect, a call to
|
||||||
|
* openTypedAssetFile() calls writeDataToPipe().
|
||||||
|
*
|
||||||
|
* The test of writeDataToPipe() is separate from other tests of openTypedAssetFile() for the
|
||||||
|
* sake of clarity.
|
||||||
|
*/
|
||||||
|
public void testWriteDataToPipe() throws FileNotFoundException {
|
||||||
|
|
||||||
|
// A string array to hold the incoming data
|
||||||
|
String[] inputData = {"","",""};
|
||||||
|
|
||||||
|
// A URI for a note ID.
|
||||||
|
Uri noteIdUri;
|
||||||
|
|
||||||
|
// A Cursor to contain the retrieved note.
|
||||||
|
Cursor noteIdCursor;
|
||||||
|
|
||||||
|
// An AssetFileDescriptor for the pipe.
|
||||||
|
AssetFileDescriptor noteIdAssetDescriptor;
|
||||||
|
|
||||||
|
// The ParcelFileDescriptor in the AssetFileDescriptor
|
||||||
|
ParcelFileDescriptor noteIdParcelDescriptor;
|
||||||
|
|
||||||
|
// Inserts test data into the provider.
|
||||||
|
insertData();
|
||||||
|
|
||||||
|
// Creates note ID URI for a note that should now be in the provider.
|
||||||
|
noteIdUri = ContentUris.withAppendedId(
|
||||||
|
NotePad.Notes.CONTENT_ID_URI_BASE, // The base pattern for a note ID URI
|
||||||
|
1 // Sets the URI to point to record ID 1 in the
|
||||||
|
// provider
|
||||||
|
);
|
||||||
|
|
||||||
|
// Gets a Cursor for the note.
|
||||||
|
noteIdCursor = mMockResolver.query(
|
||||||
|
noteIdUri, // the URI for the note ID we want to retrieve
|
||||||
|
null, // no projection, retrieve all the columns
|
||||||
|
null, // no WHERE clause
|
||||||
|
null, // no WHERE arguments
|
||||||
|
null // default sort order
|
||||||
|
);
|
||||||
|
|
||||||
|
// Checks that the call worked.
|
||||||
|
// a) Checks that the cursor is not null
|
||||||
|
// b) Checks that it contains a single record
|
||||||
|
assertNotNull(noteIdCursor);
|
||||||
|
assertEquals(1,noteIdCursor.getCount());
|
||||||
|
|
||||||
|
// Opens the pipe that will contain the data.
|
||||||
|
noteIdAssetDescriptor = mMockResolver.openTypedAssetFileDescriptor(
|
||||||
|
noteIdUri, // the URI of the note that will provide the data
|
||||||
|
MIME_TYPE_TEXT, // the "text/plain" MIME type
|
||||||
|
null // no other options
|
||||||
|
);
|
||||||
|
|
||||||
|
// Checks that the call worked.
|
||||||
|
// a) checks that the AssetFileDescriptor is not null
|
||||||
|
// b) gets its ParcelFileDescriptor
|
||||||
|
// c) checks that the ParcelFileDescriptor is not null
|
||||||
|
assertNotNull(noteIdAssetDescriptor);
|
||||||
|
noteIdParcelDescriptor = noteIdAssetDescriptor.getParcelFileDescriptor();
|
||||||
|
assertNotNull(noteIdParcelDescriptor);
|
||||||
|
|
||||||
|
// Gets a File Reader that can read the pipe.
|
||||||
|
FileReader fIn = new FileReader(noteIdParcelDescriptor.getFileDescriptor());
|
||||||
|
|
||||||
|
// Gets a buffered reader wrapper for the File Reader. This allows reading line by line.
|
||||||
|
BufferedReader bIn = new BufferedReader(fIn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The pipe should contain three lines: The note's title, an empty line, and the note's
|
||||||
|
* contents. The following code reads and stores these three lines.
|
||||||
|
*/
|
||||||
|
for (int index = 0; index < inputData.length; index++) {
|
||||||
|
try {
|
||||||
|
inputData[index] = bIn.readLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asserts that the first record in the provider (written from TEST_NOTES[0]) has the same
|
||||||
|
// note title as the first line retrieved from the pipe.
|
||||||
|
assertEquals(TEST_NOTES[0].title, inputData[0]);
|
||||||
|
|
||||||
|
// Asserts that the first record in the provider (written from TEST_NOTES[0]) has the same
|
||||||
|
// note contents as the third line retrieved from the pipe.
|
||||||
|
assertEquals(TEST_NOTES[0].note, inputData[2]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tests the provider's public API for querying data in the table, using the URI for
|
* Tests the provider's public API for querying data in the table, using the URI for
|
||||||
* a dataset of records.
|
* a dataset of records.
|
||||||
@@ -534,6 +787,7 @@ public class NotePadProviderTest extends ProviderTestCase2<NotePadProvider> {
|
|||||||
// Asserts that only one row was updated. The selection criteria evaluated to
|
// Asserts that only one row was updated. The selection criteria evaluated to
|
||||||
// "title = Note1", and the test data should only contain one row that matches that.
|
// "title = Note1", and the test data should only contain one row that matches that.
|
||||||
assertEquals(1, rowsUpdated);
|
assertEquals(1, rowsUpdated);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A utility for converting note data to a ContentValues map.
|
// A utility for converting note data to a ContentValues map.
|
||||||
|
|||||||
Reference in New Issue
Block a user