<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>UsefullCode.net</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/" />
   <link rel="self" type="application/atom+xml" href="http://www.usefullcode.net/atom.xml" />
    <id>tag:www.usefullcode.net,2006://1</id>
   <updated>2011-12-27T10:18:45Z</updated>
   
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.33-ja</generator>

<entry>
   <title>日本語版WTL 8.1.11324 アプリケーションウィザード</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/12/wtl_8111324.html" />
   <id>tag:www.usefullcode.net,2011://1.10001</id>
   
   <published>2011-12-27T10:10:18Z</published>
   <updated>2011-12-27T10:18:45Z</updated>
   
   <summary> ■はじめに WTLはライセンスがCPLのオープンソースプロジェクトとして公開さ...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="WTL" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="29" label="wtl" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/12/27/wtl001.png" rel="lightbox"><img alt="wtl001.png" src="http://www.usefullcode.net/2011/12/27/wtl001-thumb.png" width="400" height="301" align="left" /></a>

■はじめに

WTLはライセンスがCPLのオープンソースプロジェクトとして公開されている。そのためおそらく勝手に日本語化したものを配布しても問題ないと思い用意しました。ライセンス的に問題があるようでしたらお知らせください。削除します。

リボンやタブビュー、ツリービューなどが扱えます。
リボン対応のプロジェクトのビルドにはWindows 7.1 SDKが必要です。


■ダウンロード

<a href="http://www.usefullcode.net/2011/12/27/wtl81_11324jp.zip">日本語版WTL 8.1.11324をダウンロード</a>

（2011年12月27日現在最新版のWTLを元にしています）
<br clear=left>
]]>
      
   </content>
</entry>
<entry>
   <title>HTC DesireのフラッシュLEDをアプリから制御する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/htc_desireled.html" />
   <id>tag:www.usefullcode.net,2011://1.10000</id>
   
   <published>2011-01-27T03:42:44Z</published>
   <updated>2011-01-27T03:55:38Z</updated>
   
   <summary> 今回はHTC Desireに備わっているLED（カメラ撮影用フラッシュ）をネイ...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/27/test132_01.png" rel="lightbox"><img alt="test132_01.png" src="http://www.usefullcode.net/2011/01/27/test132_01-thumb.png" width="400" height="300" align="left" /></a>
今回はHTC Desireに備わっているLED（カメラ撮影用フラッシュ）をネイティブから制御してON/OFFしてみる。

まずはHTC Developerセンター<a href="http://developer.htc.com/" target="_blank">http://developer.htc.com/</a>からDesireのソースコードをダウンロードする。今回は「bravo-2.6.32-gd96f2c0.tar.gz」でした。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/27/test132_02.png" rel="lightbox"><img alt="test132_02.png" src="http://www.usefullcode.net/2011/01/27/test132_02-thumb.png" width="400" height="300" align="left" /></a>
ダウンロードしている間に雛形となるプロジェクトを<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で作る。今回はC++プロジェクトとした。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/27/test132_03.png" rel="lightbox"><img alt="test132_03.png" src="http://www.usefullcode.net/2011/01/27/test132_03-thumb.png" width="400" height="300" align="left" /></a>
そして自動生成されたプロジェクトのjniフォルダに、ダウンロードしたHTC Desireのソースコードに含まれるmsm_camera.hをコピーする。

具体的なパスは「bravo-2.6.32-gd96f2c0\ include\ media\ msm_camera.h」。スクリーンキャプチャ用の環境ではtar.gzを解凍できなかったので別PCで解凍してコピーしてきました。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/27/test132_04.png" rel="lightbox"><img alt="test132_04.png" src="http://www.usefullcode.net/2011/01/27/test132_04-thumb.png" width="400" height="300" align="left" /></a>
次にEclipseでプロジェクトを読み込んで実際にLEDを制御するコードを実装する。

/dev/msm_camera/config0を開いて、int32数値を引数にしたMSM_CAM_IOCTL_FLASH_LED_CFGコマンドをioctlに送るだけです。今回はさらにMSM_CAM_IOCTL_GET_SENSOR_INFOを使って、カメラセンサー名とフラッシュサポートの有無を調べる関数も実装しました。
<br clear=left>
<pre class=SourceCode>
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include &lt;string.h&gt;
#include &lt;jni.h&gt;

#ifdef LOCAL_LOG
#include &lt;android/log.h&gt;
#endif



#include &lt;stdlib.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;sys/syscall.h&gt;
#include &quot;msm_camera.h&quot;

/*
 //msm_camera.hより
#define	MSM_CAM_IOCTL_MAGIC	'm'
#define	MSM_CAM_IOCTL_FLASH_LED_CFG	_IOW(MSM_CAM_IOCTL_MAGIC, 22, unsigned *)

#define MSM_CAMERA_LED_OFF 0
#define MSM_CAMERA_LED_LOW 1
#define MSM_CAMERA_LED_HIGH 2
#define MSM_CAMERA_LED_LOW_FOR_SNAPSHOT 3
*/



//
//	フラッシュコントロール
//
//nModeはMSM_CAMERA_LED_OFF、MSM_CAMERA_LED_LOW、MSM_CAMERA_LED_HIGHなど
//
//事前に↓を実行すること！
//	&quot;chmod 666 /dev/msm_camera/config0&quot;
//
int	CtrlCameraLED(int nMode)
{
	int		fd;
	int		nRet;

	fd = open(&quot;/dev/msm_camera/config0&quot;,O_RDWR | O_NONBLOCK);
	if(fd &lt; 0)
		return	0;

	msm_camsensor_info	info;

	memset(&amp;info,0,sizeof(info));
	nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&amp;info);
	if(nRet &lt; 0 || info.flash_enabled == 0)
	{
		close(fd);
		return	0;
	}

	nRet = ioctl(fd,MSM_CAM_IOCTL_FLASH_LED_CFG,&amp;nMode);
	close(fd);
	if(nRet &lt; 0)
		return	0;

	return	1;
}


//
//フラッシュをサポートしないなら0、サポートするなら0以外を返す
//
//事前に↓を実行すること！
//	&quot;chmod 666 /dev/msm_camera/config0&quot;
//
int	IsSupportCameraLED(void)
{
	int		fd;
	int		nOnOff;		//uint_32
	int		nRet;
	msm_camsensor_info	info;

	fd = open(&quot;/dev/msm_camera/config0&quot;,O_RDWR | O_NONBLOCK);
	if(fd &lt; 0)
		return	0;

	memset(&amp;info,0,sizeof(info));
	nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&amp;info);
	close(fd);
	if(nRet &lt; 0)
		return	0;

	if(info.flash_enabled)
		return	1;
	return	0;
}



//
//	カメラセンサー名の取得
//
//事前に↓を実行すること！
//	&quot;chmod 666 /dev/msm_camera/config0&quot;
//
int	GetCameraSensorName(char* pszName,int nLen)
{
	int		fd;
	int		nOnOff;		//uint_32
	int		nRet;
	msm_camsensor_info	info;

	if(nLen &lt; MAX_SENSOR_NAME)
		return	0;

	fd = open(&quot;/dev/msm_camera/config0&quot;,O_RDWR | O_NONBLOCK);
	if(fd &lt; 0)
		return	0;

	memset(&amp;info,0,sizeof(info));
	nRet = ioctl(fd,MSM_CAM_IOCTL_GET_SENSOR_INFO,&amp;info);
	close(fd);
	if(nRet &lt; 0)
		return	0;

	strcpy(pszName,info.name);

	return	1;
}





extern &quot;C&quot;
jboolean Java_com_Test132_Test132Act_NativeIsSupportCameraLED(JNIEnv* env,jobject thiz)
{
	if(IsSupportCameraLED)
		return	JNI_TRUE;
	return	JNI_FALSE;
}

extern &quot;C&quot;
jboolean Java_com_Test132_Test132Act_NativeCtrlCameraLED(JNIEnv* env,jobject thiz,jint nMode)
{
	if(CtrlCameraLED(nMode))
		return	JNI_TRUE;
	return	JNI_FALSE;
}


extern &quot;C&quot;
jstring Java_com_Test132_Test132Act_NativeGetSensorName(JNIEnv* env,jobject thiz)
{
	char	pszName[MAX_SENSOR_NAME];

	if(GetCameraSensorName(pszName,MAX_SENSOR_NAME) == 0)
		return	env-&gt;NewStringUTF(&quot;Failed&quot;);

	return env-&gt;NewStringUTF(pszName);
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/27/test132_05.png" rel="lightbox"><img alt="test132_05.png" src="http://www.usefullcode.net/2011/01/27/test132_05-thumb.png" width="400" height="300" align="left" /></a>
java側では、画面をタッチしたら順々にLEDの光量を変更するようにします。

また、/dev/msm_camera/config0を開くには事前にRW属性を付けておかないといけない＆RW属性を付けるにはroot権限が必要なので、suコマンドによりchmodを実行する関数も作っておきます。

これで実機で実行すると、、、
<br clear=left>
<pre class=SourceCode>
package com.Test132;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.TextView;

public class Test132Act extends Activity
{
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		ExecSuCommand(&quot;chmod 666 /dev/msm_camera/config0&quot;);

		NativeCtrlCameraLED(_nCurrentMode);

		TextView	tv = new TextView(this);
		tv.setText( NativeGetSensorName() );
		setContentView(tv);
	}


	
	
	boolean	ExecSuCommand(String strCommandLine)
	{
		try
		{
			Process	process = Runtime.getRuntime().exec(&quot;su&quot;);
			java.io.DataOutputStream os = new java.io.DataOutputStream(process.getOutputStream());
			os.writeBytes(strCommandLine + &quot;\nexit\n&quot;);
			os.flush();
			process.waitFor();
			return	true;
		}
		catch(java.io.IOException e)
		{
		}
		catch (InterruptedException e)
		{
		}
		return	false;
	}


	int		_nCurrentMode = MSM_CAMERA_LED_OFF;
	
	final	static	int	MSM_CAMERA_LED_OFF = 0;
	final	static	int	MSM_CAMERA_LED_LOW = 1;
	final	static	int	MSM_CAMERA_LED_HIGH = 2;
	final	static	int	MSM_CAMERA_LED_LOW_FOR_SNAPSHOT = 3;


	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		switch(event.getAction() &amp; MotionEvent.ACTION_MASK)
		{
		case	MotionEvent.ACTION_DOWN:
			switch(_nCurrentMode)
			{
			case	MSM_CAMERA_LED_OFF:
				_nCurrentMode = MSM_CAMERA_LED_LOW;
				break;

			case	MSM_CAMERA_LED_LOW:
				_nCurrentMode = MSM_CAMERA_LED_HIGH;
				break;

			case	MSM_CAMERA_LED_HIGH:
				_nCurrentMode = MSM_CAMERA_LED_LOW_FOR_SNAPSHOT;
				break;

			case	MSM_CAMERA_LED_LOW_FOR_SNAPSHOT:
				_nCurrentMode = MSM_CAMERA_LED_OFF;
				break;
			}

			NativeCtrlCameraLED(_nCurrentMode);
			break;
		}

		return true;
	}

	
	public native boolean  NativeIsSupportCameraLED();
	public native boolean  NativeCtrlCameraLED(int nMode);
	public native String  NativeGetSensorName();

	static
	{
		System.loadLibrary(&quot;Test132&quot;);
	}
}
</pre>
<br>
<a href="http://www.usefullcode.net/2011/01/27/test132_06.png" rel="lightbox"><img alt="test132_06.png" src="http://www.usefullcode.net/2011/01/27/test132_06-thumb.png" width="400" height="666" align="left" /></a>
初回起動時に「Superuser Request The following app is requesting superuser access:」と出て、su権限を許可するかを問われます。ここで「Allow」を選択します。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/27/test132_07.png" rel="lightbox"><img alt="test132_07.png" src="http://www.usefullcode.net/2011/01/27/test132_07-thumb.png" width="400" height="240" align="left" /></a>
すると画面にカメラセンサー名の「s5k3e2fx」という文字が表示されて、画面をタッチすると、、、
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/27/DSC_0715.JPG" rel="lightbox"><img alt="DSC_0715.JPG" src="http://www.usefullcode.net/2011/01/27/DSC_0715-thumb.JPG" width="400" height="265" align="left" /></a>
LEDが点灯しました。

