您的位置:首页 > 移动开发 > Android开发

使用JsonCpp在android NDK中解析Json

2013-08-20 06:51 597 查看

使用JsonCpp在android NDK中解析Json

如果在android SDK环境下,则自带了org.json库,不需要再自行编译。如果在NDK环境下,本人没有找到系统自带的(压根没去找。。),故而决定使用json cpp。在将json cpp集成进去时,发觉网上没有相关的文章,就顺手写写,希望能帮到有需要的人。

JsonCpp是一个开源的Cpp用的json库,下载地址:
http://sourceforge.net/projects/jsoncpp/files/jsoncpp/0.6.0-rc2/
注意下载jsoncpp-src-0.6.0-rc2-amalgamation.tar.gz,这个版本将.h和.cpp合并在一起,而且不需要再configure。(它的make系统我觉得很奇怪。。)

下载完毕后解压缩,放到$project/jni下($project是项目根目录,下同)。

为了避免以后重复编译JsonCpp,所以决定把它编成动态库,独立出来。顺便建立一个测试程序main,放在test下边。路径具体如下:

tree $project/jni/

////////////////////////////////

Android.mk

Application.mk

jsoncpp

-------Android.mk json jsoncpp.cpp

test

-------Android.mk main.cpp

(mac没有tree命令,将就下)

1、JsonCpp用到了stl的exception,所以如果你在android的编译系统的Application文件中指定STL库路径时,如果使用: APP_STL := stlport_static,那么就无法通过编译。需要改成:APP_STL := gnustl_static

jni/Application.mk

[plain]
view plaincopyprint?

# it is needed for ndk-r5 #APP_STL := stlport_static APP_STL := gnustl_static APP_MODULES := jsoncpp main

# it is needed for ndk-r5
#APP_STL := stlport_static
APP_STL := gnustl_static
APP_MODULES := jsoncpp main


2、项目的Android.mk,指定了要编译的两个子Android.mk

jni/Android.mk

[plain]
view plaincopyprint?

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

subdirs := $(LOCAL_PATH)/test/Android.mk
subdirs += $(LOCAL_PATH)/jsoncpp/Android.mk

include $(subdirs)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

subdirs := $(LOCAL_PATH)/test/Android.mk
subdirs += $(LOCAL_PATH)/jsoncpp/Android.mk

include $(subdirs)


3、jsoncpp的make file。注意LOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION -fexceptions 这一行。宏定义JSON_IS_AMALGAMATION告诉jsoncpp是amalgamation版本,即是我们刚才下载的版本。-fexceptions则开启exception应用。

jni/jsoncpp/Android.mk

[plain]
view plaincopyprint?

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jsoncpp LOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION -fexceptions LOCAL_SRC_FILES := jsoncpp.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH)/json # it is used for ndk-r5 # if you build with ndk-r4, comment it # because the new Windows toolchain doesn't support Cygwin's drive # mapping (i.e /cygdrive/c/ instead of C:/) LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jsoncpp
LOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION -fexceptions

LOCAL_SRC_FILES := jsoncpp.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/json

# it is used for ndk-r5
# if you build with ndk-r4, comment it
# because the new Windows toolchain doesn't support Cygwin's drive
# mapping (i.e /cygdrive/c/ instead of C:/)
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi)

include $(BUILD_SHARED_LIBRARY)


4、我们的测试程序的make file。注意LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jsoncpp这一行,我们指定了头文件的地址为,当前路径(即$project/jni/test/)的上一级的jsoncpp文件夹,即$project/jni/jsoncpp/,这样在使用中我们需要inlcude的就是 "json/json.h"。

[plain]
view plaincopyprint?

LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) \ -ljsoncpp -llog

LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) \
-ljsoncpp -llog
这里则指定使用的库libjsoncpp和liblog

jni/test/Android.mk

[plain]
view plaincopyprint?

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
# for jsoncpp
LOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION

LOCAL_SRC_FILES := main.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jsoncpp

# it is used for ndk-r5
# if you build with ndk-r4, comment it
# because the new Windows toolchain doesn't support Cygwin's drive
# mapping (i.e /cygdrive/c/ instead of C:/)
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) \ -ljsoncpp -llog

