Я пытаюсь реализовать ContentProvider, обернутый вокруг базы данных SQLite.Extended ContentProvider не работает должным образом
Я следовал учебник здесь, в здании моей ContentProvider: tutorial
Я хочу, чтобы проверить, что у меня есть; поэтому я пытаюсь создать экземпляр нового ContentProvider, извлечь курсор из обработчика запросов и прикрепить его к моему CursorAdapter. В настоящее время я делаю это в onCreate моей деятельности (я знаю, что это плохая практика, я просто тестирую, я в конечном итоге перейду на службу).
Uri uri = Uri.parse("content://com.test.db.providers.Messages/messages");
String s[] = {"_id", "delivery_id", "user_id", "created_on", "subject", "summary", "messagetext", "read", "status"};
MessagesProvider p = new MessagesProvider();
if (p.open()) {
Cursor messages = p.query(uri, s, null, null, null);
startManagingCursor(messages);
}
Когда я запускаю свое приложение, метод onCreate моего расширенного ContentProvider запускается. Создается вспомогательный объект базы данных, создается база данных, а метод onCreate возвращает true. Однако, когда я пытаюсь использовать свой ContentProvider (с приведенным выше кодом), в методе open() создается вспомогательный объект базы данных, но getWritableDatabase() возвращает null. Кроме того, когда я вызываю open(), ссылка на getContext() равна null.
Примечание: все остальное, кажется, работает нормально. Когда я вызываю запрос, он обращается к моему обработчику запросов, распознает Uri и пытается запустить мой код запроса (который явно взрывается, потому что объект базы данных является нулевым).
Вот моя расширенная ContentProvider и база данных помощник:
package com.test.db.providers;
import android.content.ContentProvider;
import android.content.ContentUris;
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 com.test.db.DbDefinitions;
import com.test.db.DbHelper;
public class MessagesProvider extends ContentProvider {
private DbHelper mDbHelper;
private SQLiteDatabase mDb;
private static final UriMatcher sUriMatcher;
private static final String PROVIDER_NAME = "com.test.db.providers.Messages";
private static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/messages");
public static final String id = "_id";
public static final String delivery_id = "delivery_id";
public static final String user_id = "user_id";
public static final String created_on = "created_on";
public static final String subject = "subject";
public static final String summary = "summary";
public static final String messagetext = "messagetext";
public static final String status = "status";
private static final int MESSAGES = 1;
private static final int MESSAGES_ID = 2;
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(PROVIDER_NAME, "messages", MESSAGES);
sUriMatcher.addURI(PROVIDER_NAME, "messages/#", MESSAGES_ID);
}
public boolean open() {
mDbHelper = new DbHelper(getContext());
mDb = mDbHelper.getWritableDatabase();
return (mDb == null) ? false : true;
}
public void close() {
mDbHelper.close();
}
@Override
public boolean onCreate() {
mDbHelper = new DbHelper(getContext());
mDb = mDbHelper.getWritableDatabase();
return (mDb == null) ? false : true;
}
@Override
public String getType (Uri uri) {
switch (sUriMatcher.match(uri)) {
case MESSAGES:
return "vnd.android.cursor.dir/com.test.messages";
case MESSAGES_ID:
return "vnd.android.cursor.item/com.test.messages";
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
switch (sUriMatcher.match(uri)) {
case MESSAGES:
return queryMessages(uri, projection, selection, selectionArgs, sortOrder);
default:
throw new IllegalArgumentException("Unknown Uri " + uri);
}
}
@Override
public Uri insert (Uri uri, ContentValues initialValues) {
switch (sUriMatcher.match(uri)) {
case MESSAGES:
return insertMessages(uri, initialValues);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch (sUriMatcher.match(uri)) {
case MESSAGES:
return updateMessages(uri, values, selection, selectionArgs);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public int delete (Uri uri, String selection, String[] selectionArgs) {
switch (sUriMatcher.match(uri)) {
case MESSAGES:
return deleteMessages(uri, selection, selectionArgs);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
/*
* Messages
*/
private Cursor queryMessages(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor c = mDb.query(DbDefinitions.TABLE_MESSAGES, projection, selection, selectionArgs, null, null, sortOrder);
if (c != null) {
c.moveToFirst();
}
return c;
}
private Uri insertMessages(Uri uri, ContentValues initialValues) {
ContentValues values;
if (initialValues != null)
values = new ContentValues(initialValues);
else
values = new ContentValues();
long rowId = mDb.insert(DbDefinitions.TABLE_MESSAGES, summary, values);
if (rowId > 0) {
Uri messageUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(messageUri, null);
return messageUri;
}
throw new SQLException("Failed to insert new message " + uri);
}
private int updateMessages(Uri uri, ContentValues values, String where, String[] whereArgs) {
int result = mDb.update(DbDefinitions.TABLE_MESSAGES, values, where, whereArgs);
getContext().getContentResolver().notifyChange(uri, null);
return result;
}
public int deleteMessages(Uri uri, String where, String[] whereArgs) {
// TODO flag message as deleted
return 0;
}
}
package com.test.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DbDefinitions.DATABASE_NAME, null, DbDefinitions.DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DbDefinitions.DB_CREATE);
db.execSQL(DbDefinitions.DB_TEST_DATA);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO run upgrade string
db.execSQL("DROP TABLE IF EXISTS " + DbDefinitions.TABLE_MESSAGES);
onCreate(db);
}
}
мне интересно, если я каким-то образом должны быть ссылки на то, что экземпляр MessagesProvider был создан, когда я запустил приложение, вместо того, чтобы объявить новый (р) и используя его?
Я обновил OnCreate код в моей деятельности к следующему, но managedQuery возвращается нуль:
Uri uri = Uri.parse("content://com.test.db.providers.Messages/messages");
String s[] = {"_id", "delivery_id", "user_id", "created_on", "subject", "summary", "messagetext", "read", "status"};
Cursor messages = managedQuery(uri, s, null, null, null);
if (messages != null)
startManagingCursor(messages);
ExampleCursorAdapter msg =
new ExampleCursorAdapter(this, messages);
setListAdapter(msg);
ли вы зарегистрировать провайдера? – fedj
Да, Я разместил следующее внутри тега незадолго до tag: <поставщик android: name = "com.test.db.providers.MessagesProvider" android: authority = "com.test.db.providers.MessagesProvider" /> –
Andrew
Я также попытался переместить тег провайдера внутри тег приложения. Когда я пытаюсь запустить приложение, приложение выходит из строя (до достижения моей активности, которая создает экземпляр поставщика. В журнале говорится, что здесь есть синтаксическая ошибка: create table messages (_id integer primary key), integer delivery_id, целое число user_id, но не null, created_on integer not null, текст темы не null, сводный текст не null, текст сообщения не null, read integer not null, status text not null default 'STATE_OK'; – Andrew