アンドロイドアプリサンプルソース シェイク動作編 | ゲームアプリの攻略情報から人気のスマホサービス・アプリを特集して紹介 | スマホ情報は≪アンドロック≫

アンドロイドアプリサンプルソース シェイク動作編

イントロダクション

AndRockで開発した『納涼アプリ「風鈴」』のアンドロイドアプリの開発情報を紹介します。
風鈴を鳴らす方法は2つあるのですが、今回は本体を揺らした時に風鈴が鳴る仕組みについてソースの解説を行いたいと思います。

アンドロイドアプリサンプルソース シェイク動作編

風鈴の構成

主な処理としては、

  • タッチイベントの処理(風鈴画像をタッチしているかチェック)
  • シェイク感知処理
  • 風鈴を鳴らす処理(音の再生、画像のアニメーション動作)

となっています。
まずは、本体を揺らしたことを感知するシェイク感知処理から解説していきます。

ShakeListenerクラス(シェイク感知処理)

シェイク(本体の揺れ、傾き)を感知するための処理をまとめています。

(ソース:ShakeListener.java)

// シェイクを感知したときにonShakeメソッドを呼び出します
public interface OnShakeListener {
	void onShake();
	void setShakeSpeed(float shakeSpeed);
}

// OnShakeListenerをセット
public void setOnShakeListener(OnShakeListener Listener) {
	mListener	= Listener;
}

public ShakeListener(Context context) {
	// SensorManagerのインスタンスを取得
	mSensorManager	= (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}

「onSensorChanged」で加速度を計算し、加速度が規定値以上の値であれば風鈴を鳴らす処理を実行しています。
「onSensorChanged」はセンサーの値が変更される度に呼ばれます。(本体を揺らすたびに処理が実行されます)

(ソース:ShakeListener.java)

// センサーの値が変わったら呼び出される
public void onSensorChanged(SensorEvent event) {
	// センサーのタイプが加速度センサーじゃない場合
	if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
		return;
	}

	long nNowTime	= System.currentTimeMillis();
	long nDiffTime	= nNowTime - nBeforeTime;

	if (nDiffTime > 500) {
		float x	= event.values[0];
		float y	= event.values[1];
		float z	= event.values[2];

		// 前回の値との差からスピードを計算
		float speed = Math.abs(x + y + z - nBeforeX - nBeforeY - nBeforeZ) / nDiffTime * 10000;
		nShakeSpeed	= speed;
		
		// スピードが規定値以上なら
		if (speed > intSpeed) {
			intCount++;		// シェイクカウントを足す

			// 2回連続スピードが規定値以上なら
			if (intCount > intMaxCount) {
				intCount = 0;
				mListener.setShakeSpeed(nShakeSpeed);
				
				// リスナーがセットされていれば
				if (mListener != null) {
					mListener.onShake();
				}
			}
		} else {
			// 規定値以下ならリセット
			intCount = 0;
		}
		// 前回値として保存
		nBeforeTime	= nNowTime;
		nBeforeX	= x;
		nBeforeY	= y;
		nBeforeZ	= z;
	}
}

次に風鈴を鳴らす処理の解説をしていきます。

風鈴を鳴らす処理

ShakeListenerクラスの「onSensorChanged」で加速度が規定値以上のときに「onShake」が実行され、
加速度の値の大きさによって音の大きさ、風鈴画像の揺れ幅、繰り返し処理の回数を変更しています。

(ソース:windbell.java)

//シェイク動作
mShakeListener.setOnShakeListener(new OnShakeListener() {
	// シェイクを検知した場合
	public void onShake() {
		if(nShakeOverListArray[0] > nShakeSpeed){
			intShakeType	= 3;
		} else if(nShakeOverListArray[1] > nShakeSpeed) {
			intShakeType	= 2;
		} else if(nShakeOverListArray[2] > nShakeSpeed) {
			intShakeType	= 1;
		} else {
			intShakeType	= 0;
		}
		TimerAction();	//処理実行
	}
	public void setShakeSpeed(float values) {
		nShakeSpeed	= values;
	}
});

そして「TimerAction」で音の再生、画像のアニメーション動作を実行しています。

