使用JsonCpp在android NDK中解析Json

來源:互聯網
上載者:User

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_staticAPP_STL := gnustl_staticAPP_MODULES := jsoncpp main

2、項目的Android.mk,指定了要編譯的兩個子Android.mk
jni/Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)subdirs := $(LOCAL_PATH)/test/Android.mksubdirs += $(LOCAL_PATH)/jsoncpp/Android.mkinclude $(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 := jsoncppLOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATION -fexceptionsLOCAL_SRC_FILES := jsoncpp.cppLOCAL_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 jsoncppLOCAL_CPPFLAGS := -DJSON_IS_AMALGAMATIONLOCAL_SRC_FILES := main.cppLOCAL_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 -lloginclude $(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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubint 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下測試通過,完整項目見附件:

。。。不知道怎麼上傳附件

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.