include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
# for jsoncpp
LOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION

LOCAL_SRC_FILES := main.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jsoncpp

# it is used for ndk-r5
# if you build with ndk-r4, comment it
# because the new Windows toolchain doesn't support Cygwin's drive
# mapping (i.e /cygdrive/c/ instead of C:/)
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/armeabi) \ -ljsoncpp -llog

include $(BUILD_SHARED_LIBRARY)


5、测试程序文件main.cpp。因为是cpp,所以与java函数的接口就加extern "C",要不编译后会找不到函数名。jsoncpp 的使用很简单,就是定义一个Json::Value,然后把数据填进去就行了,它会根据数据类型重载的。
jni/test/main.cpp

[plain]
view plaincopyprint?

#include <jni.h> #include <android/log.h> #include "json/json.h" #define LOG_TAG "main" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) extern "C" { jstring Java_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson(JNIEnv* env, jobject thiz,jint id,jstring name){ jboolean isCopy = 0; const char* c_name = env->GetStringUTFChars(name, &isCopy); LOGD("on calling,id:%d,name:%s",id,c_name); // to build a json object with id and name Json::Value user; user["id"] = id; user["name"] = c_name; const char* json_str = user.toStyledString().c_str(); jstring result = env->NewStringUTF(json_str); env->ReleaseStringUTFChars(name,c_name); return result; } /* Java_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson */ } /* extern "C" */
#include <jni.h>
#include <android/log.h>
#include "json/json.h"

#define  LOG_TAG    "main"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

extern "C"
{
jstring Java_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson(JNIEnv*  env, jobject thiz,jint id,jstring name){
jboolean isCopy = 0;
const char* c_name = env->GetStringUTFChars(name, &isCopy);
LOGD("on calling,id:%d,name:%s",id,c_name);
// to build a json object with id and name
Json::Value user;
user["id"] = id;
user["name"] = c_name;
const char* json_str = user.toStyledString().c_str();
jstring result = env->NewStringUTF(json_str);
env->ReleaseStringUTFChars(name,c_name);
return result;
} /* Java_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson */

} /* extern "C" */


6、java端的接口,注意加载库的先后顺序:

[java]
view plaincopyprint?

System.loadLibrary("jsoncpp"); System.loadLibrary("main");

System.loadLibrary("jsoncpp");
System.loadLibrary("main");


$project/src/com/kevin/tutorial/jsoncpp/ToUseJsoncppActivity.java

[java]
view plaincopyprint?

package com.kevin.tutorial.jsoncpp;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ToUseJsoncppActivity extends Activity {

private static final String TAG = "ToUseJsoncppActivity.java";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button btnOk = (Button)findViewById(R.id.btnOk);
btnOk.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

int id = 1001;
String name = "Kevin";
String result = toBuildJson(id, name);
Log.i(TAG,String.format("Id:%1$d,Name:%2$s,The json formated string:%3$s", id,name,result));
}
});
}

private static native String toBuildJson(int id,String name);

static {
System.loadLibrary("jsoncpp"); System.loadLibrary("main");
}
}

package com.kevin.tutorial.jsoncpp;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ToUseJsoncppActivity extends Activity {

private static final String TAG = "ToUseJsoncppActivity.java";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button btnOk = (Button)findViewById(R.id.btnOk);
btnOk.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = 1001;
String name = "Kevin";
String result = toBuildJson(id, name);
Log.i(TAG,String.format("Id:%1$d,Name:%2$s,The json formated string:%3$s", id,name,result));
}
});
}

private static native String toBuildJson(int id,String name);

static {
System.loadLibrary("jsoncpp"); System.loadLibrary("main");
}
}


7、最后在项目路径下,ndk-build编译(需配置ndk的环境变量)。注意如果以前有使用过APP_STL := stlport_static,那么在build之前需要ndk-build clean一下。

然后android update project -p ./ 建立ant,再ant debug install,安装到机器上。

mac v10.6.8,android 2.3.3,android-ndk-r6b下测试通过,完整项目见附件:
。。。不知道怎么上传附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: