1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.ui; 18 19 import java.util.Locale; 20 21 import android.content.Context; 22 import android.media.AudioManager; 23 import android.media.SoundPool; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.util.AttributeSet; 27 import android.util.Log; 28 import android.view.View; 29 import android.view.animation.Animation; 30 import android.view.animation.AnimationUtils; 31 import android.widget.FrameLayout; 32 import android.widget.TextView; 33 34 import com.android.camera.R; 35 36 public class CountDownView extends FrameLayout { 37 38 private static final String TAG = "CAM_CountDownView"; 39 private static final int SET_TIMER_TEXT = 1; 40 private TextView mRemainingSecondsView; 41 private int mRemainingSecs = 0; 42 private OnCountDownFinishedListener mListener; 43 private Animation mCountDownAnim; 44 private SoundPool mSoundPool; 45 private int mBeepTwice; 46 private int mBeepOnce; 47 private boolean mPlaySound; 48 private final Handler mHandler = new MainHandler(); 49 50 public CountDownView(Context context, AttributeSet attrs) { 51 super(context, attrs); 52 mCountDownAnim = AnimationUtils.loadAnimation(context, R.anim.count_down_exit); 53 // Load the beeps 54 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 55 mBeepOnce = mSoundPool.load(context, R.raw.beep_once, 1); 56 mBeepTwice = mSoundPool.load(context, R.raw.beep_twice, 1); 57 } 58 59 public boolean isCountingDown() { 60 return mRemainingSecs > 0; 61 }; 62 63 public interface OnCountDownFinishedListener { 64 public void onCountDownFinished(); 65 } 66 67 private void remainingSecondsChanged(int newVal) { 68 mRemainingSecs = newVal; 69 if (newVal == 0) { 70 // Countdown has finished 71 setVisibility(View.INVISIBLE); 72 mListener.onCountDownFinished(); 73 } else { 74 Locale locale = getResources().getConfiguration().locale; 75 String localizedValue = String.format(locale, "%d", newVal); 76 mRemainingSecondsView.setText(localizedValue); 77 // Fade-out animation 78 mCountDownAnim.reset(); 79 mRemainingSecondsView.clearAnimation(); 80 mRemainingSecondsView.startAnimation(mCountDownAnim); 81 82 // Play sound effect for the last 3 seconds of the countdown 83 if (mPlaySound) { 84 if (newVal == 1) { 85 mSoundPool.play(mBeepTwice, 1.0f, 1.0f, 0, 0, 1.0f); 86 } else if (newVal <= 3) { 87 mSoundPool.play(mBeepOnce, 1.0f, 1.0f, 0, 0, 1.0f); 88 } 89 } 90 // Schedule the next remainingSecondsChanged() call in 1 second 91 mHandler.sendEmptyMessageDelayed(SET_TIMER_TEXT, 1000); 92 } 93 } 94 95 @Override 96 protected void onFinishInflate() { 97 super.onFinishInflate(); 98 mRemainingSecondsView = (TextView) findViewById(R.id.remaining_seconds); 99 } 100 101 public void setCountDownFinishedListener(OnCountDownFinishedListener listener) { 102 mListener = listener; 103 } 104 105 public void startCountDown(int sec, boolean playSound) { 106 if (sec <= 0) { 107 Log.w(TAG, "Invalid input for countdown timer: " + sec + " seconds"); 108 return; 109 } 110 setVisibility(View.VISIBLE); 111 mPlaySound = playSound; 112 remainingSecondsChanged(sec); 113 } 114 115 public void cancelCountDown() { 116 if (mRemainingSecs > 0) { 117 mRemainingSecs = 0; 118 mHandler.removeMessages(SET_TIMER_TEXT); 119 setVisibility(View.INVISIBLE); 120 } 121 } 122 123 private class MainHandler extends Handler { 124 @Override 125 public void handleMessage(Message message) { 126 if (message.what == SET_TIMER_TEXT) { 127 remainingSecondsChanged(mRemainingSecs -1); 128 } 129 } 130 } 131 }