此教程是sqlite3数据库在android平台下的移植方案,而非创建sqlite3数据库的教程
首先附上解决方案,然后用代码来说明思路。
1.首先新建一个数据库,并且填好数据(可以用代码创建,也可以用Navicat for sqlite来创建)。
2.如果在win32平台使用,则把数据库复制到 FileUtils::getInstance()->getWritablePath() 目录下。
3.为了在android平台下也可以使用该数据库,我们需要把数据库放到win32项目的Resources下面。然后在安装apk之后,把Resources目录下的数据库复制到android平台的data/data/包名/files下面,之后使用的时候就从该目录下(FileUtils::getInstance()->getWritablePath())获取。
------- 进行第三步骤的原因: 在Resources目录下的资源,在打包的时候,会自动复制一份在assets目录下,而android 采用sqlite3_open是无法访问assets目录下的数据库(assets目录下的图片资源无此问题,因此可以直接用Resources目录下的图片资源),为此我们需要在android工程下面加入以下代码,将数据库拷贝到/data/data/ 下面。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这里要说明,Android不能读取的原因,是因为对数据库的操作必须有root权限,也就是说,我们的应用程序只能对系统提供的特定目录中的数据库文件进行操作。
实现拷贝过程的代码如下:
首先需要说明两个重要的API函数:
FileUtils::getInstance()->getWritablePath(); 获取各个平台的可读写路径
FileUtils::getInstance()->fullPathForFilename(name);获取某个资源的全路径,如Resources/HelloWorld.png
在程序启动时,检查sqlite是否存在,不存在,则复制一份------------------
AppDelegate.h
bool isFileExist(const char* pFileName);
//把数据库拷贝到android的data/data/package/files下面
void copyData(const char* pFileName);
//删除android下的数据库
bool deleteDB(const char* dbName_willDel);
//当前数据库版本号
string cur_DBVersion;
bool AppDelegate::isFileExist(const char* pFileName)
{
if (!pFileName)
{
return false;
}
// data/data/包名/files/myName.db
std::string filePath= FileUtils::getInstance()->getWritablePath();
filePath += pFileName;
if (FileUtils::getInstance()->isFileExist(filePath))
{
return true;
}
return false;
}
void AppDelegate::copyData(const char* pFileName)
{
std::string strPath = FileUtils::getInstance()->fullPathForFilename(pFileName);
ssize_t len = 0;
unsigned char* data = NULL;
data = FileUtils::getInstance()->getFileData(strPath.c_str(), "r", &len);
//可写路径
std::string destPath = FileUtils::getInstance()->getWritablePath();
destPath += pFileName;
FILE *pFp = fopen(destPath.c_str(), "w+");
fwrite(data, sizeof(char), len, pFp);
fclose(pFp);
delete[]data;
data = NULL;
}
bool AppDelegate::deleteDB(const char* dbName_willDel)
{
if (!isFileExist(dbName_willDel))
{
return false;
}
std::string destPath = FileUtils::getInstance()->getWritablePath();
destPath += dbName_willDel;
FileUtils::getInstance()->removeFile(destPath);
return true;
}
把数据库复制到android平台特定目录下:
void AppDelegate::copyDataBaseToAndroid()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) //Android下需要复制数据文件
//检查数据库文件是否已经提取 如果数据库版本不一致,则复制
if (isFileExist(DB_NAME) == false)
{
//没有数据库直接复制
copyData(DB_NAME);
}
// 有数据库,判断版本号是否一致
else if (isFileExist(DB_NAME))
{
//提取版本号
DBUtil::getDataInfoFromDBVersion("select * from DBVersion", NULL);
if (DBUtil::vec_DBVersion.size() > 0)
{
//此集合只会存在一个
cur_DBVersion = "1.0";
cur_DBVersion = JsonUtils::getStringFromJson("DB_version");
if (DBUtil::vec_DBVersion.at(0)->getDB_version() != cur_DBVersion)
{
//先删除之前的数据库,再复制新的数据库
deleteDB(DB_NAME);
copyData(DB_NAME);
}
}
else
{
//数据库中,dbversion表为空
deleteDB(DB_NAME);
copyData(DB_NAME);
}
}
#endif
}
使用时,在程序启动之后,调用 copyDataBaseToAndroid()即可。
注意事项: 此处我用了一个表来控制数据库的版本(如果项目支持热更新,则不需要采用此方案来对比数据库版本,copyDataBaseToAndroid()不具备通用方案)。
DBVersion表的关键目的是,当应用程序是覆盖安装时,先判断之前的数据库版本号,如果版本不一样,则覆盖掉之前的数据库。如果版本一样,不执行操作。
表名DBVersion
参考链接: http://sxd616616.blog.163.com/blog/static/1697125201361821430501/
http://blog.youkuaiyun.com/zy19940906/article/details/47726613