I'm developing an app that (so far) pulls data from an API, inserts it to a local SQLite database & displays it on screen.
In order to make my life simpler, I wrote a master database adapter (MyDBAdapter) as well as adapters for each individual table, according to the top anser for this question.
While developing the app, I'm also teaching myself unit testing in JUnit (not sure if this is relevant, but I figured I'd throw it in there).
When trying to refresh the database I somehow dropped all the tables and now I can't get them back. When I increment the DB_VERSION value, onUpgrade() doesn't get called, and the app errors out because it's trying to access nonexistent tables.
What circumstances would cause onUpgrade() to not get called? I'm at my wits' end trying to figure this out.
MyDbAdapter:
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class MyDbAdapter {
public static final String TAG = "MyDbAdapter";
protected static final String DB_NAME = "mydb.db";
protected static final int DB_VERSION = 21;
private final Context context;
private DbHelper helper;
private SQLiteDatabase db;
private static final String CREATE_TABLE_CRUISE_LINES = "create table " + CruiseLineAdapter.TABLE + " (" + CruiseLineAdapter.C_ID + " integer primary key autoincrement, "
+ CruiseLineAdapter.C_NAME + " TEXT);";
private static final String CREATE_TABLE_SHIPS = "create table " + ShipAdapter.TABLE + " (" + ShipAdapter.C_ID + " integer primary key autoincrement, "
+ ShipAdapter.C_NAME + " TEXT, "
+ ShipAdapter.C_CRUISE_LINE + " integer);";
private static final String CREATE_TABLE_TABLE_UPDATES = "create table " + UpdateTimestampAdapter.TABLE + " (" + UpdateTimestampAdapter.C_ID + " integer primary key autoincrement, "
+ UpdateTimestampAdapter.C_TABLE_NAME + " TEXT, "
+ UpdateTimestampAdapter.C_LAST_UPDATE + " TEXT);";
private static final String DROP_TABLE = "drop table if exists %s";
private static final String DROP_TABLE_CRUISE_LINES = String.format(DROP_TABLE, CruiseLineAdapter.TABLE);
private static final String DROP_TABLE_SHIPS = String.format(DROP_TABLE, ShipAdapter.TABLE);
private static final String DROP_TABLE_TABLE_UPDATES = String.format(DROP_TABLE, UpdateTimestampAdapter.TABLE);
public MyDbAdapter (Context context) {
this.context = context;
helper = new DbHelper(this.context);
}
private static class DbHelper extends SQLiteOpenHelper {
DbHelper (Context context) {
super(context, DB_NAME, null, DB_VERSION);
Log.i(TAG, "initialized");
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Database created: version " + DB_VERSION);
db.execSQL(CREATE_TABLE_CRUISE_LINES);
db.execSQL(CREATE_TABLE_SHIPS);
db.execSQL(CREATE_TABLE_TABLE_UPDATES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database upgraded to " + DB_VERSION);
db.execSQL(DROP_TABLE_CRUISE_LINES);
db.execSQL(DROP_TABLE_SHIPS);
db.execSQL(DROP_TABLE_TABLE_UPDATES);
this.onCreate(db);
}
}
public MyDbAdapter open() throws SQLException {
db = helper.getWritableDatabase();
return this;
}
public void close() {
helper.close();
}
}
ShipAdapter:
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
public class ShipAdapter {
public static final String TAG = "ShipAdapter";
public static final String TABLE = "ships";
public static final String C_ID = BaseColumns._ID;
public static final String C_NAME = "name";
public static final String C_CRUISE_LINE = "cruise_line";
private DbHelper dbHelper;
private SQLiteDatabase db;
private final Context context;
private static class DbHelper extends SQLiteOpenHelper {
DbHelper (Context context) {
super(context, MyDbAdapter.DB_NAME, null, MyDbAdapter.DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public ShipAdapter(Context context) {
this.context = context;
}
public ShipAdapter open() throws SQLException {
dbHelper = new DbHelper(context);
db = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
public long createShip(String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insert(TABLE, null, initialValues);
}
public long createShip(long id, String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_ID, id);
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insert(TABLE, null, initialValues);
}
public long createShip(ShipModel ship) {
return createShip(ship.getName(), ship.getCruiseLineId());
}
public long insertOrIgnoreShip(long id, String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_ID, id);
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insertWithOnConflict(TABLE, null, initialValues, SQLiteDatabase.CONFLICT_IGNORE);
}
public long insertOrIgnoreShip(ShipModel ship) {
return insertOrIgnoreShip(ship.getId(), ship.getName(), ship.getCruiseLineId());
}
public List<ShipModel> getAllShips() {
List<ShipModel> ships = new ArrayList<ShipModel>();
Cursor cursor = getAllShipsCursor();
if (cursor.getCount() > 0) {
while(!cursor.isAfterLast()) {
ships.add(cursorToShip(cursor));
cursor.moveToNext();
}
}
return ships;
}
public Cursor getAllShipsCursor() {
Cursor cursor = db.query(TABLE, null, null, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public ShipModel getShip(long id) {
Cursor cursor = getShipCursor(id);
if (cursor.getCount() > 0) {
return cursorToShip(cursor);
}
return null;
}
public Cursor getShipCursor(long id) {
Cursor cursor = db.query(TABLE, null, C_ID + " = ?", new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public ShipModel getShip(String name) {
Cursor cursor = getShipCursor(name);
if (cursor.getCount() > 0) {
return cursorToShip(cursor);
}
return null;
}
public Cursor getShipCursor(String name) {
Cursor cursor = db.query(TABLE, null, C_NAME + " = ?", new String[] { name }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public List<ShipModel> getShipsByCruiseLine(long cruise_line_id) {
List<ShipModel> ships = new ArrayList<ShipModel>();
Cursor cursor = getShipsCursorByCruiseLine(cruise_line_id);
if (cursor.getCount() > 0) {
while (!cursor.isAfterLast()) {
ships.add(cursorToShip(cursor));
cursor.moveToNext();
}
}
return ships;
}
public Cursor getShipsCursorByCruiseLine(long cruise_line_id) {
Cursor cursor = db.query(TABLE, null, C_CRUISE_LINE + " = ?", new String[] { String.valueOf(cruise_line_id) }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public boolean updateShip(long id, String name, long cruise_line_id) {
ContentValues args = new ContentValues();
args.put(C_NAME, name);
args.put(C_CRUISE_LINE, cruise_line_id);
return db.update(TABLE, args, C_ID + " = ?", new String[] { String.valueOf(id) }) > 0;
}
public boolean updateShip(ShipModel ship) {
return updateShip(ship.getId(), ship.getName(), ship.getCruiseLineId());
}
public boolean deleteShip(long id) {
return db.delete(TABLE, C_ID + " = ?", new String[] { String.valueOf(id) }) > 0;
}
public boolean deleteShip(String name) {
return db.delete(TABLE, C_NAME + " = ?", new String[] { name }) > 0;
}
public boolean deleteShip(ShipModel ship) {
return deleteShip(ship.getName());
}
public boolean deleteAll() {
return db.delete(TABLE, null, null) > 0;
}
private ShipModel cursorToShip(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndex(C_ID));
String name = cursor.getString(cursor.getColumnIndex(C_NAME));
long cruise_line_id = cursor.getLong(cursor.getColumnIndex(C_CRUISE_LINE));
return new ShipModel(id, name, cruise_line_id);
}
}
Communicator:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NoHttpResponseException;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Created by mcampo on 5/30/13.
*/
public class Communicator {
private static final String TAG = "Communicator";
private static final int CONNECTION_TIMEOUT = 10000;
protected String base_url = "http://[myapi]/mobileapi/";
protected Context context;
protected CruiseLineAdapter cruise_line_adapter;
protected ShipAdapter ship_adapter;
protected UpdateTimestampAdapter table_update_adapter;
protected String update_timestamps_json;
public Communicator() {
}
public Communicator (Context context) {
this.context = context;
this.cruise_line_adapter = new CruiseLineAdapter(this.context);
this.ship_adapter = new ShipAdapter(this.context);
this.table_update_adapter = new UpdateTimestampAdapter(this.context);
}
// begin defining getters / setters
/**
*
* #param context
*/
public void setContext(Context context) {
this.context = context;
this.cruise_line_adapter = new CruiseLineAdapter(this.context);
this.ship_adapter = new ShipAdapter(this.context);
this.table_update_adapter = new UpdateTimestampAdapter(this.context);
}
public Context getContext() {
return this.context;
}
// end getters / setters
private boolean isNetworkConnected() {
if (context == null) {
return false;
}
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null;
}
private String makeApiCall(String api_extension) throws IOException {
if (!isNetworkConnected()) {
throw new IOException("Your device is not connected to the internet. Please enable your network connection and restart CabinGuru.");
}
Log.d(TAG, "Making HTTP request to " + this.base_url + api_extension);
HttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, CONNECTION_TIMEOUT);
HttpResponse response = httpClient.execute(new HttpGet(this.base_url + api_extension));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
Log.i(TAG, "HTTP Response: " + out.toString());
return out.toString();
} else {
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
}
private boolean tableIsUpToDate(String table) throws IOException {
try {
String api_timestamp = getApiUpdateTimestamp(table);
String device_timestamp = getDeviceUpdateTimestamp(table);
if (device_timestamp == null || device_timestamp.equals("")) {
throw new NullPointerException("device_timestamp is null");
}
Log.i(TAG, "API Timestamp: " + api_timestamp);
Log.i(TAG, "Device Timestamp: " + device_timestamp);
// compare device_timestamp to api_timestamp. If device_timestamp comes after api_timestamp, table is up-to-date.
DateTime api_datetime = this.strToDateTime(api_timestamp);
DateTime device_datetime = this.strToDateTime(device_timestamp);
return device_datetime.isAfter(api_datetime);
} catch (NullPointerException e) {
e.printStackTrace();
Log.e(TAG, "NullPointerException encountered in tableIsUpToDate(" + table + "): " + e.getMessage() + " " + e.getCause());
return false;
}
}
private String getDeviceUpdateTimestamp(String table) {
String return_string = "";
table_update_adapter.open();
UpdateTimestampModel timestamp = this.table_update_adapter.getUpdateTimestamp(table);
table_update_adapter.close();
try {
return_string = timestamp.getLastUpdate();
return return_string;
} catch (NullPointerException e) {
Log.e(TAG, "NullPointerException encountered in getDeviceUpdateTimestamp(" + table + "): " + e.getMessage());
return "";
}
}
private boolean updateLastUpdateTimestamp(String table) {
// set up current timestamp
DateTime timestamp = new DateTime(System.currentTimeMillis());
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
String now = formatter.print(timestamp);
// fetch ID of row to update
table_update_adapter.open();
table_update_adapter.updateOrCreateTimestamp(table, now);
table_update_adapter.close();
return true;
}
private void getApiUpdateTimestamps() throws IOException {
if (this.update_timestamps_json == null || this.update_timestamps_json.equals(""))
try {
this.update_timestamps_json = this.makeApiCall("get_update_timestamps");
} catch (NoHttpResponseException e) {
Log.e(TAG, "App was unable to connect to the servers.");
}
}
private String getApiUpdateTimestamp(String table) throws IOException {
this.getApiUpdateTimestamps();
try {
if (this.update_timestamps_json == null) {
throw new Exception("Could not fetch update timestamps. Check and make sure you are able to connect to " + this.base_url + ".");
}
JSONObject timestamps = new JSONObject(this.update_timestamps_json);
return timestamps.getString(table);
} catch (JSONException e) {
Log.e(TAG, "An error occurred when extracting update timestamps from the api: " + e.getMessage() + " | " + e.getCause());
return null;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return null;
}
}
public boolean updateCruiseLines() throws IOException {
// if the cruise lines from the API have been updated since the last update on the device, update the device.
if (!this.tableIsUpToDate(CruiseLineAdapter.TABLE)) {
Log.i(TAG, "Attempting API call for Cruise Lines.");
try {
String cruise_line_json = this.makeApiCall("cruise_lines");
JSONArray cruise_lines = new JSONArray(cruise_line_json);
// loop through cruise_lines, add to database
int array_size = cruise_lines.length();
cruise_line_adapter.open();
for (int i = 0; i < array_size; i++) {
JSONObject cruise_line = cruise_lines.getJSONObject(i);
int cruise_line_id = cruise_line.getInt("CruiseLineID");
String cruise_line_name = cruise_line.getString("Name");
// insert record into database.
this.cruise_line_adapter.insertOrIgnoreCruiseLine(cruise_line_id, cruise_line_name);
}
cruise_line_adapter.close();
this.updateLastUpdateTimestamp(CruiseLineAdapter.TABLE);
} catch (JSONException e) {
Log.e(TAG, "JSONException encountered in updateCruiseLines(): " + e.getMessage());
e.printStackTrace();
return false;
}
} else {
Log.i(TAG, "Cruise Line records exist. No API call necessary.");
}
return true;
}
public boolean updateShips() throws IOException {
// if the ships from the API have been updated since the last update on the device, update the device
if (!this.tableIsUpToDate(ShipAdapter.TABLE)) {
Log.i(TAG, "Attempting API call for Ships.");
try {
String ships_json = this.makeApiCall("ships");
JSONArray ships = new JSONArray(ships_json);
// loop through ships, add to database
int array_size = ships.length();
ship_adapter.open();
for (int i = 0; i < array_size; i++) {
JSONObject ship = ships.getJSONObject(i);
int id = ship.getInt("ShipID");
String name = ship.getString("ShipName");
int cruise_line_id = ship.getInt("CruiseLineID");
this.ship_adapter.insertOrIgnoreShip(id, name, cruise_line_id);
}
ship_adapter.close();
this.updateLastUpdateTimestamp(ShipAdapter.TABLE);
} catch (JSONException e) {
Log.e(TAG, "JSONException encountered in updateShips():" + e.getMessage());
e.printStackTrace();
return false;
}
} else {
Log.i(TAG, "Ship records exist. No API call necessary.");
}
return true;
}
private DateTime strToDateTime(String timestamp) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
return formatter.parseDateTime(timestamp);
}
}
Android would not be able to figure out that it needs to run MyDbAdapter on its own.
Create a class that extends Application.
public class MyApplication extends Application {
private static MyDbAdapter dbAdapter;
#Override
public void onCreate() {
super.onCreate();
dbAdapter = new MyDbAdapter(getApplicationContext());
}
}
On your AndroidManifest.xml, you need to set the attribute in the application element like this:
<application
android:name=".MyApplication"
...
/application>
After stepping away from the problem for a few hours I came up with this solution:
Instead of making the *Adapter classes independent of one another, I modified the code to make them children of MyDBAdapter. This way, when open() is called, it calls the open() method of MyDBAdapter, checking the DB version & upgrading when appropriate.
MyDbAdapter:
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class MyDbAdapter {
public static final String TAG = "MyDbAdapter";
protected static final String DB_NAME = "mydb.db";
protected static final int DB_VERSION = 21;
private final Context context;
private DbHelper helper;
private SQLiteDatabase db;
private static final String CREATE_TABLE_CRUISE_LINES = "create table " + CruiseLineAdapter.TABLE + " (" + CruiseLineAdapter.C_ID + " integer primary key autoincrement, "
+ CruiseLineAdapter.C_NAME + " TEXT);";
private static final String CREATE_TABLE_SHIPS = "create table " + ShipAdapter.TABLE + " (" + ShipAdapter.C_ID + " integer primary key autoincrement, "
+ ShipAdapter.C_NAME + " TEXT, "
+ ShipAdapter.C_CRUISE_LINE + " integer);";
private static final String CREATE_TABLE_TABLE_UPDATES = "create table " + UpdateTimestampAdapter.TABLE + " (" + UpdateTimestampAdapter.C_ID + " integer primary key autoincrement, "
+ UpdateTimestampAdapter.C_TABLE_NAME + " TEXT, "
+ UpdateTimestampAdapter.C_LAST_UPDATE + " TEXT);";
private static final String DROP_TABLE = "drop table if exists %s";
private static final String DROP_TABLE_CRUISE_LINES = String.format(DROP_TABLE, CruiseLineAdapter.TABLE);
private static final String DROP_TABLE_SHIPS = String.format(DROP_TABLE, ShipAdapter.TABLE);
private static final String DROP_TABLE_TABLE_UPDATES = String.format(DROP_TABLE, UpdateTimestampAdapter.TABLE);
public MyDbAdapter (Context context) {
this.context = context;
helper = new DbHelper(this.context);
}
private static class DbHelper extends SQLiteOpenHelper {
DbHelper (Context context) {
super(context, DB_NAME, null, DB_VERSION);
Log.i(TAG, "initialized");
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Database created: version " + DB_VERSION);
db.execSQL(CREATE_TABLE_CRUISE_LINES);
db.execSQL(CREATE_TABLE_SHIPS);
db.execSQL(CREATE_TABLE_TABLE_UPDATES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database upgraded to " + DB_VERSION);
db.execSQL(DROP_TABLE_CRUISE_LINES);
db.execSQL(DROP_TABLE_SHIPS);
db.execSQL(DROP_TABLE_TABLE_UPDATES);
this.onCreate(db);
}
}
public MyDbAdapter open() throws SQLException {
db = helper.getWritableDatabase();
return this;
}
public void close() {
helper.close();
}
}
ShipAdapter:
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
public class ShipAdapter extends MyDbAdapter {
public static final String TAG = "ShipAdapter";
public static final String TABLE = "ships";
public static final String C_ID = BaseColumns._ID;
public static final String C_NAME = "name";
public static final String C_CRUISE_LINE = "cruise_line";
public ShipAdapter(Context context) {
this.context = context;
}
public long createShip(String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insert(TABLE, null, initialValues);
}
public long createShip(long id, String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_ID, id);
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insert(TABLE, null, initialValues);
}
public long createShip(ShipModel ship) {
return createShip(ship.getName(), ship.getCruiseLineId());
}
public long insertOrIgnoreShip(long id, String name, long cruise_line_id) {
ContentValues initialValues = new ContentValues();
initialValues.put(C_ID, id);
initialValues.put(C_NAME, name);
initialValues.put(C_CRUISE_LINE, cruise_line_id);
return db.insertWithOnConflict(TABLE, null, initialValues, SQLiteDatabase.CONFLICT_IGNORE);
}
public long insertOrIgnoreShip(ShipModel ship) {
return insertOrIgnoreShip(ship.getId(), ship.getName(), ship.getCruiseLineId());
}
public List<ShipModel> getAllShips() {
List<ShipModel> ships = new ArrayList<ShipModel>();
Cursor cursor = getAllShipsCursor();
if (cursor.getCount() > 0) {
while(!cursor.isAfterLast()) {
ships.add(cursorToShip(cursor));
cursor.moveToNext();
}
}
return ships;
}
public Cursor getAllShipsCursor() {
Cursor cursor = db.query(TABLE, null, null, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public ShipModel getShip(long id) {
Cursor cursor = getShipCursor(id);
if (cursor.getCount() > 0) {
return cursorToShip(cursor);
}
return null;
}
public Cursor getShipCursor(long id) {
Cursor cursor = db.query(TABLE, null, C_ID + " = ?", new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public ShipModel getShip(String name) {
Cursor cursor = getShipCursor(name);
if (cursor.getCount() > 0) {
return cursorToShip(cursor);
}
return null;
}
public Cursor getShipCursor(String name) {
Cursor cursor = db.query(TABLE, null, C_NAME + " = ?", new String[] { name }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public List<ShipModel> getShipsByCruiseLine(long cruise_line_id) {
List<ShipModel> ships = new ArrayList<ShipModel>();
Cursor cursor = getShipsCursorByCruiseLine(cruise_line_id);
if (cursor.getCount() > 0) {
while (!cursor.isAfterLast()) {
ships.add(cursorToShip(cursor));
cursor.moveToNext();
}
}
return ships;
}
public Cursor getShipsCursorByCruiseLine(long cruise_line_id) {
Cursor cursor = db.query(TABLE, null, C_CRUISE_LINE + " = ?", new String[] { String.valueOf(cruise_line_id) }, null, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
}
return cursor;
}
public boolean updateShip(long id, String name, long cruise_line_id) {
ContentValues args = new ContentValues();
args.put(C_NAME, name);
args.put(C_CRUISE_LINE, cruise_line_id);
return db.update(TABLE, args, C_ID + " = ?", new String[] { String.valueOf(id) }) > 0;
}
public boolean updateShip(ShipModel ship) {
return updateShip(ship.getId(), ship.getName(), ship.getCruiseLineId());
}
public boolean deleteShip(long id) {
return db.delete(TABLE, C_ID + " = ?", new String[] { String.valueOf(id) }) > 0;
}
public boolean deleteShip(String name) {
return db.delete(TABLE, C_NAME + " = ?", new String[] { name }) > 0;
}
public boolean deleteShip(ShipModel ship) {
return deleteShip(ship.getName());
}
public boolean deleteAll() {
return db.delete(TABLE, null, null) > 0;
}
private ShipModel cursorToShip(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndex(C_ID));
String name = cursor.getString(cursor.getColumnIndex(C_NAME));
long cruise_line_id = cursor.getLong(cursor.getColumnIndex(C_CRUISE_LINE));
return new ShipModel(id, name, cruise_line_id);
}
}
Related
I have already checked the other XML files for errors, however this is the file that the error message is saying the error is in. There is also a message that pops up whenever I try to run the app that says, "Files under the build folder are generated and should not be edited".
package com.example.drive.drivercorder;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
private static final String TAG = "DBAdapter";
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
public static final String KEY_DRIVETIME = "Drive Time";
public static final String KEY_NIGHTORDAY = "Time of Day";
public static final int COL_DRIVETIME = 1;
public static final int COL_NIGHTORDAY = 2;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_DRIVETIME, KEY_NIGHTORDAY, };
public static final String DATABASE_NAME = "MyDb";
public static final String DATABASE_TABLE = "mainTable";
public static final int DATABASE_VERSION = 2;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_DRIVETIME + " integer not null, "
+ KEY_NIGHTORDAY + " text not null "
+ ");";
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
public void close() {
myDBHelper.close();
}
public long insertRow(int drivetime, String nightorday) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_DRIVETIME, Drive Time);
initialValues.put(KEY_NIGHTORDAY, Time of Day);
return db.insert(DATABASE_TABLE, null, initialValues);
}
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
public boolean updateRow(long rowId, String drivetime, String nightorday) {
String where = KEY_ROWID + "=" + rowId;
ContentValues newValues = new ContentValues();
newValues.put(KEY_DRIVETIME, Drive Time);
newValues.put(KEY_NIGHTORDAY, Time of Day);
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(_db);
}
}
}
There is also a message that pops up whenever I try to run the app that says, "Files under the build folder are generated and should not be edited".
I think you are changing the .class file in debug/DDMS mode or something like that. Please check and make sure to edit your .java file instead.
Posting your relevant logcat messages and also the XML file in question might help understand the problem.
Heyhey :)
I looked at several Questions to the same topic, but I found no solution to my problem.
A NullPointerException at this.getReadableDatabase(); appears...
Here's my Code:
public class DatabaseHandler extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "TODO_APP";
/*--------------------------- TABLE ITEMS START ---------------------------*/
private static final String TABLE_ITEMS = "items";
private static String KEY_ID_ITEMS = "id_items";
private static final String KEY_CATEGORY_ITEMS = "category";
private static final String KEY_DATETIME_ITEMS = "datetime";
private static String KEY_NAME_ITEMS = "name";
private static final String KEY_DESCRIPTION_ITEMS = "description";
private static final String KEY_ALARM_ITEMS = "alarm";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// create table ITEMS
String CREATE_ITEMS_TABLE = "CREATE TABLE " + TABLE_ITEMS + "("
+ KEY_ID_ITEMS + " INTEGER PRIMARY KEY," + KEY_CATEGORY_ITEMS
+ " INTEGER," + KEY_DATETIME_ITEMS
+ " TIMESTAMP DEFAULT CURRENT_TIMESTAMP," + KEY_NAME_ITEMS
+ " TEXT," + KEY_DESCRIPTION_ITEMS + " TEXT," + KEY_ALARM_ITEMS
+ " INTEGER" + ");";
db.execSQL(CREATE_ITEMS_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ITEMS);
// Create tables again
this.onCreate(db);
}
public void addItem(DB_Item item) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_CATEGORY_ITEMS, item.getCategory());
values.put(KEY_NAME_ITEMS, item.getName());
values.put(KEY_DESCRIPTION_ITEMS, item.getDescription());
values.put(KEY_ALARM_ITEMS, item.getAlarm());
// Inserting Row
db.insert(TABLE_ITEMS, null, values);
db.close(); // Closing database connection
}
public DB_Item getItem(String name) {
//!!!!! Here is one problem !!!!!
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_ITEMS, new String[] { KEY_ID_ITEMS,
KEY_CATEGORY_ITEMS, KEY_DATETIME_ITEMS, KEY_NAME_ITEMS,
KEY_DESCRIPTION_ITEMS, KEY_ALARM_ITEMS },
KEY_NAME_ITEMS = " = ?", new String[] { String.valueOf(name) },
null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
// DB_Item (int category, String name, String description, int
// alarm)
DB_Item item = new DB_Item(cursor.getInt(1), cursor.getString(3),
cursor.getString(4), cursor.getInt(5));
return item;
}
public List<DB_Item> getAllItems() {
List<DB_Item> itemList = new ArrayList<DB_Item>();
// SELECT ALL
String selectQuery = "SELECT * FROM " + TABLE_ITEMS;
//!!!!!!!!!! here is the other Problem
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
// go through all rows and then adding to list
if (cursor.moveToFirst()) {
do {
DB_Item item = new DB_Item();
item.setCategory(Integer.parseInt(cursor.getString(0)));
// TODO
// adding to list
itemList.add(item);
} while (cursor.moveToNext());
}
return itemList;
}
[and so on, didn't copy the whole code]
Hope you can help me...
The error appears definitely at SQLiteDatabase db = this.getReadableDatabase();
Output:
09-03 08:34:17.863: E/AndroidRuntime(7074): java.lang.RuntimeException: Unable to start activity ComponentInfo{todo.todo_list/todo.view.StartApp}: java.lang.NullPointerException
09-03 08:34:17.863: E/AndroidRuntime(7074): at todo.database.DatabaseHandler.getAllItems(DatabaseHandler.java:144)
09-03 08:34:17.863: E/AndroidRuntime(7074): at todo.helper.SortItems.sortItemsCategory(SortItems.java:16)
09-03 08:34:17.863: E/AndroidRuntime(7074): at todo.view.StartApp.onCreate(StartApp.java:36)
chnage you class to something like this:
package com.mhp.example;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
/*--------------------------- TABLE ITEMS START ---------------------------*/
private static final String TABLE_ITEMS = "items";
private static String KEY_ID_ITEMS = "id_items";
private static final String KEY_CATEGORY_ITEMS = "category";
private static final String KEY_DATETIME_ITEMS = "datetime";
private static String KEY_NAME_ITEMS = "name";
private static final String KEY_DESCRIPTION_ITEMS = "description";
private static final String KEY_ALARM_ITEMS = "alarm";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "dbname";
private static final int DATABASE_VERSION = 1;
tring CREATE_ITEMS_TABLE = "CREATE TABLE " + TABLE_ITEMS + "("
+ KEY_ID_ITEMS + " INTEGER PRIMARY KEY," + KEY_CATEGORY_ITEMS
+ " INTEGER," + KEY_DATETIME_ITEMS
+ " TIMESTAMP DEFAULT CURRENT_TIMESTAMP," + KEY_NAME_ITEMS
+ " TEXT," + KEY_DESCRIPTION_ITEMS + " TEXT," + KEY_ALARM_ITEMS
+ " INTEGER" + ");";
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
try {
db.execSQL(CREATE_ITEMS_TABLE);
} catch (SQLException e) {
e.printStackTrace();
}
}
#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 contacts");
onCreate(db);
}
}
//---opens the database---
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
public void addItem(DB_Item item) {
ContentValues values = new ContentValues();
values.put(KEY_CATEGORY_ITEMS, item.getCategory());
values.put(KEY_NAME_ITEMS, item.getName());
values.put(KEY_DESCRIPTION_ITEMS, item.getDescription());
values.put(KEY_ALARM_ITEMS, item.getAlarm());
// Inserting Row
db.insert(TABLE_ITEMS, null, values);
}
public DB_Item getItem(String name) {
Cursor cursor = db.query(TABLE_ITEMS, new String[] { KEY_ID_ITEMS,
KEY_CATEGORY_ITEMS, KEY_DATETIME_ITEMS, KEY_NAME_ITEMS,
KEY_DESCRIPTION_ITEMS, KEY_ALARM_ITEMS },
KEY_NAME_ITEMS = " = ?", new String[] { String.valueOf(name) },
null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
// DB_Item (int category, String name, String description, int
// alarm)
DB_Item item = new DB_Item(cursor.getInt(1), cursor.getString(3),
cursor.getString(4), cursor.getInt(5));
return item;
}
public List<DB_Item> getAllItems() {
List<DB_Item> itemList = new ArrayList<DB_Item>();
// SELECT ALL
String selectQuery = "SELECT * FROM " + TABLE_ITEMS;
Cursor cursor = db.rawQuery(selectQuery, null);
// go through all rows and then adding to list
if (cursor.moveToFirst()) {
do {
DB_Item item = new DB_Item();
item.setCategory(Integer.parseInt(cursor.getString(0)));
// TODO
// adding to list
itemList.add(item);
} while (cursor.moveToNext());
}
return itemList;
}
}
NOTE: when you create object from DBAdapter,you should open() db and after your work close() it.
DBAdapter db = new DBAdapter(contex);
db.open();
//do you work
db.close();
Just use getReadableDatabase() without this.
I am using sqlite database in my android application. I am pre-creating the database in the databases folder in android. The databases is created and works fine in the emulator but when I run the same code in my phone I get errors.
Here is the code on how I pre-create the database in the databases folder.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SavingData.mainActivity = this;
try {
String destPath = "/data/data/" + getPackageName() + "/databases";
File f = new File(destPath);
if (!f.exists()) {
f.mkdirs();
f.createNewFile();
// ---copy the db from the assets folder into
// the databases folder---
CopyDB(getBaseContext().getAssets().open("exercisedatedb"),
new FileOutputStream(destPath + "/ExerciseDateDB"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void CopyDB(InputStream inputStream, OutputStream outputStream)
throws IOException {
// ---copy 1K bytes at a time---
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
}
Here is the errors I get:
04-01 12:51:12.503: E/SQLiteLog(26823): (1) no such column: date
04-01 12:51:12.503: D/AndroidRuntime(26823): Shutting down VM
04-01 12:51:12.503: W/dalvikvm(26823): threadid=1: thread exiting with uncaught exception (group=0x40f722a0)
04-01 12:51:12.508: E/AndroidRuntime(26823): FATAL EXCEPTION: main
04-01 12:51:12.508: E/AndroidRuntime(26823): android.database.sqlite.SQLiteException: no such column: date (code 1): , while compiling: SELECT id, date FROM dates
04-01 12:51:12.508: E/AndroidRuntime(26823): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
04-01 12:51:12.508: E/AndroidRuntime(26823): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1013)
04-01 12:51:12.508: E/AndroidRuntime(26823): at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:624)
Here is how I insert data to database:
public void insertDate(String date) {
// TODO Auto-generated method stub
db.open();
long id = db.insertDate(date);
db.close();
}
Here is my DBAdapter class:
public class DBAdapter {
static final String KEY_ROWID = "id";
static final String KEY_DATE = "date";
static final String TAG = "DBAdapter";
static final String DATABASE_NAME = "ExerciseDateDB";
static final String DATABASE_TABLE = "dates";
static final int DATABASE_VERSION = 1;
static final String DATABASE_CREATE = "create table dates (id integer primary key autoincrement, "
+ "date text not null);";
final Context context;
DatabaseHelper DBHelper;
SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(DATABASE_CREATE);
} catch (SQLException e) {
e.printStackTrace();
}
}
#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 contacts");
onCreate(db);
}
}
// ---opens the database---
public DBAdapter open() throws SQLException {
db = DBHelper.getWritableDatabase();
return this;
}
// ---closes the database---
public void close() {
DBHelper.close();
}
// ---insert a Date into the database---
public long insertDate(String date) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_DATE, date);
return db.insert(DATABASE_TABLE, null, initialValues);
}
// ---deletes a particular date---
public boolean deleteDate(long rowId) {
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
// ---retrieves all the score---
public Cursor getAllDate() {
return db.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_DATE}, null, null, null, null, null);
}
// ---retrieves a particular score---
public Cursor getDate(long rowId) throws SQLException {
Cursor mCursor = db.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID, KEY_DATE}, KEY_ROWID + "= " + rowId + "",
null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
// ---updates a score---
public boolean updateDate(long rowId, String date) {
ContentValues args = new ContentValues();
args.put(KEY_DATE, date);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
}
This is my database solution. It is all contained in one class.
Too call it the syntax is...
DatabaseManager mDatabase = DatabaseManager.getInstance();
public class DatabaseManager {
private static DatabaseManager instance;
private final String DB_NAME = "singoff_database";
private final int DB_VERSION = 1;
private final String GAME_TABLE_NAME = "game_table";
private final String GAME_ID = "gameid";
private final String GAME_OPPONENT_ID = "opponent";
private final String GAME_TRACK = "track";
private final String GAME_FILE_PATH = "filepath";
private final String GAME_PICTURE = "picture";
private final String GAME_GUESSES = "guesses";
private final String GAME_DATE = "date";
private SQLiteDatabase mDb;
private Context context;
private DatabaseManager(Context context) {
this.context = context;
//create new or open database
DatabaseHelper helper = new DatabaseHelper(context);
this.mDb = helper.getWritableDatabase();
}
public synchronized static DatabaseManager getInstance() {
if (instance == null) {
Context context = Main.getInstance();
instance = new DatabaseManager(context);
}
return instance;
}
//__________________________________________________________________________________________//
//GAME LIST HANDLING STATEMENTS
public synchronized void addGame(String gID, String oID, String track,
String path, byte[] thumb, String datetime) {
ContentValues values = new ContentValues();
values.put(GAME_ID, gID);
values.put(GAME_OPPONENT_ID, oID);
values.put(GAME_TRACK, track);
values.put(GAME_FILE_PATH, path);
values.put(GAME_PICTURE, thumb);
values.put(GAME_DATE, datetime);
mDb.insert(GAME_TABLE_NAME, null, values);
}
public synchronized List<File> getGames() {
List<File> games = new ArrayList<File>();
Cursor cursor;
cursor = mDb.query(
GAME_TABLE_NAME,
new String[]{GAME_FILE_PATH},
null, null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
do {
File file = new File(cursor.getString(0));
games.add(file);
} while (cursor.moveToNext());
}
cursor.close();
return games;
}
public synchronized Game getGame(String filepath) {
Cursor cursor;
//Game game = null;
Bitmap picture = null;
byte[] blob;
cursor = mDb.query(
GAME_TABLE_NAME,
new String[]{
GAME_OPPONENT_ID,
GAME_FILE_PATH,
GAME_PICTURE,
GAME_DATE},
GAME_FILE_PATH + "=?",
new String[]{filepath},
null, null, null);
if (cursor.moveToNext()) {
blob = cursor.getBlob(2);
if (blob != null) {
picture = BitmapFactory.decodeByteArray(blob, 0, blob.length);
}
//game = new Game(mContext, new File(filepath), cursor.getString(0), picture);
}
return null;
}
public void updateGame(String filepath, gameColumn col,
Object object) {
ContentValues values = new ContentValues();
switch (col) {
case GAME_PICTURE:
Bitmap picture = (Bitmap) object;
ByteArrayOutputStream out = new ByteArrayOutputStream();
picture.compress(Bitmap.CompressFormat.PNG, 100, out);
values.put(GAME_PICTURE, out.toByteArray());
break;
default:
return;
}
mDb.update(GAME_TABLE_NAME, values, GAME_FILE_PATH + "=?", new String[]{filepath});
}
public synchronized void removeGame(String filepath) {
mDb.delete(GAME_TABLE_NAME, GAME_FILE_PATH + "=?", new String[]{filepath});
}
public enum gameColumn {
GAME_TABLE_NAME, GAME_OPPONENT_ID, GAME_FILE_PATH,
GAME_PICTURE, GAME_DATE
}
//__________________________________________________________________________________________//
//--------------------------------------------------------------------------------------------------
private class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String createGameTableQuery = " CREATE TABLE IF NOT EXISTS "
+ GAME_TABLE_NAME + " ("
+ GAME_ID + " INTEGER, "
+ GAME_OPPONENT_ID + " VARCHAR(20), "
+ GAME_TRACK + " VARCHAR(30), "
+ GAME_FILE_PATH + " VARCHAR(50), "
+ GAME_PICTURE + " BLOB, "
+ GAME_GUESSES + " VARCHAR, "
+ GAME_DATE + " VARCHAR(50)"
+ ");";
//create game table
db.execSQL(createGameTableQuery);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//TODO
}
}
}
Create a Database Object :
public class Database extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "Exampe.db";
private static final int DATABASE_VERSION = 1;
public static final String ID = "_id";
public static final String NAME = "name";
public static final String UUID = "uuid";
public static final String TABLE_NAME = "Example Something";
private static final String DATABASE_CREATE = "create table "
+ TABLE_NAME + "( " + ID
+ " integer primary key autoincrement, " + NAME
+ " text not null, " + UUID
+ " text not null);";
public Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(Database.class.getName(), "Upgrading database from version " + oldVersion + "to " + newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
}
}
Now where you call it
private SQLiteDatabase database;
private Database dbHelper;
private String[] allColumns = { Database.ID, Database.NAME};
public String ExampleSaveName(String name) {
database = dbHelper.getReadableDatabase();
ContentValues values = new ContentValues();
values.put("name", name);
values.put("uuid", uuid);
long insertId = database.insert(Database.TABLE_NAME, null, values);
Cursor cursor = database.query(Database.TABLE_NAME, allColumns, Database.ID + " = " + insertId, null,null, null, null);
cursor.moveToFirst();
return cursorToName(cursor);
}
}
The problem was solved by uninstalling the application from my device.
I have the following code,but i'm having some trouble with duplicates.How can i modify the code so that it won't allow duplicates in the database ? I'm using it to power an AutoCompleteTextView so the duplicates aren't helping.
Thanks a lot !
package com.giantflyingsaucer;
import android.database.*;
import android.database.sqlite.*;
import android.content.ContentValues;
import android.content.Context;
import android.util.Log;
public class SQLiteCountryAssistant extends SQLiteOpenHelper
{
private static final String DB_NAME = "usingsqlite.db";
private static final int DB_VERSION_NUMBER = 1;
private static final String DB_TABLE_NAME = "countries";
private static final String DB_COLUMN_1_NAME = "country_name";
private static final String DB_CREATE_SCRIPT = "create table " + DB_TABLE_NAME +
" (_id integer primary key autoincrement, country_name text not null);)";
private SQLiteDatabase sqliteDBInstance = null;
public SQLiteCountryAssistant(Context context)
{
super(context, DB_NAME, null, DB_VERSION_NUMBER);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// TODO: Implement onUpgrade
}
#Override
public void onCreate(SQLiteDatabase sqliteDBInstance)
{
Log.i("onCreate", "Creating the database...");
sqliteDBInstance.execSQL(DB_CREATE_SCRIPT);
}
public void openDB() throws SQLException
{
Log.i("openDB", "Checking sqliteDBInstance...");
if(this.sqliteDBInstance == null)
{
Log.i("openDB", "Creating sqliteDBInstance...");
this.sqliteDBInstance = this.getWritableDatabase();
}
}
public void closeDB()
{
if(this.sqliteDBInstance != null)
{
if(this.sqliteDBInstance.isOpen())
this.sqliteDBInstance.close();
}
}
public long insertCountry(String countryName)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DB_COLUMN_1_NAME, countryName);
Log.i(this.toString() + " - insertCountry", "Inserting: " + countryName);
return this.sqliteDBInstance.insert(DB_TABLE_NAME, null, contentValues);
}
public boolean removeCountry(String countryName)
{
int result = this.sqliteDBInstance.delete(DB_TABLE_NAME, "country_name='" + countryName + "'", null);
if(result > 0)
return true;
else
return false;
}
public long updateCountry(String oldCountryName, String newCountryName)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DB_COLUMN_1_NAME, newCountryName);
return this.sqliteDBInstance.update(DB_TABLE_NAME, contentValues, "country_name='" + oldCountryName + "'", null);
}
public String[] getAllCountries()
{
Cursor cursor = this.sqliteDBInstance.query(DB_TABLE_NAME, new String[] {DB_COLUMN_1_NAME}, null, null, null, null, null);
if(cursor.getCount() >0)
{
String[] str = new String[cursor.getCount()];
int i = 0;
while (cursor.moveToNext())
{
str[i] = cursor.getString(cursor.getColumnIndex(DB_COLUMN_1_NAME));
i++;
}
return str;
}
else
{
return new String[] {};
}
}
}
One option would be to call removeCountry from your insertCountry method before actually doing the insert. Alternatively you could modify your database structure to be country_name text not null unique. SQLite will then throw an exception if you fail the constraint which you'll need to catch and handle appropriately.
Finally, another option would be to attempt a query of the database for the string in question, if it exists, don't insert, if it doesn't then insert it.
You could use a function to see if the data already exists in the database.
public boolean checkIfDataExists(String country) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.query(TABLE_NAME, columns, null, null, null, null, null);
int iCountry = c.getColumnIndex(KEY_COUNTRY);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
if (country.equals(c.getString(iCountry))) {
db.close();
return true;
}
}
db.close();
return false;
}
Call this function in an if statement and execute the insert instruction if the condition is not true.
I tried this and it works great,at least so far.
private static final String DB_CREATE_SCRIPT = "create table " + DB_TABLE_NAME +
" (_id integer primary key autoincrement, country_name text UNIQUE);)";
Added UNIQUE instead of not null
I was trying to add the data i receive from some specific messages to SQLite database..
But when i run my application i am getting error which says ... Fatal Exception : Main caused by Java Null Pointer exception at the InsertTitle Function in my DBAdapter.java
This is my DBAdapter Class
package com.lalsoft.janko;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter
{
public static final String KEY_ROWID = "_id";
public static final String KEY_GQTY = "gqty";
public static final String KEY_NQTY = "nqty";
public static final String KEY_DATE = "ddate";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "lalaqua";
private static final String DATABASE_TABLE = "nsales";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE =
"create table titles (_id integer primary key autoincrement, "
+ "gqty text not null, nqty text not null, "
+ "ddate text not null);";
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
}
#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 titles");
onCreate(db);
}
}
//---opens the database---
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
//---insert a title into the database---
public long insertTitle(String gqty, String nqty, String ddate)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_GQTY, gqty);
initialValues.put(KEY_NQTY, nqty);
initialValues.put(KEY_DATE, ddate);
return db.insert(DATABASE_TABLE, null, initialValues);
}
//---deletes a particular title---
public boolean deleteTitle(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID +
"=" + rowId, null) > 0;
}
//---retrieves all the titles---
public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[] {
KEY_ROWID,
KEY_GQTY,
KEY_NQTY,
KEY_DATE},
null,
null,
null,
null,
null);
}
//---retrieves a particular title---
public Cursor getTitle(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID,
KEY_GQTY,
KEY_NQTY,
KEY_DATE
},
KEY_ROWID + "=" + rowId,
null,
null,
null,
null,
null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
//---updates a title---
public boolean updateTitle(long rowId, String gqtr,
String nqty, String ddate)
{
ContentValues args = new ContentValues();
args.put(KEY_GQTY, gqtr);
args.put(KEY_NQTY, nqty);
args.put(KEY_DATE, ddate);
return db.update(DATABASE_TABLE, args,
KEY_ROWID + "=" + rowId, null) > 0;
}
}
This is the class which extends from BroadcastReceiver, which is calling the inserttitle function..
package com.lalsoft.janko;
import java.util.Calendar;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
public class SMSReceiver extends BroadcastReceiver
{
public String SendMsgBody;
private static final String LOG_TAG = "JankoSMS";
public DBAdapter db;
public Integer isDone=0;
public Double GrossQty,NetQty;
#Override
public void onReceive(Context context, Intent intent)
{
db = new DBAdapter(context);
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
String PhNo;
String MsgBody;
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
PhNo=msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
MsgBody=msgs[i].getMessageBody().toString();
str += "\n";
// EncodeSMS(MsgBody);
String GQtyS,NQtyS,sDate;
GQtyS="Ok";
NQtyS="Done";
sDate=getDate();
Log.i(LOG_TAG, "Date" +" "+ sDate +" "+ GQtyS +" "+ NQtyS);
long id;
id = db.insertTitle(GQtyS ,NQtyS,sDate);
}
}
}
public static String getDate()
{
Calendar c = Calendar.getInstance();
String sDate = c.get(Calendar.DAY_OF_MONTH) + "-"
+ c.get(Calendar.MONTH)
+ "-" + c.get(Calendar.YEAR);
//+ " at " + c.get(Calendar.HOUR_OF_DAY)
//+ ":" + c.get(Calendar.MINUTE);
return sDate;
}
}
Also i have checked the database is not getting created..
So what should be the possible cause of this issue and how can i solve this?? Please help me out of this trouble.
The problem is in line db.insert() of insertTitle() method. You have to assign the value of db before using so use open the database before using by calling open() as first statement inside insertTitle() method
Your code will be something like the below
public long insertTitle(String gqty, String nqty, String ddate)
{
open();
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_GQTY, gqty);
initialValues.put(KEY_NQTY, nqty);
initialValues.put(KEY_DATE, ddate);
return db.insert(DATABASE_TABLE, null, initialValues);
}
I guess you haven't called db.open(); that is this method
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
Follow the above 2 suggestions given by sunil & lalit
include the below one also i.e place db.execSQL(DATABASE_CREATE); in try catch block
public void onCreate(SQLiteDatabase db) {
System.out.println("table created....");
try{
db.execSQL(DATABASE_CREATE);
}catch (Exception e) {
// TODO: handle exception
}
}