1

i m trying to code a simple sqlite code with javafxports.

build.gradle:

    buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.0.6'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url "https://oss.sonatype.org/content/repositories/snapshots/"
    }
    maven {
        url "https://oss.sonatype.org/content/repositories/releases"
    }

}

ext.CHARM_DOWN_VERSION = "1.0.0"

dependencies{
    compile 'org.xerial:sqlite-jdbc:3.8.11'

    compile "com.gluonhq:charm-down-common:$CHARM_DOWN_VERSION"
    desktopRuntime "com.gluonhq:charm-down-desktop:$CHARM_DOWN_VERSION"
    androidRuntime "com.gluonhq:charm-down-android:$CHARM_DOWN_VERSION"
    iosRuntime "com.gluonhq:charm-down-ios:$CHARM_DOWN_VERSION"
}
mainClassName = 'com.gluonapplication.version16'

jfxmobile {
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses= ['com.gluonhq.**.*', 'org.sqlite.**.*']
    }
}

my JavaCode:

public static Label msg = new Label();

@Override
public void start(Stage stage) {
    StackPane root = new StackPane();

    root.getChildren().add(msg);
    Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
    Scene scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());

    stage.getIcons().add(new Image(version16.class.getResourceAsStream("/icon.png")));
    stage.setScene(scene);
    stage.show();

    try {
        testSqli();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
public static void testSqli() throws SQLException, ClassNotFoundException {
    String driver = "org.sqlite.JDBC";
    //Class.forName("SQLite.JDBCDriver");
    Class.forName(driver);
    String dbName = "mtt8.db";
    String dbUrl = "jdbc:sqlite:" + dbName;

    //create table
    Statement st = null;
    Connection conn = DriverManager.getConnection(dbUrl);
    st = conn.createStatement();
    st.executeUpdate("DROP TABLE IF EXISTS village;");
    st.executeUpdate("CREATE table village (id int, name varchar(20))");
    //insert row?
    st.executeUpdate("INSERT INTO village VALUES (111, 'Concretepage')");

    //select?
    String query = "SELECT id, name from village";
    ResultSet rs = null;
    rs = st.executeQuery(query);

    while (rs.next()) {
        int id = 0;
        id = rs.getInt(1);
        String name = null;
        name = rs.getString(2);
        msg.setText("id:" + id + ", name: " + name);
        System.out.println("id:" + id + ", name: " + name);
        st.executeUpdate("DELETE from village");
        rs.close();
    }
}

and i send it with ./gradlew launchIOSDevice and get following error:

java.sql.SQLException: opening db: 'mtt8.db': open failed: EPERM (Operation not permitted)
    at org.sqlite.core.CoreConnection.open(CoreConnection.java:203)
    at org.sqlite.core.CoreConnection.<init>(CoreConnection.java:76)
    at org.sqlite.jdbc3.JDBC3Connection.<init>(JDBC3Connection.java:24)
    at org.sqlite.jdbc4.JDBC4Connection.<init>(JDBC4Connection.java:23)
    at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:45)
    at org.sqlite.JDBC.createConnection(JDBC.java:114)
    at org.sqlite.JDBC.connect(JDBC.java:88)
    at java.sql.DriverManager.getConnection(DriverManager.java:179)
    at java.sql.DriverManager.getConnection(DriverManager.java:144)
    at com.gluonapplication.version16.testSqli(version16.java:48)
    at com.gluonapplication.version16.start(version16.java:32)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.LauncherImpl$$Lambda$81.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl$$Lambda$93.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at com.sun.javafx.application.PlatformImpl$$Lambda$105.run(Unknown Source)
    at java.security.AccessController.doPrivileged(AccessController.java:52)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.javafx.application.PlatformImpl$$Lambda$92.run(Unknown Source)
    at org.robovm.apple.uikit.UIApplication.main(Native Method)
    at org.robovm.apple.uikit.UIApplication.main(UIApplication.java:369)
    at org.javafxports.jfxmobile.ios.BasicLauncher.main(BasicLauncher.java:115)
