close
The Wayback Machine - https://web.archive.org/web/20171110211900/https://developer.android.com/samples/WearSpeakerSample/src/com.example.android.wearable.speaker/MainActivity.html
Skip to content

Most visited

Recently visited

navigation
WearSpeakerSample / src / com.example.android.wearable.speaker /

MainActivity.java

1
/*
2
 * Copyright (C) 2015 Google Inc. All Rights Reserved.
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.example.android.wearable.speaker;
18
 
19
import android.Manifest;
20
import android.content.Context;
21
import android.content.pm.PackageManager;
22
import android.media.AudioDeviceInfo;
23
import android.media.AudioManager;
24
import android.media.MediaPlayer;
25
import android.os.Build;
26
import android.os.Bundle;
27
import android.os.CountDownTimer;
28
import android.support.v4.app.ActivityCompat;
29
import android.support.v4.content.ContextCompat;
30
import android.support.wearable.activity.WearableActivity;
31
import android.util.Log;
32
import android.view.View;
33
import android.widget.ImageView;
34
import android.widget.ProgressBar;
35
import android.widget.Toast;
36
 
37
import java.util.concurrent.TimeUnit;
38
 
39
/**
40
 * We first get the required permission to use the MIC. If it is granted, then we continue with
41
 * the application and present the UI with three icons: a MIC icon (if pressed, user can record up
42
 * to 10 seconds), a Play icon (if clicked, it wil playback the recorded audio file) and a music
43
 * note icon (if clicked, it plays an MP3 file that is included in the app).
44
 */
45
public class MainActivity extends WearableActivity implements UIAnimation.UIStateListener,
46
        SoundRecorder.OnVoicePlaybackStateChangedListener {
47
 
48
    private static final String TAG = "MainActivity";
49
    private static final int PERMISSIONS_REQUEST_CODE = 100;
50
    private static final long COUNT_DOWN_MS = TimeUnit.SECONDS.toMillis(10);
51
    private static final long MILLIS_IN_SECOND = TimeUnit.SECONDS.toMillis(1);
52
    private static final String VOICE_FILE_NAME = "audiorecord.pcm";
53
    private MediaPlayer mMediaPlayer;
54
    private AppState mState = AppState.READY;
55
    private UIAnimation.UIState mUiState = UIAnimation.UIState.HOME;
56
    private SoundRecorder mSoundRecorder;
57
 
58
    private UIAnimation mUIAnimation;
59
    private ProgressBar mProgressBar;
60
    private CountDownTimer mCountDownTimer;
61
 
62
    enum AppState {
63
        READY, PLAYING_VOICE, PLAYING_MUSIC, RECORDING
64
    }
65
 
66
    @Override
67
    protected void onCreate(Bundle savedInstanceState) {
68
        super.onCreate(savedInstanceState);
69
        setContentView(R.layout.main_activity);
70
        mProgressBar = (ProgressBar) findViewById(R.id.progress);
71
        mProgressBar.setMax((int) (COUNT_DOWN_MS / MILLIS_IN_SECOND));
72
        setAmbientEnabled();
73
    }
74
 
75
    private void setProgressBar(long progressInMillis) {
76
        mProgressBar.setProgress((int) (progressInMillis / MILLIS_IN_SECOND));
77
    }
78
 
79
    @Override
80
    public void onUIStateChanged(UIAnimation.UIState state) {
81
        Log.d(TAG, "UI State is: " + state);
82
        if (mUiState == state) {
83
            return;
84
        }
85
        switch (state) {
86
            case MUSIC_UP:
87
                mState = AppState.PLAYING_MUSIC;
88
                mUiState = state;
89
                playMusic();
90
                break;
91
            case MIC_UP:
92
                mState = AppState.RECORDING;
93
                mUiState = state;
94
                mSoundRecorder.startRecording();
95
                setProgressBar(COUNT_DOWN_MS);
96
                mCountDownTimer = new CountDownTimer(COUNT_DOWN_MS, MILLIS_IN_SECOND) {
97
                    @Override
98
                    public void onTick(long millisUntilFinished) {
99
                        mProgressBar.setVisibility(View.VISIBLE);
100
                        setProgressBar(millisUntilFinished);
101
                        Log.d(TAG, "Time Left: " + millisUntilFinished / MILLIS_IN_SECOND);
102
                    }
103
 
104
                    @Override
105
                    public void onFinish() {
106
                        mProgressBar.setProgress(0);
107
                        mProgressBar.setVisibility(View.INVISIBLE);
108
                        mSoundRecorder.stopRecording();
109
                        mUIAnimation.transitionToHome();
110
                        mUiState = UIAnimation.UIState.HOME;
111
                        mState = AppState.READY;
112
                        mCountDownTimer = null;
113
                    }
114
                };
115
                mCountDownTimer.start();
116
                break;
117
            case SOUND_UP:
118
                mState = AppState.PLAYING_VOICE;
119
                mUiState = state;
120
                mSoundRecorder.startPlay();
121
                break;
122
            case HOME:
123
                switch (mState) {
124
                    case PLAYING_MUSIC:
125
                        mState = AppState.READY;
126
                        mUiState = state;
127
                        stopMusic();
128
                        break;
129
                    case PLAYING_VOICE:
130
                        mState = AppState.READY;
131
                        mUiState = state;
132
                        mSoundRecorder.stopPlaying();
133
                        break;
134
                    case RECORDING:
135
                        mState = AppState.READY;
136
                        mUiState = state;
137
                        mSoundRecorder.stopRecording();
138
                        if (mCountDownTimer != null) {
139
                            mCountDownTimer.cancel();
140
                            mCountDownTimer = null;
141
                        }
142
                        mProgressBar.setVisibility(View.INVISIBLE);
143
                        setProgressBar(COUNT_DOWN_MS);
144
                        break;
145
                }
146
                break;
147
        }
148
    }
149
 
150
    /**
151
     * Plays back the MP3 file embedded in the application
152
     */
153
    private void playMusic() {
154
        if (mMediaPlayer == null) {
155
            mMediaPlayer = MediaPlayer.create(this, R.raw.sound);
156
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
157
                @Override
158
                public void onCompletion(MediaPlayer mp) {
159
                    // we need to transition to the READY/Home state
160
                    Log.d(TAG, "Music Finished");
161
                    mUIAnimation.transitionToHome();
162
                }
163
            });
164
        }
