Globally defined instance of SQLite generates error - android

I want to declare an instance of SQLite Database globally as a private final variable.
1)why the way i used in the below posted code causes the logcat to generate erros and the app crashes.
2)is there any other way so I can define an instance of my DB globally and final?
Java_Code:
public class SQLiteTest00 extends Activity {
final MyDB myDB = new MyDB(this);
final SQLiteDatabase mySQLiteDB = myDB.getWritableDatabase();
final ContentValues myContVals = new ContentValues();
private final String TABLE_NAME = "MYDATA";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_test00);
myContVals.put("name", "loc00");
myContVals.put("lat", 33);
myContVals.put("lng", 53);
myContVals.put("time", "12:30");
myContVals.put("date", "11/05/2014");
lodgeIntoDB(myContVals);
}
private void lodgeIntoDB(ContentValues cv) {
long newID = mySQLiteDB.insert(TABLE_NAME, null, cv);
if (newID == -1) {
Toast.makeText(getBaseContext(), "Error Commiting Record(s)", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "Data Commited Successfully", Toast.LENGTH_SHORT).show();
}
}
}

Is MyDB your extended version of SQLiteOpenHelper? Also, why are you creating a final version of a ContentValues? Could you explain why you need a final copy of the db? The db will be private to your app by default, that is the way Android does it. If you extend SQLiteOpenHelper, then you can call the getWritableDatabase() in the onCreate of your main activity and if your db variable is a member variable you will have it. Maybe I am missing something. Also, from what I have read, it is best to close the db if you are not using it and then to use the helper class later to get it again if you need to read from or write to it. Thanks. Ps. one other thing, anytime I have seen the helper class called to get a copy of the db, it is done inside onCreate or another method not at the top in the variable declartions. Try moving it into onCreate.

Related

Android - try with resources just for creating database tables

In Android I have this part of code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(!prefs.getBoolean("firstTime", false)) {
new DatabaseHelper(this);
} }
Lint is now saying 'DatabaseHelper' used without 'try'-with-resources statement
In DatabaseHelper class I have this:
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 2);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + "blabla");
}
So why do I need try with resources? Is it really needed here and how to do it in my case?
I tried something like:
try (DatabaseHelper myDb = new DatabaseHelper(this)){
} catch(IOException e) {
}
But I don't know what to put inside try statement as it is just creating the database tables and nothing else.
Strange is, if I define outside of onCreate DatabaseHelper myDb; and then inside onCreate I will have:
myDb = new DatabaseHelper(this);
then it is not complaining.
Why should I assign it to myDb variable, why it is complaining when I use the same without variable as new DatabaseHelper(this) ?
Is it really needed here...?
Yes, insofar as SQLiteOpenHelper extends AutoCloseable, and you seem to be hitting a Lint complaint about not closing it.
But I don't know what to put inside try statement as it is just creating the database tables and nothing else.
First, it is not creating database tables. That will not occur until you do something with the DatabaseHelper, such as call getWriteableDatabase().
Second, an AutoCloseable will have a close() method that satisfies the concern.
If your objective purely is to get rid of the Lint complaint, use:
try (DatabaseHelper myDb = new DatabaseHelper(this)){
myDb.close();
} catch(IOException e) {
}
You will need to do something else beyond close(), such as getReadableDatabase(), to get the tables to be created.

