Android NDKでZIP書庫内のファイルリストを取得する

test117_01.png
今回はデータ圧縮/解凍用のzlibを利用してzip書庫ファイル内のファイル一覧を取得する。

zlib自体はAndroid NDKに元々含まれているが、zlibの頒布ファイルにはzipファイルにアクセスするためのライブラリが用意されている。今回はそれを利用する。

http://www.zlib.net/からzlibのソースコードをダウンロードする。ダウンロードバージョンはZlib 1.2.5。

test117_02.png
AndroidのプロジェクトをEasyProjectGenerator for Androidで生成する。今回はC++用のNativeViewプロジェクトにした。

test117_03.png
ダウンロードしたzlibのソースコードの「zlib-1.2.5/ contrib/ minizip」フォルダに含まれる「ioapi.h」「ioapi.c」「unzip.h」「unzip.c」ファイルを、プロジェクトのjniフォルダ内に解凍する。

test117_04.png
Eclipseでプロジェクトを開き、まずはAndroid.mkを編集して、「ioapi.c」「unzip.c」をビルド対象に入れる。

このとき、zlibを利用するので、LOCAL_LDLIBSに「-lz」オプションが指定されているのを確認しておく。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test117
LOCAL_SRC_FILES := Test117.cpp ioapi.c unzip.c
LOCAL_LDLIBS    := -lz -ljnigraphics

LOCAL_IS_SUPPORT_LOG := true
ifeq ($(LOCAL_IS_SUPPORT_LOG),true)
	LOCAL_LDLIBS += -llog
endif

include $(BUILD_SHARED_LIBRARY)

test117_05.png 次にメイン処理を実装する。"unzip.h"に含まれる、unzOpen()でzipファイルを開き、unzGetCurrentFileInfo()で書庫内のファイル情報を取得、unzGoToNextFile()で次のファイルに進む、最後はunzClose()でクローズして終了という簡単な流れだ。
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include <jni.h>
#include <android/bitmap.h>

#ifdef LOCAL_LOG
#include <android/log.h>
#endif


/* this function is from Android NDK bitmap-plasma , and modify for green color bug */
static uint16_t  make565(int red, int green, int blue)
{
	return (uint16_t)( ((red   << 8) & 0xf800) |
					   ((green << 3) & 0x07e0) |
					   ((blue  >> 3) & 0x001f) );
}


static void DrawBitmap(AndroidBitmapInfo* pBitmapInfo, void* pPixels)
{
	int		yy;

	for(yy = 0; yy < pBitmapInfo->height; yy++)
	{
		int		xx;
		uint16_t*  pLine = (uint16_t*)pPixels;

		for(xx = 0; xx < pBitmapInfo->width; xx++)
		{
			pLine[xx] = make565(xx % 256,yy % 256,0);
		}

		// go to next line
		pPixels = (char*)pPixels + pBitmapInfo->stride;
	}
}


#include <stdio.h>
#include <string.h>

#include "unzip.h"

#define	MAX_PATH	256

int		Test(const char* pszZipFile)
{
	int		nRet;
	unzFile	zipFile = unzOpen(pszZipFile);

	nRet = unzGoToFirstFile(zipFile);
	while(nRet == UNZ_OK)
	{
		unz_file_info	info;
		char	pszFileName[MAX_PATH];

		nRet = unzGetCurrentFileInfo(zipFile,&info,pszFileName,MAX_PATH,NULL,0,NULL,0);
		if(nRet == UNZ_OK)
		{
			__android_log_print(ANDROID_LOG_INFO,"Test117","Found File in zip : %s",pszFileName);
		}

		nRet = unzGoToNextFile(zipFile);
	}
	unzClose(zipFile);

	return	1;
}

extern "C"
JNIEXPORT void JNICALL Java_com_Test117_NativeView_RenderBitmap(JNIEnv * env, jobject  obj, jobject bitmap)
{
	Test("/sdcard/desire_img.zip");

	AndroidBitmapInfo  info;
	void*			  pixels;
	int				ret;

	if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0)
		return;

	if (info.format != ANDROID_BITMAP_FORMAT_RGB_565)
		return;

	if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0)
		return;

	DrawBitmap(&info,pixels);

	AndroidBitmap_unlockPixels(env, bitmap);
}

test117_06.png このままではビルドできないので、「ioapi.h」の50行目ぐらいにUSE_FILE32APIのdefineを追加して、fopen64ではなくfopenが使われるようにする。
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"


#define	USE_FILE32API


#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#ifdef _MSC_VER
 #define fopen64 fopen
 #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
  #define ftello64 _ftelli64
  #define fseeko64 _fseeki64
 #else // old MSC
  #define ftello64 ftell
  #define fseeko64 fseek
 #endif
#endif
#endif

test117_07.png


これでSDカードにZIPファイルを配置してから実行すると、zip書庫内のファイルリストをログに出力できた。


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


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