前の10件 4  5  6  7  8  9  10  11  12  13  14

記事一覧

Android NDKでZIP書庫内の画像ファイルを解凍する

test122_01.png
今回はAndroid NDKにより、ZIP書庫内に含まれる画像ファイルを解凍するためのクラスを作成する。ZIP書庫の操作には「Android NDKの標準ライブラリにlibunzipを追加して利用する」で用意したlibunzipを利用する。

まずは雛形となるプロジェクトをEasyProjectGenerator for Androidで作る。C++、HelloJNIでSTLを有効にした。


test122_02.png
自動生成されたプロジェクトをEclipseに取り込み、「ZipedImages.h」ファイルを新規作成してZIP書庫操作用のクラスを実装する。

指定されたZIP書庫を開き、書庫内にあるすべてのファイル名をチェックして拡張子が画像ならstd::vectorにファイル位置を保存。そしてそのstd::vector上のインデックス指定によりファイルを指定フォルダへと解凍するという流れにした。かなり中途半端かつ汎用性のない実装になっている。汎用的に実装しようと思うと、ファイル名に日本語が使われていた場合やら何やら色々考えないといけないのでやめました。
#ifndef	_ZIPEDIMAGES_H
#define	_ZIPEDIMAGES_H

#include<string>
#include<vector>

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

#include <android/log.h>


#include "unzip.h"

#define	MAX_PATH	256

#define	bool	unsigned int
#define	true	(1)
#define	false	(0)




class	CZipedImages
{
protected:

	unzFile		_zipFile;
	std::vector<unz_file_pos>	_vFilePos;


public:

	CZipedImages()
	{
		_zipFile = 0;
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::CZipedImages()");
	}

	~CZipedImages()
	{
		Close();
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::~CZipedImages()");
	}

	bool	IsOpen(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::IsOpen()");
		return	(_zipFile != 0) ? true : false;
	}


	bool	OpenZipFile(const char* pszFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::OpenZipFile()");
		if(IsOpen() == true)
			return	false;

		int		nRet;

		_zipFile = unzOpen(pszFile);

		nRet = unzGoToFirstFile(_zipFile);
		while(nRet == UNZ_OK)
		{
			char	pszFileName[MAX_PATH];
			unz_file_info	info;
			unz_file_pos	pos;
			std::string		strFile;
			std::string		strExt;

			unzGetCurrentFileInfo(_zipFile,&info,pszFileName,MAX_PATH,NULL,0,NULL,0);
			strFile	= pszFileName;
			strExt	= strFile.substr(strFile.length() - 4,4);		//いい加減な方法で拡張子取得

			if(strExt == ".JPG" || strExt == ".jpg" || strExt == ".PNG" || strExt == ".png")				//いい加減な方法で拡張子チェック
			{
				unzGetFilePos(_zipFile,&pos);
				_vFilePos.push_back(pos);
			}
			else
			{
				//処理されないファイル/フォルダをログ出力
				__android_log_print(ANDROID_LOG_INFO,TAG,"NOT process : (%s)",pszFileName);
			}

			nRet = unzGoToNextFile(_zipFile);
		}

		return	true;
	}


	void	Close(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::Close()");

		if(_zipFile != 0)
			unzClose(_zipFile);
		_zipFile = 0;
		_vFilePos.clear();
	}



	int		GetCount(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::GetCount()");

		return	_vFilePos.size();
	}


	bool	Extract(int nIndex,const char* pszFolder,std::string* pstrFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,"CZipedImages::Extract()");

		if(IsOpen() == false)
			return	false;

		if(nIndex > _vFilePos.size() || nIndex < 0)
			return	false;

		int		nRet;
		char	pszFileName[MAX_PATH];
		unz_file_info	info;

		nRet = unzGoToFilePos(_zipFile,&_vFilePos[nIndex]);
		if(nRet != UNZ_OK)
			return	false;

		nRet = unzGetCurrentFileInfo(_zipFile,&info,pszFileName,MAX_PATH,NULL,0,NULL,0);
		if(nRet != UNZ_OK)
			return	false;
		__android_log_print(ANDROID_LOG_DEBUG,TAG,"CZipedImages::Extract() in process %s",pszFileName);


		std::string	strPath;

		//保存先ファイルパス作成
		{
			strPath = pszFolder;
			if(strPath.substr(strPath.length() - 1,1) != "/")
				strPath += "/";

			if(pstrFile != NULL && *pstrFile != "")
			{
				if((*pstrFile)[0] != '/')
					strPath += *pstrFile;
				else
					strPath += pstrFile->substr(1,pstrFile->length() - 1);
			}
			else
			{
				char	pszBuff[256];
				std::string	strExt;

				strExt	= pszFileName;
				strExt	= strExt.substr(strExt.length() - 4,4).c_str();	//いい加減な方法で拡張子取得
				sprintf(pszBuff,"%d%s",nIndex,strExt.c_str());

				if(pstrFile)
					*pstrFile = pszBuff;
				strPath.append(pszBuff);
			}
		}
		__android_log_print(ANDROID_LOG_DEBUG,TAG,"CZipedImages::Extract() : save to %s",strPath.c_str());

