ContentProvider fails on insert
I am brand new to developing for android and have hit something of a stumbling block that I cant seem to get around.
Using the NotePad example, I have created my own ContentProvider to serve up data from a database that I will eventually host on a webserver. But that is lightyears away from where I am right now.
Just testing my ContentProvider has caused a bit of a headache that I cant solve. For some reason, when the provider calls SQLiteDatabase db = mOpenHelper.getWritableDatabase();
I get a null pointer exception.
Code Follows:
MainWindow.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/**
* Check for DB, if none, d/l from web server
*/
Uri first_use = Rules.CONTENT_URI;
ContentResolver cr = getContentResolver();
Cursor c = cr.query(first_use, null, null, null, null);
if(c == null){
ContentProvider cp = new CoreRulesProvider();
if (cp.onCreate()) {
ContentValues values = new ContentValues();
values.put(Rules._ID, 1);
values.put(Rules.TERM, "Player");
values.put(Rules.TEXT, "You, the person reading these rules, are a Player.");开发者_运维百科
cp.insert(Rules.CONTENT_URI, values);
}
}
RulesContentProvider.java
package com.vortex.rules;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.HashMap;
import com.vortex.rules.Rule.Rules;
/**
* Provides access to a database of rules. Each rule has a TERM, the RULE itself, and a creation date and modified data.
* @author Michael Martin
*
*/
public class CoreRulesProvider extends ContentProvider {
private static final String TAG = "CoreRulesProvider";
private static final String DATABASE_NAME = "core_rules.db";
private static final int DATABASE_VERSION = 2;
private static final String RULES_TABLE_NAME = "rules";
private static HashMap<String, String> sRulesProjectionMap;
private static HashMap<String, String> sLiveFolderProjectionMap;
private static final int RULES = 1;
private static final int RULE_ID = 2;
private static final int LIVE_FOLDER_RULES = 3;
private static final UriMatcher sUriMatcher;
/**
* This class helps open, create, and upgrade the database file.
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + RULES_TABLE_NAME + " ("
+ Rules._ID + " INTEGER PRIMARY KEY,"
+ Rules.TERM + " TEXT,"
+ Rules.TEXT + " LONGTEXT"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS rules");
onCreate(db);
}
}
/**
* END OF DatabaseHelper CLASS!!!!!
*/
private DatabaseHelper mOpenHelper;
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(RULES_TABLE_NAME);
switch (sUriMatcher.match(uri)) {
case RULES:
qb.setProjectionMap(sRulesProjectionMap);
break;
case RULE_ID:
qb.setProjectionMap(sLiveFolderProjectionMap);
qb.appendWhere(Rules._ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Uknown URI " + uri);
}
//If no sort order is specified, use the default
String orderBy;
if (TextUtils.isEmpty(sortOrder)) {orderBy = Rules.DEFAULT_SORT_ORDER;
} else {
orderBy = sortOrder;
}
//Get the database and run the query
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
//Tell the cursor what uri to watch, so it knows when its source data changes
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case RULES:
case LIVE_FOLDER_RULES:
return Rules.CONTENT_TYPE;
case RULE_ID:
return Rules.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Uknown URI " + uri);
}
}
public Uri insert(Uri uri, ContentValues initialValues) {
//Validate the requested uri
if (sUriMatcher.match(uri) != RULES) {
throw new IllegalArgumentException("Uknown URI " + uri);
}
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
//Make sure that the fields are all set
if (values.containsKey(Rules.TERM) == false) {
Resources r = Resources.getSystem();
values.put(Rules.TERM, r.getString(android.R.string.untitled));
}
if (values.containsKey(Rules.TEXT) == false) {
values.put(Rules.TEXT, "");
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(RULES_TABLE_NAME, Rules.TEXT, values);
if (rowId > 0) {
Uri ruleUri = ContentUris.withAppendedId(Rules.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(ruleUri, null);
return ruleUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case RULES:
count = db.delete(RULES_TABLE_NAME, where, whereArgs);
break;
case RULE_ID:
String ruleId = uri.getPathSegments().get(1);
count = db.delete(RULES_TABLE_NAME, Rules._ID + "=" + ruleId
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""),
whereArgs);
break;
default:
throw new IllegalArgumentException("Uknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case RULES:
count = db.update(RULES_TABLE_NAME, values, where, whereArgs);
break;
case RULE_ID:
String ruleId = uri.getPathSegments().get(1);
count = db.update(RULES_TABLE_NAME, values, Rules._ID + "=" + ruleId
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : "")
, whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(Rule.AUTHORITY, "rules", RULES);
sUriMatcher.addURI(Rule.AUTHORITY, "rules/#", RULE_ID);
sUriMatcher.addURI(Rule.AUTHORITY, "live_folders/rules", LIVE_FOLDER_RULES);
sRulesProjectionMap = new HashMap<String, String>();
sRulesProjectionMap.put(Rules._ID, Rules._ID);
sRulesProjectionMap.put(Rules.TERM, Rules.TERM);
sRulesProjectionMap.put(Rules.TEXT, Rules.TEXT);
}
}
Stack Trace
07-30 10:22:19.078: ERROR/AndroidRuntime(10903): Uncaught handler: thread main exiting due to uncaught exception 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.vortex.rules/com.vortex.rules.MainWindow}: java.lang.NullPointerException 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2444) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2460) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread.access$2300(ActivityThread.java:119) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1837) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.os.Handler.dispatchMessage(Handler.java:99) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.os.Looper.loop(Looper.java:123) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread.main(ActivityThread.java:4246) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at java.lang.reflect.Method.invokeNative(Native Method) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at java.lang.reflect.Method.invoke(Method.java:521) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at dalvik.system.NativeStart.main(Native Method) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): Caused by: java.lang.NullPointerException 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at com.vortex.rules.CoreRulesProvider.insert(CoreRulesProvider.java:157) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at com.vortex.rules.MainWindow.onCreate(MainWindow.java:42) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2407) 07-30 10:22:19.208: ERROR/AndroidRuntime(10903): ... 11 more
Figuered this out on my own eventualy. Turns out I was missing a letter in my URI, got it fixed.
精彩评论