成功のように思えるのですが、何度タッチしても光量が変わりません。本当なら3段階＆OFFの4パターンが順々に変化するはずなのですが、、
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/27/Test132.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKで画像を読み込み、ピンチ操作でズームする</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk_4.html" />
   <id>tag:www.usefullcode.net,2011://1.9999</id>
   
   <published>2011-01-26T10:22:58Z</published>
   <updated>2011-01-26T10:25:32Z</updated>
   
   <summary> 今回は表示したJPEG画像をピンチ操作によりズームする。ピンチ操作というのは2...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/26/test131_01.png" rel="lightbox"><img alt="test131_01.png" src="http://www.usefullcode.net/2011/01/26/test131_01-thumb.png" width="400" height="300" align="left" /></a>
今回は表示したJPEG画像をピンチ操作によりズームする。ピンチ操作というのは2本の指で画面をタッチして、指間隔を開けば拡大、指間隔を狭めれば縮小というもの。

まずは<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で雛形になるプロジェクトを作成。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/26/test131_02.png" rel="lightbox"><img alt="test131_02.png" src="http://www.usefullcode.net/2011/01/26/test131_02-thumb.png" width="400" height="300" align="left" /></a>
そしてjavaのソースコードでアクティビティへImageFileViewクラスを割り当てる。このクラスにJPEG読み込みからピンチ操作、ズーム表示までを実装する。
<br clear=left>
<pre class=SourceCode>
package com.Test131;

import android.app.Activity;
import android.os.Bundle;
<b>import android.widget.LinearLayout;</b>

public class Test131Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

<b>		LinearLayout	layout = new LinearLayout(this);
		setContentView(layout);

		ImageFileView	view = new ImageFileView(this);
		layout.addView(view);</b>
	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/26/test131_03.png" rel="lightbox"><img alt="test131_03.png" src="http://www.usefullcode.net/2011/01/26/test131_03-thumb.png" width="400" height="300" align="left" /></a>
ImageFileView.javaというファイルを作り、実装する。

BitmapFactory.decodeFile()では、大きな画像ファイルを読み込もうとするとメモリが足りなくなってアプリが落ちてしまうので、今回は長辺がnMaxWidthピクセル以下になるように縮小して読み込むことにした。
<br clear=left>
<pre class=SourceCode>package com.Test131;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.view.View;



public class ImageFileView extends View
{
	//表示画像
	protected	Bitmap	_bmpImageFile;


	public ImageFileView(Context context)
	{
		super(context);

		{
			String	strFile = &quot;/sdcard/DSC_0670.JPG&quot;;

			_bmpImageFile = LoadImageFile(strFile,800*2);
		}
	}


	public	Bitmap	LoadImageFile(String strFile,int nMaxWidth)
	{
		Bitmap	bmpImage;
		
		//画像の解析（大きい画像が開けない対策）
		BitmapFactory.Options	options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(strFile,options);
		
		int		nWidth = options.outWidth;
		int		nHeight = options.outHeight;

		if(nWidth == 0 || nHeight == 0)
			return	null;

		if(nWidth &lt;= nMaxWidth &amp;&amp; nHeight &lt;= nMaxWidth)
		{
			//リサイズ不要。そのまま読み込んで返す
			options.inJustDecodeBounds = false;
			return	BitmapFactory.decodeFile(strFile,options);
		}



		int		nScale;

		//nScaleは2の乗数にする
		{
			float	fScale;
			float	fScaleX = (float)nWidth / nMaxWidth;
			float	fScaleY = (float)nHeight / nMaxWidth;

			fScale = (fScaleX &gt; fScaleY) ? fScaleX : fScaleY;

			nScale = 1;
			while(fScale &gt;= nScale)
			{
				nScale *= 2;
			}
		}

		//画像の本読み込み
		options.inJustDecodeBounds = false;
		options.inSampleSize = nScale;
		bmpImage = BitmapFactory.decodeFile(strFile,options);

		return	bmpImage;
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);

		if(_bmpImageFile == null)
			return;

		Matrix	matrix = new Matrix();

		//描画
		canvas.drawBitmap(_bmpImageFile, matrix, null);
	}
}
</pre>
<br>


<a href="http://www.usefullcode.net/2011/01/26/test131_04.png" rel="lightbox"><img alt="test131_04.png" src="http://www.usefullcode.net/2011/01/26/test131_04-thumb.png" width="400" height="300" align="left" /></a>
これで実行すると画像が大きく表示された。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/26/test131_05.png" rel="lightbox"><img alt="test131_05.png" src="http://www.usefullcode.net/2011/01/26/test131_05-thumb.png" width="400" height="300" align="left" /></a>
さらに画像のサイズに合わせて縮小＆余白を表示する。
<br clear=left>
<br>
<pre class=SourceCode>	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);

		if(_bmpImageFile == null)
			return;

<b>		//画面表示用ズーム率
		float	fImageScale;

		//余白
		float	fMarginX = 0.0f;
		float	fMarginY = 0.0f;
		
		//ズーム率取得
		{
			int		nImageWidth	= _bmpImageFile.getWidth();
			int		nImageHeight= _bmpImageFile.getHeight();
			int		nViewWidth = getWidth();
			int		nViewHeight = getHeight();


			//画像に合わせる
			if((long)nImageWidth * nViewHeight &gt; (long)nViewWidth * nImageHeight)
			{
				fImageScale = (float)nViewWidth / nImageWidth;
				fMarginY = (nViewHeight - fImageScale * nImageHeight) * 0.5f;
			}
			else
			{
				fImageScale = (float)nViewHeight / nImageHeight;
				fMarginX = (nViewWidth - fImageScale * nImageWidth) * 0.5f;
			}
		}


		//ズーム率
		float	fScale = fImageScale;

		//余白移動
		float	fMoveX = fMarginX;
		float	fMoveY = fMarginY;
</b>
		Matrix	matrix = new Matrix();

<b>		//ズーム
		matrix.preScale(fScale,fScale);

		//移動
		matrix.postTranslate(fMoveX,fMoveY);
</b>
		//描画
		canvas.drawBitmap(_bmpImageFile, matrix, null);
	}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/26/test131_06.png" rel="lightbox"><img alt="test131_06.png" src="http://www.usefullcode.net/2011/01/26/test131_06-thumb.png" width="400" height="300" align="left" /></a>
これで画像に合わせて縮小＆余白表示された。ここまではこれまでも紹介してきた流れで、ピンチ操作などは実装していない。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/26/test131_07.png" rel="lightbox"><img alt="test131_07.png" src="http://www.usefullcode.net/2011/01/26/test131_07-thumb.png" width="400" height="300" align="left" /></a>
次にようやくピンチ操作を実装する。

MotionEvent.ACTION_POINTER_DOWNやMotionEvent.ACTION_POINTER_MOVEでピンチ操作を簡単に検知できる。しかしどうも簡単にそれを使ってズームする仕組みは用意されていない模様。今回は簡易的なピンチズームを実装したものの、きちんとしたものを実装しようと思ったらMatrixは使わずに自分で領域計算して描画した方がよさそうです。
<br clear=left>
<pre class=SourceCode>

	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);

		if(_bmpImageFile == null)
			return;

		//画面表示用ズーム率
		float	fImageScale;

		//余白
		float	fMarginX = 0.0f;
		float	fMarginY = 0.0f;
		
		//ズーム率取得
		{
			int		nImageWidth	= _bmpImageFile.getWidth();
			int		nImageHeight= _bmpImageFile.getHeight();
			int		nViewWidth = getWidth();
			int		nViewHeight = getHeight();


			//画像に合わせる
			if((long)nImageWidth * nViewHeight &gt; (long)nViewWidth * nImageHeight)
			{
				fImageScale = (float)nViewWidth / nImageWidth;
				fMarginY = (nViewHeight - fImageScale * nImageHeight) * 0.5f;
			}
			else
			{
				fImageScale = (float)nViewHeight / nImageHeight;
				fMarginX = (nViewWidth - fImageScale * nImageWidth) * 0.5f;
			}
		}

<b>
		//ピンチを含めた総合ズーム率
		float	fScale = _fPinchScale * fImageScale;

		//余白を含めた移動量
		float	fMoveX = _fPinchMoveX + fMarginX;
		float	fMoveY = _fPinchMoveY + fMarginY;
		
		
		//ズーム原点指定
		fMoveX += _ptPinchStart.x - _ptPinchStart.x * _fPinchScale;
		fMoveY += _ptPinchStart.y - _ptPinchStart.y * _fPinchScale;
</b>
		Matrix	matrix = new Matrix();

		//ズーム
		matrix.preScale(fScale,fScale);

		//移動
		matrix.postTranslate(fMoveX,fMoveY);

		//描画
		canvas.drawBitmap(_bmpImageFile, matrix, null);
	}

<b>
	//ピンチによる現在のズーム率（拡大  &gt; 1.0f &gt; 縮小）
	private	float	_fPinchScale	= 1.0f;

	private	PointF	_ptPinchStart	= new PointF();
	private float	_fPinchStartDistance	= 0.0f;
	private	float	_fPinchMoveX	= 0.0f;
	private	float	_fPinchMoveY	= 0.0f;

	//タッチ操作内部処理用
	private static final int TOUCH_NONE = 0;
	private static final int TOUCH_DRAG = 1;
	private static final int TOUCH_ZOOM = 2;
	private int		_nTouchMode	= TOUCH_NONE;

	
	@Override
	public boolean onTouchEvent(MotionEvent event)
	{

		switch(event.getAction() &amp; MotionEvent.ACTION_MASK)
		{
			//ピンチ開始 
		case MotionEvent.ACTION_POINTER_DOWN:
			if(event.getPointerCount() &gt;= 2)
			{
				_fPinchStartDistance = GetDistance(event);
				if(_fPinchStartDistance &gt; 50f)
				{
					GetCenterPoint(event,_ptPinchStart);
					_nTouchMode = TOUCH_ZOOM;
				}
			}
		    break;

		    //ピンチ中
		case MotionEvent.ACTION_MOVE:
		    if(_nTouchMode == TOUCH_ZOOM &amp;&amp; _fPinchStartDistance &gt; 0)
		    {
		    	PointF	pt = new PointF();

		    	GetCenterPoint(event,pt);
		    	_fPinchMoveX	= pt.x - _ptPinchStart.x;
		    	_fPinchMoveY	= pt.y - _ptPinchStart.y;

		    	_fPinchScale = GetDistance(event) / _fPinchStartDistance;
				invalidate();
		    }
		    break;

		    //ピンチ終了
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			if(_nTouchMode == TOUCH_ZOOM)
			{
				//ピンチ終了処理
				_nTouchMode = TOUCH_NONE;

				_fPinchMoveX	= 0.0f;
				_fPinchMoveY	= 0.0f;
				_fPinchScale	= 1.0f;
				_ptPinchStart.x	= 0.0f;
				_ptPinchStart.y	= 0.0f;
				invalidate();
			}
			break;
		}
		
		
		switch(event.getAction() &amp; MotionEvent.ACTION_MASK)
		{
			//ドラッグ開始
		case	MotionEvent.ACTION_DOWN:
			if(_nTouchMode == TOUCH_NONE &amp;&amp; event.getPointerCount() == 1)
			{
				_nTouchMode = TOUCH_DRAG;
			}
			break;

		case MotionEvent.ACTION_MOVE:
			if(_nTouchMode == TOUCH_DRAG)
			{
			}
			break;
			
			//ドラッグ終了
		case	MotionEvent.ACTION_UP:
			if(_nTouchMode == TOUCH_DRAG)
			{
				//ドラッグ終了処理
				_nTouchMode = TOUCH_NONE;
				break;
			}
		}

		return true;
	}	

	//ピンチ距離取得用
	private	float	GetDistance(MotionEvent event)
	{
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return android.util.FloatMath.sqrt(x * x + y * y);
	}

	//ピンチ開始座標取得用
	private	void	GetCenterPoint(MotionEvent event,PointF pt)
	{
		pt.x = (event.getX(0) + event.getX(1)) * 0.5f;
		pt.y = (event.getY(0) + event.getY(1)) * 0.5f;
	}</b>