		//解凍
		{
			FILE	*fp;

			fp = fopen(strPath.c_str(),"w");
			if(fp == NULL)
				return	false;

			char	szBuffer[32768];
			int		dwSizeRead;

			nRet = unzOpenCurrentFile(_zipFile);
			if(nRet == UNZ_OK)
			{
				while ((dwSizeRead = unzReadCurrentFile(_zipFile,szBuffer,sizeof(szBuffer))) > 0)
				{
					fwrite(szBuffer,1,dwSizeRead,fp);
				}
				unzCloseCurrentFile(_zipFile);
			}
			fclose(fp);
		}

		return	true;
	}
};

#endif

test122_03.png そしてメイン処理内でCZipedImaesクラスのテスト用に2つのファイルを解凍する処理を追加する。
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include <string.h>
#include <jni.h>

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


#define	TAG	"Test122"
#include "ZipedImages.h"



extern "C"
jstring Java_com_Test122_Test122Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
	CZipedImages	cZip;

	cZip.OpenZipFile("/sdcard/desire_img.zip");

	bool		ret;
	int			nSize;
	std::string	strFile;

	nSize = cZip.GetCount();

	//最初のファイルを解凍
	strFile = "";
	ret = cZip.Extract(0,"/sdcard",&strFile);
	if(ret)
		__android_log_print(ANDROID_LOG_DEBUG,"Test122","save to %s",strFile.c_str());

	//5番目のファイルを解凍
	strFile = "";
	ret = cZip.Extract(5,"/sdcard",&strFile);
	if(ret)
		__android_log_print(ANDROID_LOG_DEBUG,"Test122","save to %s",strFile.c_str());

	cZip.Close();

	return env->NewStringUTF("Test122text");
}

test122_04.png 最後にAndroid.mkにlibunzipとlibzipのライブラリを追加する。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test122
LOCAL_SRC_FILES := Test122.cpp
LOCAL_LDLIBS += -lz -lunzip

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

include $(BUILD_SHARED_LIBRARY)

test122_05.png
これで実行するとSDカード上のZIP書庫を読み込み、その中にあるファイルのうち2つが解凍された。




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

Android NDKの標準ライブラリにlibunzipを追加して利用する

libunzip01.png
今回はAndroid NDKから簡単にzip書庫ファイルにアクセスするためのライブラリ「libunzip.a」をビルド。Android NDKの標準ライブりへ登録。そして実際に利用してみる。

まずは以前作成したAndroid NDKでZIP書庫内のファイルリストを取得するのときのプロジェクトファイル「Test117.zip」をダウンロードする。

libunzip02.png
次にEasyProjectGenerator for Androidで雛形プロジェクトを作成する。今回はC++、HelloJNIを利用した。

libunzip03.png
そして作成したプロジェクトのjniフォルダの中に、先ほどダウンロードしたTest117.zipに含まれる「ioapi.h」「ioapi.c」「unzip.h」「unzip.c」の4ファイルを解凍する。

libunzip04.png
今回はライブラリをビルドするだけなので不要な「Test120.c」を削除する。

libunzip05.png
Eclipseでプロジェクトを読み込み、「Android.mk」を編集する。

今回は.aファイルを作成するのでBUILD_STATIC_LIBRARYを指定するのがポイントだ。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libunzip
LOCAL_SRC_FILES := ioapi.c unzip.c

include $(BUILD_STATIC_LIBRARY)
libunzip06.png BUILD_STATIC_LIBRARYを指定しただけでは.aファイルはビルドされないので、「Application.mk」を編集してAPP_MODULE指定をする。
APP_MODULES := libunzip

libunzip07.png
これでビルドすると「libunzip.a」ファイルが生成された。

libunzip08.png
次に「libunzip.a」をAndroid NDKの標準ライブラリとして登録してしまう。

NDKのフォルダ「C:\android-ndk\platforms\android-xxx\arch-arm\usr\lib\」を開き、その中へ「libunzip.a」をコピーする。

libunzip09.png
忘れずにヘッダーファイルの「ioapi.h」「unzip.h」の2ファイルをコピーする。これは「C:\android-ndk\platforms\android-xxx\arch-arm\usr\include\」へコピーする。これで標準ライブラリへの登録は終りだ。






libunzip10.png
最後に実際にlibunzipを利用してみる。

まずは雛形となるプロジェクトをEasyProjectGenerator for Androidで作成。C++のHelloJNIとした。