Null object reference on database cursor [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
Been trying to retrieve data from database, my database has values and I don't know which causes this error.
public void popList(String date, String time, String type, String game, String place){
Cursor data = databaseHelper.getReports(date, time, type, game, place);
while (data.moveToNext()) {
HashMap<String, String> datax = new HashMap<>();
datax.put("id", (data.getString(data.getColumnIndex("betid"))));
datax.put("betnumber", (data.getString(data.getColumnIndex("betnum"))));
datax.put("betamount", (data.getString(data.getColumnIndex("betamt"))));
mData3.add(datax);
}
bettorAdapter = new MyAdapter(mData3);
listViewx.setAdapter(bettorAdapter);
bettorAdapter.notifyDataSetChanged();
}
public Cursor getReports(String date, String time, String type, String game, String place){
Cursor data=null;
try {
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT * FROM reports WHERE date='"+date+"' AND time ='"+time+"' AND game='"+game+"' AND type='"+type+"' AND lugar='"+place+"'";
data = db.rawQuery(query,null);
}catch (Exception e){
System.out.println(e);
}
return data;
}
You need to instantiate/construct the databaseHelper object as it will be null if it is only declared. That is you need to use an equivalent of the line :-
databaseHelper = new DatabaseHelper(appropriate_values_for the_constructor);
Where appropriate_values_for the_constructor are as it says the appropriate value(s) for the constructor, typically just the context.
The above would be used before calling the poplist method. Typically databaseHelper would be declared at the class level and the above line would be set as soon as, or shortly after, the context were available. In an activity this would be in the onCreate method probably just after the ContentView has been set.
The following is an example where databaseHelper is named mDBHlpr and the constructor just needs the one value to be passed, a valid the Context (e.g. for an activity this). :-
public class MainActivity extends AppCompatActivity {
DatabaseHelper mDBHlpr; //<<<<<<<<<< Declares the mDBHlpr instance, it will be null until instantiated
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new DatabaseHelper(this); //<<<<<<<<<<< Instantiates the Database Helper instance named mDBHlpr
.......... other code
}
.......... other code
}

How do I access the same database from different activities?

I am writing an app and I want to store the high scores. I have it working to show the high score on the end activity. However, I want to have a highscores activity to show all the highscores. I am doing this by, in the highscores activity, calling the end activity to return the high score, so the database doesn't change. After running a debug, I saw that it got to the databasehandler but got caught on getReadableDatabase(), saying that it was unable to invoke the method on a null object reference.
This is my highscores method(I didn't include the whole thing, and the ifs are because there are different difficulties of the game)
public class highscores extends Activity {
TextView mode, score;
Button right, back;
int modenum;
end get=new end();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_highscores);
mode =(TextView)findViewById(R.id.scorebar);
score =(TextView)findViewById(R.id.score);
right =(Button)findViewById(R.id.button14);
back =(Button)findViewById(R.id.highscores);
mode.setText("Easy");
score.setText(get.datatostring(1));
modenum =1;
}
public void right(View view){
if(modenum==1) {
modenum = 2;
mode.setText("Hard");
score.setText(get.datatostring(2));
}else if(modenum==2) {
modenum = 3;
mode.setText("X-Mode");
score.setText(get.datatostring(3));
}else {
modenum = 1;
mode.setText("Easy");
score.setText(get.datatostring(1));
}
}
This is in the end method
public String datatostring(int difficulty){
MyDBHandler db = new MyDBHandler(this, null,null,1);
return db.datatostring(difficulty);
}
And this is in the databasehandler
public String datatostring(int difficulty){
SQLiteDatabase db = getReadableDatabase();
String dbString = "";
String c;
if(difficulty==1)
c = COLUMN_SCORE;
else if(difficulty==2)
c = COLUMN_HARD;
else
c = COLUMN_X;
String query = "SELECT "+c+" FROM "+TABLE_SCORES;
Cursor cursor = db.rawQuery(query,null);
cursor.moveToFirst();
if(!cursor.isAfterLast()){
int index = cursor.getColumnIndex(c);
String value = cursor.getString(index);
if(value!=null){
dbString += cursor.getString(cursor.getColumnIndex(c));
}
}
db.close();
cursor.close();
return dbString;
}
I suggest to use a SQLiteOpenHelper to handle this.
You should see this example:
Android Sqlite DB
Hope that helps, i personally works in this way.
The other option is to use som ORM, i recommend to use GreenDao, its good, and lets handle easy way this kind of actions.
Regards.
Follow this tutorial to create a concurrent and scalable database
Remember :
You should always make database queries through one instance (Singleton) of your database adapter else you will face a lot of issues when accessing your database concurrently from different classes.
Use SQLiteOpenHelper class for accessing your database. As it gives you many useful functions eg. upgrading user's database when you publish app updates with schema changes.
The short answer is yes.
But as you see you have no clear concept of the connection.
Bd in the android is SQLite (recommendation) Always be on the same route, you need to create a class that allows you to manage and connect to the database. The class will be SQLiteOpenHelper
Check THIS
You can connect one or more times to the database, since activity A, B or activity you want.
The important thing is to define the handler to connect, close, make request to the database.

