Situation: I am trying to export my SQLite Tables to a XML file and have followed this answer as well as a post deleted from here and also this question (apparently both last links from the same author :) )
Update-2: I already have another class named DBAdapter which extends the SQLiteOpenHelper. So I have this:
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);
}
/*...*/
onCreate()
/*...*/
onUpgrade()
/*...*/
}
already in my DBAdapter class file. How can I reuse this?
Also, I tried passing as:
DataXmlExporter dm = new DataXmlExporter(SQLiteDatabase
Database(getReadableDatabase ()));
But still got an error.
Update-1: I used the 2nd Link to implement my solution.
Problem: I am getting a Null Pointer Exception; I guess because I haven't initialized my object correctly. At the time of calling the DataXmlExporter / exportData method what is supplied as parameter? : DataXmlExporter dm = new DataXmlExporter(WHAT_IS_PASSED_HERE?);
Thanks..
looks like you need an SQLiteDatabase.
for example you can get one with getReadableDatabase() or with getWritableDatabase().
If you implemented DatabaseAssistant like in the first link you provided you have as constructor parameter a reference to a SQLiteDatabase....
You need to pass SQLiteDatabase Database ( getReadableDatabase () ):
As per constructor
public DataXmlExporter(final SQLiteDatabase db) {
this.db = db;
}
And as per comments:
Android DataExporter that allows the passed in SQLiteDatabase
to be exported to external storage (SD card) in an XML format
What I did was to extend the SQLiteOpenHelper inside the DatabaseAssistant class and used it.
Related
My application give me this warning
A SQLiteConnection object for database
'+data+data+com_example_test+database' was leaked! Please fix
your application to end transactions in progress properly and to close
the database when it is no longer needed.
But I close the db object and the cursor after every use.
try {
while (cursor.moveToNext()) {
...
}
} finally {
if (cursor != null && !cursor.isClosed())
cursor.close();
}
...
db.close();
Can you help me for understand what is the problem?
thanks!!!
UPDATE!
I try this solution from this post
SQLite Connection leaked although everything closed
and I don't have memory leak anymore, is it a good solution?
Possible Solutions:
You have not committed the transactions you have started (You should
always close the transaction once you started)
Check whether you have closed the cursors you have opened if you are
using Sqlite (Looks like you have done this step from the code you posted)
Also move the db.close to finally block
You have not called db.close on a database before deleting it with context.deleteDatabase(...) and then recreating it with dbHelper.getWritableDatabase()
Just drag that db.close up into the finally block.
//Inside your SQLite helper class
#Override
public synchronized void close () {
if (db != null) {
db.close();
super.close();
}
}
//Inside the activity that makes a connection to the helper class
#Override
protected void onDestroy () {
super.onDestroy();
//call close() of the helper class
dbHelper.close();
}
this code stops the leak and fixes cursor problems.
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
In my case the error was caused when y try to download new data and database should be updated.
I solved it instantiating the database by calling a SELECT 0. That cause database to be updated, so after that I try to download the new data. And worked fine.
Probably you forgot to remove the break point of debugging
sample:
In my case, I was calling to getWritableDatabase or getReadableDatabase and not use it at all. for example if you use it with "execSQL" execSQL will call "releaseReference" "Releases a reference to the object, closing the object if the last reference was released."
I am creating a new class for database, the first function is to access the database
the problem is that I always get error on MODE_PRIVATE
I tried to pass the context as parameter but still shows error
anyone know how to access the database from a non activity class
public class DB {
public void OpenDB(Context ctx, SQLiteDatabase dataB)
{
dataB = openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
}
}
Change
dataB = openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
to
dataB = ctx.openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
openOrCreateDatabase is a method of Context class so you need a object of Context to call it.
use context to open databse ctx.openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
First Off: this is my first time ever looking at Java & the Android platform
I found a some sample code online that does some basic SQL database stuff using java and android.
I am receiving the "the constructor AssignmentTracker.DBAdapter(AssignmentTracker) is undefined" error.
(_ AssignmentTracker.java _) at this line:
public class AssignmentTracker extends Activity{
.....
DBAdapter db = new DBAdapter(this);
}
The DBAdapter.java looks like this:
public class DBAdapter{
....
private final Context context;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
I've seen very similar questions on this site, but none of them have helped me so far.
I found the issue.
I had another function/constructor named "DBAdapter" at the bottom of my AssignmentTracker.java file that was causing a conflict. I removed that and it all started working
public class BobDatabase extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "bob.db";
private static final int DATABASE_VERSION = 1;
public static final String DEFAULT_PROFILE = "default_profile";
public BobDatabase(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database)
{
createProfileTable(database);
createTimeTable(database);
createEventTable(database);
createLocationTable(database);
}
/**
* Creates a table for Profile objects, executes the string create_profile_table_sql
* contained within strings.xml
* #param database
*/
public void createProfileTable(SQLiteDatabase database)
{
database.execSQL(Resources.getSystem().getString(R.string.create_profile_table_sql));
}}
I get this error
01-14 12:20:57.591: E/AndroidRuntime(1825): Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7f040003
The code that causes the error is the single line inside createProfileTable specifically, Resources.getSystem().getString(R.string.create_profile_table_sql) if I use a class variable to hold a Context and do context.getString(R.string.create_profile_table_sql) I don't get any errors but I don't want to do that because I want to avoid memory leaks and according to what I know this should work. Any idea what's happening?
According to Android documentation, Resources.getSystem() only provides system-level resources, not application-level ones (like the resources inside your strings.xml file).
http://developer.android.com/reference/android/content/res/Resources.html#getSystem()
Try using the application's context if you really want to retrieve your strings this way, or take my suggestion in the comment to your question.
Using Resources.getSystem().getWhatEver() you can only access system-wide resources (you get the error because there is no system-wide resource with your ID). Since resource ID are not unique across applications you need to provide the application, when accessing a resource. In Android this is done using Context.
So if you want to access some resource you need to use it like this
context.getResources().getString(myID);
Apart from that Brandon's comment is correct.
You could get the context parametr in the function by parameter, or by a static variable, or by getApplicationContext() function.
I'm using ORMLite in an android project, and I'm not wanting to use the extended activities because I'm inserting values into the database on an AsyncTask.
In the docs it says:
"If you do not want to extend the OrmLiteBaseActivity and other base classes then you will need to duplicate their functionality. You will need to call OpenHelperManager.getHelper(Context context, Class openHelperClass) at the start of your code, save the helper and use it as much as you want, and then call OpenHelperManager.release() when you are done with it."
It also says to add the database helper class in the strings.xml, which I have. So I'm not sure what I'm doing wrong.
I'm using a class called DataAccess for my data tier that looks like this:
public class DataAccess {
private Context context;
private DBHelper dbHelper;
public DataAccess(Context _context) {
this.context = _context;
dbHelper = getDBHelper(_context);
}
private DBHelper getDBHelper(Context context) {
if (dbHelper == null) {
dbHelper = (DBHelper) OpenHelperManager.getHelper(context, DBHelper.class);
}
return dbHelper;
}
}
And I'm using the extended helper class:
public class DBHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "database.db";
private static final int DATABASE_VERSION = 1;
private Dao<SomeObject, Integer> someObjectTable = null;
private ConnectionSource connectionSource = null;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
this.connectionSource = connectionSource;
try {
TableUtils.createTable(connectionSource, SomeObject.class);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
}
public Dao<SomeObject, Integer> getSomeObjectDao() throws SQLException {
if (someObjectTable == null) {
dateTable = getDao(SomeObject.class);
}
return someObjectTable;
}
The idea is to create the DataAccess class and have it create the DBHelper if it hasn't already.
Can someone tell me if this is right or wrong, or if I'm on the right path?
Thanks!
I'm using ORMLite in an android project, and I'm not wanting to use the extended activities because I'm inserting values into the database on an AsyncTask.
You are on the right track but a little off #Matt. Frankly I'd never done a project without extending our base classes. But it is a good exercise so I've created this ORMLite example project which uses an Activity and manages its own helper.
Your DBHelper class is fine but really you do not need your DataAccess class. In each of your activities (or services...) you will need to have something like the following:
private DBHelper dbHelper = null;
#Override
protected void onDestroy() {
super.onDestroy();
if (dbHelper != null) {
OpenHelperManager.releaseHelper();
dbHelper = null;
}
}
private DBHelper getHelper() {
if (dbHelper == null) {
dbHelper = (DBHelper)OpenHelperManager.getHelper(this, DBHelper.class);
}
return dbHelper;
}
You [obviously], then use this in your code by doing something like:
Dao<SomeObject, Integer> someObjectDao = getHelper().getSomeObjectDao();
So whenever you call getHelper() the first time, it will get the helper through the manager, establishing the connection to the database. Whenever your application gets destroyed by the OS, it will release the helper -- possibly closing the underlying database connection if it is the last release.
Notice that the OpenHelperManager.getHelper() needs the Context as the first argument in case you do this without even an Activity base class.
Edit:
If you do want to create a DataAccess type class to centralize the handling of the helper class then you will need to make the methods static and do your own usage counter. If there are multiple activities and background tasks calling getHelper() then the question is when do you call releaseHelper()? You'll have to increment a count for each get and only call release when the counter gets back to 0. But even then, I'm not 100% sure how many lines you'd save out of your activity class.
I could nitpick but essentially you are doing it correct.
The call
dbHelper = (DBHelper) OpenHelperManager.getHelper(context, DBHelper.class);
Looks up the DBHelper class and instantiates it for the context. If you have defined it in your strings.xml, you can leave off the DBHelper.class at the end.
onUpgrade in you DBHelper.java, you may want to consider dropping the table you create in onCreate and then calling onCreate (to make sure you don't have conversion issues from update to update). You could do a more complex update if you wanted.
Other than that, it looks good. If you end up wanting data accessory methods for your DB objects beyond the base DAO methods, you will eventually want to create more thorough implementations of your object DAOs, but this is a good start.