libunzip11.png
Eclipseでプロジェクトを読み込み、Android.mkを編集する。

libunzipを利用するため、LOCAL_LDLIBSに「-lz」と「-lunzip」を追加する。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test121
LOCAL_SRC_FILES := Test121.cpp
LOCAL_LDLIBS += -lz -lunzip 

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

include $(BUILD_SHARED_LIBRARY)

libunzip12.png そしてテストするためのメイン処理を実装する。普通にunzip.hをincludeして利用するだけだ。
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include <string.h>
#include <jni.h>

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


#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,"Test121","Found File in zip : %s",pszFileName);
		}

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

	return	1;
}


extern "C"
jstring Java_com_Test121_Test121Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
	Test("/sdcard/desire_img.zip");

	return env->NewStringUTF("Test121text");
}

libunzip13.png
これで実行すると、SDカード上に配置したzip書庫内のファイル一覧がログに出力された。




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

Android SDKでJPG画像を画像に合わせて拡大縮小表示する

test119_01.png
今回はAndroid SDKでjpgファイルを読み込み、画面サイズに合わせて拡大縮小表示する。

まずは雛形となるプロジェクトをEasyProjectGenerator for Androidで作る。JavaのSimpleプロジェクトを利用した。

test119_02.png
そしてEclipseにプロジェクトを取り込み、「ImageFileView.java」ファイルを新しく作成してImageViewクラスを実装する。

jpg画像の読み込みはBitmapFactory.decodeFile()で行い、Bitmap.createBitmap()にMatrixを渡すことで拡大縮小、Canvas::drawBitmap()で範囲を指定して描画する。

ImageViewにBitmapやBitmapDrawableを渡す方法は、ImageViewが勝手に拡大縮小をするために利用できない。
package com.Test119;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;


public class ImageFileView extends View
{
	private	Bitmap	_bmpImageFile;		//画像ファイル
	private	Bitmap	_bmpResized;		//リサイズ画像
	private	int		_nWidthDisp;		//画面幅
	private	int		_nHeightDisp;		//画面縦


	public ImageFileView(Context context)
	{
		super(context);

		//画面サイズ取得
		WindowManager	wmWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display			display = wmWindowManager.getDefaultDisplay();
		_nWidthDisp		= display.getWidth();
		_nHeightDisp	= display.getHeight();
		Log.d("Test119","DisplaySize " + _nWidthDisp + "x" + _nHeightDisp);

		//画像ファイル読み込み
		LoadImageFile("/sdcard/test.jpg",false);	//描画更新しない
	}


	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		//タッチイベント取得
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			LoadImageFile("/sdcard/test2.jpg",true);
		}
		return true;
	}	


	public boolean	LoadImageFile(String strFile,boolean bInvalidate)
	{
		//画像読み込み
		_bmpImageFile = BitmapFactory.decodeFile(strFile);
		
		int		nWidth = _bmpImageFile.getWidth();
		int		nHeight = _bmpImageFile.getHeight();
		Log.d("Test119","ImageSize " + nWidth + "x" + nHeight);

		float	fScale;

		//拡大縮小率取得
		if(true)
		{
			//画像に合わせる
			if((long)nWidth * _nHeightDisp > (long)_nWidthDisp * nHeight)
				fScale = (float)_nWidthDisp / nWidth;
			else
				fScale = (float)_nHeightDisp / nHeight;
		}
		else if(false)
		{
			//高さに合わせる
			fScale = (float)_nHeightDisp / nHeight;
		}
		else
		{
			//幅に合わせる
			fScale = (float)_nWidthDisp / nWidth;
		}

		//リサイズ
		Matrix	matrix = new Matrix();
		matrix.postScale(fScale,fScale,0,0);
		_bmpResized = Bitmap.createBitmap(_bmpImageFile,0,0,nWidth,nHeight,matrix,true);

		if(bInvalidate)
			invalidate();		//表示更新

		return	(_bmpImageFile != null) ? true : false;
	}


	@Override
	protected void onDraw(Canvas canvas)
	{
		if(_bmpImageFile == null)
		{
			super.onDraw(canvas);
			return;
		}


		//描画
        Rect	rect = new Rect(0,0,_bmpResized.getWidth(),_bmpResized.getHeight());
        canvas.drawBitmap(_bmpResized,rect,rect,null);
	}
}

test119_03.png
上で実装したImageFileViewをアクティビティに結びつける。

今回はさらにタイトル消去とフルスクリーン化も行った。
package com.Test119;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class Test119Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(new ImageFileView(this));
	}
}

test119_04.png
これでSDカード上にjpgファイルを2つ配置してから実行すると、起動時は/sdcard/test.jpgが読み込まれ表示、画面をタッチすると、、、

test119_05.png
/sdcard/test2.jpgが表示された。




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

