« 2010年05月 | メイン | 2011年01月 »

前の10件 1  2  3

2010年12月 記事一覧

Androidで画面のタッチ操作を検出する

test111_01.png
今回は画面のタッチ操作の検出方法を見てみる。
EasyProjectGenerator for AndroidでNativeViewプロジェクトを生成して、Eclipseに読み込む。そしてjavaのソースコードを編集する。

test111_02.png
Viewに対して、setOnTouchListner()によりOnTouchListerner()のOnTouch()を指定する。Javaのソースを本格的?にいじるのはこれが初めて。処理の流れはJavascript、文法方法はC++という雰囲気です。

タッチ開始、ドラッグ中、タッチ終了などのイベントはevent.getAction()、タッチ座標は戻り値がfloatというのが意味不明がevent.getX()とevent.getY()で取得できるようです。
package com.Test111;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.MotionEvent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;


public class Test111Act extends Activity
{
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		setContentView(new NativeView(this));
	}

	static
	{
		System.loadLibrary("Test111jni");
	}
}


class NativeView extends View
{
	private Bitmap _mBitmap;

	private static native void RenderBitmap(Bitmap bitmap);


	private	boolean	_bTouchDown;
	private	float	_fTouchX;
	private	float	_fTouchY;
	private	float	_fScrollX;
	private	float	_fScrollY;


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

		_bTouchDown	= false;
		_fTouchX	= 0.0f;
		_fTouchY	= 0.0f;
		_fScrollX	= 0.0f;
		_fScrollY	= 0.0f;

		final int W = 200;
		final int H = 200;

		_mBitmap = Bitmap.createBitmap(W, H, Bitmap.Config.RGB_565);
		
		this.setOnTouchListener(new OnTouchListener()
		{
			@Override
			public boolean onTouch(View v, MotionEvent event)
			{
				float	fTouchX			= event.getX();
				float	fTouchY			= event.getY();
//				float	fTouchSize		= event.getSize();
//				float	fTouchPressure	= event.getPressure();

				switch (event.getAction() & MotionEvent.ACTION_MASK)
				{
				case MotionEvent.ACTION_DOWN:
					_bTouchDown = true;
					_fTouchX = fTouchX;
					_fTouchY = fTouchY;
					break;

				case MotionEvent.ACTION_UP:
				case MotionEvent.ACTION_POINTER_UP:
					_bTouchDown = false;
					//break;			//break処理せずにinvalidate()まで実行する

				case MotionEvent.ACTION_MOVE:
					_fScrollX -= _fTouchX - event.getX();
					_fScrollY -= _fTouchY - event.getY();
					_fTouchX = fTouchX;
					_fTouchY = fTouchY;
					v.invalidate();
					break;
				}

				return true;
			}
		});
	}


	@Override protected void onDraw(Canvas canvas)
	{
		RenderBitmap(_mBitmap);

		int		nWidth	= _mBitmap.getWidth();
		int		nHeight	= _mBitmap.getHeight();

		Rect rcSrc = new Rect(0,0,nWidth, nHeight);
		Rect rcDst = new Rect((int)_fScrollX,(int)_fScrollY,(int)_fScrollX + nWidth,(int)_fScrollY + nHeight);
		canvas.drawBitmap(_mBitmap,rcSrc,rcDst,null);
	}
}

test111_03.png
これで忘れずにネイティブコードをndk-buildでビルドしてから実行すると、、、画面のドラッグでグラデーション描画領域を好きなように移動できるようになりました。




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

Android SDK/NDKのログ出力機能を使う

test112_01.png
Android SDK/NDKには開発者向けにログ出力機能が備わっている。今回はそれを試しに使ってみる。

test112_02.png
javaではandroid.util.LogをインポートすればLog.v()、Log.d()、Log.i()、Log.w()、Log.e()関数でログ出力できる。

Android SDK/NDKではリリースビルド/デバッグビルドという概念がない?ため、一般公開した後もログ出力機能が有効なままになってしまう。リリースビルド時などログ出力が不要なときに簡単に機能を削除できるように、LOCAL_LOGやLOCAL_LOGDを定義、それを使って手動制御した方がいい。
package com.Test112;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.util.Log;

public class Test112Act extends Activity
{
	//ログを出力するならtrue、出力しないならfalse
	//リリースビルドではfalseにする
	final boolean LOCAL_LOGD = true;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		TextView	tv = new TextView(this);
		tv.setText( stringFromJNI() );
		setContentView(tv);
		
		//5種類のログを出力
		if(LOCAL_LOGD)
		{
			Log.v("Tag","Test Message : Log.v() for VERBOSE");
			Log.d("Tag","Test Message : Log.d() for DEBUG");
			Log.i("Tag","Test Message : Log.i() for INFO");
			Log.w("Tag","Test Message : Log.w() for WARN");
			Log.e("Tag","Test Message : Log.e() for ERROR");
		}
	}

	public native String  stringFromJNI();

	static
	{
		System.loadLibrary("Test112jni");
	}
}