IOSWindowSystemInterface : setSwapInterval unimp
setSwapInterval(1)

can anybody help me please, how can i give an acces in my code so that i can create a sqlite DB ?

thanks erkan kaplan

  • What is the file permission on the directory where you are trying to create the database file? – ItachiUchiha Nov 11 '15 at 13:01
  • hi, i dont know. I deploy it in my Ipad with "./gredlew launchIOSDevice" but if i try on Desktop with "./gredlew run" then is everthing is ok, i can see my DB and working with SELECT, UPDATE etc...Only on Ipad dont working this code above. – erkan kaplan Nov 11 '15 at 13:33

2 Answers2

1

As @ItachiUchiha points out, your issue is related to the place where you are trying to create the database:

String dbUrl = "jdbc:sqlite:" + dbName;
Connection conn = DriverManager.getConnection(dbUrl);

The URL you are providing may work on your desktop, but not on a mobile device, where the app has a very restricted access to the storage, and it has granted access only to a private local storage.

Using the Gluon's open source library Charm-Down, it's very easy to get the path of that local storage, regardless the platform the app is running on.

First, add these dependencies to your build.gradle script:

ext.CHARM_DOWN_VERSION = "1.0.0"
dependencies {
    compile "com.gluonhq:charm-down-common:$CHARM_DOWN_VERSION"
    desktopRuntime "com.gluonhq:charm-down-desktop:$CHARM_DOWN_VERSION"
    androidRuntime "com.gluonhq:charm-down-android:$CHARM_DOWN_VERSION"
    iosRuntime "com.gluonhq:charm-down-ios:$CHARM_DOWN_VERSION"
}

And now, on your code, the URL should be:

try {
    File dir = PlatformFactory.getPlatform().getPrivateStorage();
    File db = new File (dir, dbName);
    String dbUrl = "jdbc:sqlite:" + db.getAbsolutePath();
    Connection conn = DriverManager.getConnection(dbUrl);
    ...
} catch (Exception e) { }
José Pereda
  • 44,311
  • 7
  • 104
  • 132
  • Hi Jose, I edit my **build.gradle** above and add "charm" lines and forceLinkClasses....if i try **"./gredlew clean"** and **"./gredlew build"** i get following Error: `/Users/erkankaplan/Downloads/version16/src/main/java/com/gluonapplication/version16.java:54: error: cannot find symbol File dir = PlatformFactory.getPlatform().getPrivateStorage(); ^ symbol: method getPlatform() location: class PlatformFactory 1 error :compileJava FAILED` – erkan kaplan Nov 11 '15 at 14:15
  • and on the line **"File dir = PlatformFactory.getPlatform().getPrivateStorage();"** is **"getPlatform()"** red marked (also error)......I have IntelliJ 5.0CE and Gluon 1.0.1 installed... – erkan kaplan Nov 11 '15 at 14:19
  • Make sure you sync your project (Refresh button at Gradle toolbar) every time you add dependencies. After that, try to clean and build again, the dependencies should be there. – José Pereda Nov 11 '15 at 14:21
  • Hi Jose, now is all ok after i click refresh button on Gradle toolbar on the right side above, also **getPlatform()** is now ok and i can see 2x plugins (gluon--charm and sqlite-jdbc) under "External Libraries".... – erkan kaplan Nov 11 '15 at 14:38
  • But i get following error:`:launchIOSDevice FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':launchIOSDevice'. > -32703 * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED` – erkan kaplan Nov 11 '15 at 14:39
  • what's mean with -32703 ? – erkan kaplan Nov 11 '15 at 14:39
  • I have never seen that. Try to run from command line `./gradlew --stacktrace launchIOSDevice`. – José Pereda Nov 11 '15 at 14:41
  • I've tested it and found the same exception. It seems the `org.xerial` dependency is not valid for iOS. Following this [link](http://stackoverflow.com/a/28651165/3956070), you can use `SQLite.JDBCDriver`, which doesn't require any dependency, just `"SQLite.**.*"` on forceLinkClasses – José Pereda Nov 11 '15 at 15:51
  • bigggg thanks jose :-) i love you so much :-)....now i can get connect to mysql and result saved in sqlite.db .. – erkan kaplan Nov 11 '15 at 16:08
  • Jose, another problem is, same code dont work on Samsung Tablet.. do you have a idea why dont work on samsung? – erkan kaplan Nov 11 '15 at 16:42
  • Yes, you need another SQLite dependency for android... Add a new question with this? – José Pereda Nov 11 '15 at 16:43
  • Sure, you can use same code, but you need to load different drivers depending on the platform. Please create a new question, it will be easier to explain and people will be able to use it. – José Pereda Nov 11 '15 at 16:54
  • thanks jose for you help......here is new question: http://stackoverflow.com/questions/33655851/javafxports-and-sqlite-on-android-device – erkan kaplan Nov 11 '15 at 17:06