2011年01月18日

Android NDKでlibjpegをビルドして利用する

test118_01.png
今回はIJGのJPEGライブラリ(libjpeg、jpeglib)をAndroid NDKから利用してJpgファイルを表示する。

まずIndependent JPEG GroupからJPEGライブラリのソースファイルをダウンロードする。「jpegsr8c.zip」というファイルだった。

test118_02.png
EasyProjectGenerator for Androidで雛形となるAndroidプロジェクトを作成する。今回はC++でNativeViewを利用する。

test118_03.png
ダウンロードしたJPEGライブラリのソースファイル一式をAndroidプロジェクトのjniフォルダへ解凍する。

test118_04.png
さらにjniフォルダにあったソースファイルやmakefileを「Test118」というフォルダを作成してその中へ移動する。

test118_05.png
プロジェクトをEclipseへ取り込む。

jniフォルダ直下に「Android.mk」ファイルを作成する。そしてjniフォルダの下のフォルダをビルド対象に指定する。
include $(call all-subdir-makefiles)

test118_06.png 次にlibjpegの「jpeg-8c」フォルダの中に「Android.mk」ファイルを作成して、JPEGライブラリのビルド指定をする。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libjpeg

LOCAL_SRC_FILES := jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemname.c

include $(BUILD_STATIC_LIBRARY)

test118_07.png
次にlibjpegの「jpeg-8c」フォルダの中にある「jconfig.txt」ファイルを選択した状態で[F2]キーを押して、ファイル名を「jconfig.h」に変更する。これでJPEGライブラリのビルド準備が整った。

test118_08.png 次にcppファイルを開き、実際にlibjpegを利用してjpgファイルを読み込み表示する処理を実装する。
#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) );
}


#include <stdio.h>

extern "C"
{
#define XMD_H
#include "../jpeg-8c/jpeglib.h"
#include "../jpeg-8c/jerror.h"
}


static	void	_JpegError(j_common_ptr cinfo)
{
	char	pszMessage[JMSG_LENGTH_MAX];

	(*cinfo->err->format_message)(cinfo,pszMessage);

	__android_log_print(ANDROID_LOG_INFO,"Test118","error!  %s",pszMessage);
}

static int DrawBitmap(AndroidBitmapInfo* pBitmapInfo, void* pPixels,const char* pszJpegFile)
{
	int			yy;
	int			nJpegLineBytes;			//JPEG1ラインのバイト数

	char*		lpbtBits;
	JSAMPLE*	pSample;
	FILE*		fp;
	JSAMPROW	buffer[1];
	JSAMPLE		tmp;

	jpeg_decompress_struct		cInfo;
	jpeg_error_mgr				jError;

	fp = fopen(pszJpegFile,"rb");
	if(fp == NULL)
		return	0;

	cInfo.err = jpeg_std_error(&jError);			//エラーハンドラ設定
	jError.error_exit = _JpegError;					//エラーハンドラ設定

	jpeg_create_decompress(&cInfo);					//
	jpeg_stdio_src(&cInfo,fp);						//読込ファイル設定
	jpeg_read_header(&cInfo,TRUE);					//ヘッダー読込
	jpeg_start_decompress(&cInfo);					//デコードスタート

	nJpegLineBytes = cInfo.output_width * cInfo.output_components;		//JPEG 1ラインのバイト数

	pSample = new JSAMPLE[nJpegLineBytes + 10];		// ラインバッファ確保
	buffer[0] = pSample;

	yy = 0;
	while(cInfo.output_scanline < cInfo.output_height)
	{
		if(yy >= pBitmapInfo->height)
			break;

		jpeg_read_scanlines(&cInfo,buffer,1);		//Jpegを1ライン読み込む

		int		xx;
		int		x3;

		uint16_t*  pLine = (uint16_t*)pPixels;
		for(xx = 0, x3 = 0; xx < pBitmapInfo->width && x3 < nJpegLineBytes; xx++, x3 += 3)
		{
			//JPEGはBGRの順
			pLine[xx] = make565(buffer[0][x3 + 0],buffer[0][x3 + 1],buffer[0][x3 + 2]);
		}

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

	jpeg_finish_decompress(&cInfo);		// 読み込み終了処理
	jpeg_destroy_decompress(&cInfo);
	fclose(fp);

	return	1;
}




extern "C"
JNIEXPORT void JNICALL Java_com_Test118_NativeView_RenderBitmap(JNIEnv * env, jobject  obj, jobject bitmap)
{
	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,"/sdcard/test.jpg");

	AndroidBitmap_unlockPixels(env, bitmap);
}

test118_09.png 最後にcppファイルをビルドするための「Android.mk」ファイルにビルドしたlibjpegを利用する指定をする。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test118
LOCAL_SRC_FILES := Test118.cpp
LOCAL_LDLIBS    := -lz -ljnigraphics

