SoundPool Deprecated

Get help on issues related to the book here!
Aqualle
Rank 2
Rank 2
Posts: 8
Joined: Mon Oct 27, 2014 1:17 pm

SoundPool Deprecated

Postby Aqualle » Mon Dec 08, 2014 12:49 pm

Hi James,

Just wanted to let you know that the SoundPool is deprecated in API level 21 and that we should use SoundPool.Builder instead.

Source:
https://developer.android.com/reference ... ilder.html

I'm trying to do it how they suggests but I might be doing something wrong.. could you give a suggestion on implementing with the new class.

Thanks in advance

User avatar
jamescho7
Site Admin
Site Admin
Posts: 244
Joined: Thu Jun 12, 2014 10:25 am

Re: SoundPool Deprecated

Postby jamescho7 » Mon Dec 08, 2014 3:59 pm

Thank you for letting me know! Let me just provide context for others before I share the solution.

With each new release of Android, Google sometimes deprecates existing methods from the codebase. This means that methods that previously worked are no longer officially supported.

Chances are, those methods will still work for years to come (Google doesn't want 95% of apps to stop working overnight), but it is good practice to update your apps so that they continue to remain compatible with futuer versions of Android.

Now this is a bit ridiculous, but Android Lollipop 5.0, as of a week ago, was running on fewer than 0.1% of devices. Some Google Play Edition devices have since received the update, so the number is now probably slightly higher now. But as far as we know, the so-called "deprecated" code is perfectly valid on >99.9% of devices. If every Android device would just update to the latest version of the OS as soon as it is made available, we wouldn't need to maintain two sets of code... but as things are, we need to provide a solution that makes Android Lollipop happy while ensuring that the older devices still run our game properly.

Here are the recommended (but optional) changes:

Looks like they made things slightly more complicated, but this should work:

LISTING 1 (Abbreviated Assets Class)

Code: Select all

package com.jamescho.ellio;

import java.io.IOException;
import java.io.InputStream;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.media.AudioAttributes;
import android.media.AudioAttributes.Builder;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Build;

import com.jamescho.framework.animation.Animation;
import com.jamescho.framework.animation.Frame;

public class Assets {

   private static SoundPool soundPool;
   private static MediaPlayer mediaPlayer;
   // ... Abbreviated
   
   private static int loadSound(String filename) {
      int soundID = 0;
      if (soundPool == null) {
         soundPool = buildSoundPool();
      }
      try {
         soundID = soundPool.load(GameMainActivity.assets.openFd(filename),
               1);
      } catch (IOException e) {
         e.printStackTrace();
      }
      return soundID;
   }

   @SuppressWarnings("deprecation")
   @TargetApi(Build.VERSION_CODES.LOLLIPOP)
   private static SoundPool buildSoundPool() {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
         AudioAttributes audioAttributes = new AudioAttributes.Builder()
                                 .setUsage(AudioAttributes.USAGE_GAME)
                                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                                 .build();
                                 
         soundPool = new SoundPool.Builder()
                     .setMaxStreams(25)
                     .setAudioAttributes(audioAttributes)
                     .build();
      } else {
         soundPool = new SoundPool(25, AudioManager.STREAM_MUSIC, 0);
      }
      return soundPool;
   }

   public static void playSound(int soundID) {
      if (soundPool != null) {
         soundPool.play(soundID, 1, 1, 1, 0, 1);
      }
   }

}


EXPLANATION
Let me explain what's going on. As of Android Lollipop, the constructor used in the book has been deprecated:

Code: Select all

SoundPool soundPool = new SoundPool(25, AudioManager.STREAM_MUSIC, 0)


This means that starting with Lollipop, they do not recomend that you use that constructor (although it will likely continue to work for the next several versions of Android).

Instead of constructing a SoundPool directly, the new way to do it is to use an associated Builder class:

LISTING 2

Code: Select all

SoundPool.Builder builder =  new SoundPool.Builder();
builder.setMaxStreams(25);
builder.setAudioAttributes(...); // We will come back to this after.
SoundPool soundPool = builder.build(); // Builder.build returns a new instance of SoundPool.


Note that the entirety of LISTING 2 can be simplified into a single line (see LISTING 1) because the setMaxStreams(...) and setAudioAttributes(...) return the builder object whose method you just called. This is called chaining (a simple example is here: http://en.wikipedia.org/wiki/Method_chaining#Java)

They also encapsulated the settings for audio attributes into a class, and that too requires you to use a builder.

LISTING 3 (Note the use of chaining here)

Code: Select all

AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();


Now you will notice that the buildSoundPool() method that I created has the following tags:

1. @SuppressWarnings("deprecation")
2. @TargetApi(Build.VERSION_CODES.LOLLIPOP)

The first is there because we need to use "deprecated" construtor on Android devices whose version is not Lollipop (we check this using: if Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)).

The second is there to acknowledge that we are using code (the new Builder methods) whose minimum API requirement is Lollipop and that older devices will crash if you do not explicitly provide an alternative solution (which we did using the if statement).

Aqualle
Rank 2
Rank 2
Posts: 8
Joined: Mon Oct 27, 2014 1:17 pm

Re: SoundPool Deprecated

Postby Aqualle » Tue Dec 09, 2014 3:48 am

Thank you so much!! I had reset my target api to 20 in order for me to continue with the book. I'll try your example now. Thanks for sharing! And Yes! I agree, with your ridiculous part..

mckamike
Rank 3
Rank 3
Posts: 13
Joined: Sun Feb 22, 2015 11:59 pm

Re: SoundPool Deprecated

Postby mckamike » Fri Apr 17, 2015 3:34 am

I still am getting the "Sample was not ready. Waiting 30ms" error. What's going on with this? I was browsing around on StackOverflow and supposedly we have to implement something called an onLoadCompleteListener?

User avatar
jamescho7
Site Admin
Site Admin
Posts: 244
Joined: Thu Jun 12, 2014 10:25 am

Re: SoundPool Deprecated

Postby jamescho7 » Sat Apr 18, 2015 3:53 pm

mckamike,

When do you get this error? (e.g. what part of the book are you working from?)

mckamike
Rank 3
Rank 3
Posts: 13
Joined: Sun Feb 22, 2015 11:59 pm

Re: SoundPool Deprecated

Postby mckamike » Tue May 26, 2015 6:05 pm

James,

Sorry for the late reply. I rebuilt my project after doing what you said we should changed, and that cleared things up.

Thanks for continuing to answer questions on forums, we all appreciate it!


Return to “Book General Help”

Who is online

Users browsing this forum: No registered users and 2 guests