Version 1.2
Copyright © 2010 - 2011 Lars Vogel
01.03.2011
| Revision History | ||
|---|---|---|
| Revision 0.1 | 29.12.2010 | Lars Vogel |
| Created | ||
| Revision 0.2 - 1.2 | 29.12.2010 - 01.03.2011 | Lars Vogel |
| bug fixed and enhancements | ||
Table of Contents
Android
provides two main API's for playing sounds. The first one via
the
SoundPool
class
and
the other one via the
MediaPlayer
class.
SoundPool
can be used for small audio clips. It can
repeat
sounds and
play several
sounds simultaneously. The sound files
played
with
SoundPool
should not exceed 1 MB.
SoundPool
does load the file asynchronously. As of Android API8
it is possible
to check if the loading is
complete via a
OnLoadCompleteListener.
Android supports different audio streams for different purposes. The phone volume button can be configured to control a specific audio stream, e.g. during a call the volume button allow increase / decrease the caller volume. To set the button to control the sound media stream set the audio type in your application.
context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
MediaPlayer
is better
suited for
longer music and movies.
The
android.media.MediaRecorder
class can be used to record audio and video. To use
MediaRecorder
you need to set the source
device and the format.
You can add new Media to the Android media library.
Via an
Intent
you can tell the media application on the device that new content is
available. The following
demonstrates that.
// Add new file to your media library ContentValues values = new ContentValues(4); long current = System.currentTimeMillis(); values.put(MediaStore.Audio.Media.TITLE, "audio" + audiofile.getName()); values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000)); values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp"); values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath()); ContentResolver contentResolver = getContentResolver(); Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Uri newUri = contentResolver.insert(base, values); // Notifiy the media application on the device sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri));
Android supports a variaty of formats. See Supported Media Formats in the Android Developer Guide .
The following assumes that you are already familiar with basic Android programming. Please see Android Tutorial for an introduction.
We will create an application which will start playing a sound once the finger touches the display. Create an Android project called "de.vogella.android.soundpool" with an Activity called "PlaySound".
Change the layout "main.xml" to the following.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Click on the screen to start playing" > </TextView> </LinearLayout>
Download a sound which you want to play. For example the Free Sound Effects side contains several free sound examples.
Put the sound file into your "res/raw" folder under the name "sound1.ogg". This assumes that you downloaded an ogg file.
Create the following coding for your activity.
package de.vogella.android.soundpool; import android.app.Activity; import android.media.AudioManager; import android.media.SoundPool; import android.media.SoundPool.OnLoadCompleteListener; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; public class PlaySound extends Activity implements OnTouchListener { private SoundPool soundPool; private int soundID; boolean loaded = false;/** Called when the activity is first created. */@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); View view = findViewById(R.id.textView1); view.setOnTouchListener(this); // Set the hardware buttons to control the music this.setVolumeControlStream(AudioManager.STREAM_MUSIC); // Load the sound soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() { @Override public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { loaded = true; } }); soundID = soundPool.load(this, R.raw.sound1, 1); } @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // Getting the user sound settings AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); float actualVolume = (float) audioManager .getStreamVolume(AudioManager.STREAM_MUSIC); float maxVolume = (float) audioManager .getStreamMaxVolume(AudioManager.STREAM_MUSIC); float volume = actualVolume / maxVolume; // Is the sound loaded already? if (loaded) { soundPool.play(soundID, volume, volume, 1, 0, 1f); Log.e("Test", "Played sound"); } } return false; } }
If you touch your
Activity
your sound should be played. It will use
the current volume settings.
We will create an application which will start playing a sound
once
the
finger touches the display. Create an
Android
project called
"de.vogella.android.media.soundrecording" with an
Activity
called
"RecordSound".
Add to the AndroidManifest.xml file the permission to write to the SD card and to record audio data.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.RECORD_AUDIO" />
Change the layout "main.xml" to the following.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start Recording" android:onClick="startRecording" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Stop Recording" android:enabled="false" android:onClick="stopRecording" /> </LinearLayout>
Change your
Activity
class to the following.
package de.vogella.android.media.soundrecording; import java.io.File; import java.io.IOException; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.media.MediaRecorder; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.Toast; public class SoundRecordingActivity extends Activity { MediaRecorder recorder; File audiofile = null; private static final String TAG = "SoundRecordingActivity"; private View startButton; private View stopButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startButton = findViewById(R.id.start); stopButton = findViewById(R.id.stop); } public void startRecording(View view) throws IOException { startButton.setEnabled(false); stopButton.setEnabled(true); File sampleDir = Environment.getExternalStorageDirectory(); try { audiofile = File.createTempFile("sound", ".3gp", sampleDir); } catch (IOException e) { Log.e(TAG, "sdcard access error"); return; } recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); recorder.setOutputFile(audiofile.getAbsolutePath()); recorder.prepare(); recorder.start(); } public void stopRecording(View view) { startButton.setEnabled(true); stopButton.setEnabled(false); recorder.stop(); recorder.release(); addRecordingToMediaLibrary(); } protected void addRecordingToMediaLibrary() { ContentValues values = new ContentValues(4); long current = System.currentTimeMillis(); values.put(MediaStore.Audio.Media.TITLE, "audio" + audiofile.getName()); values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000)); values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp"); values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath()); ContentResolver contentResolver = getContentResolver(); Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Uri newUri = contentResolver.insert(base, values); sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri)); Toast.makeText(this, "Added File " + newUri, Toast.LENGTH_LONG).show(); } }
You should be able to record a sound, if you press the "Start Recording" button. Once you press the stop recording button, the recording will be stopped and the file will be added to your media library.
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
Eclipse RCP Training (German) Eclipse RCP Training with Lars Vogel
Android Tutorial Introduction to Android Programming
GWT Tutorial Program in Java and compile to JavaScript and HTML
Eclipse RCP Tutorial Create native applications in Java
JUnit Tutorial Test your application
Git Tutorial Put everything you have under distributed version control system