Recently I started to get following error in my application. This is NOT in any specific place and I can reproduce only when loop through all data read/write functionality. It comes up pretty much anywhere.
09-14 08:52:15.089: WARN/SQLiteConnectionPool(19268): The connection pool for database '/data/data/com.nnn/databases/data.db' has been unable to grant a connection to thread 1 (main) with flags 0x5 for 30.000002 seconds.
Connections: 0 active, 1 idle, 0 available.
Is there any way to avoid this? I understand that somehow I exhause all connections to database?
I'm using approach #1: http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
And my database code looks like this:
public class DatabaseHelper extends SQLiteOpenHelper
{
private final static String LOG_TAG = "com.nnnn.data.DatabaseHelper";
private static final String DATABASE_NAME = "data.db";
private static final int DATABASE_VERSION = 260;
private static SQLiteDatabase databaseInstance;
public DatabaseHelper()
{
super(MyApplication.Me, DATABASE_NAME, null, DATABASE_VERSION);
}
public static synchronized SQLiteDatabase getDatabase()
{
if (databaseInstance == null) databaseInstance = (new DatabaseHelper()).getWritableDatabase();
return databaseInstance;
}
I have never seen this error. But, I would like to point out that you are not using approach #1 from the page you linked to, and I do believe that your implementation is causing you trouble.
In the design pattern you linked, their approach is to ensure that only one DatabaseHelper instance exists throughout your applications life-cycle. Your approach is different, you are trying to ensure that only one SQLiteDatabase instance exist though-out the applications life-cycle.
So in summery, you are trying to reuse the same database connection for everything(which is not a good idea, and I would strongly suggest you change this approach), but in reality, I believe this approach is causing some issues between SQLiteOpenHelper and your static instance variable.
You are creating new instances of DatabaseHelper in your getDatabase method, sure, your databaseInstance is static, but there is a potential problem with SQLiteOpenHelper instances here. For example, lets say the databaseInstance instance is closed and set to null by a piece of code. Aka, somebody is cleaning up after them-self, then the next time getDatabase() is called, you will create a new database helper, and more importantly, a new SQLiteOpenHelper.
Try removing the synchronized from the getDatabase method. This should not be necessary.
I believe that the only correct way you can handle SQLite DB in Android is to use ContentProvider. For your code you can try to store DatabaseHelper in that static field instead SQLiteDatabase instance, as described in the first approach.
Related
I'm trying to put all the DatabaseRequests inside a module in Android to centralize all the acces to DDBB in the same place.
I'm wondering if I'm making any mistake doing that. The apps works in the right way but I'm concerned about best practices doing that.
I have an static class called DatabaseRequest where all the requests are inside, for instance:
public static void insertUser(Context context, User user) {
DataBaseHelper mDataBaseHelper = OpenHelperManager.getHelper(context, DataBaseHelper.class);
try {
Dao<User, Integer> dao = mDataBaseHelper.getUserDao();
dao.createOrUpdate(user);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (mDataBaseHelper != null) {
OpenHelperManager.releaseHelper();
}
}
}
The context param is the context of the activity that's making the request.
Is there any performance issue related with this code?
Thanks in advance ;)
No, as Gray (ORMlite creator) said in this post:
is it ok to create ORMLite database helper in Application class?
What is most important with your code is that it guarantees a single
databaseHelper instance. Each instance has it's own connection to the
database and problems happen when there are more than one (1)
connection opened to the database in a program. Sqlite handles
multiple threads using the same connection at the same time but it
doesn't handle multiple connections well and data inconsistencies may
occur.
And in your case you may have multiple connections at one time.
I can preset you my approach on how I'm using ORMlite, I have one singleton class public class DbHelper extends OrmLiteSqliteOpenHelper which takes care of creating database connection and holds all Dao fields. You will have database upgrade code there and some other stuff so consider making facade classes. In my case each facade holds one Dao object for one model class, where i keep logic for complex item retrieving (and for simple cases i just delegate it to Dao object.
I need some help on database and cursor managing. I noticed that, when entering /leaving certain fragments, I get:
W/SQLiteConnectionPool﹕ A SQLiteConnection object for database '+data+data+database' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
That made me go back from scratch and check what I'm doing and when. I have:
a DatabaseHelper class extending SQLiteOpenHelper, with just some methods for creating and updating the db;
a DatabaseManager class, extending nothing. I use this, among other things, to keep a single reference to a DatabaseHelper object:
public class DatabaseManager {
private DatabaseHelper h; //class extending SQLiteOpenHelper
public DatabaseManager(Context c) {
if (h==null) {
h = new DatabaseHelper(c.getApplicationContext()); }
public Cursor query(...) {
SQLiteDatabase db = h.getReadableDatabase();
return db.rawQuery(...)
}
public void closeConnection() {
SQLiteDatabase db = h.getWritableDatabase();
db.close();
h.close();
}
}
in this class, some methods querying the database and returning a Cursor object;
in this class, a closeConnection() method, which I'm not really sure of.
I use this class from fragments, calling each time new DatabaseManager(getActivity()). This should not create a new helper reference. Right now I am:
calling Cursor.close() as soon as I got the information I wanted from the query;
never calling open() on my helper neither on my SQLiteDatabase, although I read somewhere that should be done. When exactly? Why it all works even without calling it?
calling manager.closeConnection() in the onStop() method of fragments that make use of my database. As you can see, that calls close on h (a reference to the helper class) and on a readable SQLiteDatabase object. However, I'm not really sure about that, because it closes the helper reference h without making it null, so maybe there are some problems with future calls to new DatabaseManager() ? Maybe dealing with database with a singleton pattern does not require you to call h.close()?
Apart from that, needless to say (that's why I'm asking), when switching through fragments I get the above mentioned warning. What's wrong? What should I do? What does end transactions in progress mean? Should I modify my closeConnection() method, call it in different lifecycle times, or don't call it at all?
After embarrassing issue pointed out by #Selvin, I made h static. Now if I remove any call to closeConnection(), it all works well and I don't get any warnings. That means I'm never calling neither h.close() or db.close(). Is that ok? If not, when should I call it?
I'm creating an queued upload manager. With this answer to my previous question's guidance, I'll be using a Service, to upload these images. It was recommended that I use a database to keep track of the successfully uploaded, and the pending files.
My initial research leads me to believe that I'll want to create a Bound Service, so I can update my UI once the photos have uploaded, as well as a Started Service, so it can run independent of my Activities that create it. It seems that I'll also need to start it in its own process via the process=":something" directive in the app manifest.
My question is, what would the best way of sharing an SQLite (unless there is a better way) database amongst the N activity clients and the uploader service?
I envision it working like this, in pseudo code:
// in an app
writeRecordToDb( . . . );
// start service
if( service doesn't exist )
{
// start service, and bind
}
// in the service:
if( shared db has another row )
{
doDownload( . . . );
if( download worked )
{
notifyActivity();
if( db has another row )
doDownload( . . . );
}
else
{
retryDownload( . . . );
}
}
Is this the correct way to go about this? I'm again attempting to circumvent the problem of having multiple Activity instances request photo uploads when there is little to no cellular signal. I've just finished reading though the Service and Bound Service docs, and I'm feeling good, but not great.
My initial research leads me to believe that I'll want to create a Bound Service
I wouldn't.
so I can update my UI once the photos have uploaded
You do not need to use the binding pattern to update the UI. You can:
send a local broadcast using LocalBroadcastManager that the activity picks up, or
invoke a PendingIntent supplied in an Intent extra on startActivity() by the activity, or
give Square's Otto event bus a try (looks interesting, but I haven't used it yet)
etc.
as well as a Started Service, so it can run independent of my Activities that create it
Which is why you should not bother with binding, as you do not need that, but you do need to start the service.
My question is, what would the best way of sharing an SQLite (unless there is a better way) database amongst the N activity clients and the uploader service?
Option #1: Keep your SQLiteOpenHelper in a static data member
Option #2: Use a ContentProvider wrapper around your database
Is this the correct way to go about this?
Using a database as a communications channel between components is akin to two next-door neighbors communicating with each other using a banner towed by a biplane. Yes, it works. However, it is slow and expensive.
(also, there's never a biplane when you need one, but I digress...)
If you wish to use a database as a backing store for pending downloads, in case there is some interruption (e.g., user powers down the device) and you wish to pick up those downloads later on, that's fine. However, the service will know what to download by the command you send to it via startService().
CommonsWare covers basically everything you need... but here is some code illustrating the two options just in case there is any confusion.
Keep your SQLiteOpenHelper in a static data member.
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper mInstance = null;
private static final String DATABASE_NAME = "databaseName";
private static final String DATABASE_TABLE = "tableName";
private static final int DATABASE_VERSION = 1;
private Context mCxt;
public static DatabaseHelper getInstance(Context ctx) {
/**
* use the application context as suggested by CommonsWare.
* this will ensure that you dont accidentally leak an Activitys
* context (see this article for more information:
* http://developer.android.com/resources/articles/avoiding-memory-leaks.html)
*/
if (mInstance == null) {
mInstance = new DatabaseHelper(ctx.getApplicationContext());
}
return mInstance;
}
/**
* constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context ctx) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.mCtx = ctx;
}
}
Then in your Service/Activity, keep a reference to your DatabaseHelper and call getInstance() on it.
Wrap the database in a ContentProvider. If you already have one implemented, then you can simply use
mContext.getContentResolver().query(...);
This works because Activity and Service both extend Context (which holds a reference to the ContentResolver).
I am creating a custom ContentProvider in Android, all the examples I find show the database name being hardcoded, instantiated like this:
public class ItemProvider extends ContentProvider {
private static String DATABASE_NAME = "xyz";
public static class ItemDatabaseHelper extends SQLiteOpenHelper {
ItemDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
What I want to do is use a variable for the database name at runtime, I dont want to hard code the database name in the class. I have tried to find examples of doing this using the ContentProvider class, and have looked through the documentation as well. I can do this if I shed the ContentProvider class and just use a SQLiteOpenHelper class because I can pass in the database name to the constructor as a parameter but I cannot figure out if its possible for ContentProvider. Here is how I get a variable name for the database using SQLiteOpenHelper:
public static class ItemDatabaseHelper extends SQLiteOpenHelper {
ItemDatabaseHelper(Context context, String dbname) {
super(context, dbname, null, DATABASE_VERSION);
}
Can anyone help me get a variable database name for a Content Provider?
Thanks.
I've not really used ContentProviders myself, but looking at the docs I'm guessing the root of the problem is that you don't instantiate the ContentProvider yourself, but that Android does when it is needed to handle a request.
If you want the database name to be defined at runtime by your application, then you could simply use a public static variable, which you set appropriately from another part of your application. You could then reference this from your ContentProvider.
Alternatively, if you're wanting the person who requests something from the ContentProvider to be able to specify the database to query, then from the docs it looks like you could use the path of the request URI to specify the database to query.
The structure of the request URI is detailed here: http://developer.android.com/guide/topics/providers/content-providers.html#urisum and further up this page it says:
The authority is what identifies the provider, not the path; your provider can interpret the path part of the URI in any way you choose.
So as an example, I would imagine you could use an URI of the form:
content://com.example.yourprovider/DB_REF/ID
Then in your implementation of the abstract methods of ContentProvider you could parse the URI to determine the DB to use.
One word of warning though - if you are going to use this approach, then I would suggest not using the value passed in directly. It would be much better to use some kind of validation against a finite list, so that people can't just query any of your databases (if they know their name).
Hopefully that makes sense :)
First, let me say that I've looked at lots of examples for ContentProvider code on the web, and the one that ended up helping me the most was this one:
http://mobile.tutsplus.com/tutorials/android/android-sdk_content-providers/
I have a very similar situation to yours, where I want to have several differently-named databases containing vehicle fuel mileage data. Each of the names consists of a vehicle name (specified by the user) and the current year, plus the fixed text "fuel_data" to make the database filenames human-readable.
Unlike all of the examples I found, I do not create an instance of the database in the ContentProvider's onCreate method. This is because I don't yet know the vehicle name at that point, thanks to the way my code is written (and the fact that ContentProviders are instantiated so early in the Activity lifecycle).
Once I do know the vehicle name (from which I can easily construct the database name), I call a simple little method that I added to my ContentProvider class. As you can see, all it does is close the prior database (if one was open) and open the new one (using the name that I now have available).
I call this method again every time the user selects a new vehicle.
` private static FuelDatabase mDB = null;
public static void switchDatabases( Context context, String newVehicleName )
{
if ( mDB != null )
{
mbB.close();
}
mDB = new FuelDatabase( context, newVehicleName + "." + getCurrentYear( context ) );
}`
Some backstory on my applications code organization:
Right now I'm kind of using a ad-hoc ORM for DB access, where each table is split up into a model (just a plain Java class not inheriting from any Android components) which covers normal CRUD activities.
I'm not using a content provider as all this data is private to the application.
I'm keeping a singleton of my databaseopenhelper, and the application context in my application's Application class
class MyApplication extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
dbHelper = new DatabaseHelper(this); // Subclass of SQLiteOpenHelper
}
public static Context getContext(){
return mContext;
}
All activities that touch the db open the database onResume, and close it onPause.
This seemed to be working fine until I started unit testing, when I ran into the first problem with using singletons - breaking encapsulation (specifically not being able use RenamingDelegatingContext to test with a specific test database).
So,
1) Something tells me if I can't unit test properly, my architecture is bunk - but I can't think of a better way to do this (short of passing context and dbhelpers explicitly - which is a pain)
2) If it is not an entirely crazy idea, what would be the best way to go about unit testing this setup?