我正在制作Service
,播放从ArrayList
中挑选的歌曲。
当我使用prepare()
和prepareAsync()
方法时出现问题,所以这是代码:
public class MusicService extends Service implements MediaPlayer.OnPreparedListener{
private final static int DEF_VALUE = -1;
private Context mContext;
private ArrayList<Song> mSongsList;
private MediaPlayer mPlayer;
private boolean isPlaying = false;
private int mPosition;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate(){
super.onCreate();
mContext = getApplicationContext();
mSongsList = new ArrayList<Song>();
mPlayer = new MediaPlayer();
setMusicPlayer();
}
public void setMusicPlayer(){
//Setting player properties
mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
mPlayer.setAudioSessionId(AudioManager.STREAM_MUSIC);
mPlayer.setOnPreparedListener(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int mCommand = intent.getIntExtra("CMD", DEF_VALUE);
int mTrackSelected = intent.getIntExtra("TRACK_CLICKED", DEF_VALUE);
/** SERVICE COMMANDS
* 0 = SERVICE PERMISSIONS
* 1 = PLAY_PAUSE
* 2 = NEXT TRACK
* 3 = PREV TRACK
* 4 = SONG IN LIST
*/
switch (mCommand){
case 0:
GetTracks mGetSongs = new GetTracks();
mSongsList = mGetSongs.listAllSongs(mContext);
Log.d("test size arrayList", ""+mSongsList.size());
break;
case 1:
setPlayPause();
break;
case 2:
skipNextTrack();
break;
case 3:
skipPrevTrack();
break;
case 4:
if(mTrackSelected != DEF_VALUE){
mPosition = mTrackSelected;
setSongToPlay(mPosition);
}
break;
default:
Log.d("error cmd", "You shouldn't be here!");
break;
}
return START_STICKY;
}
private void skipPrevTrack() {
Log.d("method called:", "skipPrevTrack()");
if(mPosition == 0){
setSongToPlay(mPosition = mSongsList.size()-1);
} else setSongToPlay(--mPosition);
Log.d("test mPosition service", ""+mPosition);
}
private void skipNextTrack() {
Log.d("method called:", "skipNextTrack()");
if(mPosition == mSongsList.size()-1){
setSongToPlay(mPosition = 0);
} else setSongToPlay(++mPosition);
Log.d("test mPosition service", ""+mPosition);
}
private void setSongToPlay(int pos) {
Log.d("method called:", "setSongToPlay("+pos+")");
startSong(mSongsList.get(pos).getSongUri());
}
private void startSong(Uri uri){
try{
mPlayer.reset();
mPlayer.setDataSource(mContext, uri);
mPlayer.prepareAsync();
/** +++WORKS FINE WITH THIS CODE+++
mPlayer = MediaPlayer.create(mContext, uri);
mPlayer.start();
*/
} catch (Exception e){
e.printStackTrace();
}
}
private void setPlayPause() {
Log.d("method called:", "setPlayPause()");
}
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
}
日志:
12-19 16:12:18.325 4013-4013/sebbsoft.myApp D/method called:: setSongToPlay(3)
12-19 16:12:18.341 4013-4013/sebbsoft.myApp D/test song playing: Fiori del male ft. Sfera Ebbasta
12-19 16:12:18.363 4013-4013/sebbsoft.myApp D/MediaPlayer: setSubtitleAnchor in MediaPlayer
12-19 16:12:18.428 4013-4028/sebbsoft.myApp E/MediaPlayer: error (1, -19)
我该如何解决?
答案 0 :(得分:2)
终于解决了!经过大量的试验和错误!! 这是导致它的那条线:
mMediaPlayer.setAudioSessionId(AudioManager.STREAM_MUSIC);
setAudioSessionId的API文档并未指出仍在使用它的任何替代或任何问题,这使得难以调试。但是我在它下面看到了setAudioStreamType,不推荐使用它,建议使用setAudioAttributes,在API 21中添加w / c。
所以我将上面的代码更改为:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mMediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build());
} else {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
现在它有效!
顺便提一下,正如您所看到的,我只检查了版本N(API 24)及更高版本而不是LOLLIPOP,即使在API 21中添加了setAudioAttributes
,因为我只在Nougat设备上遇到此问题,setAudioSessionId
对我而言适用于Marshmallow设备,所以......不要打破任何已经有效的东西。
我希望有人会停下来解释为什么会发生这种情况以及错误的真正含义。
希望这可以节省任何人头痛的日子:)
修改强>
对于任何人谷歌搜索,我也将原来的mMediaPlayer.setAudioSessionId
更改为mMediaPlayer.setAudioStreamType
,正如 Eugen Pechanec 所指出的那样。详情请见他的评论和答案。
您还希望将Build.VERSION_CODES.N
与Build.VERSION_CODES.LOLLIPOP
进行核对更改。
答案 1 :(得分:2)
您未正确使用public Material skyboxMat;
voidstart(){ RenderSetting.skybox = skyboxMat;}
。
音频会话ID是此MediaPlayer实例播放的音频流的系统范围唯一标识符。
[...]
创建后, MediaPlayer实例会自动生成自己的音频会话ID 。但是,可以通过调用此方法强制此播放器成为现有音频会话的一部分。必须在其中一个重载的
setAudioSessionId
方法之前调用此方法。
您可以致电AudioManager.generateAudioSessionId()
获取音频会话ID。
如果您想要设置流类型,那么您可能正在寻找的是MediaPlayer.setAudioStreamType(int)
。
Android 5的新版API可用,MediaPlayer.setAudioAttributes(AudioAttibutes)
。
答案 2 :(得分:0)
确保您不会同时激活太多//show similar product
var categoryItems = [];
//filter random product by product title
var prodTitle = $('#productTitle').text();
$.each(json, function(i, item){
if (prodTitle.indexOf("Tomatoes") !=-1) {
if(item.itemCommodity == '1120' && item.itemBrandLetter == "C") categoryItems.push(item);
}
});
var similarProduct= '';
$.each(json, function(i,item){
similarProduct = categoryItems[Math.floor(Math.random()*categoryItems.length)];
similarProduct = '<div>' + '<a href="#" class="showProduct"' + 'data-itempageurl="' + similarProduct.itemFullUPC + '"' + 'data-itemgmo="' + similarProduct.itemGMOFree + '"' + 'data-itembpa="' + similarProduct.itemBPAFree + '"' + 'data-itemgluten="' + similarProduct.itemGlutenFree + '"' + 'data-itemlowsodium="' + similarProduct.itemLowSodium + '"' + 'data-itemorganic="' + similarProduct.itemOrganic + '"' + 'data-itemimage="' + similarProduct.imageURL + '"' + 'data-itemname="' + similarProduct.itemName + '"' + 'data-itemoz="' + similarProduct.itemPackSize + '"' + 'data-itemdescription="' + similarProduct.itemDescription + '"' + 'data-itemupc="' + similarProduct.itemFullUPC + '"' + '>' + '<img class="img-responsive img-hover similarProductImagesCategory" src="' + similarProduct.imageURL + '">' + '<h3 class="similarProductSubCategoryImgCaption">' + similarProduct.itemName + '</h3>' + '</a>' + '</div>';
});
$('#productSimilar').append(similarProduct);
个对象。
实施MediaPlayer
并将其注册到您的OnCompletionListener
实例。
在播放期间到达媒体源结束时调用MediaPlayer
。
onCompletion
完成播放所有文件后,释放void onCompletion(MediaPlayer mp){
//Here you stop it.
mp.stop();
mPlayer.reset()
//Reset the data source path to the new file
mp.setDataSource(<uri>);
mPlayer.prepare(); // or mPlayer.prepareAsync();
// start the mediaplayer after the prepare has completed.
}
实例。
可能是你的听众只听一次,然后当它试图播放下一个没有准备然后它可能会崩溃..试试这个
添加此项 - &gt;在mediaplayer
mPlayer.setOnPreparedListener(this);
方法startSong()
答案 3 :(得分:0)
我有同样的问题。将许多不同的音频上传到Mediaplayer。
15次停止工作后。
在每次在同一Mediaplayer中上传新音频之前,我每次都添加发布,这对我有用!
没有更多错误(1,-19)
希望有帮助!
答案 4 :(得分:0)
我遇到了同样的问题,我通过添加以下代码来释放播放器来解决它:
1- 获取音频使用资产文件
MediaPlayer mediaPlayer = new MediaPlayer();
AssetFileDescriptor afd;
mediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
mediaPlayer.prepare();
mediaPlayer.start();
mp1.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();}; });
2- 使用 res/raw 文件夹获取音频。
mp1 = MediaPlayer.create(sound.this, R.raw.pan1);
mp1.start();
mp1.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}; });