風鈴を鳴らす処理を「TimerTask」で繰り返している理由は、徐々に音や風鈴の揺れ幅を小さくしていくためです。
加速度の値が大きければ風鈴の揺れ、音を大きくし、繰り返し処理の回数を増やして音の再生、画像のアニメーション動作の実行回数を増やして徐々に音と揺れ幅を小さくさせています。
加速度の値が小さければ風鈴の揺れ、音を小さくし、音の再生、画像のアニメーション動作の実行回数を減らす仕組みとなっています。

(ソース:windbell.java)

//定期的に処理を実行するTimerTask処理
public void TimerAction() {
	stopAutoInvisible();					//TimerTaskの停止処理
	intShakeTypeCount	= intShakeType;
	mTimer	= new Timer(false);	// タイマーを生成
	
	// スケジュールを設定
	mTimer.schedule(mTimerTask=new TimerTask() {
		@Override
		public void run() {
			mHandler.post(new Runnable() {
				public void run() {
					SetSoundPlayer(intShakeTypeCount);			//再生する音ファイルをセット
					SoundPlayer();								//音再生・停止
					ImageMove(intMove01Array[intShakeTypeCount],intMove02Array[intShakeTypeCount]);		//画像のアニメーション動作
					intShakeTypeCount	= intShakeTypeCount + 1;
					
					if(intShakeTypeCount >= intMove01Array.length) {
						mTimer.cancel();
					}
				}
			});
		}
	}, 0, intDuration); // 初回起動の遅延(0sec)と周期(intDuration)指定
}
画像のアニメーション動作

(ソース:windbell.java)

//画像のアニメーション動作
public void ImageMove(int Rotate01, int Rotate02) {
	ImageView imgView01 		= (ImageView) findViewById(R.id.imageView1);	//動作させる対象を取得(画像01)
	ImageView imgView02 		= (ImageView) findViewById(R.id.imageView2);	//動作させる対象を取得(画像02)
	
	RotateAnimation rotateImg01 = new RotateAnimation(0, Rotate01, imgView01.getWidth()/2, 0);
	RotateAnimation rotateImg02 = new RotateAnimation(0, Rotate02, imgView02.getWidth()/2, 0);
	
	//○○秒で回転する
	rotateImg01.setDuration(intDuration);
	rotateImg02.setDuration(intDuration);
	
	//○回繰り返す
	rotateImg01.setInterpolator(new CycleInterpolator(intDurationCount));
	rotateImg02.setInterpolator(new CycleInterpolator(intDurationCount));

	//アニメーションスタート
	imgView01.startAnimation(rotateImg01);
	imgView02.startAnimation(rotateImg02);
}
音の再生

「MediaPlayer」を使って音ファイルの再生を行っています。

(ソース:windbell.java)

public void onCreate(Bundle savedInstanceState) {
	(省略)
	・
	・
	
	mp_1	= MediaPlayer.create(this, R.raw.furin001);		//メディアプレイヤー(最大の音)
	mp_2	= MediaPlayer.create(this, R.raw.furin002);		//メディアプレイヤー(少し大きい音)
	mp_3	= MediaPlayer.create(this, R.raw.furin003);		//メディアプレイヤー(中の音)
	mp_4	= MediaPlayer.create(this, R.raw.furin004);		//メディアプレイヤー(少し小さい音)
	mp_5	= MediaPlayer.create(this, R.raw.furin005);		//メディアプレイヤー(最小の音)
	
	(省略)
	・
	・
}

//playerに音ファイルをセット
public void SetSoundPlayer(int Count) {
	switch(Count) {
		case 0:	//最大の音
			mPlayer	= mp_1;
			break;
		case 1:	//少し大きい音
			mPlayer	= mp_2;
			break;
		case 2:	//中の音
			mPlayer	= mp_3;
			break;
		case 3:	//少し小さい音
			mPlayer	= mp_4;
			break;
		case 4:	//最小の音
			mPlayer	= mp_5;
			break;
		default:
			break;
	}
	return;
}

