使用JsonCpp在android NDK中解析Json

使用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.mkjsonjsoncpp.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

  1. #itisneededforndk-r5
  2. #APP_STL:=stlport_static
  3. APP_STL:=gnustl_static
  4. APP_MODULES:=jsoncppmain


2、项目的Android.mk,指定了要编译的两个子Android.mk
jni/Android.mk
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. subdirs:=$(LOCAL_PATH)/test/Android.mk
  4. subdirs+=$(LOCAL_PATH)/jsoncpp/Android.mk
  5. include$(subdirs)

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

jni/jsoncpp/Android.mk

  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=jsoncpp
  4. LOCAL_CPPFLAGS:=-DJSON_IS_AMALGAMATION-fexceptions
  5. LOCAL_SRC_FILES:=jsoncpp.cpp
  6. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/json
  7. #itisusedforndk-r5
  8. #ifyoubuildwithndk-r4,commentit
  9. #becausethenewWindowstoolchaindoesn'tsupportCygwin'sdrive
  10. #mapping(i.e/cygdrive/c/insteadofC:/)
  11. LOCAL_LDLIBS:=-L$(callhost-path,$(LOCAL_PATH)/../../libs/armeabi)
  12. include$(BUILD_SHARED_LIBRARY)

4、我们的测试程序的make file。注意LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jsoncpp这一行,我们指定了头文件的地址为,当前路径(即$project/jni/test/)的上一级的jsoncpp文件夹,即$project/jni/jsoncpp/,这样在使用中我们需要inlcude的就是 "json/json.h"。
  1. LOCAL_LDLIBS:=-L$(callhost-path,$(LOCAL_PATH)/../../libs/armeabi)\
  2. -ljsoncpp-llog
这里则指定使用的库libjsoncpp和liblog

jni/test/Android.mk

  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=main
  4. #forjsoncpp
  5. LOCAL_CPPFLAGS:=-DJSON_IS_AMALGAMATION
  6. LOCAL_SRC_FILES:=main.cpp
  7. LOCAL_C_INCLUDES:=$(LOCAL_PATH)/../jsoncpp
  8. #itisusedforndk-r5
  9. #ifyoubuildwithndk-r4,$(LOCAL_PATH)/../../libs/armeabi)\
  10. -ljsoncpp-llog
  11. include$(BUILD_SHARED_LIBRARY)


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

jni/test/main.cpp

  1. #include<jni.h>
  2. #include<android/log.h>
  3. #include"json/json.h"
  4. #defineLOG_TAG"main"
  5. #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  6. extern"C"
  7. {
  8. jstringJava_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson(jnienv*env,jobjectthiz,jintid,jstringname){
  9. jbooleaniscopy=0;
  10. constchar*c_name=env->GetStringUTFChars(name,&iscopy);
  11. LOGD("oncalling,id:%d,name:%s",id,c_name);
  12. //tobuildajsonobjectwithidandname
  13. Json::Valueuser;
  14. user["id"]=id;
  15. user["name"]=c_name;
  16. constchar*json_str=user.toStyledString().c_str();
  17. jstringresult=env->NewStringUTF(json_str);
  18. env->ReleaseStringUTFChars(name,c_name);
  19. returnresult;
  20. }/*Java_com_kevin_tutorial_jsoncpp_ToUseJsoncppActivity_toBuildJson*/
  21. }/*extern"C"*/

6、java端的接口,注意加载库的先后顺序:
  1. System.loadLibrary("jsoncpp");
  2. System.loadLibrary("main");

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

  1. packagecom.kevin.tutorial.jsoncpp;
  2. importandroid.app.Activity;
  3. importandroid.os.Bundle;
  4. importandroid.util.Log;
  5. importandroid.view.View;
  6. importandroid.view.View.OnClickListener;
  7. importandroid.widget.Button;
  8. publicclassToUseJsoncppActivityextendsActivity{
  9. privatestaticfinalStringTAG="ToUseJsoncppActivity.java";
  10. @Override
  11. publicvoidonCreate(BundlesavedInstanceState){
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.main);
  14. ButtonbtnOk=(Button)findViewById(R.id.btnOk);
  15. btnOk.setonClickListener(newOnClickListener(){
  16. @Override
  17. publicvoidonClick(Viewv){
  18. //TodoAuto-generatedmethodstub
  19. intid=1001;
  20. Stringname="Kevin";
  21. Stringresult=toBuildJson(id,name);
  22. Log.i(TAG,String.format("Id:%1$d,Name:%2$s,Thejsonformatedstring:%3$s",name,result));
  23. }
  24. });
  25. }
  26. privatestaticnativeStringtoBuildJson(intid,Stringname);
  27. static{
  28. System.loadLibrary("jsoncpp");
  29. System.loadLibrary("main");
  30. }
  31. }


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下测试通过,完整项目见附件:

。。。不知道怎么上传附件

相关文章

AJAX是一种基于JavaScript和XML的技术,能够使网页实现异步交...
在网页开发中,我们常常需要通过Ajax从后端获取数据并在页面...
在前端开发中,经常需要循环JSON对象数组进行数据操作。使用...
AJAX(Asynchronous JavaScript and XML)是一种用于创建 We...
AJAX技术被广泛应用于现代Web开发,它可以在无需重新加载页面...
Ajax是一种通过JavaScript和HTTP请求交互的技术,可以实现无...