スマホアプリならアンドロック
スマホアプリ(アンドロイド)レビューやスマホ情報はアンドロックAndRockで開発した『納涼アプリ「風鈴」』のアンドロイドアプリの開発情報を紹介します。
風鈴を鳴らす方法は2つあるのですが、今回は本体を揺らした時に風鈴が鳴る仕組みについてソースの解説を行いたいと思います。
主な処理としては、
となっています。
まずは、本体を揺らしたことを感知するシェイク感知処理から解説していきます。
シェイク(本体の揺れ、傾き)を感知するための処理をまとめています。
(ソース: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”とは何か?)
アンドロイドアプリの開発が初挑戦だったので、処理を完成させるまでにけっこう時間がかかってしまいました。
その後で風鈴の画像を用意する作業に取りかかったのですが、良い風鈴の画像を見つけることが中々できなかったので画像を作ることにしました。ただ画像編集ツールを使ったことが全くなかったため、風鈴の画像を作成するのにとても苦労しました。
最終的には処理を作るよりも画像を作るほうに時間をかけてしまってましたね。
本物の風鈴を用意して写真を撮って使えばあまり時間をかけずに作れたかもしれないですね。
アンドロイド携帯向けアプリの人気ランキングページです。ビジネスに、遊びに、とてもお役立ちのアンドロイドアプリが勢ぞろい。どのアプリも人気のある「10個」です。厳選されたラインナップ。もしかしたらあなたの携帯ライフを劇的に変えるアプリも現れるかもしれません!日々変わるこのアプリのランキング動向を、ぜひチェックしてください。
2024年シリーズ1 セレクション第2弾の評価ランキングを紹介します! 第・・・
プロスピA(プロ野球スピリッツA)の攻略情報をまとめたページです。 基本・・・
2024年シリーズ1 セレクション第1弾の評価ランキングを紹介します! 最・・・
2024年シリーズ1 TS第3弾の評価ランキングを紹介します! 前回はイチロ・・・
現役の選手・監督・コーチが全盛期の能力になって登場するTS(タイムスリッ・・・
2024年シリーズ1 エキサイティングプレイヤー第2弾の評価ランキングを紹介・・・
この記事では、エキサイティングプレイヤーに続くシリーズ1の目玉スカウト「プ・・・