test112_03.png ネイティブコードでログ出力機能を利用する場合は、Android.mkで「LOCAL_LDLIBS」に「-llog」のリンク指定を追加する。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test112jni
LOCAL_SRC_FILES := Test112jni.c
LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

test112_04.png
実際の出力は__android_log_write()や__android_log_print()で行う。__android_log_write()は固定メッセージをログ出力、__android_log_print()はprintfのように書式化して出力できる。

ログの種別はANDROID_LOG_VERBOSE、ANDROID_LOG_DEBUG、ANDROID_LOG_INFO、ANDROID_LOG_WARN、ANDROID_LOG_ERROR、ANDROID_LOG_FATALなどの定数が利用できる。
//ログを出力する。ログ出力しないなら次の1行をコメントアウトすること
#define	LOCAL_LOG

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

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

jstring
Java_com_Test112_Test112Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
#ifdef	LOCAL_LOG
	//ログを出力
	__android_log_write(ANDROID_LOG_DEBUG,"Tag","Test Message : __android_log_write() with ANDROID_LOG_DEBUG");
	__android_log_print(ANDROID_LOG_DEBUG,"Tag","Test Message : __android_log_print(%s) with ANDROID_LOG_DEBUG","test string");

//	int	nTest = 123;
//	__android_log_assert("nTest == 123","Tag","Test Message : __android_log_assert(nTest == 123) with nTest=%d",nTest);
//	__android_log_assert("nTest != 123","Tag","Test Message : __android_log_assert(nTest != 123) with nTest=%d",nTest);
#endif

	return (*env)->NewStringUTF(env, "Test112text");
}

test112_05.png
ログ出力を実装して実行した。実行時の見た目は実装前と変わらない。

test112_06.png
出力されたログを見るには、Eclipseの「DDMS」画面の「LogCat」を利用する。

test112_07.png
ここにログ出力日時とログ出力関数を呼び出したときの引数が表示される。

test112_08.png
ログには種別があり、上部のボタンで表示レベルを切り換えれる。

VERBOSEでは全て表示、DEBUGではVERBOSE以外を表示、INFOではVERBOSEとDEBUG以外を表示、、、とV>D>I>W>Eの順番で表示されるログ種別が多い。

test112_09.png
フィルター機能も備え、タグなどを指定して絞り込み表示できる。

test112_10.png
絞り込みタブを削除するには「Delete Filter」ボタンを使う




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

2010年12月30日

Android NDKでC++を利用する

Test113_01.png
これまでAndroidのネイティブコードをC言語で扱った。しかしC言語だとクラスは使えないし、メモリ確保も面倒なのでこれからはC++を利用する。まずソースコードの拡張子をcppに変更する。

Test113_02.png AndroidでJavaとネイティブの橋渡しをするJNIの記述がC言語とC++とでは異なる。コメントアウトしたのがC言語での書き方。C++の方がスマートだ。
#include <string.h>
#include <jni.h>
#include <android/log.h>


class CTest113
{
public:
	CTest113()
	{
		__android_log_write(ANDROID_LOG_DEBUG,"Test113","CTest113::CTest113()");
	}

	~CTest113()
	{
		__android_log_write(ANDROID_LOG_DEBUG,"Test113","CTest113::~CTest113()");
	}

	void	TestFunc()
	{
		__android_log_write(ANDROID_LOG_DEBUG,"Test113","CTest113::TestFunc()");
	}
};

extern "C" jstring
Java_com_Test113_Test113Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
	CTest113*	pcTest;

	pcTest = new CTest113;
	pcTest->TestFunc();
	delete	pcTest;

	return env->NewStringUTF("Test113text");
//	return (*env)->NewStringUTF(env, "Test113text");
}

Test113_03.png Android.mkでC言語からC++に変更するのはソースファイル指定の拡張子を変えるだけだ。今回はログ出力を利用するので-llogも追加した。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test113jni
LOCAL_SRC_FILES := Test113jni.cpp
LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

Test113_04.png
これで実行するとC++のクラスが生成、破棄されてそれがログに出力されたことが、DDMSのLogCatで確認できた。

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

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

test114_01.png
Android NDKには標準でStandard Template Library「STL」が用意されている(ただし2010年末現在β実装)。今回はそれを使ってSTLプログラミングをしみる。
まずネイティブのソースコードをC++にするため拡張子をcppに変更する。

test114_02.png そしてSTLを利用したネイティブコードを実装する。
#include <string.h>
#include <jni.h>

#include <vector>
#include <string>
#include <iterator>
#include <algorithm>


