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.
Related
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.
Here is my model classes that are persisted in sqlite db using ORMLITE.
public class Site{
...
...
Collection<Visit> visits;
}
public class Visit{
...
...
Collection<Pic> pics;
}
public class Pic{
...
...
}
Now in one view i add,edit or delete from these three tables. There is a button in my view to cancel the changes(add,edit,delete). So i need to rollback to previous state of the db.
How can i achieve this roll back to a certain state of the three tables using ormlite with android?
I have read in ormlite docs about DAO.SetAutoCommit() and startThreadConnection() methods. I think i can do it by using this two. But cant figure it out how to use them. Please suggest me how to do it.
Here is my DBHelper Class:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// name of the database file
private static final String DATABASE_NAME = "Test.db";
private static final int DATABASE_VERSION = 1;
private Dao<Site, Integer> siteListDao = null;
private Dao<Visit, Integer> visitDao= null;
private Dao<Pic,Integer> picDao=null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database,ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, Site.class);
TableUtils.createTable(connectionSource, Visit.class);
TableUtils.createTable(connectionSource, Pic.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
} catch (java.sql.SQLException e) {
e.printStackTrace();
}
}
public Dao<Visit, Integer> getVisitDao() {
if (null == visitDao) {
try {
visitDao = getDao(Visit.class);
}catch (java.sql.SQLException e) {
e.printStackTrace();
}
}
return visitDao;
}
.....
.....
Hmm don't know about any methods that will do this for you automatically. If you really wanna do it automatically, you could also check out Transactions. They have build-in controls to roll-back on fail. Not exactly what you want, but maybe adjustable.
You could also just do it more manually and save 1 (last) object in memory, the object you're going to delete. If a person wants to 'undo' the change, you can just re-add that object with ORMLite. Probably a lot easier than other options.
Yeah I mostly agree with #Stefan. I think you need to do this inside of your application and not rely on a database construct to all you to return to a previous state.
Turning off auto-commit (which ORMLite uses transactions under Sqlite) or using transactions directly is not how to do this. Transactions are designed to allow you to make multiple changes to the database and then roll them all back if one database change fails. They are not intended to stay open for seconds waiting for user input.
You could have a committed boolean field or some such in your data to make it easier to "revert" the database by deleting all objects where the committed = false or some such.
You could have separate tables so objects are stored to a session table and then copied over to the main tables when the user commits their work.
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.
I'm using Android's SQLite to create a database of levels, based on some files. I first create a SQLiteOpenHelper, and on it I call getReadableDatabase() or getWritableDatabase() so the onCreate() method is called and my DB will be created:
#Override //Main Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DbOpenHelper(this);
database = dbHelper.getWritableDatabase(); //is a field
-
public DbOpenHelper(Context context) {
super(context, DB_NAME, null, DATABASE_VERSION);
Log.d("CREATING CLASSS", "OSDIFJE*(#");
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_TABLE_CREATE);
loadLevelData();
}
// Load data into the database on creation
private void loadLevelData() {
Log.d("DbOpenHelper", "Loading Level Data");
AssetManager mgr = MenuActi ~~snip~~
Log.d("dataaosdifj",MenuActivity.database.toString()); //NullPointerException!
MenuActivity.database.insert(DB_TABLE_NAME, null, info);
}
i Also tried calling getWritableDatabase() inside the loadLevelData() method, same results.
I saw this is quite a common problem, however most threads about it don't have any solution!
Please :'(
Why are accessing an instance variable from an activity from inside your open helper? If I understand your code correctly, your loadLevelData() method is a method of your open helper. Instead of what you have, why not this:
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_TABLE_CREATE);
loadLevelData(db);
}
// Load data into the database on creation
private void loadLevelData(SQLiteDatabase db) {
...
db.insert(DB_TABLE_NAME, null, info);
}
The root of your problem is that the database instance variable in your activity isn't assigned by the time you access it down in your DbOpenHelper... you're still in the call that's creating the database -- which happens to be dbHelper.getWritableDatabase() -- and the result hasn't returned for the assignment.
Hi I am new to android and I have a problem in creating a database.
public class database extends ListActivity {
/** Called when the activity is first created. */
private final String MY_DATABASE_NAME = "myCoolUserDB.db";
private final String MY_DATABASE_TABLE = "t_Users";
Context c;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> results = new ArrayList<String>();
setContentView(R.layout.main);
SQLiteDatabase mydb=null;
try
{
mydb.openOrCreateDatabase(MY_DATABASE_NAME, null);
} catch(Exception e){}
}
}
When I run this code it throws a run time exception. Please help me.
If you are going to call a static method like openOrCreateDatabase, do it on the class (SQLiteDatabase.openOrCreateDatabase(...)), not an instance. It's a lot clearer - the way you've done it looks like you're calling an instance method, so looks like a sure NullPointerException, which of course is misleading.
As someone else has stated, the stack trace would be the most useful thing when asking for help with an exception.
(Almost) never catch an exception without at the very least logging it. Don't just do nothing with it. There are of course exceptions to every rule, but let's not go there for the moment. Anyway, if you don't at least log it, you're just throwing away information that would tell you what went wrong when everything goes to crap later.
You shouldn't be using that method directly, and should instead be extending SQLiteOpenHelper . See the android developers page on data storage to get started (I'd post a link but apparently I'm only allowed one link in my post ?!), and since you've probably had to download the SDK to get going, look in the samples that come with it for the Notepad sample application. That contains a NotePadProvider class, which is a good example of both a content provider and database access, which often go hand-in-hand on android. I'd suggest compiling that application and making some simple changes to it before you jump into making your own one.
For working with sqlite database you need to create class extended from SQLiteOpenHelper:
private class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLES);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(UPGRADE_TABLES);
}
}
Then you can get access to db using DbHelper object:
DBHelper dbHelper = new DBHelper(Activity.this);
SQLiteDatabase db = dbHelper.getReadableDatabase();
I run into the same problem. It figures out that two bugs happens during development
dir "databases" was not existent
accendently ".db" was created as directory.
They following code cover both
File dbFile = getDatabasePath ("abc.db");
if (dbFile.isDirectory ()) {
dbFile.delete();
}
if (! dbFile.exists()) {
String path = dbFile.getParent ();
new File (path).mkdirs ();
}
database = SQLiteDatabase.openDatabase (dbFile.getAbsolutePath (), this, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_NECESSARY);
Hope this helps
I think SQLiteOpenHelper is only useful for "single table" databases. For multiple table applications I consider directly using SQLiteDatabase fit better to a good architecture.
This is a simple post which tells you how to insert data in to a SQLite database in Android and further more this links shows you how to retrieve data from a SQLite database in Android .