开发MTK平台的机器一般比较幸福,非常友好的支持(对比国外大厂),N多国内运营商的功能支持早有实现,比如T9。但是开发高大上的高通咋办?木有T9啊。不过目前有多种方案可选则。
static void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jlong connectionPtr,
jobject functionObj) {
...
int err = sqlite3_create_function_v2(connection->db, name, numArgs, SQLITE_UTF16,
reinterpret_cast(functionObjGlobal),
&sqliteCustomFunctionCallback, NULL, NULL, &sqliteCustomFunctionDestructor);
...
}
注册方法中使用sqlite3_create_function_v2方法注册custom方法,这个和C++代码的添加方式是基本一样的。
static void sqliteCustomFunctionCallback(sqlite3_context *context,
int argc, sqlite3_value **argv) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
// Get the callback function object.
// Create a new local reference to it in case the callback tries to do something
// dumb like unregister the function (thereby destroying the global ref) while it is running.
jobject functionObjGlobal = reinterpret_cast(sqlite3_user_data(context));
jobject functionObj = env->NewLocalRef(functionObjGlobal);
jobjectArray argsArray = env->NewObjectArray(argc, gStringClassInfo.clazz, NULL);
if (argsArray) {
for (int i = 0; i < argc; i++) {
const jchar* arg = static_cast(sqlite3_value_text16(argv[i]));
if (!arg) {
ALOGW("NULL argument in custom_function_callback. This should not happen.");
} else {
size_t argLen = sqlite3_value_bytes16(argv[i]) / sizeof(jchar);
jstring argStr = env->NewString(arg, argLen);
if (!argStr) {
goto error; // out of memory error
}
env->SetObjectArrayElement(argsArray, i, argStr);
env->DeleteLocalRef(argStr);
}
}
// TODO: Support functions that return values.
env->CallVoidMethod(functionObj,
gSQLiteCustomFunctionClassInfo.dispatchCallback, argsArray);
error:
env->DeleteLocalRef(argsArray);
}
env->DeleteLocalRef(functionObj);
if (env->ExceptionCheck()) {
ALOGE("An exception was thrown by custom SQLite function.");
LOGE_EX(env);
env->ExceptionClear();
}
}
上面是java层custom方法回调的代码,可以看出完全没有返回值的相关代码(sqlite中的返回值是通过sqlite3_result_int等方法返回的,并不是通过return语句,sqlite定义的custom方法返回值都是void )。这样java层的代码只能是干些无返回值的活,例如MediaProvider中是在删除数据库的时候删除对应项目的文件。