extern "C" jstring
Java_com_Test114_Test114Act_stringFromJNI(JNIEnv* env,jobject thiz)
{
	std::vector<std::string>  vstrTest;

	//ランダムに追加
	vstrTest.push_back("A");
	vstrTest.push_back("D");
	vstrTest.push_back("C");
	vstrTest.push_back("B");

	//ソート
	std::sort(vstrTest.begin(),vstrTest.end());

	//結果の結合
	std::string		strOut;
	{
		std::vector<std::string>::iterator	ivnPos;

		for(ivnPos = vstrTest.begin(); ivnPos != vstrTest.end(); ivnPos++ )
			strOut += *ivnPos;
	}

	//出力
	return env->NewStringUTF(strOut.c_str());
}

test114_03.png 次にAndroid.mkを編集する。STL向けの設定項目はなく、単にソースファイルをcppに変えるだけだ。
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test114jni
LOCAL_SRC_FILES := Test114jni.cpp
LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

test114_04.png
このままではAndroid NDKはSTLを認識しない。STLを使えるようにするためにはApplication.mkファイルを用意する。jniフォルダを選択して右クリックして現れるメニューの「New」にある「File」を選択する。

test114_05.png
そしてApplication.mkファイルを作成する。

test114_06.png 「APP_STL := stlport_static」の1行を追加する。これがAndroid NDKでSTLを使うための設定だ。今回はstaticライブラリとした。
APP_STL := stlport_static

test114_07.png
これでビルド/実行すると、STLによってソートされた結果が表示された。






test114_08.png メイン環境では上のApplication.mkで正常にビルドが終わったのだが、Virtual PC上の開発環境では下のようなエラーが出て失敗しました。どこかAndroid NDKのパス設定がうまくいっていないようで、ビルド済みのlibstlport_static.aが見つかっていないようです。
C:\Users\assist\Desktop\EasyProjectGenerator\Test114>bash -i -c "ndk-build"
Compile++ thumb  : Test114jni <= Test114jni.cpp
StaticLibrary  : libstdc++.a
Prebuilt       : libstlport_static.a <= <NDK>/sources/cxx-stl/stlport/libs/armea
bi/
SharedLibrary  : libTest114jni.so
C:/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe:
C:/Users/assist/Desktop/EasyProjectGenerator/Test114/obj/local/armeabi/libstlport_static.a: No such file: Permission denied
collect2: ld returned 1 exit status
make: *** [/cygdrive/c/Users/assist/Desktop/EasyProjectGenerator/Test114/obj/local/armeabi/libTest114jni.so] Error 1

C:\Users\assist\Desktop\EasyProjectGenerator\Test114>pause
続行するには何かキーを押してください . . .

test114_09.png そんなときは、Application.mkに「STLPORT_FORCE_REBUILD := true」を追加すると、Android NDKに含まれるSTLのソースファイル一式が強制ビルドされてプロジェクトフォルダ内にlibstlport_static.aが生成、利用されるようになります。
APP_STL := stlport_static
STLPORT_FORCE_REBUILD := true

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

2010年12月31日

EasyProjectGenerator for Androd Ver1.03

epg103_01.png
Android SDK/NDK用の雛形プロジェクトを簡単に自動生成できる「EasyProjectGenerator for Android」の新バージョンをアップしました。新たにC++やSTL、ログ出力機能やJavaの雛形プロジェクト生成に対応します。それに伴い前バージョンとは使い方が変わりました。

起動バッチファイルは「start_wizard.bat」に統合しています。



ダウンロードページ

epg103_02.png
「start_wizard.bat」を実行すると、最初に生成するプロジェクトの名前の入力が求められます。アルファベットと数字のみのプロジェクト名を指定してください。

epg103_03.png
次に開発言語選択(C++、C、Java)、雛形となるプロジェクト選択(HelloJNI、NativeView、Simple)などウイザードに沿って指定します。これらはそのまま[Enter]キーでデフォルトの値を使うこともできます。

epg103_04.png
バッチファイルが終わると、「EasyProjectGenerator for Android」のインストールフォルダ内にプロジェクト名のフォルダができます。これが自動生成されたプロジェクトのフォルダです。好きな場所に移動します。

epg103_05.png
そしてEclipseを起動して、「File」メニューにある「New」から「Android Project」を選択。

epg103_06.png
「Create project from existing source」にチェックを入れて、先ほど作成したプロジェクトのフォルダを指定して取り込みます。

epg103_07.png
これでEclipseからプロジェクトが使えるようになりました。

epg103_08.png
ネイティブコードのビルドは、プロジェクトフォルダ内にあるバッチファイル「_build_jni.bat」のダブルクリックで行えます。

epg103_09.png
これで作成された雛形プロジェクトを実行できました。





「EasyProjectGenerator for Android」のダウンロードページ

前の10件 1  2  3





usefullcode@gmail.com

About 2010年12月

2010年12月にブログ「UsefullCode.net」に投稿されたすべてのエントリーです。

前の記事は2010年05月です。

次の記事は2011年01月です。

他にも多くのエントリーがあります。メインページ記事一覧も見てください。