</pre>
<br>
<br>
<a href="http://www.usefullcode.net/2011/01/26/Test131.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android OSソースコード一式のダウンロード</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_os.html" />
   <id>tag:www.usefullcode.net,2011://1.9998</id>
   
   <published>2011-01-26T01:47:51Z</published>
   <updated>2011-02-05T15:45:30Z</updated>
   
   <summary> 公式サイトにある具体的なダウンロード方法やビルド方法はhttp://sourc...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[公式サイトにある具体的なダウンロード方法やビルド方法は<a href="http://source.android.com/source/download.html" target="_blank">http://source.android.com/source/download.html</a>。

公式サイトからのソースコード配布はRepoとかGitが必要で、また、そのためにLinuxの環境が必要。ちなみにCygwinでもダウンロードしようと思えばできるもののビルドはできないらしいです。

ソースコードのダウンロードは何だかんだと面倒な作業になり、敷居がかなり高いので私がダウンロードしたAndroidソースコード一式をtar.zipに固めてアップロードしました。無責任な話しですがビルドなどの確認はしていないので本当にきちんとダウンロードできているのかは不明です。



■Android 2.3ソースコード一式

<a href="http://www.oqst.com/android23_20110122.tar.gz" target="_blank">android23_20110122.tar.gz</a>（3GB）


]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKでフォルダ内のファイルをソートして列挙する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk_3.html" />
   <id>tag:www.usefullcode.net,2011://1.9997</id>
   
   <published>2011-01-21T10:46:12Z</published>
   <updated>2011-01-21T10:47:45Z</updated>
   
   <summary> フォルダ内のファイル一覧は「File[] files = new File(s...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/21/test130_01.png" rel="lightbox"><img alt="test130_01.png" src="http://www.usefullcode.net/2011/01/21/test130_01-thumb.png" width="400" height="300" align="left" /></a>
フォルダ内のファイル一覧は「File[] files = new File(strPath) .listFiles();」のような感じで簡単に習得できる。しかしこうやって取得したファイル配列は名前順に並んでいないし、隠しファイルや隠しフォルダも含まれている。

今回は隠しファイル／隠しフォルダを省き、さらにソートした状態のファイル配列を取得できる関数を作成した。
<br clear=left>
<pre class=SourceCode>
package com.Test130;

<b>import java.io.File;</b>
import android.app.Activity;
import android.os.Bundle;
<b>import android.util.Log;</b>

public class Test130Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

<b>		File[]	aFiles = GetFileList(&quot;/system/lib/&quot;);

		for(File file : aFiles)
		{
			if(file.isDirectory())
				Log.d(&quot;Test130&quot;,&quot;Found : &quot; + file.getAbsolutePath() + &quot;/&quot;);
			else
				Log.d(&quot;Test130&quot;,&quot;Found : &quot; + file.getAbsolutePath());
		}</b>
	}


<b>	//
	//パスで指定されたフォルダ内のファイル／フォルダをソートして返す
	//
	public	File[]	GetFileList(String strPath)
	{
		//ソート用の独自オブジェクトクラス　ここでしか使わないから関数内で無理やり宣言
		final class Data
		{
			private File _data;

			public Data(File data)
			{
				_data = data;
			}

			public	File	getFile()
			{
				return	_data;
			}
			
			public	int	Compare(Data cmp)
			{
				String	str1 = _data.getAbsolutePath();
				String	str2 = cmp._data.getAbsolutePath();

				if(cmp == null || cmp._data == null || _data == null)
					return	0;
				
				if(_data.isDirectory() == cmp._data.isDirectory())
					return	str1.compareToIgnoreCase(str2);
				if(_data.isDirectory())
					return	-1;
				return	1;
			}
		}

		//ソート用比較関数 　ここでしか使わないから関数内で無理やり宣言
		final class DataComparator implements java.util.Comparator
		{
			public int compare(Object o1, Object o2)
			{
				return	((Data)o1).Compare((Data)o2);
			}
		}
		
		
		//strPathをファイルオブジェクトにする
		File	file = new File(strPath);

		//strPathがファイルだったらそのファイルが含まれるフォルダを処理対象とする
		if(file.isFile())
		{
			file = file.getParentFile();
			if(file == null)
				return	null;
		}

		int		i;
		File[]	afTmp;

		//フォルダ内のファイル配列を取得
		afTmp = file.listFiles();
		if(afTmp == null || afTmp.length == 0)
			return	null;
		
		//一度独自オブジェクトのリストに変換して、、、
		java.util.ArrayList	alist = new java.util.ArrayList();
		for(i = 0; i &lt; afTmp.length; i++)
		{
			if(afTmp[i].isHidden() == false)	//隠しファイル／フォルダは無視
				alist.add(new Data(afTmp[i]));
		}

		//オブジェクトリストからオブジェクト配列に変換
		Object[]	aObject = alist.toArray();

		//javaのオブジェクト用メソッドを使ってソート
		java.util.Arrays.sort(aObject,new DataComparator());

		//オブジェクト配列からファイル配列に変換
		afTmp = new File[aObject.length];
		for(i = 0; i &lt; aObject.length; i++)
			afTmp[i] = ((Data)aObject[i]).getFile();

		return	afTmp;
	}</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test130_02.png" rel="lightbox"><img alt="test130_02.png" src="http://www.usefullcode.net/2011/01/21/test130_02-thumb.png" width="400" height="300" align="left" /></a>
これで指定したフォルダ内のファイルとフォルダがソートされた状態でログに出力された。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/21/Test130.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>実行時クラスを取得／比較する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/post_57.html" />
   <id>tag:www.usefullcode.net,2011://1.9996</id>
   
   <published>2011-01-21T07:04:11Z</published>
   <updated>2011-01-21T07:05:57Z</updated>
   
   <summary> JavaではgetClass()を使えば実行時クラスを取得、比較できる。派生ク...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/21/test129_01.png" rel="lightbox"><img alt="test129_01.png" src="http://www.usefullcode.net/2011/01/21/test129_01-thumb.png" width="400" height="300" align="left" /></a>
JavaではgetClass()を使えば実行時クラスを取得、比較できる。派生クラスの判別に利用可能。
<br clear=left>
<pre class=SourceCode>
package com.Test129;

import android.app.Activity;
import android.os.Bundle;
<b>import android.util.Log;</b>

public class Test129Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

<b>		BASE	test = new AAA();

		if(test.getClass() == BASE.class)
			Log.d(&quot;Test129&quot;,&quot;test == BASE&quot;);
		else
			Log.d(&quot;Test129&quot;,&quot;test != BASE&quot;);

		if(test.getClass() == AAA.class)
			Log.d(&quot;Test129&quot;,&quot;test == AAA&quot;);
		else
			Log.d(&quot;Test129&quot;,&quot;test != AAA&quot;);

		if(test.getClass() == BBB.class)
			Log.d(&quot;Test129&quot;,&quot;test == BBB&quot;);
		else
			Log.d(&quot;Test129&quot;,&quot;test != BBB&quot;);</b>
	}

<b>	private	class	BASE
	{
	};
	
	private	class	AAA extends BASE
	{
	};
	
	private	class	BBB extends BASE
	{
	};</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test129_02.png" rel="lightbox"><img alt="test129_02.png" src="http://www.usefullcode.net/2011/01/21/test129_02-thumb.png" width="400" height="300" align="left" /></a>
きちんと比較できた。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/21/Test129.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKでメニュー項目を動的に操作する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk_2.html" />
   <id>tag:www.usefullcode.net,2011://1.9995</id>
   
   <published>2011-01-21T05:57:26Z</published>
   <updated>2011-01-21T05:58:26Z</updated>
   
   <summary> 以前にAndroid SDKで「menu」ボタンでメニューを表示するでメニュー...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/21/test128_01.png" rel="lightbox"><img alt="test128_01.png" src="http://www.usefullcode.net/2011/01/21/test128_01-thumb.png" width="400" height="300" align="left" /></a>
以前に<a href="http://www.usefullcode.net/2011/01/android_sdkmenu.html" target="_blank">Android SDKで「menu」ボタンでメニューを表示する</a>でメニューを表示した。onCreateOptionsMenu()でメニュー項目を作り表示、onOptionsItemSelected()で選択されたメニュー項目を実行できる。

しかしonCreateOptionsMenu()は初回に1度だけ呼ばれるのみなので、動的にメニュー項目を増やしたり減らしたり、表示するメニューの文字を変えることはできなかった。動的にメニュー項目を変更するにはonPrepareOptionsMenu()をオーバーライドして、そこでメニュー項目を操作する。
<br clear=left>
<pre class=SourceCode>
package com.Test128;

<b>import java.util.Calendar;</b>
import android.app.Activity;
import android.os.Bundle;
<b>import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;</b>


public class Test128Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		super.onCreateOptionsMenu(menu);

		int		nId = 0;

		menu.add(0,nId++,Menu.NONE,&quot;AAA&quot;).setIcon(android.R.drawable.ic_menu_set_as);
		menu.add(0,nId++,Menu.NONE,&quot;BBB&quot;);
		menu.add(0,nId++,Menu.NONE,&quot;CCC&quot;).setIcon(R.drawable.icon);


		return true;
	}


<b>	@Override
	public boolean onPrepareOptionsMenu(Menu menu)
	{
		String	str;

		str = Calendar.getInstance().getTime().toString();
		menu.findItem(1).setTitle(str);

		return true;
	}