LOCAL_STATIC_LIBRARIES += libjpeg

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

include $(BUILD_SHARED_LIBRARY)

test118_10.png
これでビルドをかけると、libjpeg.aとそれを利用したバイナリが生成される。

test118_11.png
テスト表示用のjpgファイル「test.jpg」をAndroidエミュレーターのSDカードへと転送する。

test118_12.png
そしてプロジェクトを実行すると、jpgファイルが表示された。




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

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

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

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

https://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端末へドラッグアンドドロップでファイルを転送する

adb_push01.png
WindowsからAndroidエミュレーターや実機へファイルを送り込むのに、毎回、コマンドプロンプトでadb pushをしたりDDMSするのは面倒。そのため今回はドラッグアンドドロップで簡単に転送できるようにする。

まずメモ帳を管理者権限で開く。「スタート」メニューに「notepad」と入力して、現れた実行ファイルを右クリックして現れるメニューから「管理者として実行」を選択する。

adb_push02.png そしてメモ帳にadb pushコマンドを入力する。
adb push %1 /sdcard/
pause

adb_push03.png
コマンドを入力したら「ファイル」メニューの「名前を付けて保存」で保存する。

adb_push04.png
保存する場所はAndroid SDKのフォルダ内にある「platform-tools」フォルダだ。adb.exeなどと同じフォルダへ保存する。今回はファイル名を「adb_push_to_sdcard.bat」とした。バッチファイル(.bat)として保存するのがポイント。

adb_push05.png
保存したらもう一度「名前を付けて保存」を開く。

adb_push06.png
そして保存したフォルダを再び開き、「すべてのファイル」を選択する。

adb_push07.png
先ほど保存したバッチファイルがある。このファイルを右クリックして現れるメニューから「送る」にある「デスクトップ(ショートカットを作成)」を選択する。

adb_push08.png
これでデスクトップにショートカットが作成された。保存はしなくていいので「キャンセル」ボタンを押してメモ帳を閉じる。






adb_push09.png
実際にファイルを転送する。

実機を接続するかAndroidエミュレーターを起動した状態で、転送したいファイルをデスクトップ上のショートカットへドラッグアンドドロップする。

adb_push10.png
するとコマンドプロンプトが開き、AndroidのSDカード上へ選択したファイルが転送される。

adb_push11.png
DDMSでも転送したファイルが確認できた。


2011年01月17日

Androidのカメラアプリをオートフォーカス対応にする

test116af_01.png
前回はシンプルなAndroidカメラアプリを作成した。今回は前回のカメラアプリをオートフォーカス対応にする。

まずはAndroidManifest.xmlにオートフォーカスの利用宣言を追加する。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
      package="com.Test116"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Test116Act"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

</manifest>

test116af_02.png
「オートフォーカス」というと実装が難しいように感じるが、ものすごく簡単にできる。

今まで撮影用にCamera.takePicture()を呼んでいた所で、代わりにCamera.autoFocus()を使ってオートフォーカスコールバックを指定する。するとオートフォーカスが終了したときにコールバックが実行されるので、そこで改めてCamera.takePicture()を呼んで撮影するだけだ。

	private Camera.AutoFocusCallback	_pfnAutoFocusCallback = new AutoFocusCallback();

	private final class AutoFocusCallback implements Camera.AutoFocusCallback
	{
		public void onAutoFocus(boolean success, Camera camera)
		{
			Log.d(TAG, "CameraView::onAutoFocus()");

			camera.autoFocus(null);
			camera.takePicture(_pfnShutterCallback, _pfnRawPictureCallback,new JpgPictureCallback());
		};
	}


	public void TakePicture()
	{
		Log.d(TAG, "CameraView::takePicture()");
		
		if(_nReady != 0)
		{
			_nReady = 0;
			if(true)
			{
				//オートフォーカス撮影
				_Camera.autoFocus(_pfnAutoFocusCallback);
			}
			else
			{
				//即撮影
				_Camera.takePicture(_pfnShutterCallback, _pfnRawPictureCallback,new JpgPictureCallback());
			}
		}
	}

test116af_03.png
実際に撮影してギャラリーで確認。きちんとピントが合っている。

test116af_04.jpg
これが実際に撮影した画像を縮小したもの。前回のピンぼけ写真とは比べ物にならないぐらいよくなった。




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

Androidで簡単なカメラアプリを作る

test116_01.png
今回はシンプルなカメラアプリを作成する。

まずは雛形となるプロジェクトをEasyProjectGenerator for Androidで作る。今回はJavaのSimpleプロジェクトを利用した。

test116_02.png 自動生成されたプロジェクトをEclipseに取り込み、AndroidManifest.xmlにカメラ利用のパーミッション宣言を追加する。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
      package="com.Test116"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Test116Act"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

