Support free tutorials

vogella training Training Books



Handling Media with Android - Tutorial

Lars Vogel

Version 1.2

01.03.2011

Android Media - Sounds

This tutorial describes the usage of the Android media API for playing and recording sound. It is based on Eclipse 3.7, Java 1.6 and Android 4.0.3 (Ice Cream Sandwich).


Table of Contents

1. Android Sound and Media
1.1. Playing sound
1.2. MediaRecorder
1.3. Adding to the Media library
1.4. Supported formats
2. Prerequisites
3. Tutorial: Play sounds via SoundPool
4. Tutorial: Record media via MediaRecorder
5. About this website
5.1. Donate to support free tutorials
5.2. Questions and discussion
5.3. License for this tutorial and its code
6. Links and Literature
6.1. Source Code
6.2. Android Resources
6.3. vogella Resources

1. Android Sound and Media

1.1. Playing sound

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.

1.2. MediaRecorder

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.

1.3. Adding to the Media library

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)); 

1.4. Supported formats

Android supports a variaty of formats. See Supported Media Formats in the Android Developer Guide.

2. Prerequisites

The following assumes that you are already familiar with basic Android programming. Please see Android Tutorial for an introduction.

3. Tutorial: Play sounds via SoundPool

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="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="match_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 site 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.

4. Tutorial: Record media via MediaRecorder

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="match_parent"
    android:layout_height="match_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.

5. About this website

5.1. Donate to support free tutorials

Please consider a contribution Support free tutorials if this article helped you. It will help to maintain our content and our Open Source activities.

5.2. Questions and discussion

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

5.3. License for this tutorial and its code

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

6. Links and Literature

6.1. Source Code

Source Code of Examples

6.3. vogella Resources

TRAINING SERVICE & SUPPORT
The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”. The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.