</b>
	
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		Log.d(&quot;Test124&quot;,&quot;MenuSelected &quot; + item.getItemId() + &quot; &quot; + item.getTitle());

		switch(item.getItemId())
		{
		case 0:
			return	true;

		case 1:
			return	true;

		case 2:
			return	true;

		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test128_02.png" rel="lightbox"><img alt="test128_02.png" src="http://www.usefullcode.net/2011/01/21/test128_02-thumb.png" width="400" height="300" align="left" /></a>
これでメニューを動的に操作して、表示するたびにそのときの日時をメニューとして表示することができた。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/21/Test128.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKでキーロック状態を取得する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk_1.html" />
   <id>tag:www.usefullcode.net,2011://1.9994</id>
   
   <published>2011-01-21T05:14:32Z</published>
   <updated>2011-01-21T05:24:39Z</updated>
   
   <summary> Androidアプリの実行中に今現在画面がロックされているかどうかのロック状態...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/21/test127.png" rel="lightbox"><img alt="test127.png" src="http://www.usefullcode.net/2011/01/21/test127-thumb.png" width="400" height="300" align="left" /></a>
Androidアプリの実行中に今現在画面がロックされているかどうかのロック状態を調べるにはKeyguardManager:: inKeyguardRestrictedInputMode()を使う。trueならロック中、falseならロックされていない。

問題はロック／アンロックの検出。HTC Desireでは下のソースで検出できましたが、Androidエミュレーターでは検出できませんでした。また下のソースではアンロックの検出にフォーカス状態を利用しているので、フォーカスが一定しないアプリの場合は使えないはずです。
電源ボタンをハンドルすれば手動でのロック／アンロックは検出できるはずですが、そうすると今度はソフトウエア的なロックなどは検出できないはずですし、、、ということでロック／アンロックの検出方法は不明です。
<br clear=left>
<pre class=SourceCode>
package com.Test127;

import android.app.Activity;
<b>import android.app.KeyguardManager;
import android.content.Context;</b>
import android.os.Bundle;
<b>import android.util.Log;</b>

public class Test127Act extends Activity
{
<b>	private	KeyguardManager	_KeyguardManager;
	private	boolean			_bScreenLocked = false;</b>
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

<b>		_KeyguardManager = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
		_bScreenLocked = _KeyguardManager.inKeyguardRestrictedInputMode();</b>
	}

	
<b>	@Override
	public void	onPause()
	{
		super.onPause();

		_bScreenLocked = _KeyguardManager.inKeyguardRestrictedInputMode();
		if(_bScreenLocked)
		{
			//ロックされた
			//呼ばれないことあり
			Log.d(&quot;Test127&quot;,&quot;onPause() Locked!!! Do something ....&quot;);
		}
	}

	
	@Override
	public void	onWindowFocusChanged(boolean hasFocus)
	{

		super.onWindowFocusChanged(hasFocus);

		if(_bScreenLocked == true &amp;&amp; hasFocus)
		{
			//アンロックされた
			//呼ばれないことあり
			Log.d(&quot;Test127&quot;,&quot;onWindowFocusChanged() Unlocked!!! Do something ....&quot;);
		}
		_bScreenLocked = _KeyguardManager.inKeyguardRestrictedInputMode();
	}</b>
}
</pre>
<br>
<br>
<a href="http://www.usefullcode.net/2011/01/21/Test127.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKで画面が533x320ドットになる問題の解決策</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk533x320.html" />
   <id>tag:www.usefullcode.net,2011://1.9993</id>
   
   <published>2011-01-20T15:29:25Z</published>
   <updated>2011-01-20T15:48:40Z</updated>
   
   <summary> Androidで画像表示をしているうちに、画面サイズが533×320ドットとし...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/21/test126_01.png" rel="lightbox"><img alt="test126_01.png" src="http://www.usefullcode.net/2011/01/21/test126_01-thumb.png" width="400" height="300" align="left" /></a>
Androidで画像表示をしているうちに、画面サイズが533×320ドットとして認識される問題にぶつかりました。

以下のようなソースコードで画面のサイズや解像度などの情報を取得する。実行にはHTC Desireを利用した。
<br clear=left>
<pre class=SourceCode>package com.Test126;

import android.app.Activity;
<b>import android.content.Context;</b>
import android.os.Bundle;
<b>import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;</b>

public class Test126Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

<b>
		WindowManager	wmWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
		Display			display = wmWindowManager.getDefaultDisplay();

		Log.d(&quot;Test126&quot;,&quot;Display.getWidth() &quot; + display.getWidth());
		Log.d(&quot;Test126&quot;,&quot;Display.getWidth() &quot; + display.getHeight());
		
		DisplayMetrics	displayMetrics = new DisplayMetrics();
		display.getMetrics(displayMetrics);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.widthPixels   &quot; + displayMetrics.widthPixels);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.heightPixels  &quot; + displayMetrics.heightPixels);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.density       &quot; + displayMetrics.density);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.densityDpi    &quot; + displayMetrics.densityDpi);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.scaledDensity &quot; + displayMetrics.scaledDensity);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.xdpi          &quot; + displayMetrics.xdpi);
		Log.d(&quot;Test126&quot;,&quot;DisplayMetrics.ydpi          &quot; + displayMetrics.ydpi);
</b>	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test126_02.png" rel="lightbox"><img alt="test126_02.png" src="http://www.usefullcode.net/2011/01/21/test126_02-thumb.png" width="400" height="300" align="left" /></a>
するとこのような結果になった。HTC Desireの物理的な画面サイズは800×480ドットだが、取得できたサイズは533×320ドット。

マニフェスト設定によってはこのような結果になるらしい。もちろんこの状態だと、アプリ内での描画サイズも533×320ドットになり、800×480ドットの画面サイズを活かした緻密な描画ができない。
<br clear=left>
<pre class=SourceCode>
01-21 00:22:41.873: DEBUG/Test126(8149): Display.getWidth() 533
01-21 00:22:41.873: DEBUG/Test126(8149): Display.getWidth() 320
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.widthPixels   533
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.heightPixels  320
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.density       1.5
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.densityDpi    240
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.scaledDensity 1.5
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.xdpi          254.0
01-21 00:22:41.873: DEBUG/Test126(8149): DisplayMetrics.ydpi          254.0
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test126_03.png" rel="lightbox"><img alt="test126_03.png" src="http://www.usefullcode.net/2011/01/21/test126_03-thumb.png" width="400" height="300" align="left" /></a>
533×320ドットになる問題の解決策のひとつはAndroidManifest.xmlの中でuses-sdk android:minSdkVersionを指定する方法。
<br clear=left>
<pre class=SourceCode>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      package=&quot;com.Test126&quot;
      android:versionCode=&quot;1&quot;
      android:versionName=&quot;1.0&quot;&gt;
    &lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
        &lt;activity android:name=&quot;.Test126Act&quot;
                  android:label=&quot;@string/app_name&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

    &lt;/application&gt;

<b>&lt;uses-sdk android:minSdkVersion=&quot;4&quot;/&gt;</b>

&lt;/manifest&gt;
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test126_04.png" rel="lightbox"><img alt="test126_04.png" src="http://www.usefullcode.net/2011/01/21/test126_04-thumb.png" width="400" height="300" align="left" /></a>
これできちんと800×480ドットと認識できた。
<br clear=left>
<pre class=SourceCode>
01-21 00:23:46.933: DEBUG/Test126(8221): Display.getWidth() 800
01-21 00:23:46.933: DEBUG/Test126(8221): Display.getWidth() 480
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.widthPixels   800
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.heightPixels  480
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.density       1.5
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.densityDpi    240
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.scaledDensity 1.5
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.xdpi          254.0
01-21 00:23:46.933: DEBUG/Test126(8221): DisplayMetrics.ydpi          254.0
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/21/test126_05.png" rel="lightbox"><img alt="test126_05.png" src="http://www.usefullcode.net/2011/01/21/test126_05-thumb.png" width="400" height="300" align="left" /></a>
もう一つの解決策はsupports-screensでandroid:largeScreensなどを有効にする方法。
<br clear=left>
<pre class=SourceCode>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      package=&quot;com.Test126&quot;
      android:versionCode=&quot;1&quot;
      android:versionName=&quot;1.0&quot;&gt;
    &lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
        &lt;activity android:name=&quot;.Test126Act&quot;
                  android:label=&quot;@string/app_name&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

    &lt;/application&gt;


<b>&lt;supports-screens
	android:smallScreens=&quot;true&quot;
	android:normalScreens=&quot;true&quot;
	android:largeScreens=&quot;true&quot;
	android:anyDensity=&quot;true&quot; /&gt;</b>
&lt;/manifest&gt;
</pre>
<br>


<a href="http://www.usefullcode.net/2011/01/21/test126_06.png" rel="lightbox"><img alt="test126_06.png" src="http://www.usefullcode.net/2011/01/21/test126_06-thumb.png" width="400" height="300" align="left" /></a>
こちらでも800×480ドットと認識された。
<br clear=left>
<pre class=SourceCode>
01-21 00:24:52.513: DEBUG/Test126(8294): Display.getWidth() 800
01-21 00:24:52.513: DEBUG/Test126(8294): Display.getWidth() 480
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.widthPixels   800
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.heightPixels  480
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.density       1.5
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.densityDpi    240
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.scaledDensity 1.5
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.xdpi          254.0
01-21 00:24:52.513: DEBUG/Test126(8294): DisplayMetrics.ydpi          254.0
</pre>
<br>
<a href="http://www.usefullcode.net/2011/01/21/Test126.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKでファイル選択ダイアログを作る</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdk.html" />
   <id>tag:www.usefullcode.net,2011://1.9992</id>
   
   <published>2011-01-20T07:41:02Z</published>
   <updated>2011-01-20T07:42:36Z</updated>
   
   <summary> Androidはユーザーにファイルを意識させない設計がされているためなのか、標...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/20/test125_01.png" rel="lightbox"><img alt="test125_01.png" src="http://www.usefullcode.net/2011/01/20/test125_01-thumb.png" width="400" height="300" align="left" /></a>
Androidはユーザーにファイルを意識させない設計がされているためなのか、標準でファイル選択ダイアログが用意されていません。ちょっと不便すぎるので今回はファイル選択ダイアログを作成します。

まずはJavaで雛形となるプロジェクトを作り、「menu」ボタンからファイル選択画面を開くSelectFile()を呼び出す流れを作る。この状態ではSelectFile()が実装されていないのでビルドできません。
<br clear=left>
<pre class=SourceCode>package com.Test125;

import android.app.Activity;
import android.os.Bundle;
<b>import android.view.Menu;
import android.view.MenuItem;</b>

public class Test125Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