165
        mMediaPlayer.start();
166
    }
167
 
168
    /**
169
     * Stops the playback of the MP3 file.
170
     */
171
    private void stopMusic() {
172
        if (mMediaPlayer != null) {
173
            mMediaPlayer.stop();
174
            mMediaPlayer.release();
175
            mMediaPlayer = null;
176
        }
177
    }
178
 
179
    /**
180
     * Checks the permission that this app needs and if it has not been granted, it will
181
     * prompt the user to grant it, otherwise it shuts down the app.
182
     */
183
    private void checkPermissions() {
184
        boolean recordAudioPermissionGranted =
185
                ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
186
                        == PackageManager.PERMISSION_GRANTED;
187
 
188
        if (recordAudioPermissionGranted) {
189
            start();
190
        } else {
191
            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.RECORD_AUDIO},
192
                    PERMISSIONS_REQUEST_CODE);
193
        }
194
 
195
    }
196
 
197
    @Override
198
    public void onRequestPermissionsResult(int requestCode,
199
            String permissions[], int[] grantResults) {
200
        if (requestCode == PERMISSIONS_REQUEST_CODE) {
201
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
202
                start();
203
            } else {
204
                // Permission has been denied before. At this point we should show a dialog to
205
                // user and explain why this permission is needed and direct him to go to the
206
                // Permissions settings for the app in the System settings. For this sample, we
207
                // simply exit to get to the important part.
208
                Toast.makeText(this, R.string.exiting_for_permissions, Toast.LENGTH_LONG).show();
209
                finish();
210
            }
211
        }
212
    }
213
 
214
    /**
215
     * Starts the main flow of the application.
216
     */
217
    private void start() {
218
        mSoundRecorder = new SoundRecorder(this, VOICE_FILE_NAME, this);
219
        int[] thumbResources = new int[] {R.id.mic, R.id.play, R.id.music};
220
        ImageView[] thumbs = new ImageView[3];
221
        for(int i=0; i < 3; i++) {
222
            thumbs[i] = (ImageView) findViewById(thumbResources[i]);
223
        }
224
        View containerView = findViewById(R.id.container);
225
        ImageView expandedView = (ImageView) findViewById(R.id.expanded);
226
        int animationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
227
        mUIAnimation = new UIAnimation(containerView, thumbs, expandedView, animationDuration,
228
                this);
229
    }
230
 
231
    @Override
232
    protected void onStart() {
233
        super.onStart();
234
        if (speakerIsSupported()) {
235
            checkPermissions();
236
        } else {
237
            findViewById(R.id.container2).setOnClickListener(new View.OnClickListener() {
238
                @Override
239
                public void onClick(View v) {
240
                    Toast.makeText(MainActivity.this, R.string.no_speaker_supported,
241
                            Toast.LENGTH_SHORT).show();
242
                }
243
            });
244
        }
245
    }
246
 
247
    @Override
248
    protected void onStop() {
249
        if (mSoundRecorder != null) {
250
            mSoundRecorder.cleanup();
251
            mSoundRecorder = null;
252
        }
253
        if (mCountDownTimer != null) {
254
            mCountDownTimer.cancel();
255
        }
256
 
257
        if (mMediaPlayer != null) {
258
            mMediaPlayer.release();
259
            mMediaPlayer = null;
260
        }
261
        super.onStop();
262
    }
263
 
264
    @Override
265
    public void onPlaybackStopped() {
266
        mUIAnimation.transitionToHome();
267
        mUiState = UIAnimation.UIState.HOME;
268
        mState = AppState.READY;
269
    }
270
 
271
    /**
272
     * Determines if the wear device has a built-in speaker and if it is supported. Speaker, even if
273
     * physically present, is only supported in Android M+ on a wear device..
274
     */
275
    public final boolean speakerIsSupported() {
276
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
277
            PackageManager packageManager = getPackageManager();
278
            // The results from AudioManager.getDevices can't be trusted unless the device
279
            // advertises FEATURE_AUDIO_OUTPUT.
280
            if (!packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
281
                return false;
282
            }
283
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
284
            AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
285
            for (AudioDeviceInfo device : devices) {
286
                if (device.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
287
                    return true;
288
                }
289
            }
290
        }
291
        return false;
292
    }
293
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

BERJAYA

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)