</manifest>

test116_03.png
次にメインソースコードを編集する

。今回はメインの背景が緑色のレイアウトに1×1ドットのCameraViewを追加する形にした。CameraViewのサイズはCameraView内で変更することにする。

また総ショット数(画像保存時の連番に利用)を保存/利用するためにonSaveInstanceState()やonRestoreInstanceState()を作り、CameraViewへと渡すようにした。
package com.Test116;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.graphics.Color;

public class Test116Act extends Activity
{
	private	CameraView	_view = null;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setBackgroundColor(Color.GREEN);

		_view = new CameraView(this,savedInstanceState);

		layout.addView(_view,new LinearLayout.LayoutParams(1,1));
		setContentView(layout);
	}


	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);

		if(_view != null)
			_view.OnSaveState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		super.onRestoreInstanceState(savedInstanceState);
		
		if(_view != null)
			_view.OnLoadState(savedInstanceState);
	}
}

test116_04.png
そして「CameraView.java」ファイルを作成。CameraViewクラスを実装する。

プレビューはカメラがサポートする最小サイズで表示。プレビューを画面タッチすると撮影。撮影時はサポートする最大サイズでjpg保存。ファイル名は総ショット数を利用して決定している。


package com.Test116;

import android.hardware.Camera;
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.MotionEvent;
import java.io.FileOutputStream;
import java.io.File;

import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import java.util.List;
import android.view.ViewGroup.LayoutParams;
import android.content.ContentValues;
import android.content.ContentResolver;