<b>	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		super.onCreateOptionsMenu(menu);

		int		nId = 0;

		menu.add(0,nId++,Menu.NONE,&quot;Open&quot;).setIcon(android.R.drawable.ic_menu_set_as);

		return true;
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch(item.getItemId())
		{
		case 0:
			SelectFile();
			return	true;

		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/20/test125_02.png" rel="lightbox"><img alt="test125_02.png" src="http://www.usefullcode.net/2011/01/20/test125_02-thumb.png" width="400" height="300" align="left" /></a>
プロジェクトに「SelectFileDialog.java」ファイルを追加して、ファイル選択ダイアログのメイン処理を実装する。

AlertDialog.Buildeを作り、そこにファイル名のリストメニューを表示。クリックされたアイテムがフォルダならさらに下のフォルダ用のAlertDialog.Builderを作り表示。クリックされたのがファイルなら終了という流れです。
<br clear=left>
<pre class=SourceCode>package com.Test125;
 
import java.io.File;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.KeyEvent;

public class SelectFileDialog extends Activity
	implements	DialogInterface.OnClickListener
				,DialogInterface.OnKeyListener
{
	private	File		_fileCurrent;	//現在表示しているフォルダ
	private	File[]		_aFileList;		//現在表示しているフォルダのファイル一覧
	private	String[]	_astrFileName;	//現在表示しているフォルダのメニュー用ファイル名
	private	Context		_context;

	private	Dialog		_dlgThis;

	public SelectFileDialog(Context context)
	{
		_context = context;
	}



	@Override
	public void onPause()
	{
		if(_dlgThis != null &amp;&amp; _dlgThis.isShowing())
			_dlgThis.dismiss();
		
		super.onPause();
	}


/*	@Override
	public void onResume()
	{
		Log.d(&quot;Test125&quot;,&quot;--onResume--- &quot;);

		if(_dlgThis != null)
			_dlgThis.show();
		
		super.onResume();
	}

	public	String	GetCurrentPath()
	{
		if(_dlgThis == null || _dlgThis.isShowing() == false || _fileCurrent == null)
			return	&quot;&quot;;

		return	_fileCurrent.getAbsolutePath();
	}
*/	

	public	boolean	Show(String strInitPath)
	{
		boolean	ret;

		ret = CreateFileList(strInitPath);
		if(ret == false)
			return	false;

		
		AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(_context);
		dlgBuilder.setCancelable(true);
		dlgBuilder.setOnKeyListener(this);
		dlgBuilder.setTitle(_fileCurrent.getPath());
		dlgBuilder.setItems(_astrFileName,this);

		_dlgThis = dlgBuilder.create();
		_dlgThis.show();

		return	true;
	}


	public	void	Close(DialogInterface dialog,File fileSelected)
	{
		((onSelectFileDialogListener)_context).onFileSelected_by_SelectFileDialog(fileSelected);
		dialog.dismiss();
		_dlgThis = null;
	}


	@Override
	public void onClick(DialogInterface dialog, int which)
	{
		File	file = _aFileList[which];

		if(file.isDirectory())
		{
			//フォルダが選択されたので開く
			Show(file.getAbsolutePath());
			dialog.dismiss();
		}
		else
		{
			//選択されたので終了
			Close(dialog,file);
		}
	}


	@Override
	public boolean  onKey(DialogInterface dialog, int keyCode, KeyEvent event)
	{
		if(keyCode == KeyEvent.KEYCODE_BACK &amp;&amp; event.getAction() == KeyEvent.ACTION_DOWN)
		{
			File	fileParent;

			fileParent = _fileCurrent.getParentFile();
			if(fileParent != null)
			{
				Show(fileParent.getAbsolutePath());
				dialog.dismiss();
			}
			else
			{
				//ルートだったので終了
				Close(dialog,null);
			}

			return	true;
		}
		return	false;
	}


	private	boolean	CreateFileList(String strPath)
	{
		File[]	aFiles;
		
		_aFileList = null;
		_astrFileName = null;

		_fileCurrent = new File(strPath);
		if(_fileCurrent == null)
			return	false;
		
		aFiles = _fileCurrent.listFiles();
		if(aFiles == null || aFiles.length == 0)
		{
			_aFileList = new File[0];
			_astrFileName = new String[0];
			return	true;
		}
		

		int			i;
		int			nCount;
		String[]	astrName;

		astrName = new String[aFiles.length];

		nCount = 0;
		for(i = 0; i &lt; aFiles.length; i++)
		{
			if(aFiles[i].isDirectory() &amp;&amp; aFiles[i].isHidden() == false)
			{
				//ディレクトリの場合
				astrName[i] = aFiles[i].getName() + &quot;/&quot;;
				nCount++;
			}
			else if(aFiles[i].isFile() &amp;&amp; aFiles[i].isHidden() == false)
			{
				//通常のファイル
				astrName[i] = aFiles[i].getName();
				nCount++;
			}
			else
			{
				aFiles[i] = null;
			}
		}


		_aFileList = new File[nCount];
		_astrFileName = new String[nCount];

		nCount = 0;
		for(i = 0; i &lt; aFiles.length; i++)
		{
			if(aFiles[i] != null)
			{
				_aFileList[nCount] = aFiles[i];
				_astrFileName[nCount] = astrName[i];
				nCount++;
			}
		}

		//ソートするならここでソート
		
		return	true;
	}


	public interface onSelectFileDialogListener
	{
		public void onFileSelected_by_SelectFileDialog(File file);
	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/20/test125_03.png" rel="lightbox"><img alt="test125_03.png" src="http://www.usefullcode.net/2011/01/20/test125_03-thumb.png" width="400" height="300" align="left" /></a>
そして再び戻ってSelectFileDialogを呼び出す処理を実装する。

本当はSelectFileDialogをメンバー変数ではなく、ローカルに宣言して利用できるようにしたかったのですが、、、ファイル選択ダイアログを開いているときに端末の向きを変えてオリエンテーションが変わるとOnPause、OnResumeが呼ばれずにメモリリークが起きるので、苦肉の策としてこのような実装にしました。
<br clear=left>
<pre class=SourceCode>package com.Test125;

import java.io.File;

import com.Test125.SelectFileDialog.onSelectFileDialogListener;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class Test125Act extends Activity
<b>		implements onSelectFileDialogListener</b>
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		super.onCreateOptionsMenu(menu);

		int		nId = 0;

		menu.add(0,nId++,Menu.NONE,&quot;Open&quot;).setIcon(android.R.drawable.ic_menu_set_as);

		return true;
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch(item.getItemId())
		{
		case 0:
			SelectFile();
			return	true;

		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}


<b>	protected	SelectFileDialog	_dlgSelectFile;

	
	private	void	SelectFile()
	{
		//ここで画面回転を固定すべき（画面が固定されていないなら）

		_dlgSelectFile = new SelectFileDialog(this);
		_dlgSelectFile.Show(&quot;/sdcard/&quot;);
	}

	
	@Override
	public void onFileSelected_by_SelectFileDialog(File file)
	{
		//ここで画面回転の固定を解除すべき（SelectFileDialog利用前に画面が固定されていなかったなら）

		if(file != null)
			Log.d(&quot;Test125&quot;,&quot;selected : &quot; + file.getName());
		else
			Log.d(&quot;Test125&quot;,&quot;not selected&quot;);

		_dlgSelectFile = null;
	}

	
	@Override
	public void onPause()
	{
		if(_dlgSelectFile != null)
			_dlgSelectFile.onPause();
		
		super.onPause();
	}</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/20/test125_04.png" rel="lightbox"><img alt="test125_04.png" src="http://www.usefullcode.net/2011/01/20/test125_04-thumb.png" width="400" height="300" align="left" /></a>
これで実行して、「memu」ボタンを押すとメニューが表示され、、、
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/20/test125_05.png" rel="lightbox"><img alt="test125_05.png" src="http://www.usefullcode.net/2011/01/20/test125_05-thumb.png" width="400" height="300" align="left" /></a>
メニューの「Open」をクリックすると、、、
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/20/test125_06.png" rel="lightbox"><img alt="test125_06.png" src="http://www.usefullcode.net/2011/01/20/test125_06-thumb.png" width="400" height="300" align="left" /></a>
ファイル選択ダイアログが開きました。フォルダを選択するとその中が表示され、「戻る」ボタンを押すとひとつ上のフォルダに移ります。

そして端末の向きを変えると、、、メニューが終了します。本当は向きを変えてメニューを再表示させるべきですが複雑になるのでやめました。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/20/Test125.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKで「menu」ボタンでメニューを表示する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdkmenu.html" />
   <id>tag:www.usefullcode.net,2011://1.9991</id>
   
   <published>2011-01-19T12:57:26Z</published>
   <updated>2011-01-19T12:58:38Z</updated>
   
   <summary> 今回は「menu」ボタンを押したときのメニュー表示を実装する。 と言ってもon...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/19/test124_01.png" rel="lightbox"><img alt="test124_01.png" src="http://www.usefullcode.net/2011/01/19/test124_01-thumb.png" width="400" height="300" align="left" /></a>
今回は「menu」ボタンを押したときのメニュー表示を実装する。

と言ってもonCreateOptionsMenu()とonOptionsItemSelected()をオーバーライドするだけで非常に簡単。気をつけることはIDの管理ぐらいだ。
<br clear=left>
<pre class=SourceCode>
package com.Test124;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class Test124Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}


<b>	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		super.onCreateOptionsMenu(menu);

		int		nId = 0;

		menu.add(0,nId++,Menu.NONE,&quot;AAA&quot;).setIcon(android.R.drawable.ic_menu_set_as);
		menu.add(0,nId++,Menu.NONE,&quot;BBB&quot;);
		menu.add(0,nId++,Menu.NONE,&quot;CCC&quot;).setIcon(R.drawable.icon);

		menu.add(1,nId++,Menu.NONE,R.string.app_name);	//本当はこのようにリソース文字列を使わないとダメ
		menu.add(1,nId++,Menu.NONE,&quot;BBB1&quot;);
		menu.add(1,nId++,Menu.NONE,&quot;CCC1&quot;);
		menu.add(1,nId++,Menu.NONE,&quot;DDD1&quot;);

		menu.add(2,nId++,Menu.NONE,&quot;AAA2&quot;);

		return true;
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		Log.d(&quot;Test124&quot;,&quot;MenuSelected &quot; + item.getItemId() + &quot; &quot; + item.getTitle());

		switch(item.getItemId())
		{
		case 0:
			return	true;

		case 1:
			return	true;

		case 2:
			return	true;

		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test124_02.png" rel="lightbox"><img alt="test124_02.png" src="http://www.usefullcode.net/2011/01/19/test124_02-thumb.png" width="400" height="300" align="left" /></a>
実際に実行して、「menu」ボタンを押すとメニューが表示された。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test124_03.png" rel="lightbox"><img alt="test124_03.png" src="http://www.usefullcode.net/2011/01/19/test124_03-thumb.png" width="400" height="300" align="left" /></a>
項目が多い場合は「more」ができ、このように追加画面へと切り換えれる。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/19/Test124.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDK/NDKでZIP書庫内の画像ファイルを順々に表示する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdkndkzip.html" />
   <id>tag:www.usefullcode.net,2011://1.9990</id>
   
   <published>2011-01-19T11:25:52Z</published>
   <updated>2011-01-20T14:41:23Z</updated>
   
   <summary> 今回はこれまでに実装してきたAndroid NDKでZIP書庫内の画像ファイル...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/19/test123_01.png" rel="lightbox"><img alt="test123_01.png" src="http://www.usefullcode.net/2011/01/19/test123_01-thumb.png" width="400" height="300" align="left" /></a>
今回はこれまでに実装してきた<a href="http://www.usefullcode.net/2011/01/android_ndkzip_1.html" target="_blank">Android NDKでZIP書庫内の画像ファイルを解凍する</a>や<a href="http://www.usefullcode.net/2011/01/android_sdkjpg.html" target="_blank">Android SDKでJPG画像を画像に合わせて拡大縮小表示する</a>を組み合わせて、ZIP書庫内の画像を順々に表示させるアプリを作成する。

まずは雛形となるプロジェクトを<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で作る。C++、HelloJNI、STL有効とする。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test123_02.png" rel="lightbox"><img alt="test123_02.png" src="http://www.usefullcode.net/2011/01/19/test123_02-thumb.png" width="400" height="300" align="left" /></a>
Eclipseでプロジェクトを読み込み、まずはZIP書庫解凍用のライブラリlibunzipを使うための設定をAndroid.mkに追加する。
<br clear=left>
<pre class=SourceCode>
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test123
LOCAL_SRC_FILES := Test123.cpp
<b>LOCAL_LDLIBS    := -lz -lunzip</b>

LOCAL_IS_SUPPORT_LOG := true
ifeq ($(LOCAL_IS_SUPPORT_LOG),true)
	LOCAL_LDLIBS += -llog
endif

include $(BUILD_SHARED_LIBRARY)
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_03.png" rel="lightbox"><img alt="test123_03.png" src="http://www.usefullcode.net/2011/01/19/test123_03-thumb.png" width="400" height="300" align="left" /></a>
次に<a href="http://www.usefullcode.net/2011/01/android_ndkzip_1.html" target="_blank">Android NDKでZIP書庫内の画像ファイルを解凍する</a>で作成したZipedImages.hと同じものを追加する。
<br clear=left>
<pre class=SourceCode>
#ifndef	_ZIPEDIMAGES_H
#define	_ZIPEDIMAGES_H

#include&lt;string&gt;
#include&lt;vector&gt;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

#include &lt;android/log.h&gt;


#include &quot;unzip.h&quot;

#define	MAX_PATH	256

#define	bool	unsigned int
#define	true	(1)
#define	false	(0)




class	CZipedImages
{
protected:

	unzFile		_zipFile;
	std::vector&lt;unz_file_pos&gt;	_vFilePos;


public:

	CZipedImages()
	{
		_zipFile = 0;
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::CZipedImages()&quot;);
	}

	~CZipedImages()
	{
		Close();
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::~CZipedImages()&quot;);
	}

	bool	IsOpen(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::IsOpen()&quot;);
		return	(_zipFile != 0) ? true : false;
	}


	bool	OpenZipFile(const char* pszFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::OpenZipFile()&quot;);
		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,&amp;info,pszFileName,MAX_PATH,NULL,0,NULL,0);
			strFile	= pszFileName;
			strExt	= strFile.substr(strFile.length() - 4,4);		//いい加減な方法で拡張子取得

			if(strExt == &quot;.JPG&quot; || strExt == &quot;.jpg&quot; || strExt == &quot;.PNG&quot; || strExt == &quot;.png&quot;)				//いい加減な方法で拡張子チェック
			{
				unzGetFilePos(_zipFile,&amp;pos);
				_vFilePos.push_back(pos);
			}
			else
			{
				//処理されないファイル／フォルダをログ出力
				__android_log_print(ANDROID_LOG_INFO,TAG,&quot;NOT process : (%s)&quot;,pszFileName);
			}

			nRet = unzGoToNextFile(_zipFile);
		}

		return	true;
	}


	void	Close(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Close()&quot;);

		if(_zipFile != 0)
			unzClose(_zipFile);
		_zipFile = 0;
		_vFilePos.clear();
	}



	int		GetCount(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::GetCount()&quot;);

		return	_vFilePos.size();
	}


	bool	Extract(int nIndex,const char* pszFolder,std::string* pstrFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract()&quot;);

		if(IsOpen() == false)
			return	false;

		if(nIndex &gt; _vFilePos.size() || nIndex &lt; 0)
			return	false;

		int		nRet;
		char	pszFileName[MAX_PATH];
		unz_file_info	info;

		nRet = unzGoToFilePos(_zipFile,&amp;_vFilePos[nIndex]);
		if(nRet != UNZ_OK)
			return	false;

		nRet = unzGetCurrentFileInfo(_zipFile,&amp;info,pszFileName,MAX_PATH,NULL,0,NULL,0);
		if(nRet != UNZ_OK)
			return	false;
		__android_log_print(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract() in process %s&quot;,pszFileName);


		std::string	strPath;

		//保存先ファイルパス作成
		{
			strPath = pszFolder;
			if(strPath.substr(strPath.length() - 1,1) != &quot;/&quot;)
				strPath += &quot;/&quot;;

			if(pstrFile != NULL &amp;&amp; *pstrFile != &quot;&quot;)
			{
				if((*pstrFile)[0] != '/')
					strPath += *pstrFile;
				else
					strPath += pstrFile-&gt;substr(1,pstrFile-&gt;length() - 1);
			}
			else
			{
				char	pszBuff[256];
				std::string	strExt;

				strExt	= pszFileName;
				strExt	= strExt.substr(strExt.length() - 4,4).c_str();	//いい加減な方法で拡張子取得
				sprintf(pszBuff,&quot;%d%s&quot;,nIndex,strExt.c_str());

				if(pstrFile)
					*pstrFile = pszBuff;
				strPath.append(pszBuff);
			}
		}
		__android_log_print(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract() : save to %s&quot;,strPath.c_str());

		//解凍
		{
			FILE	*fp;

			fp = fopen(strPath.c_str(),&quot;w&quot;);
			if(fp == NULL)
				return	false;

			char	szBuffer[32768];
			int		dwSizeRead;

			nRet = unzOpenCurrentFile(_zipFile);
			if(nRet == UNZ_OK)
			{
				while ((dwSizeRead = unzReadCurrentFile(_zipFile,szBuffer,sizeof(szBuffer))) &gt; 0)
				{
					fwrite(szBuffer,1,dwSizeRead,fp);
				}
				unzCloseCurrentFile(_zipFile);
			}
			fclose(fp);
		}

		return	true;
	}


};

