Ich bin neu in Libgdx und ich bekomme Probleme mit einer Datenbank in meinem Spiel.Verwenden einer SQLite-Datenbank in Libgdx
Ich suchte nach einem Tutorial, wie SQLite funktioniert sowohl mit Android und Desktop-Anwendungen mit Libgdx, aber ich habe keine einfache gefunden.
Das letzte Mal, als ich eine Datenbank in Android verwendet habe, erstellte ich eine Klasse, die sich von SQLiteOpenHelper
erstreckt.
Gibt es eine einfache Möglichkeit, das Gleiche mit Libgdx zu tun? Oder kann mich jemand auf ein Schritt-für-Schritt-Tutorial oder ähnliches hinweisen?
EDIT
habe ich vergessen zu sagen, dass ich für etwas bin auf der Suche, die mich Versionen verwalten wie SQLiteOpenHelper
lassen. Mit anderen Worten, ich möchte meine Datenbank in Android auf apk-Installation neu erstellen, wenn ich die Version meines DB auf Code ändere.
SOLUTION
Nach @42n4
Antwort, ich schaffte es, wie SQLite Datenbank mit SQLiteOpenHelper
auf Android-Anwendung und JDBC
auf Desktop-Anwendung zu verbinden.
Zuerst habe ich eine "gemeinsame Klasse" für Desktop und Android Anwendungen:
//General class that needs to be implemented on Android and Desktop Applications
public abstract class DataBase {
protected static String database_name="recycling_separation";
protected static DataBase instance = null;
protected static int version=1;
//Runs a sql query like "create".
public abstract void execute(String sql);
//Identical to execute but returns the number of rows affected (useful for updates)
public abstract int executeUpdate(String sql);
//Runs a query and returns an Object with all the results of the query. [Result Interface is defined below]
public abstract Result query(String sql);
public void onCreate(){
//Example of Highscore table code (You should change this for your own DB code creation)
execute("CREATE TABLE 'highscores' ('_id' INTEGER PRIMARY KEY NOT NULL , 'name' VARCHAR NOT NULL , 'score' INTEGER NOT NULL);");
execute("INSERT INTO 'highscores'(name,score) values ('Cris',1234)");
//Example of query to get DB data of Highscore table
Result q=query("SELECT * FROM 'highscores'");
if (!q.isEmpty()){
q.moveToNext();
System.out.println("Highscore of "+q.getString(q.getColumnIndex("name"))+": "+q.getString(q.getColumnIndex("score")));
}
}
public void onUpgrade(){
//Example code (You should change this for your own DB code)
execute("DROP TABLE IF EXISTS 'highscores';");
onCreate();
System.out.println("DB Upgrade maded because I changed DataBase.version on code");
}
//Interface to be implemented on both Android and Desktop Applications
public interface Result{
public boolean isEmpty();
public boolean moveToNext();
public int getColumnIndex(String name);
public float getFloat(int columnIndex);
[...]
}
}
Dann habe ich eine DatabaseDesktop
Klasse für Desktop-Anwendung:
public class DatabaseDesktop extends DataBase{
protected Connection db_connection;
protected Statement stmt;
protected boolean nodatabase=false;
public DatabaseDesktop() {
loadDatabase();
if (isNewDatabase()){
onCreate();
upgradeVersion();
} else if (isVersionDifferent()){
onUpgrade();
upgradeVersion();
}
}
public void execute(String sql){
try {
stmt.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
public int executeUpdate(String sql){
try {
return stmt.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public Result query(String sql) {
try {
return new ResultDesktop(stmt.executeQuery(sql));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private void loadDatabase(){
File file = new File (database_name+".db");
if(!file.exists())
nodatabase=true;
try {
Class.forName("org.sqlite.JDBC");
db_connection = DriverManager.getConnection("jdbc:sqlite:"+database_name+".db");
stmt = db_connection.createStatement();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void upgradeVersion() {
execute("PRAGMA user_version="+version);
}
private boolean isNewDatabase() {
return nodatabase;
}
private boolean isVersionDifferent(){
Result q=query("PRAGMA user_version");
if (!q.isEmpty())
return (q.getInt(1)!=version);
else
return true;
}
public class ResultDesktop implements Result{
ResultSet res;
boolean called_is_empty=false;
public ResultDesktop(ResultSet res) {
this.res = res;
}
public boolean isEmpty() {
try {
if (res.getRow()==0){
called_is_empty=true;
return !res.next();
}
return res.getRow()==0;
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public boolean moveToNext() {
try {
if (called_is_empty){
called_is_empty=false;
return true;
} else
return res.next();
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public int getColumnIndex(String name) {
try {
return res.findColumn(name);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public float getFloat(int columnIndex) {
try {
return res.getFloat(columnIndex);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
[...]
}
}
Und ein DatabaseAndroid
für Android Anwendung
public class DatabaseAndroid extends DataBase{
protected SQLiteOpenHelper db_connection;
protected SQLiteDatabase stmt;
public DatabaseAndroid(Context context) {
db_connection = new AndroidDB(context, database_name, null, version);
stmt=db_connection.getWritableDatabase();
}
public void execute(String sql){
stmt.execSQL(sql);
}
public int executeUpdate(String sql){
stmt.execSQL(sql);
SQLiteStatement tmp = stmt.compileStatement("SELECT CHANGES()");
return (int) tmp.simpleQueryForLong();
}
public Result query(String sql) {
ResultAndroid result=new ResultAndroid(stmt.rawQuery(sql,null));
return result;
}
class AndroidDB extends SQLiteOpenHelper {
public AndroidDB(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public void onCreate(SQLiteDatabase db) {
stmt=db;
DatabaseAndroid.this.onCreate();
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
stmt=db;
DatabaseAndroid.this.onUpgrade();
}
}
public class ResultAndroid implements Result{
Cursor cursor;
public ResultAndroid(Cursor cursor) {
this.cursor=cursor;
}
public boolean isEmpty() {
return cursor.getCount()==0;
}
public int getColumnIndex(String name) {
return cursor.getColumnIndex(name);
}
public String[] getColumnNames() {
return cursor.getColumnNames();
}
public float getFloat(int columnIndex) {
return cursor.getFloat(columnIndex);
}
[...]
}
}
Schließlich, ich cha nged die Hauptklassen der beiden Android und Desktop-Anwendungen:
public class Main extends AndroidApplication {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialize(new MyGame(new DatabaseAndroid(this.getBaseContext())), false);
}
}
public class Main {
public static void main(String[] args) {
new LwjglApplication(new MyGame(new DatabaseDesktop()), "Example", MyGame.SCREEN_WIDTH, MyGame.SCREEN_HEIGHT,false);
}
}
Beachten Sie, dass:
ich eine Versionsverwaltung wie derjenige, der die PRAGMA user_version
in SQLiteOpenHelper
mit geschieht gemacht. Auf diese Weise ändere ich einfach die Version der Klasse DataBase
, wenn ich sie aktualisieren muss.
Ich habe nicht alle Methoden, die ich gemacht habe auf Result
gesetzt, aber ich habe diejenigen, die ich denke, die wichtiger sind. Das sind wichtiger.
Also, für Android und Desktop, ich lege eine Klasse mit dem Namen 'StatusData' richtig? In Android kann ich 'SQLiteOpenHelper' wie zuvor verwenden. Aber was ist mit der Desktop-Anwendung? Wie könnte ich beispielsweise die Desktop-Anwendung dazu bringen, die DB neu zu erstellen, wenn sich die DB-Version auf 'StatusData' ändert? –
Vielleicht wird es helfen: http://code.google.com/p/libgdx-users/wiki/SQLite – 42n4
Also, um klar zu sein, kann ich den 'SQLiteOpenHelper' auf Android verwenden und in Desktop könnte ich das gleiche machen Sache mit 'JDBC' und beide von ihnen sind in einer Klasse namens' StatusData' oder etwas ähnliches erstellt. Recht? –