使用JsonCpp在android NDK中解析Json

Json是一个轻量级的数据交换格式,在许多地方被经常用到。在开发android程序时有时候跟服务器通讯,也需要用到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

# 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

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

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"。

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

jni/test/Android.mk

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

#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端的接口,注意加载库的先后顺序:

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

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

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

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值