Android NDKが標準で備えるzlibを利用する

test109_01.png
自分でビルドしたライブラリファイルをプロジェクトで利用するための方法を探している過程で、Android NDKのフォルダ内にzlibのヘッダーファイルを見つけました。場所は「C:\android-ndk\platforms\android-9\arch-arm\usr\include\」です。以前、「Android NDK用にzlibをビルドして利用する」や「Android NDK用にlibpngをビルドして利用する」で自分でzlibのソースコードをビルド/利用しましたが、無駄な行為だったようです。
今回はこの標準zlibを使った圧縮/解凍処理をします。

test109_02.png まずEasyProjectGenerator for AndroidのHelloJni.batでプロジェクトを作成します。そして含まれるAndroid.mkに次の1行を追加します。このlibzというのが標準のzlibでした。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test109jni
LOCAL_SRC_FILES := Test109jni.c
LOCAL_LDLIBS    := -lz

include $(BUILD_SHARED_LIBRARY)

test109_03.png そしてメイン処理を実装します。基本的に「Android NDK用にzlibをビルドして利用する」のときとまったく同じです。
#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_Test109_Test109Act_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, "Test109text");
}

test109_04.png
これで実行すると仮想SDカード上でデータの圧縮/解凍が確認できました。




プロジェクトファイルをダウンロード


カテゴリー「android」 のエントリー