![]()
今回はデータ圧縮/解凍用のzlibをAndroidのネイティブ環境から利用してみる。基本的な流れは前回のSQLiteを利用したときと同じだ。
http://www.zlib.net/からzlibのソースコードをダウンロードする。今回はzlib 1.2.5を利用した。
![]()
次にEasyProjectGenerator for Android Ver 1.00を利用してAndroid NDKプロジェクトを生成して、jniフォルダ直下に「zlb」というフォルダを作る。そして、そこへダウンロードしたzlibのソースファイルのうち、上位のフォルダに入っている*.cと*.hファイルをすべて解凍する。
![]()
さらにjniフォルダ直下のソースファイルとmakefileも新しく「Test106」というフォルダを作り、そこへ移動しておく。
![]()
ここまでの操作でできたプロジェクトフォルダをEclipseにAndroidプロジェクトとして取り込んだ。
![]()
次にビルド用のAndroid.mkファイルを順次作成する。まずはjniフォルダの直下に作る。
include $(call all-subdir-makefiles)
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libzip LOCAL_LDLIBS := -lz LOCAL_SRC_FILES := adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c include $(BUILD_STATIC_LIBRARY)
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <zlib.h>
int CompressTest(int bCompress,const char* pszDstFile,const char* pszSrcFile)
{
int ret;
int nFd;
char* pszMapped;
long nFileSize;
//処理対象ファイルを開く
nFd = open(pszSrcFile,O_RDONLY);
if(nFd < 0)
return 0;
//処理対象ファイルのサイズ取得
{
struct stat sFileStat;
ret = fstat(nFd,&sFileStat);
if(ret < 0)
{
close(nFd);
return 0;
}
nFileSize = sFileStat.st_size;
}
//処理対象ファイルをメモリマップドファイルにする
pszMapped = (char*)mmap(NULL,nFileSize,PROT_READ,MAP_SHARED,nFd,0);
if(pszMapped == MAP_FAILED)
{
close(nFd);
return 0;
}
//メイン処理
{
Bytef* pcbCompData;
long nCompLen;
if(bCompress)
{
//圧縮処理
nCompLen = nFileSize * 1.1 + 13;
pcbCompData = (Bytef*)malloc(nCompLen);
compress(pcbCompData,&nCompLen,pszMapped,nFileSize);
}
else
{
//解凍処理
//元サイズ取得&バッファ確保
nCompLen = *(long*)pszMapped;
pcbCompData = (Bytef*)malloc(nCompLen);
char* pTmp;
//サイズが保存されていた分だけポインタを進めて解凍処理
pTmp = pszMapped;
pTmp += sizeof(nFileSize);
uncompress(pcbCompData,&nCompLen,pTmp,nFileSize - sizeof(nFileSize));
}
{
FILE *fp;
fp = fopen(pszDstFile,"w");
if(fp)
{
if(bCompress)
{
//圧縮時は圧縮前のサイズを保存
fwrite(&nFileSize,sizeof(nFileSize),1,fp);
}
fwrite(pcbCompData,1,nCompLen,fp);
fclose(fp);
}
}
free(pcbCompData);
}
//メモリマップドファイル開放
munmap(pszMapped,nFileSize);
close(nFd);
return 1;
}
jstring
Java_com_Test106_Test106Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
//テスト用ファイル作成
FILE *fp;
fp = fopen("/sdcard/test.txt","w");
if(fp)
{
fputs("--------------------------------------------------",fp);
fputs("----------this is compress data-------------------",fp);
fputs("--------------------------------------------------",fp);
fputs("Test line.Test line.Test line.Test line.Test line.",fp);
fputs("Test line.Test line.Test line.Test line.Test line.",fp);
fputs("Test line.Test line.Test line.Test line.Test line.",fp);
fputs("--------------------------------------------------",fp);
fclose(fp);
}
//圧縮
CompressTest(1,"/sdcard/test.cmp","/sdcard/test.txt");
//解凍
CompressTest(0,"/sdcard/decomp.txt","/sdcard/test.cmp");
return (*env)->NewStringUTF(env, "Test106text");
}
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := Test106jni LOCAL_SRC_FILES := Test106jni.c LOCAL_STATIC_LIBRARIES := libzip LOCAL_C_INCLUDES += $(call my-dir)/../zlib include $(BUILD_SHARED_LIBRARY)
![]()
以上の操作でプロジェクトの設定が終わった。ndk-buildによりネイティブコードをビルドする。
![]()
EclipseのDDMSから仮想SDカード内を見ると、圧縮前のtest.txt、圧縮したtest.cmp、解凍したdecomp.txtの3ファイルを確認できた。
