说明:
android的NDK本来就提供了zlib库,但是由于zlib相对简单,所以我第一次编译的就是zlib,只是为了了解一下大概如何编译的思路。
这里使用的zlib的版本是zlib-1.2.3。
(1)使用ndk-build的方式
解压zlib包后,将其放入JNI文件夹下,目录树结构如下:
NDK#tree -L 3 . ├── prj_zlib │ └── jni │ └── zlib-1.2.3 └── zlib-1.2.3.tar在jni目录下,新建Android.mk(注意大写)文件,其内容如下:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) include $(CLEAR_VARS) LOCAL_SRC_FILES := mytest.c LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_STATIC_LIBRARIES := libzlib LOCAL_MODULE := libmyzlibtest include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH))
其中,mytest.c为使用JNI封装zlib函数的测试例子,内容如下(根据需要去调用):
#include <jni.h> #include "zlib.h" #include <string.h> jstring chartojstring( JNIEnv* env, const char* pat) { /*jclass strClass = (*env)->FindClass(env,"java/lang/String;"); jmethodID ctorID = (*env)->GetMethodID(env,strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat)); (*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = (*env)->NewStringUTF(env,"utf-8"); return (jstring)(*env)->NewObject(env,strClass, ctorID, bytes, encoding); */ /* jstring stoJstring(JNIEnv* env, const char* pat) { jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF("utf-8"); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } */ return (*env) -> NewStringUTF(env, pat); } char* jstringTostring(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env, "utf-8"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); jsize alen = (*env)->GetArrayLength(env, barr); jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); return rtn; } jbyteArray Java_com_hello_zlib_ZlibActivity_compressStr(JNIEnv* env, jobject thiz, jstring str) { char* strSrc = jstringTostring(env, str); Byte buff[1024]={0}; unsigned long bufLen = sizeof(buff)/sizeof(buff[0]); int ret = compress(buff, &bufLen, strSrc, strlen(strSrc) + 1); if (Z_OK != ret) { memcpy(buff, "error", strlen("error")+1 ); } jbyteArray retArray = (*env)->NewByteArray(env, bufLen); (*env)->SetByteArrayRegion(env, retArray, 0, bufLen, buff); return retArray; } jstring Java_com_hello_zlib_ZlibActivity_uncompressStr(JNIEnv* env, jobject thiz, jbyteArray bArray) { jsize length = (*env)->GetArrayLength(env, bArray); jbyte* pArrayByte = (*env)->GetByteArrayElements(env, bArray, 0); unsigned char buff[1024]={0}; unsigned long bufLen = sizeof(buff)/sizeof(buff[0]); int ret = uncompress(buff, &bufLen, pArrayByte, length); /* if (Z_OK != ret) { memcpy(buff, "error", strlen("error")+1); } */ if (Z_DATA_ERROR == ret) { memcpy(buff, "data_error", strlen("data_error")+1); } if (Z_BUF_ERROR == ret) { memcpy(buff, "buf_error", strlen("buf_error")+1); } if (Z_MEM_ERROR == ret) { memcpy(buff, "mem_error", strlen("mem_error")+1); } return chartojstring(env, buff); } jstring Java_com_hello_zlib_ZlibActivity_getVersion(JNIEnv* env, jobject thiz) { const char* version= zlibVersion(); return chartojstring(env, version); }在jni下的zlib-1.2.3文件夹下新建Android.mk,内容如下:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := adler32.c compress.c crc32.c deflate.c gzio.c infback.c inffast.c inflate.c inftrees.c minigzip.c trees.c uncompr.c zutil.c LOCAL_MODULE:= libzlib include $(BUILD_STATIC_LIBRARY)最后,整个”工程“目录树如下(说明,只有在上面的Android.mk中列举的相关的c文件和对应的h文件对编译有用,所以下面显示的目录树将原本zlib源码中的其它无关文件和文件夹删除了):
$tree . ├── prj_zlib │ └── jni │ ├── Android.mk │ ├── mytest.c │ └── zlib-1.2.3 │ ├── adler32.c │ ├── Android.mk │ ├── compress.c │ ├── crc32.c │ ├── crc32.h │ ├── deflate.c │ ├── deflate.h │ ├── example.c │ ├── gzio.c │ ├── infback.c │ ├── inffast.c │ ├── inffast.h │ ├── inffixed.h │ ├── inflate.c │ ├── inflate.h │ ├── inftrees.c │ ├── inftrees.h │ ├── minigzip.c │ ├── trees.c │ ├── trees.h │ ├── uncompr.c │ ├── zconf.h │ ├── zconf.in.h │ ├── zlib.3 │ ├── zlib.h │ ├── zutil.c │ └── zutil.h └── zlib-1.2.3.tar 3 directories, 30 files
$ls prj_zlib zlib-1.2.3.tar $cd prj_zlib/ $ls jni $NDK/ndk-build Compile thumb : myzlibtest <= mytest.c Compile thumb : zlib <= adler32.c Compile thumb : zlib <= compress.c Compile thumb : zlib <= crc32.c Compile thumb : zlib <= deflate.c Compile thumb : zlib <= gzio.c Compile thumb : zlib <= infback.c Compile thumb : zlib <= inffast.c Compile thumb : zlib <= inflate.c Compile thumb : zlib <= inftrees.c Compile thumb : zlib <= minigzip.c Compile thumb : zlib <= trees.c Compile thumb : zlib <= uncompr.c Compile thumb : zlib <= zutil.c StaticLibrary : libzlib.a SharedLibrary : libmyzlibtest.so Install : libmyzlibtest.so => libs/armeabi/libmyzlibtest.so $下面是在android中调用上面的.so中函数的代码:
package com.hello.zlib; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class ZlibActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String version = getVersion(); String comSrc = "中文测试 EnglishTesting 1234567890\n" + "中文测试 EnglishTesting 1234567890\n" + "中文测试 EnglishTesting 1234567890\n" + "中文测试 EnglishTesting 1234567890\n" + "中文测试 EnglishTesting 1234567890"; byte[] comByte = compressStr(comSrc); String uncomStr = uncompressStr(comByte); String str = "Ther version of zlib is: " + version + "\n\n"; str = str + "SrcStr: \n" + comSrc + "\nLen: " + comSrc.length() + "\n\n"; str = str + "Com byte: \n" + comByte + "\nLen: " + comByte.length + "\n\n"; str = str + "Un-com Str: \n" + uncomStr + "\nLen: " + uncomStr.length() + "\n\n"; TextView tx = (TextView) findViewById(R.id.txt); tx.setText(str); } public native String getVersion(); public native byte[] compressStr(String str); public native String uncompressStr(byte b[]); static { System.loadLibrary("myzlibtest"); } }这样,就在jni下的libs中生成了libmyzlibtest.so了,编译完成。
(2)使用GCC
略。