Related
I'm trying to make an app that involves a database. I'm using a ContentProvider and it's crashing in the query method when it tries to getWritableDatabase.
It returns a NullPointerException. I know for a fact that the Context isn't null, since that seems to be the main cause of this kind of problem.
Here's the ContentProvider code:
package com.corvus.corvusenterprises.digimonapp;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.Arrays;
import java.util.HashSet;
import static com.corvus.corvusenterprises.digimonapp.DBHelper.presentDigimon;
/**
* Created by Jack on 01/05/2017.
*/
public class DigimonContentProvider extends ContentProvider {
private static DigimonContentProvider instance;
private DBHelper dbHelper;
private SQLiteDatabase db;
private static final int DIGIMON = 10;
private static final int DIGIMON_ID = 20;
private static final int ATTACKS = 30;
private static final int ATTACKS_ID = 40;
private static final int EVOLUTIONS = 50;
private static final int EVOLUTIONS_ID = 60;
private static final String AUTHORITY = "com.corvus.corvusenterprises.digimonapp";
private static final String BASE_PATH_DIGIMON = "digimon";
private static final String BASE_PATH_ATTACKS = "attacks";
private static final String BASE_PATH_EVOLUTIONS = "evolutions";
public static final Uri CONTENT_URI_DIGIMON = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_DIGIMON);
public static final Uri CONTENT_URI_ATTACKS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_ATTACKS);
public static final Uri CONTENT_URI_EVOLUTIONS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_EVOLUTIONS);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/digimon";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/digimon";
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON, DIGIMON);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON + "/#", DIGIMON_ID);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS, ATTACKS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS + "/#", ATTACKS_ID);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS, EVOLUTIONS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS + "/#", EVOLUTIONS_ID);
}
private DigimonContentProvider()
{
}
public static DigimonContentProvider getInstance() {
if (instance == null)
instance = new DigimonContentProvider();
return instance;
}
#Override
public boolean onCreate() {
Context ctx = MyApp.getContext();
dbHelper = DBHelper.getInstance(ctx);
dbHelper.insertDigimon("Guilmon", "Guilmon", "Child/Rookie", "Virus", "Dinosaur", "TRUE","R.mipmap.guilmon.jpg");
dbHelper.insertDigimon("Growmon", "Growlmon", "Adult/Champion", "Virus", "Bigger Dinosaur", "FALSE","R.mipmap.growmon.jpg");
dbHelper.insertDigimon("Terriermon", "terriermon", "Child/Rookie", "Vaccine", "Dogbunny", "FALSE","R.mipmap.terriermon.jpg");
dbHelper.insertDigimon("Galgomon", "Gargomon", "Adult/Champion", "Vaccine", "Gunbunny", "FALSE","R.mipmap.galgomon.jpg");
dbHelper.insertDigimon("Kyubimon", "Kyubimon", "Adult/Champion", "Data", "9-Tailed Fox", "FALSE","R.mipmap.kyubimon.jpg");
dbHelper.insertDigimon("Taomon", "Taomon", "Perfect/Ultimate", "Data", "Kitsune Miko", "FALSE","R.mipmap.taomon.jpg");
dbHelper.insertDigimon("Impmon", "Impmon", "Child/Rookie", "Virus", "Kid in a purple onesie", "FALSE","R.mipmap.impmon.jpg");
dbHelper.insertDigimon("Beelzebumon", "Beelzemon", "Ultimate/Mega", "Virus", "Demon Lord of Gluttony", "FALSE","R.mipmap.beelzebumon.jpg");
presentDigimon[460] = true; presentDigimon[454] = true;
presentDigimon[1019] = true; presentDigimon[374] = true;
presentDigimon[572] = true; presentDigimon[1013] = true;
presentDigimon[507] = true; presentDigimon[100] = true;
dbHelper.insertEvolution("Guilmon", "Growmon", "");
dbHelper.insertEvolution("Terriermon", "Galgomon","");
dbHelper.insertEvolution("Kyubimon", "Taomon","");
dbHelper.insertEvolution("Impmon", "Beelzebumon", "(Warp Evolution)");
dbHelper.insertAttack("Fireball", "Pyro Sphere", "Guilmon", "Explosive Fireball");
dbHelper.insertAttack("Rock Breaker", "Rock Breaker", "Guilmon", "Claw Swipe");
dbHelper.insertAttack("Exhaust Flame", "Pyro Blaster", "Growmon", "Fire Laser");
dbHelper.insertAttack("Plasma Blade", "Dragon Slash", "Growmon", "Forearm Blades");
dbHelper.insertAttack("Blazing Fire", "Bunny Blast", "Terriermon", "Energy Blast");
dbHelper.insertAttack("Petit Twister", "Terrier Tornado", "Terriermon", "Throws Tornado");
dbHelper.insertAttack("Gatling Arm", "Gargo Laser", "Galgomon", "Fires Guns");
dbHelper.insertAttack("Dum Dum Upper", "Bunny Pummel", "Galgomon", "Fires Guns While Punching");
dbHelper.insertAttack("Koenryu", "Dragon Wheel", "Kyubimon", "Fire Dragon");
dbHelper.insertAttack("Onibidama", "Fox-Tail Inferno", "Kyubimon", "Fireballs from the tails");
dbHelper.insertAttack("Bonhitsusen", "Talisman of Light", "Taomon", "Energy Seal Laser");
dbHelper.insertAttack("Oṃ", "Talisman Spell", "Taomon", "Makes a dome shield");
dbHelper.insertAttack("Night of Fire", "Badaboom", "Impmon", "Mini-Fireballs");
dbHelper.insertAttack("Pillar of Fire", "", "Impmon", "Wall of Flames");
dbHelper.insertAttack("Double Impact", "Double Impact", "Beelzebumon", "Fires two bullets");
dbHelper.insertAttack("Darkness Claw", "", "Beelzebumon", "Kills Leomon");
db = dbHelper.getWritableDatabase();
return false;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
Uri _uri = null;
switch (sURIMatcher.match(uri)) {
case DIGIMON:
long _ID1 = db.insert(DigimonTable.DIGIMON_TABLE_NAME, "", values);
if (_ID1 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_DIGIMON, _ID1);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
case ATTACKS:
long _ID2 = db.insert(AttacksTable.ATTACKS_TABLE_NAME, "", values);
if (_ID2 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_ATTACKS, _ID2);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
case EVOLUTIONS:
long _ID3 = db.insert(EvolutionsTable.EVOLUTIONS_TABLE_NAME, "", values);
if (_ID3 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_EVOLUTIONS, _ID3);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
default:
throw new SQLException("Failed to insert row into " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return _uri;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
checkColumns(projection, uriType);
queryBuilder.setTables(DigimonTable.DIGIMON_TABLE_NAME + ", " + EvolutionsTable.EVOLUTIONS_TABLE_NAME + ", " + AttacksTable.ATTACKS_TABLE_NAME);
switch (uriType) {
case DIGIMON:
break;
case DIGIMON_ID:
queryBuilder.appendWhere(DigimonTable.DIGIMON_COLUMN_ID+"="+uri.getLastPathSegment());
case ATTACKS:
break;
case ATTACKS_ID:
queryBuilder.appendWhere(AttacksTable.ATTACKS_COLUMN_ID+"="+uri.getLastPathSegment());
case EVOLUTIONS:
break;
case EVOLUTIONS_ID:
queryBuilder.appendWhere(EvolutionsTable.EVOLUTIONS_COLUMN_ID+"="+uri.getLastPathSegment());
default:
throw new IllegalArgumentException("Unknown URI: "+ uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(MyApp.getContext().getContentResolver(), uri);
return cursor;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
int rowsDeleted = 0;
switch (uriType) {
case DIGIMON:
rowsDeleted = db.delete(DigimonTable.DIGIMON_TABLE_NAME, selection, selectionArgs);
break;
case DIGIMON_ID:
String id1 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
DigimonTable.DIGIMON_TABLE_NAME,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
null);
} else {
rowsDeleted = db.delete(
DigimonTable.DIGIMON_TABLE_NAME,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
+ " and " + selection,
selectionArgs);
}
break;
case ATTACKS:
rowsDeleted = db.delete(AttacksTable.ATTACKS_TABLE_NAME, selection, selectionArgs);
break;
case ATTACKS_ID:
String id2 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
AttacksTable.ATTACKS_TABLE_NAME,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
null);
} else {
rowsDeleted = db.delete(
AttacksTable.ATTACKS_TABLE_NAME,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
+ " and " + selection,
selectionArgs);
}
break;
case EVOLUTIONS:
rowsDeleted = db.delete(EvolutionsTable.EVOLUTIONS_TABLE_NAME, selection, selectionArgs);
break;
case EVOLUTIONS_ID:
String id3 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
EvolutionsTable.EVOLUTIONS_TABLE_NAME,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
null);
} else {
rowsDeleted = db.delete(
EvolutionsTable.EVOLUTIONS_TABLE_NAME,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
+ " and " + selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
int rowsUpdated = 0;
switch (uriType) {
case DIGIMON:
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case DIGIMON_ID:
String id1 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
null);
} else {
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
+ " and "
+ selection,
selectionArgs);
}
break;
case ATTACKS:
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case ATTACKS_ID:
String id2 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
null);
} else {
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
+ " and "
+ selection,
selectionArgs);
}
break;
case EVOLUTIONS:
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case EVOLUTIONS_ID:
String id3 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
null);
} else {
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
+ " and "
+ selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
private void checkColumns(String[] projection, int uri) {
HashSet<String> availableColumns;
String[] availableDigimon = { DigimonTable.DIGIMON_COLUMN_ID,
DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_DUB_NAME,
DigimonTable.DIGIMON_COLUMN_LEVEL, DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,
DigimonTable.DIGIMON_COLUMN_DESCRIPTION, DigimonTable.DIGIMON_COLUMN_FAVOURITE,
DigimonTable.DIGIMON_COLUMN_PATH};
String[] availableAttacks = {AttacksTable.ATTACKS_COLUMN_ID, AttacksTable.ATTACKS_COLUMN_NAME,
AttacksTable.ATTACKS_COLUMN_DUB_NAME, AttacksTable.ATTACKS_COLUMN_DIGIMON,
AttacksTable.ATTACKS_COLUMN_DESCRIPTION};
String[] availableEvolutions = {EvolutionsTable.EVOLUTIONS_COLUMN_ID,EvolutionsTable.EVOLUTIONS_COLUMN_FROM,
EvolutionsTable.EVOLUTIONS_COLUMN_TO, EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS};
if (projection != null) {
HashSet<String> requestedColumns = new HashSet<String>(
Arrays.asList(projection));
switch(uri){
case DIGIMON:
case DIGIMON_ID: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
break;
case ATTACKS:
case ATTACKS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableAttacks));
break;
case EVOLUTIONS:
case EVOLUTIONS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableEvolutions));
break;
default: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
}
// check if all columns which are requested are available
if (!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException(
"Unknown columns in projection");
}
}
}
public Cursor defaultMainMenu()
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON, new String[]{DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_FAVOURITE}, null, null, DigimonTable.DIGIMON_COLUMN_NAME + " ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor searchMenuQuery(String search)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME,DigimonTable.DIGIMON_COLUMN_FAVOURITE},DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{search},DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor favouritesMenuQuery()
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME},DigimonTable.DIGIMON_COLUMN_FAVOURITE+" = true",null,DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonProfileQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,null,DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonAttacksQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_ATTACKS,null,AttacksTable.ATTACKS_COLUMN_DIGIMON+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonEvolutionFromQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_FROM+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonEvolutionToQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_TO+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
}
And here's the Logcat results:
Process: com.corvus.corvusenterprises.digimonapp, PID: 12198
java.lang.RuntimeException: Unable to get provider com.corvus.corvusenterprises.digimonapp.DigimonContentProvider: java.lang.NullPointerException
at android.app.ActivityThread.installProvider(ActivityThread.java:5084)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
at android.app.ActivityThread.access$1800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.onCreate(DigimonContentProvider.java:62)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1616)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1587)
at android.app.ActivityThread.installProvider(ActivityThread.java:5081)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
at android.app.ActivityThread.access$1800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711)
at dalvik.system.NativeStart.main(Native Method)
Here's the DBHelper code, in case it helps:
package com.corvus.corvusenterprises.digimonapp;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_ATTACKS;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_DIGIMON;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_EVOLUTIONS;
/**
* Created by Jack on 01/05/2017.
*/
public class DBHelper extends SQLiteOpenHelper {
public static final String[]digimonArray = {
"Gigantic array of names"};
private static final String DATABASE_NAME = "DigimonDatabase.db";
private static final int version = 1;
private static DBHelper instance;
public static boolean[]presentDigimon = new boolean[digimonArray.length];
private DBHelper(Context context) {
super(context, DATABASE_NAME, null, version);
}
public static DBHelper getInstance(Context ctx) {
if (instance == null)
instance = new DBHelper(ctx);
return instance;
}
#Override
public void onCreate(SQLiteDatabase db) {
DigimonTable.onCreate(db);
AttacksTable.onCreate(db);
EvolutionsTable.onCreate(db);
}
public void onUpgrade(SQLiteDatabase db, int oldver, int newVer)
{
DigimonTable.onUpgrade(db,oldver,newVer);
AttacksTable.onUpgrade(db,oldver,newVer);
EvolutionsTable.onUpgrade(db,oldver,newVer);
}
public void insertDigimon(String name, String dub_name, String level, String attribute, String description, String favourite, String path)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(DigimonTable.DIGIMON_COLUMN_NAME,name);
values.put(DigimonTable.DIGIMON_COLUMN_DUB_NAME,dub_name);
values.put(DigimonTable.DIGIMON_COLUMN_LEVEL,level);
values.put(DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,attribute);
values.put(DigimonTable.DIGIMON_COLUMN_DESCRIPTION,description);
values.put(DigimonTable.DIGIMON_COLUMN_FAVOURITE, favourite);
values.put(DigimonTable.DIGIMON_COLUMN_PATH,path);
dcp.insert(CONTENT_URI_DIGIMON, values);
}
public void insertAttack(String name, String dub_name, String digimon, String description)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(AttacksTable.ATTACKS_COLUMN_NAME, name);
values.put(AttacksTable.ATTACKS_COLUMN_DUB_NAME,dub_name);
values.put(AttacksTable.ATTACKS_COLUMN_DIGIMON, digimon);
values.put(AttacksTable.ATTACKS_COLUMN_DESCRIPTION, description);
dcp.insert(CONTENT_URI_ATTACKS, values);
}
public void insertEvolution(String from, String to, String conditions)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_TO,to);
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_FROM,from);
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS,conditions);
dcp.insert(CONTENT_URI_EVOLUTIONS, values);
}
}
Any and all help appreciated. If you need more information, just let me know.
(EDITED): New version being worked on. Code updated.
(EDITED 2): Fixed a possible issue with recursive calls.
I know for a fact that the Context isn't null
How do you know that? MyApp.getContext() looks strange to me.
Try giving the Context to the ContentProvider
private Context mContext;
private DigimonContentProvider(Context context)
{
this.mContext = context;
}
private DigimonContentProvider() { }
public static DigimonContentProvider getInstance(Context context) {
if (instance == null)
instance = new DigimonContentProvider(context);
return instance;
}
#Override
public boolean onCreate() {
dbHelper = DBHelper.getInstance(this.mContext);
However, you don't need a ContentProvider to have a database, so try getting the database working without it.
It is throwing a NullPointerException because you are trying to access your ContentProvider methods directly instead of using a ContentResolver for the same.
You can abstract the code you have written in the ContentProvider to access it in an another class. And this time use a ContentResolver instance for the same.
Edit:
Maybe your problem is that your dbHelper is not singleton and you are creating an another instances of it through dbHelper.getInstance(getContext) in insert() method.
Try getting a new instance of dbHelper only in onCreate() method and not in other methods.
You can use this example: MoviesContentProvider.java
in my code I have a my custom ContentProvider class that can be seen here:
public class MaiMobileProvider extends ContentProvider {
protected MaiMobileDbHelper mHelper;
protected UriMatcher mMatcher = buildUriMatcher();
//region code return on UriMatcher
public static final int GNR_CODE = 1;
public static final int PSP_CODE = 2;
public static final int SERVICES_CODE = 3;
public static final int HIGHLIGHT_CODE = 4;
//endregion
static UriMatcher buildUriMatcher() {
// 1) The code passed into the constructor represents the code to return for the root
// URI. It's common to use NO_MATCH as the code for this case. Add the constructor below.
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = MaiMobileContract.CONTENT_AUTHORITY;
// 2) Use the addURI function to match each of the types. Use the constants from
// WeatherContract to help define the types to the UriMatcher.
matcher.addURI(authority, MaiMobileContract.PATH_GNR, GNR_CODE);
matcher.addURI(authority, MaiMobileContract.PATH_PSP, PSP_CODE);
matcher.addURI(authority, MaiMobileContract.PATH_SERVICES, SERVICES_CODE);
matcher.addURI(authority, MaiMobileContract.PATH_SERVICES, HIGHLIGHT_CODE);
// 3) Return the new matcher!
return matcher;
}
//region Selections
//services.isHighlighted = 1
private static final String sServicesIsHighlightedSelection =
MaiMobileContract.ServicesEntry.TABLE_NAME +
"." + MaiMobileContract.ServicesEntry.COLUMN_IS_HIGHLIGHTED + " = 1 ";
//endregion
//region custom cursors
protected Cursor getHighlightedServices(Uri uri, String[] projection, String sortOrder) {
boolean isHighlighted = MaiMobileContract.ServicesEntry.isServiceHighlighted(uri);
String selection = null;
if (isHighlighted)
selection = sServicesIsHighlightedSelection;
return mHelper.getReadableDatabase().query(
MaiMobileContract.ServicesEntry.TABLE_NAME,
projection,
selection,
null,
null,
null,
sortOrder);
}
//endregion
#Override
public boolean onCreate() {
mHelper = new MaiMobileDbHelper(getContext());
return (mHelper == null) ? false : true;
}
#Nullable
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor mCursor;
switch (mMatcher.match(uri)) {
case GNR_CODE:
mCursor = mHelper.getReadableDatabase().query(
MaiMobileContract.GnrEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
case PSP_CODE:
mCursor = mHelper.getReadableDatabase().query(
MaiMobileContract.PspEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
case SERVICES_CODE:
mCursor = mHelper.getReadableDatabase().query(
MaiMobileContract.ServicesEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
case HIGHLIGHT_CODE:
mCursor = getHighlightedServices(uri, projection, sortOrder);
break;
default:
throw new UnsupportedOperationException("Unknow uri: " + uri);
}
mCursor.setNotificationUri(getContext().getContentResolver(), uri);
return mCursor;
}
#Nullable
#Override
public String getType(Uri uri) {
final int match = mMatcher.match(uri);
switch (match) {
case GNR_CODE:
return MaiMobileContract.GnrEntry.CONTENT_TYPE;
case PSP_CODE:
return MaiMobileContract.PspEntry.CONTENT_TYPE;
case SERVICES_CODE:
return MaiMobileContract.ServicesEntry.CONTENT_TYPE;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
#Nullable
#Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = mHelper.getWritableDatabase();
final int match = mMatcher.match(uri);
Uri returnedUri;
switch (match) {
case GNR_CODE: {
long id = db.insert(MaiMobileContract.GnrEntry.TABLE_NAME, null, values);
if (id > 0)
returnedUri = MaiMobileContract.GnrEntry.buildGnrUri(id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
break;
}
case PSP_CODE: {
long id = db.insert(MaiMobileContract.PspEntry.TABLE_NAME, null, values);
if (id > 0)
returnedUri = MaiMobileContract.PspEntry.buildPspUri(id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
break;
}
case SERVICES_CODE: {
long id = db.insert(MaiMobileContract.ServicesEntry.TABLE_NAME, null, values);
if (id > 0)
returnedUri = MaiMobileContract.ServicesEntry.buildServicesUri(id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
break;
}
case HIGHLIGHT_CODE: {
long id = db.insert(MaiMobileContract.ServicesEntry.TABLE_NAME, null, values);
if (id > 0)
returnedUri = MaiMobileContract.ServicesEntry.buildServicesUri(id);
else
throw new android.database.SQLException("Failed to insert row into " + uri);
break;
}
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return returnedUri;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mHelper.getWritableDatabase();
// Student: Use the uriMatcher to match the WEATHER and LOCATION URI's we are going to
final int match = mMatcher.match(uri);
int rowsDeleted;
// handle. If it doesn't match these, throw an UnsupportedOperationException.
if (null == selection)
selection = "1";
switch (match) {
case GNR_CODE:
rowsDeleted = db.delete(MaiMobileContract.GnrEntry.TABLE_NAME, selection,
selectionArgs);
break;
case PSP_CODE:
rowsDeleted = db.delete(MaiMobileContract.PspEntry.TABLE_NAME, selection,
selectionArgs);
break;
case SERVICES_CODE:
rowsDeleted = db.delete(MaiMobileContract.ServicesEntry.TABLE_NAME, selection,
selectionArgs);
break;
case HIGHLIGHT_CODE:
rowsDeleted = db.delete(MaiMobileContract.ServicesEntry.TABLE_NAME, selection,
selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if (rowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mHelper.getWritableDatabase();
final int match = mMatcher.match(uri);
int updatedRows;
switch (match) {
case GNR_CODE:
updatedRows = db.update(MaiMobileContract.GnrEntry.TABLE_NAME, values, selection,
selectionArgs);
break;
case PSP_CODE:
updatedRows = db.update(MaiMobileContract.PspEntry.TABLE_NAME, values, selection,
selectionArgs);
break;
case SERVICES_CODE:
updatedRows = db.update(MaiMobileContract.ServicesEntry.TABLE_NAME, values, selection,
selectionArgs);
break;
case HIGHLIGHT_CODE:
updatedRows = db.update(MaiMobileContract.ServicesEntry.TABLE_NAME, values, selection,
selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if (updatedRows != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return updatedRows;
}
#Override
#TargetApi(11)
public void shutdown() {
mHelper.close();
super.shutdown();
}
}
This provider is used on requesting a method that I use to make my map markers and eventually add them to the ClusterManager, which can be seen here:
public class BaseMapFragment extends SupportMapFragment {
//region Parameters
private final String LOG_TAG = "BaseMapFragment";
public static int layout;
protected FetchDataInterface mApiGson;
protected GoogleMap gMap;
protected SecurityMapFragment mapFragment;
protected MaiMobileProvider mProvider;
protected List<MaiClusterItem> pspItems = new ArrayList<>();
protected List<MaiClusterItem> gnrItems = new ArrayList<>();
protected ClusterManager<MaiClusterItem> mClusterManager;
//endregion
//region Methods
protected void addMapMarkers(MaiMobileProvider provider, String markerGroup) {
switch (markerGroup) {//between a switch and a if statement, I adopted the switch for future implementations
case "psp":{
Cursor cursor = provider.query(MaiMobileContract.PspEntry.CONTENT_URI,null,null,null,MaiMobileContract.PspEntry.COLUMN_DISTANCE +" ASC");
cursor.moveToFirst();
Log.v("Cursor psp: ", cursor.toString());
Log.v("Cursor psp ", "has: " + cursor.getCount());
while(cursor.moveToNext()){
//cyclic add items to each MaiClusterItem List
LatLng coco = new LatLng(
cursor.getDouble(ColumnIndexes.PspIndexes.COLUMN_COORD_LAT),
cursor.getDouble(ColumnIndexes.PspIndexes.COLUMN_COORD_LONG));
pspItems.add(new MaiClusterItem(coco,
BitmapDescriptorFactory.fromResource(R.mipmap.psp),
cursor.getString(ColumnIndexes.PspIndexes.COLUMN_NAME),
cursor.getString(ColumnIndexes.PspIndexes.COLUMN_DESCRIPTION)));
Log.v("pspItems ", "has: " + pspItems.size());
}
cursor.close();
break;
}
case "gnr": {
Cursor cursor = provider.query(MaiMobileContract.GnrEntry.CONTENT_URI, null, null, null, MaiMobileContract.GnrEntry.COLUMN_DISTANCE + " ASC");
cursor.moveToFirst();
Log.v("Cursor gnr: ", cursor.toString());
while(cursor.moveToNext()){
LatLng coco = new LatLng(
cursor.getDouble(ColumnIndexes.GnrIndexes.COLUMN_COORD_LAT),
cursor.getDouble(ColumnIndexes.GnrIndexes.COLUMN_COORD_LONG));
gnrItems.add(new MaiClusterItem(
coco,
BitmapDescriptorFactory.fromResource(R.mipmap.gnr_green),
cursor.getString(ColumnIndexes.GnrIndexes.COLUMN_NAME),
""));
Log.v("gnrItems ", "has: " + gnrItems.size());
}
cursor.close();
break;
}
default:
throw new UnsupportedOperationException("Unknown error adding markers: " + getContext() + " at " + LOG_TAG);
}
}
//region PspData Call
protected void makePspMarkers() {
addMapMarkers(mProvider, "psp");
mClusterManager.addItems(pspItems);
mClusterManager.setRenderer(new MaiClusterItem.ClusterItemRenderer(getActivity(), gMap, mClusterManager));
}
//endregion
//region GnrData Call
protected void makeGnrMarkers() {
addMapMarkers(mProvider, "gnr");
mClusterManager.addItems(gnrItems);
mClusterManager.setRenderer(new MaiClusterItem.ClusterItemRenderer(getActivity(), gMap, mClusterManager));
}
//endregion
//endregion
}
and this BaseMapFragment is extended on SecurityMapFragment class:
public class SecurityMapFragment extends BaseMapFragment implements
OnMapReadyCallback {
//region Properties
public CameraPosition userCameraPosition;
//endregion
//region Methods
//region MapReady
#Override
public void onMapReady(GoogleMap googleMap) {
gMap = googleMap;
//region map design
gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
gMap.getUiSettings().setZoomControlsEnabled(false);
gMap.setMyLocationEnabled(true);
gMap.getUiSettings().setMyLocationButtonEnabled(false);
//endregion
//region camera+clustering
userCameraPosition =
new CameraPosition.Builder()
.target(MainActivity.userCoords)
.zoom(9f)
.bearing(-10f)
.build();
gMap.moveCamera(CameraUpdateFactory.newCameraPosition(userCameraPosition));//set camera on user position (static for now)
mClusterManager = new ClusterManager<>(getContext(), gMap);
gMap.setOnCameraChangeListener(mClusterManager);//cluster call
//endregion
}
//endregion
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mProvider = new MaiMobileProvider();
//generate map
mapFragment = (SecurityMapFragment) this.getFragmentManager().findFragmentById(R.id.security_map_view);
getMapAsync(this);
//interface api instance for Gson
mApiGson = RetrofitUtils.createGsonRetrofitInterface();
makePspGnrMarkers();//this will be called on created and also on filter selection
}
//region Add markers methods
private void makePspGnrMarkers() {
//Todo mClusterManager.clearItems();
makePspMarkers();
makeGnrMarkers();
}
//endregion
//endregion
}
The MainActivity calls the SecurityMapFragment, then on the fragment it is called the methods to use the data from the Database that was created on my service.
The problem comes now, for some reason on doing mHelper.getReadableDatabase().query(...); it gives me a NullPointerException on that method call, this happens on the MaiMobileProvider on the .query() method, which is the method that BaseMapFragment uses to fetch Database data.
I know that the mHelper is null, what I don't know is why. The inicialization of mHelper is made on the onCreate of the Provider.
NOTE: yes my provider is being declared on the manifest inside the <application>
<provider
android:name=".data.database.MaiMobileProvider"
android:authorities="pt.gov.mai.mobile.android"
android:exported="false" />
Thank you all in advance for reading and for your insight.
Just like Selvin said I should use the ContentResolver.query() because the application is already in charge of instantiating the Provider that is in the manifest.
So as part of "what has changed":
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mResolver = getContext().getContentResolver();//From a Provider to a ContentResolver
//generate map
mapFragment = (SecurityMapFragment) this.getFragmentManager().findFragmentById(R.id.security_map_view);
getMapAsync(this);
//interface api instance for Gson
mApiGson = RetrofitUtils.createGsonRetrofitInterface();
makePspGnrMarkers();//this will be called on created and also on filter selection
}
And then after we get our ContentResolver from our context we can use it to query our provider, the same way it was done.
Also have to refer on Selvin that commented my question and pointed that a Resolver should be used.
And also Android documentation on ContentProvider and ContentResolver.
I am totally new in this and I am sure I screwed the code somehow, please help me fix it.
I have the following contentprovider for building a database to store favourite tags:
public class FTagsContentProvider extends ContentProvider {
static final String AUTHORITY = "ch.ethz.twimight.FTags";
private static final String BASE_PATH = "ftags";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + BASE_PATH);
// fields for the database
public static final String COL_ID = "id";
public static final String COL_TEXT = "text";
public static final String COL_COUNT = "count";
static final int FTAGS = 1;
static final int FTAGS_ID = 2;
DBHelper dbHelper;
private static HashMap<String, String> FTagsMap;
static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, BASE_PATH, FTAGS);
uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", FTAGS_ID);
}
// database declarations
private SQLiteDatabase database;
static final String DATABASE_NAME = "ftagtable.db";
static final String TABLE_FTAGS = "FTags";
static final int DATABASE_VERSION = 1;
private static final String TABLE_FTAGS_CREATE = "create table "
+ TABLE_FTAGS
+ "("
+ COL_ID + " integer primary key autoincrement, "
+ COL_TEXT + " text not null, "
+ COL_COUNT + " integer"
+ ");";
private static class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(TABLE_FTAGS_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.w(DBHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ". Old data will be destroyed");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FTAGS);
onCreate(db);
}
}
#Override
public boolean onCreate() {
// TODO Auto-generated method stub
Context context = getContext();
dbHelper = new DBHelper(context);
database = dbHelper.getWritableDatabase();
if(database == null)
return false;
else
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(TABLE_FTAGS);
switch (uriMatcher.match(uri)) {
case FTAGS:
queryBuilder.setProjectionMap(FTagsMap);
break;
case FTAGS_ID:
queryBuilder.appendWhere( COL_ID + "=" + uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (sortOrder == null || sortOrder == ""){
sortOrder = COL_TEXT;
}
Cursor cursor = queryBuilder.query(database, projection, selection,
selectionArgs, null, null, sortOrder);
/**
* register to watch a content URI for changes
*/
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
long row = database.insert(TABLE_FTAGS, "", values);
if(row > 0) {
Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
throw new SQLException("Fail to add a new record into " + uri);
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
int rowsUpdated = 0;
switch (uriMatcher.match(uri)){
case FTAGS:
rowsUpdated = database.update(TABLE_FTAGS, values, selection, selectionArgs);
break;
case FTAGS_ID:
rowsUpdated = database.update(TABLE_FTAGS, values, COL_ID +
" = " + uri.getLastPathSegment() +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI " + uri );
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
int count = 0;
switch (uriMatcher.match(uri)){
case FTAGS:
count = database.delete(TABLE_FTAGS, selection, selectionArgs);
break;
case FTAGS_ID:
String id = uri.getLastPathSegment(); //gets the id
count = database.delete( TABLE_FTAGS, COL_ID + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
#Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
}
I want to set the COL_COUNT as a value of keeping count the times that a tag has been inserted into the database, originally it should be 1 for each tag, and I want it to update only the count like from 1 to 2 and so on every time an existing tag is input.
Here is the Activity:
public class TestActivity extends Activity {
private EditText mText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
}
public boolean check(String s){
boolean t = false;
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(FTagsContentProvider.CONTENT_URI,
new String []{FTagsContentProvider.COL_TEXT}, FTagsContentProvider.COL_TEXT + "=?", new String[]{s}, null);
if(cursor.getCount > 0){
t = true;
}
else{
t = false;
}
cursor.close();
return t;
}
public void addFTag(View view) {
// Add a new tag
ContentValues values = new ContentValues();
mText = (EditText)findViewById(R.id.name);
String mFtag = mText.getText().toString();
boolean exist = check(mFtag);
if(exist == false){
values.put(FTagsContentProvider.COL_TEXT,
mFtag);
Uri uri = getContentResolver().insert(
FTagsContentProvider.CONTENT_URI, values);
Toast.makeText(getBaseContext(),
"Record inserted!", Toast.LENGTH_LONG).show();
}
else{
// code for only updating the COL_COUNT somehow
Toast.makeText(this, "Some tag meet you again :)",
Toast.LENGTH_LONG).show();
}}
public void showAllTags(View view) {
Cursor c = getContentResolver().query(FTagsContentProvider.CONTENT_URI, null, null, null, null);
String result = "Results:";
if (!c.moveToFirst()) {
Toast.makeText(this, result+" no content yet!", Toast.LENGTH_LONG).show();
}else{
do{
result = result + "\n" + c.getString(c.getColumnIndex(FTagsContentProvider.COL_TEXT)) +
" with id " + c.getString(c.getColumnIndex(FTagsContentProvider.COL_ID)) +
" has count: " + c.getString(c.getColumnIndex(FTagsContentProvider.COL_COUNT));
} while (c.moveToNext());
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
}
}
}
Any help would be much appreciated :)
I have the following method for updating only the COL_COUNT(originally set to 1) of an existing record "tag" in database:
public void addCount(){
mFtag = "tag";
String t = "2";
ContentValues values = new ContentValues();
values.put(FTagsContentProvider.COL_COUNT, t );
getContentResolver().update(FTagsContentProvider.CONTENT_URI, values, "COL_TEXT=?", new String[]{mFtag});
}
When I run it I got the following exception:
I tried changing the line
getContentResolver().update(FTagsContentProvider.CONTENT_URI, values, "COL_TEXT=?", new String[]{mFtag});
to
getContentResolver().update(FTagsContentProvider.CONTENT_URI, values, FTagsContentProvider.COL_TEXT + "=?", new String[]{mFtag});
Still same exception just change from "no such column: COL_TEXT" to "no such column: tag"
Here is the ContentProvider:
public class FTagsContentProvider extends ContentProvider {
static final String AUTHORITY = "ch.ethz.twimight.FTags";
private static final String BASE_PATH = "ftags";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + BASE_PATH);
// fields for the database
public static final String COL_ID = "id";
public static final String COL_TEXT = "text";
public static final String COL_COUNT = "count";
static final int FTAGS = 1;
static final int FTAGS_ID = 2;
DBHelper dbHelper;
private static HashMap<String, String> FTagsMap;
static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, BASE_PATH, FTAGS);
uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", FTAGS_ID);
}
// database declarations
private SQLiteDatabase database;
static final String DATABASE_NAME = "ftagtable.db";
static final String TABLE_FTAGS = "FTags";
static final int DATABASE_VERSION = 1;
private static final String TABLE_FTAGS_CREATE = "create table "
+ TABLE_FTAGS
+ "("
+ COL_ID + " integer primary key autoincrement, "
+ COL_TEXT + " text not null, "
+ COL_COUNT + " integer"
+ ");";
private static class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(TABLE_FTAGS_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
Log.w(DBHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ". Old data will be destroyed");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FTAGS);
onCreate(db);
}
}
#Override
public boolean onCreate() {
// TODO Auto-generated method stub
Context context = getContext();
dbHelper = new DBHelper(context);
database = dbHelper.getWritableDatabase();
if(database == null)
return false;
else
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(TABLE_FTAGS);
switch (uriMatcher.match(uri)) {
case FTAGS:
queryBuilder.setProjectionMap(FTagsMap);
break;
case FTAGS_ID:
queryBuilder.appendWhere( COL_ID + "=" + uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (sortOrder == null || sortOrder == ""){
sortOrder = COL_TEXT;
}
Cursor cursor = queryBuilder.query(database, projection, selection,
selectionArgs, null, null, sortOrder);
/**
* register to watch a content URI for changes
*/
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
long row = database.insert(TABLE_FTAGS, "", values);
if(row > 0) {
Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
throw new SQLException("Fail to add a new record into " + uri);
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
int rowsUpdated = 0;
switch (uriMatcher.match(uri)){
case FTAGS:
rowsUpdated = database.update(TABLE_FTAGS, values, selection, selectionArgs);
break;
case FTAGS_ID:
rowsUpdated = database.update(TABLE_FTAGS, values, COL_ID +
" = " + uri.getLastPathSegment() +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI " + uri );
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
int count = 0;
switch (uriMatcher.match(uri)){
case FTAGS:
count = database.delete(TABLE_FTAGS, selection, selectionArgs);
break;
case FTAGS_ID:
String id = uri.getLastPathSegment(); //gets the id
count = database.delete( TABLE_FTAGS, COL_ID + " = " + id +
(!TextUtils.isEmpty(selection) ? " AND (" +
selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
#Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
}
Is it a problem with the method or there is something wrong with the ContentProvider? Please help
getContentResolver().update(FTagsContentProvider.CONTENT_URI, values, FTagsContentProvider.COL_TEXT + "=?", new String[]{mFtag});
is the correct usage.
public static final String COL_TEXT = "text";
text is a reserved keyword. You can't have a column named text. Change the name of the column and you'll be fine.
When trying to add information to my SQLite database which goes to my content provider. I get this error message on my Logcat.
10-21 12:37:48.045: E/SQLiteLog(25929): (1) near "TABLECows": syntax error
I have looked all over and can't seem to find the where the mistake is. When I use the debugger it doesn't give the location of error. Can you help me see what I am missing to correct this error?
My Database.java
package ag.access.cowsdb;
import ag.access.cowsdb.provider.Cows_Provider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class Cowsdatabase extends SQLiteOpenHelper {
private ContentResolver cowcr;
public Cowsdatabase(Context context, String name, CursorFactory factory,
int version) {
super(context,DATABASE_NAME, factory, DATABASE_VERSION);
cowcr = context.getContentResolver();
}
public static final String Key_id = "_id";
public static final String Key_Cow = "Cowid";
public static final String Key_Sire = "Sire";
public static final String Key_Dam = "Dam";
public static final String Key_DOBM = "Month";
public static final String Key_DOBD = "Date";
public static final String Key_DOBY = "Year";
private static final String DATABASE_NAME = "CowsDB";
public static final String DATABASE_TABLE = "Cows";
private static final int DATABASE_VERSION = 1;
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String Create_Cows_Table = "CREATE TABLE" +
DATABASE_TABLE + "(" +
Key_id + "INTEGER PRIMARY KEY AUTOINCREMENT," +
Key_Cow + "INTEGER NOT NULL" +
Key_Sire + "TEXT NOT NULL," +
Key_Dam + "TEXT NOT NULL," +
Key_DOBM + "INTEGER NOT NULL," +
Key_DOBD + "INTEGER NOT NULL," +
Key_DOBY + "INTEGER NOT NULL," + ")";
db.execSQL(Create_Cows_Table);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXIST " + DATABASE_TABLE);
}
public void addcow(cow Cow) {
ContentValues values = new ContentValues();
values.put(Key_Cow, Cow.getCowid());
values.put(Key_Sire, Cow.getSire());
values.put(Key_Dam, Cow.getDam());
values.put(Key_DOBM, Cow.getMonth());
values.put(Key_DOBD, Cow.getDate());
values.put(Key_DOBY, Cow.getYear());
cowcr.insert(Cows_Provider.Content_Uri, values);
}
public cow findcow(int cowid) {
String[] projection = {Key_id, Key_Cow, Key_Sire, Key_Dam, Key_DOBM, Key_DOBD, Key_DOBY};
String selection = "cowid = \"" + cowid + "\"";
Cursor cursor = cowcr.query(Cows_Provider.Content_Uri, projection, selection, null, null);
cow cow = new cow();
if (cursor.moveToFirst()) {
cursor.moveToFirst();
cow.Setid(Integer.parseInt(cursor.getString(0)));
cow.SetCowid(Integer.parseInt(cursor.getString(1)));
cow.setSire(cursor.getString(2));
cow.setDam(cursor.getString(3));
cow.setMonth(Integer.parseInt(cursor.getString(4)));
cow.setDate(Integer.parseInt(cursor.getString(5)));
cow.setYear(Integer.parseInt(cursor.getString(6)));
cursor.close();
} else {
cow = null;
}
return cow;
}
public boolean deleteCow (int cowid) {
boolean result = false;
String selection = "cowid = \"" + cowid + "\"";
int rowsDeleted = cowcr.delete(Cows_Provider.Content_Uri, selection, null);
if (rowsDeleted > 0)
result = true;
return result;
}
}
My Content Provider.java
package ag.access.cowsdb.provider;
import ag.access.cowsdb.Cowsdatabase;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class Cows_Provider extends ContentProvider {
private Cowsdatabase cowsdbh;
private static final String Authority =
"ag.access.cowsdb.provider.Cows_Provider";
private static final String Cows = "Cows";
public static final Uri Content_Uri = Uri.parse("content://" + Authority + "/" + Cows);
public static final int COWS = 1;
public static final int COWS_ID = 2;
private static final UriMatcher cURIMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
static {
cURIMatcher.addURI(Authority, Cows, COWS);
cURIMatcher.addURI(Authority, Cows + "/#", COWS_ID);
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = cURIMatcher.match(uri);
SQLiteDatabase mysqldb = cowsdbh.getWritableDatabase();
int rowsDeleted = 0;
switch (uriType) {
case COWS:
rowsDeleted = mysqldb.delete(Cowsdatabase.DATABASE_TABLE, selection, selectionArgs);
break;
case COWS_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = mysqldb.delete(Cowsdatabase.DATABASE_TABLE, Cowsdatabase.Key_Cow + "=" + id, null);
} else {
rowsDeleted = mysqldb.delete(Cowsdatabase.DATABASE_TABLE, Cowsdatabase.Key_Cow + "=" + id + " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknow URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = cURIMatcher.match(uri);
SQLiteDatabase mydb = cowsdbh.getWritableDatabase();
long id = 0;
switch (uriType) {
case COWS:
id = mydb.insert(Cowsdatabase.DATABASE_TABLE, null, values);
break;
default:
throw new IllegalArgumentException("Unknow Uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(Cows + "/" + id);
}
#Override
public boolean onCreate() {
cowsdbh = new Cowsdatabase(getContext(), null, null, 1);
return false;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(Cowsdatabase.DATABASE_TABLE);
int uriType = cURIMatcher.match(uri);
switch (uriType) {
case COWS_ID:
qb.appendWhere(cowsdbh.Key_Cow + "=" + uri.getLastPathSegment());
break;
case COWS:
break;
default:
throw new IllegalArgumentException("Unknown URI");
}
Cursor cursor = qb.query(cowsdbh.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = cURIMatcher.match(uri);
SQLiteDatabase mysqldb = cowsdbh.getWritableDatabase();
int rowsUpdated = 0;
switch (uriType) {
case COWS:
rowsUpdated = mysqldb.update(Cowsdatabase.DATABASE_TABLE, values, selection, selectionArgs);
break;
case COWS_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated =
mysqldb.update(Cowsdatabase.DATABASE_TABLE, values, Cowsdatabase.Key_Cow + "=" + id, null);
} else {
rowsUpdated =
mysqldb.update(Cowsdatabase.DATABASE_TABLE, values, Cowsdatabase.Key_Cow + "=" + id + " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI:" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
#Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
}
How and where can i correct this error?
Thanks
On the first line of the onCreate method, add a space, so that it looks like this.
String Create_Cows_Table = "CREATE TABLE " +