SQLite IllegalStateException: where do I close the database?

I'm getting two contradicting Exceptions when creating and populating my new SQLiteDatabase in Android. In short my code:
SQLiteOpenHelper extending class:
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_TABLE_CREATE);
loadLevelData(db); //puts data in the database
//db.close(); <<< ?
}
In my activity class I instantiate this class (in onCreate()), and call getWritableDatabase():
dbHelper = new DbOpenHelper(getApplicationContext());
database = dbHelper.getWritableDatabase();
Now if I don't call db.close() after populating the database, like above, I get
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
However if I DO close it, I get the following exception:
java.lang.IllegalStateException: database not open
on getWritableDatabase().
This really confuses me, so could anyone help me with what's wrong?
You are not expected to close the database in the DatabaseHelper class. However you need to close it every time you open it calling getWritableDatabase:
dbHelper = new DbOpenHelper(getApplicationContext());
database = dbHelper.getWritableDatabase();
//... do something with database
database.close();
You are closing your database at the wrong time.
I typically keep the database around like this:
public class MyActivity extends Activity {
SQLiteDatabase writeableDb;
// ...
// Code
// ...
public void onStart(){
super.onCreate(savedState);
// Do stuff, get your helper, etc
writeableDb = helper.getWriteableDatabase();
}
public void onStop(){
writeableDb.close();
super.onStop();
}
}
Alternatively, wrap all your code working with that db connection in a try/finally block
db = helper.getWriteableDatabase();
try { // ... do stuff ... }
finally { db.close(); }
Note: All of the opening/closing should be done in the Activity working with the database, not the open helper.

where do i insert values in sqlite android

When I insert values in sqlite android, does it happens once or the database is created every time I run my application?
Specifically I have categories that will populate a list (food, drinks ....etc).
Where do I put my insert method?
In my dbHelper class or the class that needs the data?
public class ShoppingCategories extends ListActivity{
private AppSQLite mDbHelper;
private Cursor mNotesCursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDbHelper = new AppSQLite(this);
insertShoppingCategories();
}
public void insertShoppingCategories(){
mDbHelper.open();
long id;
id = mDbHelper.createShoppingCategory("food", 5, "#drawable/ic_launcher");
id = mDbHelper.createShoppingCategory("drink", 3, "#drawable/ic_launcher");
mDbHelper.close();
}
and the createShoppingCategory from dbHelper class is:
public long createShoppingCategory(String name, int priority, String icon) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_PRIORITY, priority);
initialValues.put(KEY_ICON, icon);
return mDb.insert(tShopCateg, null, initialValues);
}
Database is created only if it doesn't exist. If there are values need to be inserted only once you should put them inside onCreate inside your dbHelper class.
The Database is created once when you create the first instance of the mDbHelper.open(); (this may change depending on your implementation of the DB Helper class onCreate() method). The data you insert in the DB remains in the DB even after the App is closed (this is the reason for having a DB). You use the insert function when you need to save user input in the database persistantly.
put it where you really want to have functionality to insert data at a particular event/instance. You define how you DB would be (table rows and column) in dbHelpr and performs operation like insert delete in the activity.And yes, DB is created only the first time run of your app when you create the object of dbHelper and db._exec command is executed.
Once your database is created it will recreate only if your version of DB is changed or when you clear your data from settings>>Application>>manage Application>>clear data.
And if you want to insert your data once then you should put that code in onCreat() of dbHelper class.

Categories

Resources