[SOLVED] AndroidLauncher: Setting a Context?

Anything libgdx related goes here!

[SOLVED] AndroidLauncher: Setting a Context?

Postby shatterblast » Thu Jun 14, 2018 2:58 am

So I am trying to copy a SQLite database from the APK file to " /data/data/ ... whatever ... / databases/ ". I found some code that would seem to do the job, but all examples seem to require the "Context" variable. I would love to hard-code it, but apparently, that is a bad practice. Also, I am not sure how to pull assets from the APK directly in any measure.

Do I need to have a Context set? If so, how should I do that with just the beginnings of the AndroidLauncher class? Thank you for your time.

In case it benefits anyone, here is some code:

Code: Select all
   /**
    * Copy database file from assets folder inside the apk to the system database path.
    * @param context Context
    * @param databaseName Database file name inside assets folder
    * @param overwrite True to rewrite on the database if exists
    * @return True if the database have copied successfully or if the database already exists without overwrite, false otherwise.
    */
   private boolean copyDatabaseFromAssets( Context context, String databaseName, boolean overwrite )  {

      File outputFile = context.getDatabasePath( databaseName );

      if ( outputFile.exists() && !overwrite ) {

         return true;

      }

      outputFile = context.getDatabasePath( databaseName + ".temp" ) ;
      outputFile.getParentFile().mkdirs();

      try {

         InputStream inputStream = context.getAssets().open( databaseName );
         OutputStream outputStream = new FileOutputStream( outputFile );


         // transfer bytes from the input stream into the output stream
         byte[] buffer = new byte[1024];
         int length;

         while ( ( length = inputStream.read( buffer ) ) > 0 ) {

            outputStream.write( buffer, 0, length );

         }

         // Close the streams
         outputStream.flush();
         outputStream.close();
         inputStream.close();

         outputFile.renameTo( context.getDatabasePath( databaseName ) );

      } catch (IOException e) {

         if ( outputFile.exists() ) {

            outputFile.delete();

         }

         return false;

      }

      return true;

   }
Last edited by shatterblast on Thu Jun 14, 2018 3:12 am, edited 1 time in total.
shatterblast
 
Posts: 126
Joined: Sun Jul 06, 2014 1:14 pm

Re: AndroidLauncher: Setting a Context?

Postby shatterblast » Thu Jun 14, 2018 3:10 am

I accidentally got it working. I used " this " for the Context field, so it reads as follows:

Code: Select all
copyDatabaseFromAssets( this, "test.db", true );



Here is the complete code block in case it helps someone:

Code: Select all
public class AndroidLauncher extends AndroidApplication {

   @Override
   protected void onCreate ( Bundle savedInstanceState ) {

      super.onCreate( savedInstanceState );
      AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();

      copyDatabaseFromAssets( this, "test.db", true );

      initialize( new SSSTest_MAIN(), config );

   }


   /**
    * Copy database file from assets folder inside the apk to the system database path.
    * @param context Context
    * @param databaseName Database file name inside assets folder
    * @param overwrite True to rewrite on the database if exists
    * @return True if the database have copied successfully or if the database already exists without overwrite, false otherwise.
    */
   private boolean copyDatabaseFromAssets( Context context, String databaseName, boolean overwrite )  {

      File outputFile = context.getDatabasePath( databaseName );

      if ( outputFile.exists() && !overwrite ) {

         return true;

      }

      outputFile = context.getDatabasePath( databaseName + ".temp" ) ;
      outputFile.getParentFile().mkdirs();

      try {

         InputStream inputStream = context.getAssets().open( databaseName );
         OutputStream outputStream = new FileOutputStream( outputFile );


         // transfer bytes from the input stream into the output stream
         byte[] buffer = new byte[1024];
         int length;

         while ( ( length = inputStream.read( buffer ) ) > 0 ) {

            outputStream.write( buffer, 0, length );

         }

         // Close the streams
         outputStream.flush();
         outputStream.close();
         inputStream.close();

         outputFile.renameTo( context.getDatabasePath( databaseName ) );

      } catch (IOException e) {

         if ( outputFile.exists() ) {

            outputFile.delete();

         }

         return false;

      }

      return true;

   }

}