//音ファイルの再生
public void SoundPlayer() {
	try {
		if (mPlayer.isPlaying()) { // 再生中
			mPlayer.stop();
				try {
					mPlayer.prepare();
					mPlayer.start();
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
		} else { // 停止中
			mPlayer.start();
		}
	} catch (Exception e) {
		//再生失敗
	}
}

苦労話

着信時に音の再生が止まらない!!

風鈴を鳴らすための処理の開発が完了して、動作の確認も問題なかったので「完成した」と思ったのですが、アプリを起動しているときに着信やメールの受信があった場合、「音の再生は止まるのか?」という疑問が浮かびました。確認してみると着信があっても音の再生が止まらないため、着信時などに音の再生を停止させる方法を調査しました
調査した結果、音の再生が止まらない理由は「MediaPlayer」の再生は停止させない限り再生時間が終わるまで再生し続けてしまうためでした。

解決策としては「onPause」に「MediaPlayer」の再生を停止する処理を入れました。「onPause」が実行されるのは別のアクティビティが呼ばれるとき(着信やメールの受信など)なので、今回解決したかったのが着信やメールの受信などのときに音の再生を止めたいということだったので、「onPause」に止めたい処理を入れて解決しています。(「TimerTask」も停止させています。)

Activityのライフサイクルについての知識がなかったのが原因でした。
(参考URL:Androidアプリ作成の基本“Activity”とは何か?

裏話

アンドロイドアプリの開発が初挑戦だったので、処理を完成させるまでにけっこう時間がかかってしまいました。
その後で風鈴の画像を用意する作業に取りかかったのですが、良い風鈴の画像を見つけることが中々できなかったので画像を作ることにしました。ただ画像編集ツールを使ったことが全くなかったため、風鈴の画像を作成するのにとても苦労しました。
最終的には処理を作るよりも画像を作るほうに時間をかけてしまってましたね。

本物の風鈴を用意して写真を撮って使えばあまり時間をかけずに作れたかもしれないですね。



あなたにオススメの記事

この記事を共有する

  • このエントリーをはてなブックマークに追加

オススメ新着記事

Recommended by

スマホ情報のAndRockを共有する



follow us in feedly


アンドロイド携帯向けアプリの人気ランキングページです。ビジネスに、遊びに、とてもお役立ちのアンドロイドアプリが勢ぞろい。どのアプリも人気のある「10個」です。厳選されたラインナップ。もしかしたらあなたの携帯ライフを劇的に変えるアプリも現れるかもしれません!日々変わるこのアプリのランキング動向を、ぜひチェックしてください。




人気・定番のアンドロイドアプリレビュー

HUNTER×HUNTER ワールドハント

HUNTER×HUNTER ワールドハント

キャラの特性を活かしたターン制アクティブタイムバトル!

マスター オブ カオス - Master of Chaos

マスター オブ カオス - Master of Chaos

超ハイクオリティーなアクションRPG

ジョジョの奇妙な冒険 ダイヤモンドレコーズ

ジョジョの奇妙な冒険 ダイヤモンドレコーズ

ジョジョの3D「ドドド」アクションゲーム




スマートフォン、アンドロイド、アプリの使い方を解説

LINE アプリの使い方 完全マニュアル(Android,iPhone)

6000万ダウンロードを突破した無料通話・チャットが使える神アプリLINEの使い方のまとめ


Viberの使い方、設定まとめ (Android , iPhone)

無料通話のできるViberの使い方から、初期設定、日本語化などなどのまとめ


Skypeの使い方、設定(Android , iPhone)

無料通話・無料チャットの定番Skypeの使い方まとめ


無料・おトク電話アプリ「050 plus」のまとめ

スマートフォンで月額を抑えたい人におススメのアプリ!「050 plus」の使い方を解説




ドラゴンボールZドッカンバトル攻略情報
ONE PIECE トレジャークルーズ攻略情報
LINE アプリの使い方 完全マニュアル(Android,iPhone)
インスタグラム完全使い方ガイド
iPhone説明書
LINEで絶対使いたいLINEスタンプ検索

アプリ人気ランキング

Androidアプリ
iPhone/iOSアプリ

新着スマホ情報


▼アプリ・記事の新着一覧へ

LINEで使えるオススメのスタンプアプリ まとめ20選

スマホアプリ カテゴリ一覧

スマートフォンサイト
QR-code AndRock(アンドロック)は、スマートフォンでもご利用いただけます。 QRコードスキャナーで読み取ってご利用ください。
Follow Us