在 Libgdx 中使用 SQLite 数据库
Posted
技术标签:
【中文标题】在 Libgdx 中使用 SQLite 数据库【英文标题】:Using a SQLite database in Libgdx 【发布时间】:2013-03-30 06:46:50 【问题描述】:我是 Libgdx 的新手,在我的游戏中使用数据库时遇到了麻烦。
我搜索了有关如何使用 Libgdx 使 SQLite 在 android 和桌面应用程序上运行的教程,但没有找到一个简单的教程。
上次在 Android 中使用数据库时,我创建了一个从 SQLiteOpenHelper
扩展的类。
有没有一种简单的方法可以使用 Libgdx 来做同样的事情?或者至少,任何人都可以向我指出一个分步教程或类似的东西吗?
编辑
我忘了说我正在寻找可以让我管理像SQLiteOpenHelper
这样的版本的东西。换句话说,当我在代码上更改我的数据库版本时,我想在安装 apk 时在 Android 中重新创建我的数据库。
解决方案
按照@42n4
的回答,我管理了如何在Android 应用程序上使用SQLiteOpenHelper
和在桌面应用程序上使用JDBC
连接到SQLite 数据库。
首先,我为桌面和 Android 应用程序创建了一个“通用类”:
//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);
[...]
然后,我为桌面应用程序创建了一个DatabaseDesktop
类:
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;
[...]
还有一个DatabaseAndroid
用于 Android 应用程序
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);
[...]
最后,我更改了 Android 和桌面应用程序的主要类:
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);
注意:
我使用PRAGMA user_version
进行了类似于SQLiteOpenHelper
中的版本管理。这样,我只需要在需要升级时更改DataBase
类的版本即可。
我没有把我所做的所有方法都放在Result
上,但是,我把我认为更重要的那些方法都放在了。那更重要。
【问题讨论】:
【参考方案1】:http://marakana.com/techtv/android_bootcamp_screencast_series.html 第 4 课,第 1 部分:Android 训练营 - statusData,用于 libgdx:http://code.google.com/p/libgdx-users/wiki/SQLite
编辑: 我应该提到 Udacity 的两门关于 libgdx 游戏的新课程: https://github.com/udacity/ud405
https://github.com/udacity/ud406
【讨论】:
那么,对于 Android 和桌面,我创建了一个名为StatusData
的类,对吗?在 Android 中,我可以像以前一样使用SQLiteOpenHelper
。但是桌面应用程序呢?例如,当StatusData
上的数据库版本更改时,我如何让桌面应用程序重新创建数据库?
所以,为了清楚起见,我可以在 Android 上使用 SQLiteOpenHelper
,在桌面上我可以使用 JDBC
做同样的事情,它们都是在名为 StatusData
的类上创建的或类似的东西。对吗?
我认为那个网站甚至有一个例子,尝试实现它。
我已经尝试过第二个教程,但我卡住了,因为我不知道如何在更改数据库内容时重新创建数据库,也不知道如何将 SQLDroid 添加到我当前的项目中.无论如何,感谢您的帮助 =)。【参考方案2】:
我编写了一个扩展程序(称为 gdx-sqlite),它可以完成您需要的大部分工作。可以从here 下载此扩展的最新版本。源代码和读我位于:https://github.com/mrafayaleem/gdx-sqlite
此扩展目前支持 Android 和桌面平台。此外,不支持打开位于 Android 应用程序资产文件夹中的数据库。不过,这是一项待定的功能,很快就会添加。
按照阅读我的说明设置您的项目以进行数据库处理。以下是示例代码:
package com.mrafayaleem.gdxsqlitetest;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.sql.Database;
import com.badlogic.gdx.sql.DatabaseCursor;
import com.badlogic.gdx.sql.DatabaseFactory;
import com.badlogic.gdx.sql.SQLiteGdxException;
public class DatabaseTest
Database dbHandler;
public static final String TABLE_COMMENTS = "comments";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_COMMENT = "comment";
private static final String DATABASE_NAME = "comments.db";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table if not exists "
+ TABLE_COMMENTS + "(" + COLUMN_ID
+ " integer primary key autoincrement, " + COLUMN_COMMENT
+ " text not null);";
public DatabaseTest()
Gdx.app.log("DatabaseTest", "creation started");
dbHandler = DatabaseFactory.getNewDatabase(DATABASE_NAME,
DATABASE_VERSION, DATABASE_CREATE, null);
dbHandler.setupDatabase();
try
dbHandler.openOrCreateDatabase();
dbHandler.execSQL(DATABASE_CREATE);
catch (SQLiteGdxException e)
e.printStackTrace();
Gdx.app.log("DatabaseTest", "created successfully");
try
dbHandler
.execSQL("INSERT INTO comments ('comment') VALUES ('This is a test comment')");
catch (SQLiteGdxException e)
e.printStackTrace();
DatabaseCursor cursor = null;
try
cursor = dbHandler.rawQuery("SELECT * FROM comments");
catch (SQLiteGdxException e)
e.printStackTrace();
while (cursor.next())
Gdx.app.log("FromDb", String.valueOf(cursor.getString(1)));
try
dbHandler.closeDatabase();
catch (SQLiteGdxException e)
e.printStackTrace();
dbHandler = null;
Gdx.app.log("DatabaseTest", "dispose");
【讨论】:
以上是关于在 Libgdx 中使用 SQLite 数据库的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ActionResolver 创建 jdbc sqlite 连接?