---------------------------------------------

Edit:

I do not know how long it will last with the new released styles of Java in the future, but the " com.rgi-corp.sqldroid " version of SQLDroid works very well for AndroidLauncher. The " org.xerial " version of the SQLite JDBC driver functions great for the DesktopLauncher. These two, of course, come from the " Gdx-setup.jar " setup. These both operate together in IntelliJ IDEA Ultimate, but the " ./gradlew " should slide.


Appropriate links for the Xerial SQLite JDBC driver:

http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.xerial%22%20AND%20a%3A%22sqlite-jdbc%22

https://github.com/xerial/sqlite-jdbc


On the Desktop side of things, I use the following through Xerial's driver:

Code: Select all
Connection connectorForDB = DriverManager.getConnection( "jdbc:sqlite::resource:database/test.db" );


The Desktop side should automatically detect the SQLite Driver. I think that is a Java 8 thing, but I do not remember. The reason I use the " :: resource: " part is because it will treat your Runnable JAR as a normal file space. Do keep in mind that stuff inside a JAR is read-only, so you will need to put something outside of the Runnable JAR in some form if you want to save a game status. This basic layout works for Eclipse as well, but I would advise to just give up on Eclipse if you want to build a LibGDX project for Android or iOS. Gradle will still work and Android Studio as well to some degree.


---------------------------------------------

Appropriate links for the SQLDroid SQLite JDBC driver:

http://search.maven.org/#search%7Cga%7C1%7Csqldroid

https://github.com/SQLDroid/SQLDroid


On the Android side of things, I use the following through the SQLDroid driver:

Code: Select all
try {

   try {

      DriverManager.registerDriver( ( Driver ) Class.forName( "org.sqldroid.SQLDroidDriver" ).newInstance() );

   } catch ( Exception e ) {

      throw new RuntimeException( "Failed to register SQLDroidDriver" );

   }

   Connection connectorForDB = DriverManager.getConnection( "jdbc:sqldroid:" + databaseURL );

    ... other SQL stuff ...

}



The basic concept is that you need to follow the directions exactly as listed in SQLDroid's GitHub site, because this is Android we are focusing on. The Desktop environment operates differently in regards to Android. The code block will work the same for either version of the SQLDroid driver on the Maven site, so it is just a matter of choosing the best one. Unless things change, go with the " com.rgi-corp.sqldroid " version. Avoid the " org.sqldroid " version, unless you need "Flyaway" for some definite reason. (As of the time of this posting, I am not using Flyaway. It is meant for SQL migrations.) SQLDroid spoofs the Java compiler into thinking that Android allows JDBC-style connections. That is why you need to explicitly define " DriverManager.registerDriver() ".


---------------------------------------------

My Gradle dependencies for the "Core" module (sub-project):

Code: Select all
project(":core") {
    apply plugin: "java"


    dependencies {
        compile "com.badlogicgames.gdx:gdx:$gdxVersion"
        compile "com.esotericsoftware.spine:spine-libgdx:3.6.52.1"
        compile "com.rgi-corp.sqldroid:SQLDroid:0.1.1"
        compile "org.xerial:sqlite-jdbc:3.23.1"

    }
}



---------------------------------------------

At the minimum, this means you can keep Android and Desktop "modules" (sub-projects) together in the same project space. Android code will treat SQL code the same as it does on the Desktop side with these two drivers.

I hope this helps any others on this path.
shatterblast
 
Posts: 126
Joined: Sun Jul 06, 2014 1:14 pm


Return to Libgdx

Who is online

Users browsing this forum: No registered users and 1 guest