Hi all i’m trying to figure out an insert exception in my code. Before I start i start inserting strings EditText I wanted to put in Strings of my own first. However I am getting an error from logcat. They are both of type string, there is a primary key row also set to autoincrement. Does anyone have any guidance.
database Activity
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_MODULECODE + " TEXT, " +
KEY_MODULENAME + " TEXT); "
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABEL IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
public database(Context c){
myContext = c;
}
public database openToWrite()throws SQLException{
myHelper = new DbHelper(myContext);
moduleDatabase = myHelper.getWritableDatabase();
return this;
}
public database openToRead()throws SQLException{
myHelper = new DbHelper(myContext);
moduleDatabase = myHelper.getReadableDatabase();
return this;
}
public void close(){
myHelper.close();
}
public void createEntry(String moduleCode, String moduleName) throws SQLException {
ContentValues cv = new ContentValues();
cv.put(KEY_MODULECODE,moduleCode);
cv.put(KEY_MODULENAME,moduleName);
moduleDatabase.insert(DATABASE_TABLE,null,cv);
// TODO Auto-generated method stub
}
public Cursor getData() {
String[] columns = new String [] {KEY_ROWID,KEY_MODULECODE, KEY_MODULENAME};
Cursor c = moduleDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
return c;
}
}
Main Activity
public class MyCourses extends Activity {
static final String TEST = "com.example.mycoursetimetable.TEST";
String [] MODULE;
database MODULEDATABASE;
ListView listContent;
Boolean didItWork;
Cursor cursor;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_courses);
listContent =(ListView)findViewById(R.id.list);
MODULEDATABASE = new database(MyCourses.this);
MODULEDATABASE.openToWrite();
MODULEDATABASE.createEntry("TestCode", "TestName");
MODULEDATABASE.close();
MODULEDATABASE.openToRead();
cursor = MODULEDATABASE.getData();
MODULEDATABASE.close();
listContent = (ListView)findViewById(R.id.list);
TestCursorAdapter ca = new TestCursorAdapter(this, cursor, 0);
listContent.setAdapter(ca);
}
}
CursorAdatpter
public class TestCursorAdapter extends CursorAdapter {
private LayoutInflater viewInflater;
boolean didItWork;
public TestCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
// TODO Auto-generated constructor stub
viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void bindView(View v, Context context, Cursor c)
{
TextView text_modulecode = (TextView)v.findViewById(R.id.labelModuleCode);
TextView text_modulename = (TextView)v.findViewById(R.id.labelEditModuleFull);
text_modulecode.setText(String.valueOf(c.getColumnIndex(database.KEY_MODULECODE)));
text_modulename.setText(String.valueOf(c.getColumnIndex(database.KEY_MODULENAME)));
}
@Override
public View newView(Context context, Cursor c, ViewGroup parent) {
View v = viewInflater.inflate(R.layout.listcourses, parent, false);
return v;
}
}
LogCat line 80 refers to moduleDatabase.insert(DATABASE_TABLE,null,cv);
10-21 22:42:19.812: E/Database(19591): Error inserting module_name=TestName module_code=TestCode
10-21 22:42:19.812: E/Database(19591): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:66)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1426)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1286)
10-21 22:42:19.812: E/Database(19591): at com.example.mycoursetimetable.database.createEntry(database.java:80)
10-21 22:42:19.812: E/Database(19591): at com.example.mycoursetimetable.MyCourses.onCreate(MyCourses.java:48)
10-21 22:42:19.812: E/Database(19591): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
10-21 22:42:19.812: E/Database(19591): at android.os.Handler.dispatchMessage(Handler.java:99)
10-21 22:42:19.812: E/Database(19591): at android.os.Looper.loop(Looper.java:123)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.main(ActivityThread.java:4363)
10-21 22:42:19.812: E/Database(19591): at java.lang.reflect.Method.invokeNative(Native Method)
10-21 22:42:19.812: E/Database(19591): at java.lang.reflect.Method.invoke(Method.java:521)
10-21 22:42:19.812: E/Database(19591): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
10-21 22:42:19.812: E/Database(19591): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
10-21 22:42:19.812: E/Database(19591): at dalvik.system.NativeStart.main(Native Method)
10-21 22:42:19.862: E/Cursor(19591): Invalid statement in fillWindow()
you’re getting the cursor error:
Invalid statement in fillWindow()because of a wonky database setup. you closed the database, twice in fact, and then you attached your closed database and thus inactive cursor to your listview, seems off right? Best practices usually say that you close your cursor and then your database object – in that order. Normally you can put these anywhere when you’re done querying, but a listview backed by a cursor adapter is special. The whole time that the listview is open and you’re accessing it, you need the cursor open so that the data source is available like any array object or any data container. Otherwise, you’ll get an error sayingattempting to re-open an already-closed object. So the best place to put it, imho, is in youronDestroy()method, when your listview is being eradicated anyway.Now, i have to tell you that i have some beef with you opening two instances of the database in the same activity. I might get backlash for saying this but
.getWritableDatabase()and.getReadableDatabase()really opens the same connection, they aren’t much different. It simply isn’t a good practice that you closed one connection to open another, even though it seems prudent. I’m not saying that you should delete one method from the app entirely (the getReadable), but opening both in the same activity life-cycle is fighting for peanuts. This is even more true now that we’ve just established that the cursor must be open the whole time the activity is. Well, since we’re talking about what’s necessary and not, you instantiatedlistContenttwice.Sorry for the long explanation, but i wanted to make sure the details have been made lucid.