#endif
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_04.png" rel="lightbox"><img alt="test123_04.png" src="http://www.usefullcode.net/2011/01/19/test123_04-thumb.png" width="400" height="300" align="left" /></a>
<br clear=left>
Javaからネイティブで実装したZIP書庫操作用の関数にアクセスできるようにJNIを実装する。CZipedImagesのメンバー関数を単純にJNIでラッピングした。これでネイティブ側の実装は終りだ。
<pre class=SourceCode>
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include &lt;string.h&gt;
#include &lt;jni.h&gt;

#ifdef LOCAL_LOG
#include &lt;android/log.h&gt;
#endif

<b>#define	TAG	&quot;Test123&quot;
#include &quot;ZipedImages.h&quot;

CZipedImages	g_cZip;


extern &quot;C&quot;
jint Java_com_Test123_ZipImageFileView_OpenZipFile(JNIEnv* env,jobject thiz,jstring jstrFile)
{
	bool	ret;

	const	char*	pszFile = env-&gt;GetStringUTFChars(jstrFile,NULL);
	ret = g_cZip.OpenZipFile(pszFile);
	env-&gt;ReleaseStringUTFChars(jstrFile,pszFile);

	return	(ret == true) ? 1 : 0;
}

extern &quot;C&quot;
jint Java_com_Test123_ZipImageFileView_GetInZipCount(JNIEnv* env,jobject thiz)
{
	return	g_cZip.GetCount();
}


extern &quot;C&quot;
jstring Java_com_Test123_ZipImageFileView_Extract(JNIEnv* env,jobject thiz,jint jnIndex,jstring jstrFolder)
{
	std::string		strFile;

	int		nIndex = jnIndex;
	bool	ret;

	const	char*	pszFolder = env-&gt;GetStringUTFChars(jstrFolder,NULL);
	ret = g_cZip.Extract(nIndex,pszFolder,&amp;strFile);
	env-&gt;ReleaseStringUTFChars(jstrFolder,pszFolder);

	if(ret)
		return env-&gt;NewStringUTF(strFile.c_str());
	else
		return env-&gt;NewStringUTF(&quot;&quot;);
}


extern &quot;C&quot;
void Java_com_Test123_ZipImageFileView_Close(JNIEnv* env,jobject thiz)
{
	g_cZip.Close();
}</b>
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_05.png" rel="lightbox"><img alt="test123_05.png" src="http://www.usefullcode.net/2011/01/19/test123_05-thumb.png" width="400" height="300" align="left" /></a>
次にImageFileView.javaファイルを追加して、画像ファイルを読み込みビュー表示するクラスを実装する。

基本的に<a href="http://www.usefullcode.net/2011/01/android_sdkjpg.html" target="_blank">Android SDKでJPG画像を画像に合わせて拡大縮小表示する</a>と同じだが、画像ファイルが大きくなるとメモリが足りなくなって落ちる問題の修正などをしている。nScaleの計算が間違えているのはご愛嬌。
<br clear=left>
<pre class=SourceCode>
package com.Test123;

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.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;


public class ImageFileView extends View
{
	protected	Bitmap	_bmpImageFile;		//画像ファイル
	protected	Bitmap	_bmpResized;		//リサイズ画像

	protected	int		_nWidthDisp;
	protected	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();
	}

	//設定の保存
	public void OnSaveState(Bundle outState)
	{
		if(outState == null)
			return;
	}

	//設定の読込
	public void OnLoadState(Bundle savedInstanceState)
	{
		if(savedInstanceState == null)
			return;
	}
	


	//画像を大まかに縮小して_bmpImageFileへ読み込み、
	//表示用にリサイズして_bmpResizedへ保存する
	public boolean	LoadImageFile(String strFile,boolean bInvalidate)
	{
		//画像の解析（大きい画像が開けない対策）
		BitmapFactory.Options	options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		_bmpImageFile = BitmapFactory.decodeFile(strFile,options);
		
		int		nWidth = options.outWidth;
		int		nHeight = options.outHeight;


		int		nScale;

		//nScaleは2の乗数にする
		{
			int	nScaleX = (int)(float)(nWidth / _nWidthDisp + 0.5f);
			int	nScaleY = (int)(float)(nHeight / _nHeightDisp + 0.5f);

			nScale = (nScaleX &lt; nScaleY) ? nScaleX : nScaleY;
			
			int		i = 1;

			while(nScale &gt; i)
			{
				i *= 2;
			}
			nScale = i - 1;
			if(nScale &lt;= 0)
				nScale = 1;
		}
		
		//画像の本読み込み
		options.inJustDecodeBounds = false;
		options.inSampleSize = nScale;
		_bmpImageFile = BitmapFactory.decodeFile(strFile,options);


		/////////////////////////////////
		//画像のリサイズ
		
		nWidth = _bmpImageFile.getWidth();
		nHeight = _bmpImageFile.getHeight();

		float	fScale;

		//拡大縮小率取得
		if(true)
		{
			//画像に合わせる
			if((long)nWidth * _nHeightDisp &gt; (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);
	}

}

</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_06.png" rel="lightbox"><img alt="test123_06.png" src="http://www.usefullcode.net/2011/01/19/test123_06-thumb.png" width="400" height="300" align="left" /></a>
次にImageFileView派生でZipImageFileViewクラスを作る。

ZIPファイルから画像ファイルを解凍、ImageFileViewに読み込ませ、画像ファイルを削除という単純な流れにした。
<br clear=left>
<pre class=SourceCode>
package com.Test123;

import java.io.File;

import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MotionEvent;


public class ZipImageFileView extends ImageFileView
{
	private	int		_nImageIndex = -1;	//現在読み込まれている画像のzip内の画像インデックス
	private	int		_nImageCount;		//zip内の画像数
	
	public ZipImageFileView(Context context)
	{
		super(context);
		
		//zipファイル読み込み
		OpenZipFile(&quot;/sdcard/desire_img.zip&quot;);
		_nImageCount = GetInZipCount();
	}

	//設定の保存
	@Override
	public void OnSaveState(Bundle outState)
	{
		super.OnSaveState(outState);
		if(outState == null)
			return;

		outState.putInt(&quot;_nImageIndex&quot;,_nImageIndex);
	}

	
	//設定の読込
	@Override
	public void OnLoadState(Bundle savedInstanceState)
	{
		super.OnLoadState(savedInstanceState);
		if(savedInstanceState == null)
			return;

		int		nIndex;
		
		nIndex = savedInstanceState.getInt(&quot;_nImageIndex&quot;);
		LoadImageFromZip(nIndex,true);
	}

	
	
	public boolean	LoadImageFromZip(int nIndex,boolean bInvalidate)
	{
		if(nIndex &gt;= _nImageCount || _nImageCount == 0 || nIndex &lt; 0)
			return	false;
		if(nIndex == _nImageIndex)
			return	true;				//すでに読み込まれている

		String	strFile;

		//画像解凍
		strFile = Extract(nIndex,&quot;/sdcard/&quot;);
		if(strFile == &quot;&quot;)
			return	false;
		strFile = &quot;/sdcard/&quot; + strFile;

		//画像読み込み
		LoadImageFile(strFile,bInvalidate);
		_nImageIndex = nIndex;

		//ファイル削除
		File	file = new File(strFile);
		file.delete();

		return	true;
	}

	
	
	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		//タッチイベント取得
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			int		nIndex;

			nIndex = _nImageIndex + 1;
			if(nIndex &gt;= _nImageCount)
				nIndex = 0;

			LoadImageFromZip(nIndex,true);
		}
		return true;
	}	

	
	@Override
	protected void onDraw(Canvas canvas)
	{
		if(_bmpImageFile == null)
		{
			LoadImageFromZip(0,true);
			return;
		}

		super.onDraw(canvas);
	}
	
	

	private native int  OpenZipFile(String strFile);
	private native int  GetInZipCount();
	private native String  Extract(int nIndex,String strFolder);
	private native void  Close();

	static
	{
		System.loadLibrary(&quot;Test123&quot;);
	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_07.png" rel="lightbox"><img alt="test123_07.png" src="http://www.usefullcode.net/2011/01/19/test123_07-thumb.png" width="400" height="300" align="left" /></a>
最後にアクティビティに作成したビューを割り当てる。
<br clear=left>
<pre class=SourceCode>
package com.Test123;

import android.app.Activity;
import android.os.Bundle;
<b>import android.view.Window;
import android.view.WindowManager;</b>

public class Test123Act extends Activity
{
<b>	private	ImageFileView	_view;</b>

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

<b>		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		_view = new ZipImageFileView(this);
		setContentView(_view);
</b>	}

<b>	@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);
	}</b>
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test123_08.png" rel="lightbox"><img alt="test123_08.png" src="http://www.usefullcode.net/2011/01/19/test123_08-thumb.png" width="400" height="300" align="left" /></a>
これで実行するとZIP書庫内の画像ファイルが表示され、画面をタッチすると、、、
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test123_09.png" rel="lightbox"><img alt="test123_09.png" src="http://www.usefullcode.net/2011/01/19/test123_09-thumb.png" width="400" height="300" align="left" /></a>
書庫内の次の画像が表示された。