0

A BIG THANKS TO JOSE,

here is my build.gradle , so i can connect to mysql-server on my Lan and results save as sqlite.db on Ipad-Devices;

buildscript {
    repositories {
        jcenter()
        mavenCentral()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
    }
    dependencies { classpath 'org.javafxports:jfxmobile-plugin:1.0.6' }
}

apply plugin: 'org.javafxports.jfxmobile'


repositories {
    jcenter()
    mavenCentral()
    maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
    maven { url 'https://oss.sonatype.org/content/repositories/releases' }
}

ext.CHARM_DOWN_VERSION = "1.0.0"

dependencies {
    compile 'mysql:mysql-connector-java:3.1.12'
    compile 'org.xerial:sqlite-jdbc:3.9.0-SNAPSHOT'

    compile "com.gluonhq:charm-down-common:$CHARM_DOWN_VERSION"
    desktopRuntime "com.gluonhq:charm-down-desktop:$CHARM_DOWN_VERSION"
    androidRuntime "com.gluonhq:charm-down-android:$CHARM_DOWN_VERSION"
    iosRuntime "com.gluonhq:charm-down-ios:$CHARM_DOWN_VERSION"
}




mainClassName = 'com.mtt8.version15'

jfxmobile {
    android {
        manifest = 'src/android/AndroidManifest.xml'
        packagingOptions {
            exclude 'META-INF/INDEX.LIST'
        }
    }

    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = ['com.mtt8.**.*', 'com.mysql.**.*', 'SQLite.**.*', 'com.gluonhq.**.*']
    }

}

and sqlite.java

import com.gluonhq.charm.down.common.PlatformFactory;

import java.io.File;
import java.io.IOException;
import java.sql.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;



/**
 * Created by erkankaplan on 10.11.15.
 */
public class sqliteDBConnector {

    public static void testSqli() throws SQLException, ClassNotFoundException{
        Class.forName("SQLite.JDBCDriver");

        String dbName = "mtt8.db";
        File dir = null;
        try {
            dir = PlatformFactory.getPlatform().getPrivateStorage();
        } catch (IOException e) {
            e.printStackTrace();
        }

        File db = new File (dir, dbName);
        String dbUrl = "jdbc:sqlite:" + db.getAbsolutePath();




        Connection conn = DriverManager.getConnection(dbUrl);

        //create table
        Statement st=null;

            st = conn.createStatement();
            st.executeUpdate("DROP TABLE IF EXISTS village;");
        st.executeUpdate("CREATE table village (id int, name varchar(20))");
            //insert row
            st.executeUpdate("INSERT INTO village VALUES (111, 'Concretepage')");

        //select
        String query = "SELECT id, name from village";
        ResultSet rs = null;

                rs = st.executeQuery(query);

                while(rs.next()) {
                    int id = 0;
                    id = rs.getInt(1);

                    String name = null;

                        name = rs.getString(2);

                    System.out.println("id:"+ id+ ", name: "+ name);
                st.executeUpdate("DELETE from village");
                rs.close();

        }

    }

}