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.
Related
I'm new to Android Studio and SQLite and wanted to run a query when the app is run for the very first time only, and when the app is run again it wont run the query again.
This will depend upon how you are accessing the database.
The most common way is to utilise the SQLiteOpenHelper class. In which case the onCreate method is called when the database is created. The database only ever being created the once (unless it is deleted e.g. the App uninstalled).
When onCreate is called the database will have been created BUT will not have any components (tables, indexes, views, triggers) other than some system components. Typically this is where the components are created but meets the criteria of your question IF using a class that extends SQLiteOpenHelper. However, unless the query is to store data, it would probably be of little use as there would be no data to query.
However, using a class that extends SQLiteOpenHelper is not the only way in which an SQLite database can be accessed, nor would onCreate be called if you were utilising a pre-existing database copied from the assets folder of the package (e.g. using SQLiteAssetHelper).
In these latter cases, you could test to see if the database actually exists and set a flag/indicator. If it does not and then after opening the database you could then check the indicator and run the query.
Demonstration
Here's a demonstration of two methods.
The first using the more typical SQLiteOpenHelper and thus the onCreate method.
The second using an indicator.
The first method utilises a class that extends SQLiteOpenHelper called DBHelper :-
class DBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "thedatabase.db";
public static final int DATABASE_VERSION = 1;
private static volatile DBHelper instance;
private DBHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
this.getWritableDatabase(); //Force database open
}
public static DBHelper getInstance(Context context) {
if (instance==null) {
instance = new DBHelper(context);
}
return instance;
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Run the query here AFTER creating the components
Log.d("DBHELPER","First run detected");
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Rather than run a query, data is written to the log from within the onCreate method.
The second method utilises the SQLiteDatabase openOrCreateDatabase (i.e. circumventing using the SQLiteOpenHelper). Thus it has to do some of the things that SQLiteOpenHelper conveniently does automatically:-
class OtherDBHelper {
public static final String DATABASE_NAME = "otherdatabase.db";
public static final int DATABASE_VERSION = 1;
private static boolean databaseCreateIndicator = false;
private static boolean databaseVersionChanged = false;
private SQLiteDatabase database;
private static OtherDBHelper instance;
private OtherDBHelper(Context context) {
if (!context.getDatabasePath(DATABASE_NAME).exists()) {
databaseCreateIndicator = true;
File database_dir = context.getDatabasePath(DATABASE_NAME).getParentFile();
if (!database_dir.exists()) {
database_dir.mkdirs();
}
// Copy database from assets
}
database = SQLiteDatabase.openOrCreateDatabase(context.getDatabasePath(DATABASE_NAME),null);
//* Database now open */
// If utilising Version number check and set the version number
// If not copying pre-existing database create components (tables etc)
if (databaseCreateIndicator) {
//<<<<<<<<<< Query here >>>>>>>>>>
Log.d("OTHERDBHELPER","First run detected");
}
}
public SQLiteDatabase getSQLiteDatabase() {
return database;
}
public static OtherDBHelper getInstance(Context context) {
if (instance==null) {
instance = new OtherDBHelper(context);
}
return instance;
}
}
again the instead of running a query outputting to the log is used.
To test both in unison then some activity code:-
public class MainActivity extends AppCompatActivity {
DBHelper dbHelper;
OtherDBHelper otherDBHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("PREDBMSG","Just prior to getting the databases.");
dbHelper = DBHelper.getInstance(this);
otherDBHelper = OtherDBHelper.getInstance(this);
Log.d("POSTDBMSG","Just after getting the databases.");
}
}
Results
When run for the first time then the log includes:-
2022-10-20 07:09:27.633 D/PREDBMSG: Just prior to getting the databases.
2022-10-20 07:09:27.663 D/DBHELPER: First run detected
2022-10-20 07:09:27.697 D/OTHERDBHELPER: First run detected
2022-10-20 07:09:27.697 D/POSTDBMSG: Just after getting the databases.
When run again :-
2022-10-20 07:10:41.258 D/PREDBMSG: Just prior to getting the databases.
2022-10-20 07:10:41.266 D/POSTDBMSG: Just after getting the databases.
I'm trying to create a little android app.
My problem is that one: After creating a JDBC Connection to my DB in the first Activity, how can i use the same connection in other activities to make querys?
I know how to make the query with the statement, but can i pass the connection of the Main Activity in order to use only the first connection in all the other activity of the application?
My db is AS400 of the IBM and i can access to it only with JDBC (in the Android platform). I know that is simple with web service but the company want to make everything in this way.
Sorry for my english, i'm an Italian guy!
Usually it's not a problem to use your DB in many components simultaneously. If you use common pattern of your DB-class to encapsulate standard DBhelper extends SQLiteOpenHelper - you can instantiate your DB class in many Activities and it will be used in thread-safe mode.
public class DB {
private static final String TAG = "DB";
public static final int SCHEMA_VERSION = 7;
final DBhelper mDBhelper;
public SQLiteDatabase mDB;
public DB ( Context context ) {
mDBhelper = new DBhelper(context);
// open the DB for read and write
mDB = mDBhelper.getWritableDatabase();
}
public synchronized long insertSite ( objSite s ) {
...
}
...
private class DBhelper
extends SQLiteOpenHelper {
public DBhelper ( Context context ) {
super(context, C.DB_NAME, null, SCHEMA_VERSION);
}
#Override
public void onCreate ( SQLiteDatabase db ) {
...
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "entering onUpgrade(): oldVersion="+oldVersion+", newVersion="+newVersion);
...
}
...
}
}
And use it as usually
public class MainActivity extends Activity {
DB eventsDB;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
eventsDB = new DB(this);
...
eventsDB.insertSite(objectSite);
}
...
}
In Android usually you use SQLite to persist your data. Try this tutorial.
If you have a database server and you want to access throw an android device, i suggest you to wrap database access with an intermediate server which expose data with web service (REST).
You don't specify if database access is in internet or intranet context, so i thought it is in an mixed context.
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."
So I've come to a point where I need to implement an SQLite database for my app.
Following "The Busy Coder's guide to Android Development" I have created a DatabaseHelper class that extends SQLiteOpenHelper.
One of my use cases is to run a query against the database and display the results on a ListView within a Fragment (I use fragments from the support library).
From what I understand, using managedQuery() is not really appropriate and even if it were it isn't recommended due to the fact that some of the logic encapsulated inside this method is actually executed on the main thread, specifically reQuery() which to my understanding is performed when the Activity is restarted.
So I've been trying to get acquainted with the Loader class for the first time, only to see this:
"The only supplied concrete implementation of a Loader is CursorLoader, and that is only for use with a ContentProvider"
My initial thought was to implement my own content provider and perhaps prevent other apps from getting access to it, then I read the following in the ContentProvider documentation via developer.android.com:
"You don't need a provider to use an SQLite database if the use is entirely within your own application."
I've also been playing with this:
https://github.com/commonsguy/cwac-loaderex
Yet I am not familiar with this project, and not sure if it can be used on a production environment.
So, right now all I can think of is creating a bunch of AsyncTask instances within my Fragment and manage their lifecycle appropriately, make sure they're cancelled whenever needed and whatnot.
Are there any other options?
I think implementing content provider is a good idea, no matter that data will not be accessible outside of the application. It provides very modern interface and from my experience makes your application error prone to database locking issues and other db-specific problems.
I've implemented it in my latest project and I was very happy to use it.
You can extend Loader class in order to perform other Async work such as loading directly from your DB.
Here is an example of that
Edit: added A better example of Loader usage.
Finally managed to find the tutorial that really helped me understand how things work.
By extending the loader class you can avoid messing with content observers and its quite easy to implement (at last)
the modifications that need to be taken in your code are
Add implementation of LoaderManager.LoaderCallbacks<D>, where D is your data list (snippet 1)
Create your loader class, copy snippet 2, and add the loading of your data from the DB
Finally call the loaders 1 call for init and then for refreshing the restart call. (snippet 2 & 3)
Snippet 1: How to "link" the loader with your fragment:
public static class AppListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<List<SampleItem>> {
public Loader<List<SampleItem>> onCreateLoader(int id, Bundle args) {
//...
return new SampleLoader (getActivity());
}
public void onLoadFinished(Loader<List<SampleItem>> loader, List<SampleItem> data) {
// ...
mAdapter.setData(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
// ...
}
public void onLoaderReset(Loader<List<SampleItem>> loader) {
// ...
mAdapter.setData(null);
// ...
}
/* ... */
}
Snippet 2: Schema of your custom loader: (I have double commented the observer things as I believe that it is quite difficult to implement it from the beginning and you can simple recall the loader without messing with that automated refreshing)
public class SampleLoader extends AsyncTaskLoader<List<SampleItem>> {
// We hold a reference to the Loader’s data here.
private List<SampleItem> mData;
public SampleLoader(Context ctx) {
// Loaders may be used across multiple Activitys (assuming they aren't
// bound to the LoaderManager), so NEVER hold a reference to the context
// directly. Doing so will cause you to leak an entire Activity's context.
// The superclass constructor will store a reference to the Application
// Context instead, and can be retrieved with a call to getContext().
super(ctx);
}
/****************************************************/
/** (1) A task that performs the asynchronous load **/
/****************************************************/
#Override
public List<SampleItem> loadInBackground() {
// This method is called on a background thread and should generate a
// new set of data to be delivered back to the client.
List<SampleItem> data = new ArrayList<SampleItem>();
// TODO: Perform the query here and add the results to 'data'.
return data;
}
/********************************************************/
/** (2) Deliver the results to the registered listener **/
/********************************************************/
#Override
public void deliverResult(List<SampleItem> data) {
if (isReset()) {
// The Loader has been reset; ignore the result and invalidate the data.
releaseResources(data);
return;
}
// Hold a reference to the old data so it doesn't get garbage collected.
// We must protect it until the new data has been delivered.
List<SampleItem> oldData = mData;
mData = data;
if (isStarted()) {
// If the Loader is in a started state, deliver the results to the
// client. The superclass method does this for us.
super.deliverResult(data);
}
// Invalidate the old data as we don't need it any more.
if (oldData != null && oldData != data) {
releaseResources(oldData);
}
}
/*********************************************************/
/** (3) Implement the Loader’s state-dependent behavior **/
/*********************************************************/
#Override
protected void onStartLoading() {
if (mData != null) {
// Deliver any previously loaded data immediately.
deliverResult(mData);
}
// Begin monitoring the underlying data source.
////if (mObserver == null) {
////mObserver = new SampleObserver();
// TODO: register the observer
////}
//// takeContentChanged() can still be implemented if you want
//// to mix your refreshing in that mechanism
if (takeContentChanged() || mData == null) {
// When the observer detects a change, it should call onContentChanged()
// on the Loader, which will cause the next call to takeContentChanged()
// to return true. If this is ever the case (or if the current data is
// null), we force a new load.
forceLoad();
}
}
#Override
protected void onStopLoading() {
// The Loader is in a stopped state, so we should attempt to cancel the
// current load (if there is one).
cancelLoad();
// Note that we leave the observer as is. Loaders in a stopped state
// should still monitor the data source for changes so that the Loader
// will know to force a new load if it is ever started again.
}
#Override
protected void onReset() {
// Ensure the loader has been stopped.
onStopLoading();
// At this point we can release the resources associated with 'mData'.
if (mData != null) {
releaseResources(mData);
mData = null;
}
// The Loader is being reset, so we should stop monitoring for changes.
////if (mObserver != null) {
// TODO: unregister the observer
//// mObserver = null;
////}
}
#Override
public void onCanceled(List<SampleItem> data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
// The load has been canceled, so we should release the resources
// associated with 'data'.
releaseResources(data);
}
private void releaseResources(List<SampleItem> data) {
// For a simple List, there is nothing to do. For something like a Cursor, we
// would close it in this method. All resources associated with the Loader
// should be released here.
}
/*********************************************************************/
/** (4) Observer which receives notifications when the data changes **/
/*********************************************************************/
// NOTE: Implementing an observer is outside the scope of this post (this example
// uses a made-up "SampleObserver" to illustrate when/where the observer should
// be initialized).
// The observer could be anything so long as it is able to detect content changes
// and report them to the loader with a call to onContentChanged(). For example,
// if you were writing a Loader which loads a list of all installed applications
// on the device, the observer could be a BroadcastReceiver that listens for the
// ACTION_PACKAGE_ADDED intent, and calls onContentChanged() on the particular
// Loader whenever the receiver detects that a new application has been installed.
// Please don’t hesitate to leave a comment if you still find this confusing! :)
////private SampleObserver mObserver;
}
Snippet 3: How to call the loader for the first time (ONLY)
// Initialize a Loader with an id. If the Loader with this id is not
// initialized before
getLoaderManager().initLoader(LOADER_ID, null, this);
Snippet 4: For refreshing data (recalling the query)
// Check if the loader exists and then restart it.
if (getLoaderManager().getLoader(LOADER_ID) != null)
getLoaderManager().restartLoader(LOADER_ID, null, this);
Reference:
Snippet 1 : usage of loader extracted from here
Snippet 2 : here for more info and logic read throughout the hole article
Snippet 3 & 4: are just loader usage.
Full code of these is also uploaded by the creator on github
I recommend OrmLite library, a lightweight Object Relational Mapping that can work for Android. This library will make your life easier . You don't need to create or update database by hand, you don't need to focus on managing database connection, all queries select, insert, update will be easier with a DAO approach (usually you don't need to write your own sql query) and a lot of features. They have some examples that you can start with.
And if you want to use the Loader, there is a ORMLite Extras , additional functionality for ORMLite available on github (You can use the support package which is compatible with support android library). Here is an example usage on my previous project:
public class EventsFragment extends Fragment implements LoaderCallbacks<Cursor>{
private static final int LOADER_ID = EventsFragment.class.getName().hashCode();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layoutRoot = inflater.inflate(
R.layout.fragment_events, null);
lvEvents = (ListView) layoutRoot.findViewById(R.id.lvEvents);
adapter = new EventAdapter(getActivity(), null, null);
lvEvents.setAdapter(adapter);
return layoutRoot;
}
#Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
try {
PreparedQuery<Event> query = getDatabaseHelper().getEventDao().getQuery();
return getDatabaseHelper().getEventDao().getSQLCursorLoader(query );
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
adapter.swapCursor(cursor);
try {
adapter.setQuery(getDatabaseHelper().getEventDao().getQuery());
} catch (SQLException e) {
e.printStackTrace();
}
}
#Override
public void onLoaderReset(Loader<Cursor> arg0) {
adapter.swapCursor(null);
}
private OrmliteDatabaseHelper getDatabaseHelper(){
return ((MainActivity)getActivity()).getDatabaseHelper();
}
}
The adapter
public class EventAdapter extends OrmliteCursorAdapter<Event>{
public EventAdapter(Context context, Cursor c, PreparedQuery<Event> query) {
super(context, c, query);
}
#Override
public void bindView(View itemView, Context context, Event item) {
TextView tvEventTitle = (TextView) itemView.findViewById(R.id.tvEventTitle);
TextView tvEventStartDate = (TextView) itemView.findViewById(R.id.tvEventStartDate);
tvEventTitle.setText(item.getTitle());
tvEventStartDate.setText(item.getFormatStartDate());
}
#Override
public View newView(Context context, Cursor arg1, ViewGroup arg2) {
LayoutInflater inflater = LayoutInflater.from(context);
View retView = inflater.inflate(R.layout.event_item_row, arg2, false);
return retView;
}
}
And a custom Dao which provides PreparedQuery for cursor adapter above:
public interface IEventDao extends Dao<Event, Integer>{
PreparedQuery<Event> getQuery() throws SQLException;
OrmliteCursorLoader<Event> getSQLCursorLoader(Context context, PreparedQuery<Event> query) throws SQLException;
}
public class EventDao extends AndroidBaseDaoImpl<Event, Integer> implements IEventDao{
public EventDao(ConnectionSource connectionSource) throws SQLException {
super(connectionSource, Event.class);
}
public EventDao(ConnectionSource connectionSource,
DatabaseTableConfig<Event> tableConfig) throws SQLException {
super(connectionSource, tableConfig);
}
#Override
public PreparedQuery<Event> getQuery() throws SQLException{
return queryBuilder().prepare();
}
}
Hope this can help!
If your database contains thousands of records consider madlymad's answer
If not keep it stupid and simple, use SQLiteOpenHelper and create a method that returns you your data as array of strings or define your one objects.
Also use custom/regular CursorAdapter or ArrayAdapter.
I use the SQLiteOpenHelper to create my database. I have made Java classes for all the tables and when I get the data from my database I put it in an ArrayList. The ArrayList I then load into the adapter of the Listview.
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.