先読み処理や別スレッドでの解凍処理などをしていないため、全体的にモッサリ。実機ではまぁまぁ使えるものの、VirtualPC上のAndroidエミュレーターでは論外なほどの遅さでした。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/19/Test123.zip">ファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android NDKでZIP書庫内の画像ファイルを解凍する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_ndkzip_1.html" />
   <id>tag:www.usefullcode.net,2011://1.9989</id>
   
   <published>2011-01-19T09:05:11Z</published>
   <updated>2011-01-19T09:06:57Z</updated>
   
   <summary> 今回はAndroid NDKにより、ZIP書庫内に含まれる画像ファイルを解凍す...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/19/test122_01.png" rel="lightbox"><img alt="test122_01.png" src="http://www.usefullcode.net/2011/01/19/test122_01-thumb.png" width="400" height="300" align="left" /></a>
今回はAndroid NDKにより、ZIP書庫内に含まれる画像ファイルを解凍するためのクラスを作成する。ZIP書庫の操作には「<a href="http://www.usefullcode.net/2011/01/android_ndk_libunzip.html" target="_blank">Android NDKの標準ライブラリにlibunzipを追加して利用する</a>」で用意したlibunzipを利用する。

まずは雛形となるプロジェクトを<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で作る。C++、HelloJNIでSTLを有効にした。

<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test122_02.png" rel="lightbox"><img alt="test122_02.png" src="http://www.usefullcode.net/2011/01/19/test122_02-thumb.png" width="400" height="300" align="left" /></a>
自動生成されたプロジェクトをEclipseに取り込み、「ZipedImages.h」ファイルを新規作成してZIP書庫操作用のクラスを実装する。

指定されたZIP書庫を開き、書庫内にあるすべてのファイル名をチェックして拡張子が画像ならstd::vectorにファイル位置を保存。そしてそのstd::vector上のインデックス指定によりファイルを指定フォルダへと解凍するという流れにした。かなり中途半端かつ汎用性のない実装になっている。汎用的に実装しようと思うと、ファイル名に日本語が使われていた場合やら何やら色々考えないといけないのでやめました。
<br clear=left>
<pre class=SourceCode>
#ifndef	_ZIPEDIMAGES_H
#define	_ZIPEDIMAGES_H

#include&lt;string&gt;
#include&lt;vector&gt;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

#include &lt;android/log.h&gt;


#include &quot;unzip.h&quot;

#define	MAX_PATH	256

#define	bool	unsigned int
#define	true	(1)
#define	false	(0)




class	CZipedImages
{
protected:

	unzFile		_zipFile;
	std::vector&lt;unz_file_pos&gt;	_vFilePos;


public:

	CZipedImages()
	{
		_zipFile = 0;
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::CZipedImages()&quot;);
	}

	~CZipedImages()
	{
		Close();
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::~CZipedImages()&quot;);
	}

	bool	IsOpen(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::IsOpen()&quot;);
		return	(_zipFile != 0) ? true : false;
	}


	bool	OpenZipFile(const char* pszFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::OpenZipFile()&quot;);
		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,&amp;info,pszFileName,MAX_PATH,NULL,0,NULL,0);
			strFile	= pszFileName;
			strExt	= strFile.substr(strFile.length() - 4,4);		//いい加減な方法で拡張子取得

			if(strExt == &quot;.JPG&quot; || strExt == &quot;.jpg&quot; || strExt == &quot;.PNG&quot; || strExt == &quot;.png&quot;)				//いい加減な方法で拡張子チェック
			{
				unzGetFilePos(_zipFile,&amp;pos);
				_vFilePos.push_back(pos);
			}
			else
			{
				//処理されないファイル／フォルダをログ出力
				__android_log_print(ANDROID_LOG_INFO,TAG,&quot;NOT process : (%s)&quot;,pszFileName);
			}

			nRet = unzGoToNextFile(_zipFile);
		}

		return	true;
	}


	void	Close(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Close()&quot;);

		if(_zipFile != 0)
			unzClose(_zipFile);
		_zipFile = 0;
		_vFilePos.clear();
	}



	int		GetCount(void)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::GetCount()&quot;);

		return	_vFilePos.size();
	}


	bool	Extract(int nIndex,const char* pszFolder,std::string* pstrFile)
	{
		__android_log_write(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract()&quot;);

		if(IsOpen() == false)
			return	false;

		if(nIndex &gt; _vFilePos.size() || nIndex &lt; 0)
			return	false;

		int		nRet;
		char	pszFileName[MAX_PATH];
		unz_file_info	info;

		nRet = unzGoToFilePos(_zipFile,&amp;_vFilePos[nIndex]);
		if(nRet != UNZ_OK)
			return	false;

		nRet = unzGetCurrentFileInfo(_zipFile,&amp;info,pszFileName,MAX_PATH,NULL,0,NULL,0);
		if(nRet != UNZ_OK)
			return	false;
		__android_log_print(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract() in process %s&quot;,pszFileName);


		std::string	strPath;

		//保存先ファイルパス作成
		{
			strPath = pszFolder;
			if(strPath.substr(strPath.length() - 1,1) != &quot;/&quot;)
				strPath += &quot;/&quot;;

			if(pstrFile != NULL &amp;&amp; *pstrFile != &quot;&quot;)
			{
				if((*pstrFile)[0] != '/')
					strPath += *pstrFile;
				else
					strPath += pstrFile-&gt;substr(1,pstrFile-&gt;length() - 1);
			}
			else
			{
				char	pszBuff[256];
				std::string	strExt;

				strExt	= pszFileName;
				strExt	= strExt.substr(strExt.length() - 4,4).c_str();	//いい加減な方法で拡張子取得
				sprintf(pszBuff,&quot;%d%s&quot;,nIndex,strExt.c_str());

				if(pstrFile)
					*pstrFile = pszBuff;
				strPath.append(pszBuff);
			}
		}
		__android_log_print(ANDROID_LOG_DEBUG,TAG,&quot;CZipedImages::Extract() : save to %s&quot;,strPath.c_str());

		//解凍
		{
			FILE	*fp;

			fp = fopen(strPath.c_str(),&quot;w&quot;);
			if(fp == NULL)
				return	false;

			char	szBuffer[32768];
			int		dwSizeRead;

			nRet = unzOpenCurrentFile(_zipFile);
			if(nRet == UNZ_OK)
			{
				while ((dwSizeRead = unzReadCurrentFile(_zipFile,szBuffer,sizeof(szBuffer))) &gt; 0)
				{
					fwrite(szBuffer,1,dwSizeRead,fp);
				}
				unzCloseCurrentFile(_zipFile);
			}
			fclose(fp);
		}

		return	true;
	}
};

#endif
</pre>
<br>


<a href="http://www.usefullcode.net/2011/01/19/test122_03.png" rel="lightbox"><img alt="test122_03.png" src="http://www.usefullcode.net/2011/01/19/test122_03-thumb.png" width="400" height="300" align="left" /></a>
そしてメイン処理内でCZipedImaesクラスのテスト用に2つのファイルを解凍する処理を追加する。
<br clear=left>
<pre class=SourceCode>
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include &lt;string.h&gt;
#include &lt;jni.h&gt;

#ifdef LOCAL_LOG
#include &lt;android/log.h&gt;
#endif

<b>
#define	TAG	&quot;Test122&quot;
#include &quot;ZipedImages.h&quot;
</b>


extern &quot;C&quot;
jstring Java_com_Test122_Test122Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
<b>	CZipedImages	cZip;

	cZip.OpenZipFile(&quot;/sdcard/desire_img.zip&quot;);

	bool		ret;
	int			nSize;
	std::string	strFile;

	nSize = cZip.GetCount();

	//最初のファイルを解凍
	strFile = &quot;&quot;;
	ret = cZip.Extract(0,&quot;/sdcard&quot;,&amp;strFile);
	if(ret)
		__android_log_print(ANDROID_LOG_DEBUG,&quot;Test122&quot;,&quot;save to %s&quot;,strFile.c_str());

	//5番目のファイルを解凍
	strFile = &quot;&quot;;
	ret = cZip.Extract(5,&quot;/sdcard&quot;,&amp;strFile);
	if(ret)
		__android_log_print(ANDROID_LOG_DEBUG,&quot;Test122&quot;,&quot;save to %s&quot;,strFile.c_str());

	cZip.Close();
</b>
	return env-&gt;NewStringUTF(&quot;Test122text&quot;);
}
</pre>
<br>


<a href="http://www.usefullcode.net/2011/01/19/test122_04.png" rel="lightbox"><img alt="test122_04.png" src="http://www.usefullcode.net/2011/01/19/test122_04-thumb.png" width="400" height="300" align="left" /></a>
最後にAndroid.mkにlibunzipとlibzipのライブラリを追加する。
<br clear=left>
<pre class=SourceCode>
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test122
LOCAL_SRC_FILES := Test122.cpp
<b>LOCAL_LDLIBS += -lz -lunzip</b>

LOCAL_IS_SUPPORT_LOG := true
ifeq ($(LOCAL_IS_SUPPORT_LOG),true)
	LOCAL_LDLIBS += -llog
endif

