7

I've created a Qt dynamic lib that uses Qt SQL to open an SQLite database, but I'm getting this error:

QSqlDatabase: QSQLITE driver not loaded
QSqlDatabase: available drivers: 

The DLL was working fine as part of a Qt Android application, however I need to use it through JNI from an existing Java application developed in Eclipse.

This is the shortest example code that reproduces the problem. I load the library from Java and call its init() method:

System.loadLibrary("plugins_sqldrivers_libqsqlite");
System.loadLibrary("Qt5Sql");
System.loadLibrary("MyQtLib");
MyQtLib.init();

And inside the Qt library I just call QSqlDatabase::addDatabase():

JNIEXPORT void JNICALL Java_test_MyQtLib_foo(JNIEnv *, jclass)
{
    // Manually create a QCoreApplication instance.
    int argc = 1;
    static char arg[] = "";
    static char *arg2 = arg;
    app = new QCoreApplication(argc, &arg2);
    // Try to add an SQLite db connection.
    QSqlDatabase::addDatabase("QSQLITE");
}

Since the error is QSQLITE driver not loaded, and the Qt library was working inside a Qt application, I assume that Qt is doing some initialization that I'm missing.

But this didn't remove the error, so it must be something else. Normally, the Qt application will use QtApplication.java and QtActivity.java to perform some initialization, so they must be doing something more there that I'm not doing.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • might help you... http://stackoverflow.com/questions/15944120/how-to-install-mysql-c-driver-on-windows – AngryDuck Jul 24 '15 at 13:08
  • @AngryDuck Thanks for the link, but I couldn't find anything relevant to my question except the error message is the same. This guy is on Windows instead of Android, and his use-scenario is completely different - he doesn't load a Qt shared library in an existing Eclipse android project. Did you have some specific reason to post the link, i.e. am I missing something? – sashoalm Jul 25 '15 at 16:25

1 Answers1

5

Eventually I stepped into the Qt sources to see how the SQLITE plugin is loaded (for the desktop build at least).

The relevant function was QFactoryLoader::update(). In it I noticed that it iterates all the directories in QCoreApplication::libraryPaths():

QStringList paths = QCoreApplication::libraryPaths();
for (int i = 0; i < paths.count(); ++i) {

If any of them has a sub-directory named "sqldrivers", it goes inside it and tries to load all the dynamic libraries in that sub-directory.

I then printed out the library paths in a test project I ran directly from Qt Creator - qDebug() << a.libraryPaths();, and I saw this path - /data/data/org.qtproject.example.untitled/qt-reserved-files/plugins. In this directory on my android phone there was a subdirectory named sqldrivers, that contained a single file - libqsqlite.so.

I then checked the .java files, and indeed QtActivity::startApp() adds the library path:

boolean bundlingQtLibs = false;
if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
    && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
    localPrefix = getApplicationInfo().dataDir + "/";
    pluginsPrefix = localPrefix + "qt-reserved-files/";
    cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
    extractBundledPluginsAndImports(pluginsPrefix);
    bundlingQtLibs = true;
}

The solution then would be to ensure that there is a sqldrivers/libqsqlite.so somewhere on the phone, and then add the parent folder of sqldrivers to the library path using QCoreApplication::addLibraryPath().

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • Dude you saved my life. I had the same problem and stayed blocked several days. Your post help me a lot Thank you very much!!!! – suns9 Jul 30 '16 at 13:46
  • I stayed blocked several days too. At the end I thought if this helps at least one person it's worth posting, considering how much of a blocker this problem was. Why did you wait several days before hitting SO though? – sashoalm Jul 30 '16 at 16:06
  • Because I started reading again and again the qt doc to try understanding the driver deployment part. But after days of reading this did not unblock my situation. I also tried to use sqlite3 in my app but this was also too hard to import in the native part of my app – suns9 Aug 01 '16 at 09:14