所以我现在正在为我正在进行的游戏实现播放声音。现在游戏支持API 8到最新的21.我使用SoundPool来播放和处理声音,但似乎使用API 21,你必须为SoundPool设置AudioAttributes。
我目前收到以下错误:
05-15 13:56:48.202 26245-26245 / thedronegame.group08.surrey.ac.uk.thedronegame E / dalvikvm: 找不到类' android.media.AudioAttributes $ Builder', 从方法中引用 thedronegame.group08.surrey.ac.uk.thedronegame.Sound.initializeRecentAPISoundPool
声音等级
<pre>package thedronegame.group08.surrey.ac.uk.thedronegame;
import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.MediaPlayer;
import android.os.Build;
import android.util.Log;
/**
* Created by Michael on 19/03/15.
*/
public class Sound {
/**
* The sound pool
*/
private SoundPool soundPool = null;
/**
* The current Sound.
*/
private int sound = 0;
/**
* false Boolean.
*/
private boolean loaded = false;
/**
* The context.
*/
private Context context = null;
/**
* Audio Manager.
*/
private AudioManager audioManager = null;
/**
* Literal Volume.
*/
private float literalVolume = 0;
/**
* Maximum Volume.
*/
private float maximumVolume = 0;
/**
* Volume.
*/
private float volume = 0;
/**
* A constructor for creating a new Sound object
*/
public Sound(Context context) {
this.context = context;
this.audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE);
// Set Literal Volume for Audio Manager.
this.literalVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
// Set Maximum Volume for Audio Manager.
this.maximumVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
// Set volume for GameSound Pool.
this.volume = literalVolume / maximumVolume;
}
/**
* Initialize the SoundPool for later API versions
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void initializeRecentAPISoundPool() {
// Create AudioAttributes.
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
this.soundPool = new SoundPool.Builder()
.setAudioAttributes(attributes)
.setMaxStreams(7)
.build();
}
/**
* Intialize SoundPool for older API
versions
*/
@SuppressWarnings("deprecation")
private void initializeDeprecatedAPISoundPool() {
// Initialize SoundPool.
this.soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC,0);
}
/**
* Load Sounds into the SoundPool.
*/
private void loadIntoSoundPool() {
//todo: finish loadIntoSoundPool() method
// Loads all sounds from array
// Sound 0.
this.soundPool.load(this.context, R.raw.blip_select2, 0);
// Sound 1.
//this.soundPool.load(context, R.raw.sound, 1);
}
/**
* Set the initial SoundPool.
* Call to Method differs dependent on API Version.
*/
public void setInitialSoundPool() {
// Initialize SoundPool, call specific dependent on SDK Version
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
initializeRecentAPISoundPool();
}
else {
initializeDeprecatedAPISoundPool();
}
this.soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
loaded = true;
soundPool.load(context, R.raw.blip_select2, 0);
}
});
// Load sounds into sound pool from resources.
//this.loadIntoSoundPool();
}
/**
* Plays the sound
* @param id - the sound id
* @param context - the context
*/
public void playSound(int id, final Context context) {
// Create Audio Manager using Context.
soundPool.play(id, this.volume, this.volume, 1, 0, 1f);
// Play GameSound from GameSound Pool with defined Volumes.
Log.e("SoundPool", "Game GameSound Played");
}
}</code>
有没有人遇到这个问题?非常感谢任何帮助。
答案 0 :(得分:3)
谢谢David Wasser :)
我想与大家分享最终的实现,以及目前适用于API 21和Lower的内容。
在为API 21 +构建SoundPool时发现,您必须先创建AudioAttributes:
Log.d("Sound", "Initialize Audio Attributes.");
// Initialize AudioAttributes.
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
在构建AudioAttributes后,您可以使用Sound.Builder初始化SoundPool:
Log.d("Sound", "Set AudioAttributes for SoundPool.");
// Set the audioAttributes for the SoundPool and specify maximum number of streams.
soundPool = new SoundPool.Builder()
.setAudioAttributes(attributes)
.setMaxStreams(7)
.build();
请注意,正如David Wasser指出的那样,此AudioAttributes必须与默认类的类别分开,以便处理声音,因为API 21不兼容AudioAttributes - 兼容设备因此会报告错误。我为API 21 SoundPool和AudioAttributes实现创建了一个类:
<强> SoundRecent.java 强>
import android.annotation.TargetApi;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
/**
* Created by michaelstokes on 17/05/15.
*/
public class SoundRecent {
/**
* Initialize the SoundPool for later API versions
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SoundPool initializeRecentAPISoundPool(SoundPool soundPool) {
Log.d("Sound", "Initialize Audio Attributes.");
// Initialize AudioAttributes.
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
Log.d("Sound", "Set AudioAttributes for SoundPool.");
// Set the audioAttributes for the SoundPool and specify maximum number of streams.
soundPool = new SoundPool.Builder()
.setAudioAttributes(attributes)
.setMaxStreams(7)
.build();
return soundPool;
}
}
**对于您的原始SoundClass,将调用Devices API版本以及相应的初始化程序:**
package thedronegame.group08.surrey.ac.uk.thedronegame;
import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
/**
* Created by Michael on 19/03/15.
*/
public class Sound {
/**
* The sound pool
*/
private SoundPool soundPool = null;
/**
* The current Sound.
*/
private int sound = 0;
/**
* false Boolean.
*/
private boolean loaded = false;
/**
* The context.
*/
private Context context = null;
/**
* Audio Manager.
*/
private AudioManager audioManager = null;
/**
* Literal Volume.
*/
private float literalVolume = 0;
/**
* Maximum Volume.
*/
private float maximumVolume = 0;
/**
* Volume.
*/
private float volume = 0;
/**
* A constructor for creating a new Sound object
*/
public Sound(Context context) {
this.context = context;
this.audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE);
// Set Literal Volume for Audio Manager.
this.literalVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
// Set Maximum Volume for Audio Manager.
this.maximumVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
// Set volume for GameSound Pool.
this.volume = literalVolume / maximumVolume;
}
/**
* Initialize the SoundPool for later API versions
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void initializeRecentAPISoundPool() {
Log.d("SoundPool", "Initialize recent API Sound Pool");
this.soundPool = new SoundRecent().initializeRecentAPISoundPool(this.soundPool);
}
/**
* Intialize SoundPool for older API
versions
*/
@SuppressWarnings("deprecation")
private void initializeDeprecatedAPISoundPool() {
// Initialize SoundPool.
this.soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
/**
* Load Sounds into the SoundPool.
*/
private void addSoundsToSoundPool() {
Log.d("Sound", "Load Sounds.");
int soundID = 0;
// Load Sound 1
soundID = soundPool.load(context, R.raw.blip_select2, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 2
soundID = soundPool.load(context, R.raw.pickup_coin3, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 3
soundID = soundPool.load(context, R.raw.explosion2, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 4
soundID = soundPool.load(context, R.raw.powerup8, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 5
soundID = soundPool.load(context, R.raw.powerup15, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 6
soundID = soundPool.load(context, R.raw.jump9, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
// Load Sound 7
soundID = soundPool.load(context, R.raw.powerup18, 1);
Log.d("Sound", "Sound " + soundID + " Loaded.");
}
/**
* Set the initial SoundPool.
* Call to Method differs dependent on API Version.
*/
public void setInitialSoundPool() {
Log.d("Sound", "Initialize Recent or Deprecated API SoundPool.");
// Initialize SoundPool, call specific dependent on SDK Version
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.d("Sound", "Initialize Recent API SoundPool.");
initializeRecentAPISoundPool();
}
else {
Log.d("Sound", "Initialize Old API SoundPool.");
initializeDeprecatedAPISoundPool();
}
this.soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
loaded = true;
}
});
// Add and Load sounds into SoundPool.
this.addSoundsToSoundPool();
}
/**
* Plays the sound
* @param id - the sound id
* @param context - the context
*/
public void playSound(int id, final Context context) {
Log.d("Sound", "Play GameSound " + id + 1 + ".");
soundPool.play(id + 1, this.volume, this.volume, 1, 0, 1f);
Log.d("Sound", "GameSound " + id + 1 + " Played");
}
}
答案 1 :(得分:2)
为了支持较旧的API级别,您需要将initializeRecentAPISoundPool()
中的代码封装到单独的类中。加载Sound
类时,类加载器会检查它引用的所有类是否也存在(它不加载它们,只检查它们是否存在)。在您的情况下,在较旧的API级别上,类AudioAttributes$Builder
不存在,因此类加载器无法加载您的Sound
类。
解决这个问题的方法是将仅在较新的API级别中支持的代码移动到单独的类中,并且当您知道自己在至少具有该API级别的设备上运行时,仅实例化(或使用)该类
您已经通过检查API级别并调用2种不同的方法来正确执行此操作,具体取决于设备的API级别。要完成这项工作,您只需将代码移到一个单独的类中。
注意:有趣的是,当使用现有类的较新方法时,这不是问题。类加载器在加载类时不会检查您引用的所有方法是否存在。