include $(BUILD_SHARED_LIBRARY)
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test122_05.png" rel="lightbox"><img alt="test122_05.png" src="http://www.usefullcode.net/2011/01/19/test122_05-thumb.png" width="400" height="300" align="left" /></a>
これで実行するとSDカード上のZIP書庫を読み込み、その中にあるファイルのうち2つが解凍された。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/19/Test122.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android NDKの標準ライブラリにlibunzipを追加して利用する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_ndk_libunzip.html" />
   <id>tag:www.usefullcode.net,2011://1.9988</id>
   
   <published>2011-01-19T02:46:34Z</published>
   <updated>2011-01-19T02:48:04Z</updated>
   
   <summary> 今回はAndroid NDKから簡単にzip書庫ファイルにアクセスするためのラ...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/19/libunzip01.png" rel="lightbox"><img alt="libunzip01.png" src="http://www.usefullcode.net/2011/01/19/libunzip01-thumb.png" width="400" height="300" align="left" /></a>
今回はAndroid NDKから簡単にzip書庫ファイルにアクセスするためのライブラリ「libunzip.a」をビルド。Android NDKの標準ライブりへ登録。そして実際に利用してみる。

まずは以前作成した<a href="http://www.usefullcode.net/2011/01/android_ndkzip.html" target="_blank">Android NDKでZIP書庫内のファイルリストを取得する</a>のときのプロジェクトファイル「Test117.zip」をダウンロードする。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip02.png" rel="lightbox"><img alt="libunzip02.png" src="http://www.usefullcode.net/2011/01/19/libunzip02-thumb.png" width="400" height="300" align="left" /></a>
次に<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で雛形プロジェクトを作成する。今回はC++、HelloJNIを利用した。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip03.png" rel="lightbox"><img alt="libunzip03.png" src="http://www.usefullcode.net/2011/01/19/libunzip03-thumb.png" width="400" height="300" align="left" /></a>
そして作成したプロジェクトのjniフォルダの中に、先ほどダウンロードしたTest117.zipに含まれる「ioapi.h」「ioapi.c」「unzip.h」「unzip.c」の4ファイルを解凍する。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip04.png" rel="lightbox"><img alt="libunzip04.png" src="http://www.usefullcode.net/2011/01/19/libunzip04-thumb.png" width="400" height="300" align="left" /></a>
今回はライブラリをビルドするだけなので不要な「Test120.c」を削除する。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip05.png" rel="lightbox"><img alt="libunzip05.png" src="http://www.usefullcode.net/2011/01/19/libunzip05-thumb.png" width="400" height="300" align="left" /></a>
Eclipseでプロジェクトを読み込み、「Android.mk」を編集する。

今回は.aファイルを作成するのでBUILD_STATIC_LIBRARYを指定するのがポイントだ。
<br clear=left>
<pre class=SourceCode>
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

<b>LOCAL_MODULE    := libunzip
LOCAL_SRC_FILES := ioapi.c unzip.c

include $(BUILD_STATIC_LIBRARY)</b>
</pre>

<a href="http://www.usefullcode.net/2011/01/19/libunzip06.png" rel="lightbox"><img alt="libunzip06.png" src="http://www.usefullcode.net/2011/01/19/libunzip06-thumb.png" width="400" height="300" align="left" /></a>
BUILD_STATIC_LIBRARYを指定しただけでは.aファイルはビルドされないので、「Application.mk」を編集してAPP_MODULE指定をする。
<br clear=left>
<pre class=SourceCode>
APP_MODULES := libunzip
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/libunzip07.png" rel="lightbox"><img alt="libunzip07.png" src="http://www.usefullcode.net/2011/01/19/libunzip07-thumb.png" width="400" height="300" align="left" /></a>
これでビルドすると「libunzip.a」ファイルが生成された。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip08.png" rel="lightbox"><img alt="libunzip08.png" src="http://www.usefullcode.net/2011/01/19/libunzip08-thumb.png" width="400" height="300" align="left" /></a>
次に「libunzip.a」をAndroid NDKの標準ライブラリとして登録してしまう。

NDKのフォルダ「C:\android-ndk\platforms\android-xxx\arch-arm\usr\lib\」を開き、その中へ「libunzip.a」をコピーする。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip09.png" rel="lightbox"><img alt="libunzip09.png" src="http://www.usefullcode.net/2011/01/19/libunzip09-thumb.png" width="400" height="300" align="left" /></a>
忘れずにヘッダーファイルの「ioapi.h」「unzip.h」の2ファイルをコピーする。これは「C:\android-ndk\platforms\android-xxx\arch-arm\usr\<b>include</b>\」へコピーする。これで標準ライブラリへの登録は終りだ。
<br clear=left>

<br>
<br>
<br>

<a href="http://www.usefullcode.net/2011/01/19/libunzip10.png" rel="lightbox"><img alt="libunzip10.png" src="http://www.usefullcode.net/2011/01/19/libunzip10-thumb.png" width="400" height="300" align="left" /></a>
最後に実際にlibunzipを利用してみる。

まずは雛形となるプロジェクトを<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で作成。C++のHelloJNIとした。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/libunzip11.png" rel="lightbox"><img alt="libunzip11.png" src="http://www.usefullcode.net/2011/01/19/libunzip11-thumb.png" width="400" height="300" align="left" /></a>
Eclipseでプロジェクトを読み込み、Android.mkを編集する。

libunzipを利用するため、LOCAL_LDLIBSに「-lz」と「-lunzip」を追加する。
<br clear=left>
<pre class=SourceCode>
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test121
LOCAL_SRC_FILES := Test121.cpp
<b>LOCAL_LDLIBS += -lz -lunzip </b>

LOCAL_IS_SUPPORT_LOG := true
ifeq ($(LOCAL_IS_SUPPORT_LOG),true)
	LOCAL_LDLIBS += -llog
endif

include $(BUILD_SHARED_LIBRARY)
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/libunzip12.png" rel="lightbox"><img alt="libunzip12.png" src="http://www.usefullcode.net/2011/01/19/libunzip12-thumb.png" width="400" height="300" align="left" /></a>
そしてテストするためのメイン処理を実装する。普通にunzip.hをincludeして利用するだけだ。
<br clear=left>
<pre class=SourceCode>
#if(true)
#define LOCAL_LOG
#define LOCAL_LOGD
#endif

#include &lt;string.h&gt;
#include &lt;jni.h&gt;

#ifdef LOCAL_LOG
#include &lt;android/log.h&gt;
#endif

<b>
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

#include &lt;unzip.h&gt;

#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,&amp;info,pszFileName,MAX_PATH,NULL,0,NULL,0);
		if(nRet == UNZ_OK)
		{
			__android_log_print(ANDROID_LOG_INFO,&quot;Test121&quot;,&quot;Found File in zip : %s&quot;,pszFileName);
		}

		nRet = unzGoToNextFile(zipFile);
	}
	unzClose(zipFile);

	return	1;
}
</b>

extern &quot;C&quot;
jstring Java_com_Test121_Test121Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
<b>	Test(&quot;/sdcard/desire_img.zip&quot;);</b>

	return env-&gt;NewStringUTF(&quot;Test121text&quot;);
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/libunzip13.png" rel="lightbox"><img alt="libunzip13.png" src="http://www.usefullcode.net/2011/01/19/libunzip13-thumb.png" width="400" height="300" align="left" /></a>
これで実行すると、SDカード上に配置したzip書庫内のファイル一覧がログに出力された。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/19/Test120.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>
<entry>
   <title>Android SDKでJPG画像を画像に合わせて拡大縮小表示する</title>
   <link rel="alternate" type="text/html" href="http://www.usefullcode.net/2011/01/android_sdkjpg.html" />
   <id>tag:www.usefullcode.net,2011://1.9987</id>
   
   <published>2011-01-19T00:42:18Z</published>
   <updated>2011-01-19T00:43:42Z</updated>
   
   <summary> 今回はAndroid SDKでjpgファイルを読み込み、画面サイズに合わせて拡...</summary>
   <author>
      <name></name>
      
   </author>
         <category term="android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.usefullcode.net/">
      <![CDATA[<a href="http://www.usefullcode.net/2011/01/19/test119_01.png" rel="lightbox"><img alt="test119_01.png" src="http://www.usefullcode.net/2011/01/19/test119_01-thumb.png" width="400" height="300" align="left" /></a>
今回はAndroid SDKでjpgファイルを読み込み、画面サイズに合わせて拡大縮小表示する。

まずは雛形となるプロジェクトを<a href="http://www.usefullcode.net/2010/12/easyprojectgenerator_for_andro.html" target="_blank">EasyProjectGenerator for Android</a>で作る。JavaのSimpleプロジェクトを利用した。
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test119_02.png" rel="lightbox"><img alt="test119_02.png" src="http://www.usefullcode.net/2011/01/19/test119_02-thumb.png" width="400" height="300" align="left" /></a>
そしてEclipseにプロジェクトを取り込み、「ImageFileView.java」ファイルを新しく作成してImageViewクラスを実装する。

jpg画像の読み込みはBitmapFactory.decodeFile()で行い、Bitmap.createBitmap()にMatrixを渡すことで拡大縮小、Canvas::drawBitmap()で範囲を指定して描画する。

ImageViewにBitmapやBitmapDrawableを渡す方法は、ImageViewが勝手に拡大縮小をするために利用できない。
<br clear=left>
<pre class=SourceCode>
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(&quot;Test119&quot;,&quot;DisplaySize &quot; + _nWidthDisp + &quot;x&quot; + _nHeightDisp);

		//画像ファイル読み込み
		LoadImageFile(&quot;/sdcard/test.jpg&quot;,false);	//描画更新しない
	}


	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		//タッチイベント取得
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			LoadImageFile(&quot;/sdcard/test2.jpg&quot;,true);
		}
		return true;
	}	


	public boolean	LoadImageFile(String strFile,boolean bInvalidate)
	{
		//画像読み込み
		_bmpImageFile = BitmapFactory.decodeFile(strFile);
		
		int		nWidth = _bmpImageFile.getWidth();
		int		nHeight = _bmpImageFile.getHeight();
		Log.d(&quot;Test119&quot;,&quot;ImageSize &quot; + nWidth + &quot;x&quot; + nHeight);

		float	fScale;

		//拡大縮小率取得
		if(true)
		{
			//画像に合わせる
			if((long)nWidth * _nHeightDisp &gt; (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);
	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test119_03.png" rel="lightbox"><img alt="test119_03.png" src="http://www.usefullcode.net/2011/01/19/test119_03-thumb.png" width="400" height="300" align="left" /></a>
上で実装したImageFileViewをアクティビティに結びつける。

今回はさらにタイトル消去とフルスクリーン化も行った。
<br clear=left>
<pre class=SourceCode>package com.Test119;

import android.app.Activity;
import android.os.Bundle;
<b>import android.view.Window;
import android.view.WindowManager;
</b>
public class Test119Act extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

<b>		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(new ImageFileView(this));
</b>	}
}
</pre>
<br>

<a href="http://www.usefullcode.net/2011/01/19/test119_04.png" rel="lightbox"><img alt="test119_04.png" src="http://www.usefullcode.net/2011/01/19/test119_04-thumb.png" width="400" height="300" align="left" /></a>
これでSDカード上にjpgファイルを2つ配置してから実行すると、起動時は/sdcard/test.jpgが読み込まれ表示、画面をタッチすると、、、
<br clear=left>

<a href="http://www.usefullcode.net/2011/01/19/test119_05.png" rel="lightbox"><img alt="test119_05.png" src="http://www.usefullcode.net/2011/01/19/test119_05-thumb.png" width="400" height="300" align="left" /></a>
/sdcard/test2.jpgが表示された。
<br clear=left>
<br>
<a href="http://www.usefullcode.net/2011/01/19/Test119.zip">プロジェクトファイルをダウンロード</a>
]]>
      
   </content>
</entry>

</feed>

