【说明】
Cocos2d-x已经集成了SQLite3,但是并未做加密处理,处于安全考虑,一般不会直接使用。wxSQLite3是一个开源项目,是对SQLite3的C++封装,并做了加密处理,使用起来也很方便。这里介绍我集成wxSQLite3的过程,期间参考了其他大神的文章,后面已做说明。
【下载】
http://sourceforge.net/projects/wxcode/files/Components/wxSQLite3/
【集成】
1. 下载wxSQLite3后解压,将 wxsqlite3-3.2.1\sqlite3\secure\src 文件夹拷贝到项目中。
2. 由于wxSQLite3内部已经引用,所以在Xcode中只需要引用 “sqlite3.h” 和 “sqlite3secure.c” 两个文件,引用其他文件会导致编译出错。
3. 由于我们需要用到加密功能,所以需要在 “sqlite3.h” 和 “sqlite3secure.c” 两个文件中都添加启用加密宏定义。这里我没有使用预编译宏定义的方式,是因为我更倾向于使用平台无关的方式。但是这里要注意添加的位置,否则可能会编译出错。
#ifndef SQLITE_HAS_CODEC #define SQLITE_HAS_CODEC #endif
5. 以上是在Xcode上的集成过程,对于Android平台,需要编写一个一个 Android.mk 文件。这段借鉴网上文章,我还没实践。
LOCAL_PATH := $(call my-dir) #清理变量定义 include $(CLEAR_VARS) #模块名称 LOCAL_MODULE := wxsqlite3_static #库文件名称 LOCAL_MODULE_FILENAME := libwxsqlite3 #定义预编译宏 LOCAL_CFLAGS += -DSQLITE_HAS_CODEC ##该宏用于开启加密功能,我已经把定义写到代码里了,这里可以不要 #源文件 LOCAL_SRC_FILES := src/sqlite3secure.c LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src #头文件目录 LOCAL_C_INCLUDES := $(LOCAL_PATH)/src #构建静态库 include $(BUILD_STATIC_LIBRARY)在 jni/Android.mk 中(不一定是这个,反正就是在应用的Android.mk中)添加引用:
<pre name="code" class="cpp">LOCAL_CFLAGS += -DSQLITE_HAS_CODEC #该宏用于开启加密功能 LOCAL_WHOLE_STATIC_LIBRARIES += wxsqlite3_static #引入静态库 $(call import-module,../Classes/wxsqlite3) #引入模块 (Android.mk位置)
【使用】
使用部分可以参考Cocos2d-x自带的 LocalStorage 类,加密功能需要在 “sqlite3_open()” 和 “sqlite3_close()” 之间调用 “sqlite3_key()” 设置密码。
// SET KEY #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) sqlite3_key(_db, key.c_str(), (int)key.size()); #endif
最后附上我封(xiu)装(gai)的类,基本上都是 LocalStorage 的代码,只做了一点点修改。原本我是做成单例模式的,后来打算把集中存储合并到一个存储类里面,方便使用,就改成了普通类。前面才是重点,这部分不重要。
//==================================================================================== // LSqlite.h // Local storage by sqlite3. // Use wxsqlite3 in order to encrypt data. // Created by Dolphin Lee. //==================================================================================== #ifndef __L_SQLITE_H__ #define __L_SQLITE_H__ #include "cocos2d.h" USING_NS_CC; #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) #include "sqlite3.h" #else #include "wxsqlite3/sqlite3.h" #endif //==================================================================================== class LSqlite { public: /** * Constructor function. */ LSqlite(); /** * Frees the allocated resources and close database. */ ~LSqlite(); public: /** * Initializes the database. If path is null, it will create an in-memory DB. * @param filename Name of database file. (like "data.db") * @param key The key to encrypt database. */ void init(const std::string& filename, const std::string& key); /** * Sets an item in the LS. * The item is divided into key and values. */ void setItem(const std::string& key, const std::string& value); /** * Gets an item from the LS. * Will return the value according to key. */ std::string getItem(const std::string& key); /** * Removes an item from the LS. * Will delete the value according to key. */ void removeItem(const std::string& key); protected: /** * Initializes the database. If path is null, it will create an in-memory DB. * @param fullpath Full path with file name. * @param key The key to encrypt database. */ void initWithFullpath(const std::string& fullpath, const std::string& key); /** * Create table in the database. * This function has been invoked in init, you don't need to call. */ void createTable(); private: int _initialized; sqlite3 *_db; sqlite3_stmt *_stmt_select; sqlite3_stmt *_stmt_remove; sqlite3_stmt *_stmt_update; }; //==================================================================================== #endif
//==================================================================================== // LSqlite.cpp //==================================================================================== #include "LSqlite.h" #include <stdio.h> #include <stdlib.h> #include <assert.h> //==================================================================================== // Create //==================================================================================== /** constructors */ LSqlite::LSqlite() { _initialized = 0; _db = nullptr; _stmt_select = nullptr; _stmt_remove = nullptr; _stmt_update = nullptr; } /** free database */ LSqlite::~LSqlite() { if( _initialized ) { sqlite3_finalize(_stmt_select); sqlite3_finalize(_stmt_remove); sqlite3_finalize(_stmt_update); sqlite3_close(_db); _initialized = 0; } } /** create table */ void LSqlite::createTable() { const char *sql_createtable = "CREATE TABLE IF NOT EXISTS data(key TEXT PRIMARY KEY,value TEXT);"; sqlite3_stmt *stmt; int ok=sqlite3_prepare_v2(_db, sql_createtable, -1, &stmt, NULL); ok |= sqlite3_step(stmt); ok |= sqlite3_finalize(stmt); if( ok != SQLITE_OK && ok != SQLITE_DONE) { printf("[sqlite3] Error in CREATE TABLE\n"); } } /** init database */ void LSqlite::initWithFullpath( const std::string& fullpath, const std::string& key) { if( ! _initialized ) { int ret = 0; // OPEN DATABASE if (fullpath.empty()) { ret = sqlite3_open(":memory:",&_db); } else { ret = sqlite3_open(fullpath.c_str(), &_db); } // SET KEY #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) sqlite3_key(_db, key.c_str(), (int)key.size()); #endif // EXPAND FUNCTION //sqlite3_exec(_db, "PRAGMA synchronous = OFF", 0 ,0, 0); // 提交性能 //sqlite3_exec(_db, "PRAGMA cache_size = 8000", 0 ,0, 0); // 加大缓存 //sqlite3_exec(_db, "PRAGMA count_changes = 1", 0 ,0, 0); // 返回改变记录数 //sqlite3_exec(_db, "PRAGMA case_sensitive_like = 1", 0 ,0, 0); // 支持中文LIKE查询 // CREATE TABLE createTable(); // SELECT const char *sql_select = "SELECT value FROM data WHERE key=?;"; ret |= sqlite3_prepare_v2(_db, sql_select, -1, &_stmt_select, NULL); // REPLACE const char *sql_update = "REPLACE INTO data (key, value) VALUES (?,?);"; ret |= sqlite3_prepare_v2(_db, sql_update, -1, &_stmt_update, NULL); // DELETE const char *sql_remove = "DELETE FROM data WHERE key=?;"; ret |= sqlite3_prepare_v2(_db, sql_remove, -1, &_stmt_remove, NULL); if( ret != SQLITE_OK ) { printf("[sqlite3] Error initializing DB\n"); // report error } _initialized = 1; } } //==================================================================================== // Functions //==================================================================================== /** init database */ void LSqlite::init(const std::string& filename, const std::string& key) { std::string path = FileUtils::getInstance()->getWritablePath(); path += filename; initWithFullpath(path, key); } /** sets an item in the LS */ void LSqlite::setItem( const std::string& key, const std::string& value) { assert( _initialized ); int ok = sqlite3_bind_text(_stmt_update, 1, key.c_str(), -1, SQLITE_TRANSIENT); ok |= sqlite3_bind_text(_stmt_update, 2, value.c_str(), -1, SQLITE_TRANSIENT); ok |= sqlite3_step(_stmt_update); ok |= sqlite3_reset(_stmt_update); if( ok != SQLITE_OK && ok != SQLITE_DONE) { printf("[sqlite3] Error in locaLSqlite.setItem()\n"); } } /** gets an item from the LS */ std::string LSqlite::getItem( const std::string& key ) { assert( _initialized ); std::string ret; int ok = sqlite3_reset(_stmt_select); ok |= sqlite3_bind_text(_stmt_select, 1, key.c_str(), -1, SQLITE_TRANSIENT); ok |= sqlite3_step(_stmt_select); const unsigned char *text = sqlite3_column_text(_stmt_select, 0); if (text) { ret = (const char*)text; } if( ok != SQLITE_OK && ok != SQLITE_DONE && ok != SQLITE_ROW) { printf("[sqlite3] Error in locaLSqlite.getItem()\n"); } return ret; } /** removes an item from the LS */ void LSqlite::removeItem( const std::string& key ) { assert( _initialized ); int ok = sqlite3_bind_text(_stmt_remove, 1, key.c_str(), -1, SQLITE_TRANSIENT); ok |= sqlite3_step(_stmt_remove); ok |= sqlite3_reset(_stmt_remove); if( ok != SQLITE_OK && ok != SQLITE_DONE) { printf("[sqlite3] Error in locaLSqlite.removeItem()\n"); } } //==================================================================================== // //====================================================================================
【参考】
http://blog.csdn.net/linchaolong/article/details/41286297
http://www.yiwuye.com/archives/cocos2d-x-encrpt-sqlite.html
http://www.cocoachina.com/bbs/read.php?tid=199953