搞了好久Android 一直没搞过NDK开发
以前被卡在环境搭建
后面Android Studio 支持NDK之后
又被没有C++代码提示卡住了
最近发现用vscode写C++代码有代码提示后
封装一个sqlite3的库试试水
总结
我发现如果不去熟悉源码,很多方法使用都是不科学的。
- 首先就是Android自带的Cusor.getColumnIndex 我发现源码是读取查询结果所有列名之后 将列名放在hashmap里面 再从haspmap里面查找index 如果sql语句是自己写的那个列在第几个位置完全知道 不需要掉这个方法 虽然浪费不了多少时间
- 其次就是Cusor.getCount 方法 sqlite3的源码里面我就没有找到获取查询结果行数的方法
我也没有找到源码是怎么实现的 我猜估计是执行过一次sql select count(*) from 不然我也想不到其他高效的方法了 这个方法只能说能不用尽量不用吧
开发环境
怎么搭建就不说了 百度一大堆
写说明下最重要的2点
- 第一 VSCODE代码提示
c_cpp_properties.json 配置JNI的头文件地址 配置好之后就有代码提示了
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include",
"E:\\android_sdk\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\sysroot\\usr\\include\\",
"E:\\android_sdk\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\sysroot\\usr\\include\\c++\\v1",
"E:\\android_sdk\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\sysroot\\usr\\include\\x86_64-linux-android"
],
"defines": ["_DEBUG", "UNICODE", "_UNICODE"],
"compilerPath": "E:\\soft\\TDM-GCC-64\\bin\\gcc.exe",
"cStandard": "gnu11",
"cppStandard": "gnu++98",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}
- 第二 NDK编译
Android现在推荐用的CMAKE编译 需要把编译的文件添加到这个列表
网上好像有自动添加所有文件的代码 问题我加上之后 就一直卡在编译中
只能放弃了
CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library(native-lib SHARED
native-lib.cpp
include/changeType.cpp
sqlite/shell.c
sqlite/sqlite3.c
sqlite/sqliteDb.cpp
)
#include的文件夹
include_directories(jniSTDualCamPreview
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sqlite
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
sqlite3库的引入
可以去官网下载 源码SQLite Home Page
sqlite3操作介绍
- 打开数据库
bool SqliteDb::open(const char* file)
{
//返回值: 成功返回SQLITE_OK,失败返回其他值。
// 一个打开的数据库实例
// 根据文件路径打开数据库连接。如果数据库不存在,则创建。
// 数据库文件的路径必须以C字符串传入。
int result = sqlite3_open_v2(file, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
if (result == SQLITE_OK) {
LOGE("打开数据库连接成功");
return true;
}
else {
LOGE("打开数据库连接失败");
return false;
}
}
- 关闭数据库
void SqliteDb::close(){
if(db!=NULL)
{
if(inTransaction)
{
commitTransaction();
}
sqlite3_close(db);
db=NULL;
}
}
- 执行sql
bool SqliteDb::execSql(const char* sql)
{
if(db==NULL)
{
return false;
}
// const char *sqlSentence = "INSERT INTO t_person(name, age) VALUES('夏明', 22); "; //SQL语句
sqlite3_stmt *stmt = NULL; //stmt语句句柄
//进行插入前的准备工作——检查语句合法性
//-1代表系统会自动计算SQL语句的长度
int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//执行该语句
sqlite3_step(stmt);
LOGE("执行SQL成功");
}
else {
LOGE("SQL语句有误");
}
//清理语句句柄,准备执行下一个语句
sqlite3_finalize(stmt);
return result == SQLITE_OK;
}
- 执行查询语句
sqlite3_stmt * SqliteDb::querySql(const char* sql){
// const char *sqlSentence = "SELECT name, age FROM t_person WHERE age < 30;"; //SQL语句
sqlite3_stmt *stmt = NULL; // stmt语句句柄
//进行查询前的准备工作——检查语句合法性
//-1代表系统会自动计算SQL语句的长度
int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//每调一次sqlite3_step()函数,stmt语句句柄就会指向下一条记录
// while (sqlite3_step(stmt) == SQLITE_ROW) {
// // 取出第0列字段的值
// const unsigned char *name = sqlite3_column_text(stmt, 0);
// // 取出第1列字段的值
// int age = sqlite3_column_int(stmt, 1);
// //输出相关查询的数据
// // std::clog << "name = " << name <<", age = "<< age;
// }
// LOGE("执行SQL成功");
return stmt;
}
else {
LOGE("SQL语句有误");
//清理语句句柄,准备执行下一个语句
sqlite3_finalize(stmt);
return NULL;
}
}
- 查询结果的读取
要封装的方法太多了 只封装了几个重要的方法
//获取查询结果的列数
int getColumnCount(sqlite3_stmt* stmt){
return sqlite3_column_count(stmt);
}
//销毁以防止内存泄露
void closeCusor(sqlite3_stmt* stmt){
if(stmt!=NULL)
{
sqlite3_finalize(stmt);
stmt=NULL;
}
}
//查询结果读取下一行
extern "C" JNIEXPORT jboolean JNICALL Java_com_test_sqlite_SqliteDb_moveNext(JNIEnv* env,
jobject /* this */
,jlong ptr)
{
if(ptr==0)
{
return 0;
}
sqlite3_stmt* stmt=(sqlite3_stmt*)ptr;
if(sqlite3_step(stmt) == SQLITE_ROW)
{
return 1;
}
else{
return 0;
}
}
//获取列名
extern "C" JNIEXPORT jstring JNICALL Java_com_test_sqlite_SqliteDb_getColumnName(JNIEnv* env,
jobject /* this */
,jlong ptr,int index)
{
if(ptr==0)
{
return NULL;
}
sqlite3_stmt* stmt=(sqlite3_stmt*)ptr;
int count=getColumnCount(stmt);
if(index>=count)
{
return NULL;
}
const char* name=sqlite3_column_name(stmt,index);
jstring str=env->NewStringUTF(name);
return str;
}
//获取结果中的int值
extern "C" JNIEXPORT jint JNICALL Java_com_test_sqlite_SqliteDb_getColumnInt(JNIEnv* env,
jobject /* this */
,jlong ptr,int index)
{
if(ptr==0)
{
return 0;
}
sqlite3_stmt* stmt=(sqlite3_stmt*)ptr;
int count=getColumnCount(stmt);
if(index>=count)
{
return 0;
}
int value=sqlite3_column_int(stmt,index);
return value;
}
//获取结果中的double值
extern "C" JNIEXPORT jdouble JNICALL Java_com_test_sqlite_SqliteDb_getColumnDouble(JNIEnv* env,
jobject /* this */
,jlong ptr,int index)
{
if(ptr==0)
{
return 0;
}
sqlite3_stmt* stmt=(sqlite3_stmt*)ptr;
int count=getColumnCount(stmt);
if(index>=count)
{
return 0;
}
double value=sqlite3_column_double(stmt,index);
return value;
}
//获取结果中的string值
extern "C" JNIEXPORT jstring JNICALL Java_com_test_sqlite_SqliteDb_getColumnString(JNIEnv* env,
jobject /* this */
,jlong ptr,int index)
{
if(ptr==0)
{
return NULL;
}
sqlite3_stmt* stmt=(sqlite3_stmt*)ptr;
int count=getColumnCount(stmt);
if(index>=count)
{
return NULL;
}
const unsigned char* value=sqlite3_column_text(stmt,index);
jstring str=unsigchar2jstring(env,value);
return str;
}
分享代码
链接:https://pan.baidu.com/s/1PrSV8Ry9tvcSjl3yB5YqEA?pwd=4fow
提取码:4fow