public class CameraView extends SurfaceView
	implements SurfaceHolder.Callback
{
	private final String	TAG = "Test116";
	
	private	SurfaceHolder	_SurfaceHolder;
	private	Camera			_Camera;
	private	int				_nReady;
	private	long			_nShotNo;


	public CameraView(Context context,Bundle savedInstanceState)
	{
		super(context);

		Log.d(TAG, "CameraView::CameraView()");

		_nReady = 0;
		_nShotNo = 0;
		OnLoadState(savedInstanceState);
	
		_SurfaceHolder = getHolder();
		_SurfaceHolder.addCallback(this);
		_SurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	//設定の保存
	public void OnSaveState(Bundle outState)
	{
		Log.d(TAG, "CameraView::OnSaveState()");

		if(outState != null)
		{
			outState.putLong("_nShotNo",_nShotNo);
		}
	}

	//設定の読込
	public void OnLoadState(Bundle savedInstanceState)
	{
		Log.d(TAG, "CameraView::OnLoadState()");

		if(savedInstanceState != null)
		{
			_nShotNo = savedInstanceState.getLong("_nShotNo");
		}
	}
	

	public void surfaceCreated(SurfaceHolder holder)
	{
		Log.d(TAG, "CameraView::surfaceCreated()");

		try
		{
			_Camera = Camera.open();
			_Camera.setPreviewDisplay(holder);
		}
		catch (Exception e)
		{
			Log.e(TAG, "CameraView::surfaceCreated() : Fail to setPreviewDisplay.");
		}
	}

	
	public void surfaceChanged(SurfaceHolder holder,int format,int w,int h)
	{
		Log.d(TAG, "CameraView::surfaceChanged()");

		Camera.Parameters	paramCamera = _Camera.getParameters();
		List<Size>			asizeSupport;
		Size		size;

		//カメラがサポートする撮影サイズ一覧を取得
		asizeSupport = paramCamera.getSupportedPictureSizes();
		if(asizeSupport.size() != 0)
		{
			//一番大きい撮影サイズを利用
			size = asizeSupport.get(0);
			paramCamera.setPictureSize(size.width,size.height);
		}
		
		//カメラがサポートするプレビューサイズ一覧を取得
		asizeSupport = paramCamera.getSupportedPreviewSizes();
		if(asizeSupport.size() != 0)
		{
			//一番小さいプレビューサイズを利用
			size = asizeSupport.get(asizeSupport.size() - 1);
			paramCamera.setPreviewSize(size.width,size.height);


			LayoutParams	paramLayout;

			//ビューサイズをプレビューサイズに合わせる
			paramLayout = getLayoutParams();
			paramLayout.width = size.width;
			paramLayout.height = size.height;
			setLayoutParams(paramLayout);
		}

		//カメラパラメーター設定
		_Camera.setParameters(paramCamera);
		
		_Camera.startPreview();		//プレビューの開始
		_nReady = 1;
	}

	
	public void surfaceDestroyed(SurfaceHolder holder)
	{
		Log.d(TAG, "CameraView::surfaceDestroyed()");

		//カメラの破棄
		_nReady = 0;
		_Camera.setPreviewCallback(null);
		_Camera.stopPreview();
		_Camera.release();
		_Camera = null;
	}


	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		//タッチイベント取得
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			Log.d(TAG, "CameraView::onTouchEvent()");

			TakePicture();			//撮影
		}
		return true;
	}



	private ShutterCallback		_pfnShutterCallback = new ShutterCallback();

	private final class ShutterCallback implements android.hardware.Camera.ShutterCallback
	{
		public void onShutter()
		{
			Log.d(TAG, "CameraView::onShutter()");
		}
	};



	private RawPictureCallback	_pfnRawPictureCallback = new RawPictureCallback();
	
	private final class RawPictureCallback implements PictureCallback
	{
		public void onPictureTaken(byte [] rawData, android.hardware.Camera camera)
		{
			Log.d(TAG, "CameraView::onRawPictureTaken()");
		};
	}

	
	private final class JpgPictureCallback implements PictureCallback
	{
		public void onPictureTaken(byte [] data, android.hardware.Camera camera)
		{
			Log.d(TAG, "CameraView::onJpgPictureTaken()");

			String	strFolder;
			String	strFile;

			strFolder = Environment.getExternalStorageDirectory()+"/DCIM/Camera/";

			//保存ファイル名
			//重複チェックをしていないので、もしもすでにファイルがあったら上書きされる!
			strFile = strFolder + "test" + _nShotNo + ".jpg";
			
			//if(_nShotNo == 0)
			//{
			//	//フォルダ作成
			//	File	newFolder = new File(strFolder);
			//	newFolder.mkdir();
			//}

			try
			{
				//撮影画像保存(dataがすでにjpg画像になっているので、これをそのままファイルに落とすだけ)
				FileOutputStream	cFile = new FileOutputStream(strFile);
				cFile.write(data);
				cFile.close();

				//コンテンツ登録(androidギャラリーへの登録)
				long	nDate;
				ContentValues values = new ContentValues();

				nDate = System.currentTimeMillis();
				values.put(Images.Media.MIME_TYPE,"image/jpeg");			//必須
				values.put(Images.Media.DATA,strFile);						//必須:ファイルパス(uriからストリーム作るなら不要)
				values.put(Images.Media.SIZE,new File(strFile).length()); 	//必須:ファイルサイズ(同上)
//				values.put(Images.Media.TITLE,strFile);
//				values.put(Images.Media.DISPLAY_NAME,strFile);
				values.put(Images.Media.DATE_ADDED,nDate);
				values.put(Images.Media.DATE_TAKEN,nDate);
				values.put(Images.Media.DATE_MODIFIED,nDate);
//				values.put(Images.Media.DESCRIPTION,"");
//				values.put(Images.Media.LATITUDE,0.0);
//				values.put(Images.Media.LONGITUDE,0.0);
//				values.put(Images.Media.ORIENTATION,"");
				
				ContentResolver	contentResolver = getContext().getContentResolver();
				contentResolver.insert(Media.EXTERNAL_CONTENT_URI, values);
			}
			catch(Exception e)
			{
				Log.e(TAG, "CameraView::onJpgPictureTaken() : Fail to save image file.");
			}
			_nShotNo++;

			camera.startPreview();		//プレビュー再開
			_nReady = 1;
		};
	};


	
	public void TakePicture()
	{
		Log.d(TAG, "CameraView::takePicture()");
		
		if(_nReady != 0)
		{
			_nReady = 0;
			_Camera.takePicture(_pfnShutterCallback, _pfnRawPictureCallback,new JpgPictureCallback());
		}
	}
}

test116_05.png
実装が終わったので実行してみる。

test116_06.png
デバイスの選択画面で「Choose a running Android device」から実機を選択する。

test116_07.png
これで実機でアプリが実行されてプレビューが表示された。プレビュー画面を指でタッチすると撮影される。

test116_08.png
撮影した画像はAndroid標準のギャラリーアプリで確認できる。

test1.jpg
これが実際に撮影した画像を縮小したもの。保存サイズは2592×1952ドットでした。オートフォーカスを実装していないのでピンぼけすぎです。




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

Android実機をPCにUSB接続する

usb01.png
今回はAndroidの実機をPCにUSB接続する。まずはUSBドライバーを取得する。Android SDKのあるフォルダをエクスプローラーで開き、「SDK Manager」を右クリックして現れるメニューから「管理者として実行」を選択して起動する。

usb02.png
そして「Available packages」を選択、ここで「Third parth Add-ons」にチェックを入れる。

usb03.png
するとネットから利用可能なパッケージ一覧が自動取得される。

usb04.png
「Google Inc.add-ons(dl-ssl.google.com)」の中に「Google Usb Driver package, revision 4」があり、チェックが入っていることを確認して、「Install Selected」ボタンを押す。

