Error is cursor index out of bounds exception, cursor is empty, receiving nothing.
Here is logcat:
FATAL EXCEPTION: main: com.example.root.notebook, PID:
.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at com.example.root.notebook.NotebookDbAdapter.cursorToNote(NotebookDbAdapter.java:101)
at com.example.root.notebook.NotebookDbAdapter.createNote(NotebookDbAdapter.java:67)
at com.example.root.notebook.NoteEditFragment$4.onClick(NoteEditFragment.java:160)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:163)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
NotebookDbAdapter.java
package com.example.root.notebook;
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;
import java.util.ArrayList;
import java.util.Calendar;
/**
* Created by root on 28/04/2016.
*/
public class NotebookDbAdapter {
private static final String DATABASE_NAME="notebook.db";
private static final int DATABASE_VERSION=1;
public static final String NOTE_TABLE="note";
public static final String COLUMN_ID="_id";
public static final String COLUMN_TITLE="title";
public static final String COLUMN_MESSAGE="message";
public static final String COLUMN_CATEGORY="category";
public static final String COLUMN_DATE="date";
public String[] allColumns={COLUMN_ID, COLUMN_TITLE, COLUMN_MESSAGE, COLUMN_CATEGORY, COLUMN_DATE};
public static final String CREATE_TABLE_NOTE= " create table " + NOTE_TABLE + " ( "
+ COLUMN_ID +" integer primary key autoincrement, "
+COLUMN_TITLE +" text not null, "
+COLUMN_MESSAGE+ " text not null, "
+COLUMN_CATEGORY+" integer not null, "
+COLUMN_DATE+" ); ";
private SQLiteDatabase sqlDB;
private NotebookDbHelper notebookDbHelper;
private Context context;
public NotebookDbAdapter (Context ctx){
context=ctx;
}
public NotebookDbAdapter open() throws android.database.SQLException{
notebookDbHelper=new NotebookDbHelper(context);
sqlDB=notebookDbHelper.getWritableDatabase();
return this;
}
public void close(){
notebookDbHelper.close();
}
public Note createNote(String title,String message,Note.Category category){
ContentValues values=new ContentValues();
values.put(COLUMN_TITLE,title);
values.put(COLUMN_MESSAGE,message);
values.put(COLUMN_CATEGORY,category.name());
values.put(COLUMN_DATE, Calendar.getInstance().getTimeInMillis() + "");
long insertId=sqlDB.insert(NOTE_TABLE,null,values);
Cursor cursor=sqlDB.query(NOTE_TABLE,allColumns, COLUMN_ID + " = " + insertId , null, null, null, null);
cursor.moveToFirst();
Note newNote=cursorToNote(cursor);
cursor.close();
return newNote;
}
public long deleteNote(long idToDelete){
return sqlDB.delete(NOTE_TABLE,COLUMN_ID +" = "+idToDelete ,null);
}
public long updateNote(long idToUpdate,String newTitle,String newMessage,Note.Category newCategory){
ContentValues values=new ContentValues();
values.put(COLUMN_TITLE,newTitle);
values.put(COLUMN_MESSAGE,newMessage);
values.put(COLUMN_CATEGORY,newCategory.name());
values.put(COLUMN_DATE, Calendar.getInstance().getTimeInMillis() + "");
return sqlDB.update(NOTE_TABLE, values ,COLUMN_ID + " = " + idToUpdate, null);
}
public ArrayList<Note> getAllnotes(){
ArrayList<Note> notes=new ArrayList<Note>();
Cursor cursor=sqlDB.query(NOTE_TABLE,allColumns, null ,null ,null ,null ,null);
for (cursor.moveToLast(); !cursor.isBeforeFirst(); cursor.moveToPrevious()){
Note note=cursorToNote(cursor);
notes.add(note);
}
cursor.close();
return notes;
}
private Note cursorToNote(Cursor cursor){
Note newNote=new Note(cursor.getString(1),cursor.getString(2), Note.Category.valueOf(cursor.getString(3)),
cursor.getLong(0),cursor.getLong(4));
return newNote;
}
private static class NotebookDbHelper extends SQLiteOpenHelper{
NotebookDbHelper(Context ctx){
super(ctx,DATABASE_NAME,null,DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_TABLE_NOTE);
}
#Override
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
Log.w(NotebookDbHelper.class.getName(),"upgrading database from version "+ newVersion+"to"+oldVersion+",which will destroy all old data");
db.execSQL("Drop table if exist "+ NOTE_TABLE);
onCreate(db);
}
}
}
Replace your below code
cursor.moveToFirst();
Note newNote=cursorToNote(cursor);
cursor.close();
return newNote;
With
if (cursor != null && cursor.moveToFirst()) {
Note newNote=cursorToNote(cursor);
cursor.close();
return newNote;
}
else {
return null;
}
Try this :
public ArrayList<Note> getAllnotes(){
ArrayList<Note> notes=new ArrayList<Note>();
Cursor cursor = sqlDB.rawQuery("SELECT * FROM " + NOTE_TABLE, null);
if(cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
Note note=new Note(cursor.getString(1),cursor.getString(2), Note.Category.valueOf(cursor.getString(3)), cursor.getLong(0),cursor.getLong(4));
notes.add(note);
} while (cursor.moveToNext());
}
}
cursor.close();
return notes;
}
Related
At first the app would just crash when I started it with an emulator, Not sure what I changed to get it to run but now it will run the onCreate method however, when I implement the addButtonClicked method the app just stalls and the Android Monitor displays "Suspending all threads" every few seconds and I'm not sure where to even begin debugging. Any pointers in the right direction would be greatly appreciated as I'm fairly new to Android development.
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
EditText testInput;
TextView testText;
MyDBHandler dbHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testInput = (EditText) findViewById(R.id.testInput);
testText = (TextView) findViewById(R.id.testText);
dbHandler = new MyDBHandler(this, null, null, 1);
printDatabase();
}
//Add product to database
public void addButtonClicked(View view){
Products product = new Products((testInput.getText().toString()));
dbHandler.addProduct(product);
printDatabase();
}
// Delete Items
public void deleteButtonClicked(View view){
String inputText = testText.getText().toString();
dbHandler.deleteProduct(inputText);
printDatabase();
}
public void printDatabase(){
String dbString = dbHandler.databaseToString();
testText.setText(dbString);
testInput.setText("");
}
}
Products.java
public class Products {
private int _id;
private String _productname;
public Products(){
}
public Products(String productname) {
this._productname = productname;
}
public void set_id(int _id) {
this._id = _id;
}
public void set_productname(String _productname) {
this._productname = _productname;
}
public int get_id() {
return _id;
}
public String get_productname() {
return _productname;
}
}
MyDBHandler.java
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;
public class MyDBHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 15;
private static final String DATABASE_NAME = "products.db";
public static final String TABLE_PRODUCTS = "products";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_PRODUCTNAME = "productname";
public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TABLE_PRODUCTS +"(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT ," +
COLUMN_PRODUCTNAME +" TEXT " +
");";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUCTS);
onCreate(db);
}
//Add new row to the database
public void addProduct(Products product){
ContentValues values = new ContentValues();
values.put(COLUMN_PRODUCTNAME, product.get_productname());
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_PRODUCTS, null, values);
db.close();
}
//Delete product from database
public void deleteProduct(String productName){
SQLiteDatabase db = getWritableDatabase();
db.execSQL("DELETE FROM " + TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME + "=\"" + productName + "\";" );
}
//Print of DB as sting
public String databaseToString(){
String dbString = "";
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM " + TABLE_PRODUCTS + " WHERE 1";
//Cursor point to a location in your results
Cursor c = db.rawQuery(query, null);
//Move to the first row in your results
c.moveToFirst();
while (!c.isAfterLast()){
if(c.getString(c.getColumnIndex("productname"))!= null){
dbString += c.getString(c.getColumnIndex("productname"));
dbString += "\n";
}
}
db.close();
return dbString;
}
}
for your databaseToString method you are performing a retrieve operation. You should be doing a read operation in a thread other than UI thread. Try fetching in AsyncTask. It should work. Implementation for your databaseToString should be handled by AsyncTask.
Happy Coding..
package ru.phonebook;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.SyncStateContract;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
// Класс для работы БД
public class DatabaseHandler extends SQLiteOpenHelper
{
// Версия базы данных
private static final int _DatabaseVersion = 3;
// Название базы
private static final String _DatabaseName = "ContaсtDatabase";
// Таблица
private static final String _TableName = "subscribers";
// Поля в таблице
private static final String _Field_ID = "id_subscribers";
private static final String _Field_Name = "name_subscribers";
private static final String _Field_Phone = "phone_subscribers";
// Запрос создания таблицы
private static final String _Query_CreateTable = "CREATE TABLE " + _TableName + "("
+ _Field_ID + " INTEGER PRIMARY KEY,"
+ _Field_Name + " TEXT,"
+ _Field_Phone + " TEXT);";
// Запрос вывода всех контактов
private static final String _Query_SelectTable = "SELECT * FROM " + _TableName;
// Запрос на вывода количества контактов
private static final String _Query_CountRows_Table = "SELECT COUNT(*) FROM " + _TableName;
// Конструктор
public DatabaseHandler(Context context)
{
super(context, _DatabaseName, null, _DatabaseVersion);
Log.e("n", "Call constructor");
}
// Добавление абонента в базу данных
public void AddSubcriber(Subscriber contact)
{
SQLiteDatabase db = this.getWritableDatabase();
/*ContentValues values = new ContentValues();
values.put(_Field_Name, contact.getName());
values.put(_Field_Phone, contact.getPhone());
db.insert(_TableName, null, values);
db.close();
*/
Log.d("n", "Insert rows: " + contact.getName());
}
// Вывод всех абонентов
public List<Subscriber> getAllSubscriber()
{
List<Subscriber> allSubscriber = new ArrayList<Subscriber>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(_Query_SelectTable, null);
if(cursor.getCount() != 0)
{
do
{
Subscriber tmpSub = new Subscriber(cursor.getInt(0), cursor.getString(1), cursor.getString(2));
allSubscriber.add(tmpSub);
} while(cursor.moveToNext());
}
cursor.close();
db.close();
return allSubscriber;
}
// Вывод количества абонентов
public int getSubscriberCount()
{
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(_Query_CountRows_Table, null);
db.close();
cursor.close();
return cursor.getCount();
}
// Удаление всех контактов
public void deleteAllSubscriber()
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(_TableName, null, null);
db.close();
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(_Query_CreateTable);
Log.e("n", "Database create");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + _TableName);
onCreate(db);
Log.e("n", "Database onUpgrade");
}
}
This is my class for communicate with database, and after in main programm i add new rows:
DatabaseHandler dbConnect = new DatabaseHandler(this);
dbConnect.AddSubcriber(new Subscriber("Petr Umine", "19234234432"));
In my logCat i view error:
"02-24 19:12:41.440 17415-17415/ru.phonebook W/System.err﹕ Invalid int: "" "
i am debuging method "AddSubcriber", and this error crush after this line SQLiteDatabase db = this.getWritableDatabase();
what is it?
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'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);
}
}
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
}
}