usb05.png
「Accept All」をチェックして「Install」ボタンを押し、インストールを開始する。

usb06.png
自動ダウンロード&インストールされる。

usb07.png
最後にADBを再起動したら終了だ。

usb08.png
もう「Android SDK and AVD Manager」は終了して構わない。

usb09.png
これでAndroid SDKフォルダの中に「google-usb_driver」というドライバーの格納されたフォルダができた。






usb10.png
まずは接続するAndroidの実機のベンダーID(VID)とプロダクトID(PID)を調べる。

Androidの実機をUSBケーブルでPCに接続する。そして「スタート」ボタンの「コンピューター」を右クリックして現れるメニューから「プロパティ」を開く。

usb11.png
「デバイスマネージャー」を選択する。

usb12.png
デバイスマネージャーが開いた。Androidの実機を示す「ADB」にビックリマークが付いている。この項目をダブルクリックして開く。

usb13.png
ADBの「詳細」タブで「ハードウエアID」プロパティを開く。

ここで「Vid_xxxx」と「Pid_xxxx」の部分をメモしておく。今回はHTC Desireを利用したのでVIDが0BB4、PIDが0C87となった。
USB\Vid_0bb4&Pid_0c87&Rev_0226&MI_01
USB\Vid_0bb4&Pid_0c87&MI_01







usb14.png
次にAndroid用のUSBドライバーのファイルを編集する。

「スタート」ボタンのテキストボックスに「notepad」と入力し、「notepad」を右クリックして現れるメニューから「管理者として実行」を選択してメモ帳を開く。

usb15.png
そしてメモ帳で先ほどダウンロードしたAndroid用のUSBドライバーのフォルダにある「android_winusb.inf」を開く。

usb16.png
infファイルが開いたら「Google.NTx86」(32ビットWindowsを利用の場合)もしくは「Google.NTamd64」(64ビットWindowsを利用の場合)というセクションを探す。

usb17.png
そして先ほど調べたAndroid実機のVIDとPIDを追加する。

Desireの場合であれば「HTC Desire」の2行だけ追加すればいい。今回はPIDを0C94に変えた「HTC Desire for taking root by unrevoked3」の2行も追加した。これはDesireでRootを取得したときになぜか一時的に?実機のPIDが変わったためだ。
;
; HTC Desire
%SingleAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C87
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C87&MI_01

; HTC Desire for taking root by unrevoked3
%SingleAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C94
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C94&MI_01

usb18.png
android_winusb.infファイルの編集が終わったら保存する。これでドライバーの編集作業は終わりだ。






usb19.png
次に実際にドライバーをインストールする。

デバイスマネージャーを開き、「ADB」を右クリックして現れるメニューから「ドライバーソフトウエアの更新」を選択する。

usb20.png
そして「コンピューターを参照してドライバーソフトウエアを検索します」を選択する。

usb21.png
ここで先ほどダウンロード&編集したドライバーが含まれるフォルダを指定する。

usb23.png
「ドライバーソフトウエアの発行元を検証できません」と言われても気にせずに「このドライバーソフトウエアをインストールします」を選択する。

usb24.png
これで「Android Composite ADB Interface」としてドライバーがインストールできた。

usb25.png
デバイスマネージャー上でもビックリマークのついた「ADB」が消え、「Android Composite ADB Interface」に変わった。






usb26.png
最後にきちんとAndroid実機が接続できていることを確認する。

Eclipseを起動して、「DDMS」を開く。すると「Device」タブに実機の項目が表示されている。「Screen Capture」ボタンを押すと、、、

usb27.png
Android実機のスクリーンショットも確認できた。


Androidのスクリーンショットを保存する

cap01.png
今回はAndroidエミュレーターのスクリーンショットを撮る。実機が接続されていればエミュレーターだけでなく実機でも同じようにキャプターをとれる。

まずはAndroidエミュレーターを起動する。Eclipseを起動して、「Window」メニューから「Android SDK and AVD Manager」を選択する。

cap02.png
そして起動したいエミュレーター設定を選択して「Start」ボタンを押す。

cap03.png
これでAndroidエミュレーターが起動した。

cap04.png
スクリーンショットを撮るためにEclipseのDDMS画面を開く。ここで「Devices」タブにある「Screen Capture」ボタンを押すだけだ。

cap05.png
「Screen Capture」ボタンを押すと「Device Screen Capture」ウインドウが開く。ここで「Save」ボタンを押す。

cap06.png
そして保存先を指定する。

cap07.png
これでデスクトップにAndroidエミュレーターのスクリーンショットが保存された。

device.png
これが実際に撮ったスクリーンショット。エミュレーターであればホストOS側から簡単にキャプチャーできるのでメリットは少ないが、実機では活躍しそうな機能だ。


前の10件 4  5  6  7  8  9  10  11  12  13  14