一、错误码
1.(-38,0)
这个问题是由于在不对的状态底下调用了不该调用的方法。比方说:
在prepareAsyc的过程中在调用start,
在prepare的过程中切换streamType。
在相应的状态下只能调用相应的方法才不会出错。
工作中遇到的情况:
在抢了音频焦点的时候,这时候开始prepareAsync,还没有到达Prepared的状态,就接收到了音频焦点Gain(1)的回调,这个时候我直接调用start导致-38的问题
2.(-1004,0)
这个问题是由于服务器返回的状态码不对。(当然可能还由于其他问题导致,这里只是自己遇到的一种情况)
由于在自己本地搭建了一个服务,即Mediaplayer中设置的路径都为127.0.0.1的形式所以可以监控到Mediaplayer的请求头,和组装给Mediaplayer的响应头。所以发现了这个问题。
二:使用Mediaplayer的过程中的发现点
1.Mediaplayer不支持opus的解码,故不支持opus的播放,这里可以替换FFmpeg来进行解码,这样就需要替换播放器,IJKPlayer开源项目,你值得拥有
2.Mediaplayer请求数据在不同的设备,请求的方式基本相同,即先请求头部和尾部的一点数据,用于解码,故可以看图片。
缓冲条就是Mediaplayer进行请求的缓冲区域
3.Mediaplayer的重试机制:一般在Mediaplayer发出请求,收取不到响应的时候就会重新请求,如果需要达到请求的时候,不至于因为其他的操作导致mediaplayer的重新请求,这个时候可以返回空包给到Mediaplayer进行响应,printEmptyData(byte[] EMPTY_DATA = new byte[0])。
4.在有一些设备上,会收到其他应用使用Mediaplayer导致的错误,故此时需要判断该Mediaplayer是否是自己的使用的Mediaplayer导致的错误
5.音频焦点的处理,多次注册相同的音频焦点,会导致在某些情况下系统回调音频焦点的方式只有丢失,没有恢复的方式
6.媒体按键的注册,音频焦点和媒体按键是属于两种不同的形式,在Android-19之前的版本不区分,之后区分,注册的方式和模拟发送的方式都不一样
模拟发送的方式:
keycode的取值有KeyEvent的枚举类。
可以使用adb shell进行模拟:
adb shell input keyevent 87
使用代码模拟发送
if (Build.VERSION.SDK_INT >= 19) {
if (null == sAudioManager) {
sAudioManager = (AudioManager) GlobalContext.get()
.getSystemService(Context.AUDIO_SERVICE);
}
sAudioManager.dispatchMediaKeyEvent(new KeyEvent(
KeyEvent.ACTION_DOWN, keycode));
sAudioManager.dispatchMediaKeyEvent(new KeyEvent(
KeyEvent.ACTION_UP, keycode));
} else {
dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
keycode));
dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
keycode));
}
应用响应的方式:
AndroidManifest中注册
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<service
android:name="com.txznet.music.service.MediaPlaybackService"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
代码:
package com.txznet.music.service;
import java.util.List;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
import android.support.v4.media.MediaBrowserServiceCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import com.txznet.comm.remote.util.LogUtil;
import com.txznet.music.engine.MediaPlayerActivityEngine;
import com.txznet.music.ui.MediaPlayerActivity;
public class MediaPlaybackService extends MediaBrowserServiceCompat {
public static String TAG = MediaPlaybackService.class.getSimpleName();
@Override
public IBinder onBind(Intent intent) {
return null;
}
private MediaSessionCompat mSession;
@Override
public void onCreate() {
super.onCreate();
LogUtil.logd(TAG + ":onCreate");
mSession = new MediaSessionCompat(this, "MusicService");
setSessionToken(mSession.getSessionToken());
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
Intent intent = new Intent(this, MediaPlayerActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 99 /* request code */,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
mSession.setSessionActivity(pi);
mSession.setCallback(new MediaSessionCallback());
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(getAvailableActions())
.setState(PlaybackStateCompat.STATE_PLAYING, 1, 1.0f,
SystemClock.elapsedRealtime())
.setActiveQueueItemId(Math.round(Integer.MAX_VALUE)).build());
mSession.setActive(true);
}
@Override
public void onDestroy() {
LogUtil.logd(TAG + ":onDestroy");
super.onDestroy();
mSession.setCallback(null);
mSession.setActive(false);
mSession.release();
}
private long getAvailableActions() {
long actions = PlaybackStateCompat.ACTION_PLAY
| PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
actions |= PlaybackStateCompat.ACTION_PAUSE;
return actions;
}
public int onStartCommand(Intent intent, int flags, int startId) {
MediaButtonReceiver.handleIntent(mSession, intent);
LogUtil.logd(TAG + ":onstartCommand");
return super.onStartCommand(intent, flags, startId);
}
public static final String MEDIA_ID_ROOT = "__ROOT__";
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName,
int clientUid, Bundle rootHints) {
Log.d(TAG, "OnGetRoot: clientPackageName=" + clientPackageName
+ "; clientUid=" + clientUid + " ; rootHints=");
return new BrowserRoot(MEDIA_ID_ROOT, null);
}
@Override
public void onLoadChildren(@NonNull final String parentMediaId,
@NonNull final Result<List<MediaItem>> result) {
Log.d(TAG, "OnLoadChildren: parentMediaId=" + parentMediaId);
}
private class MediaSessionCallback extends MediaSessionCompat.Callback {
@Override
public void onPlay() {
LogUtil.logd(TAG + ":play");
MediaPlayerActivityEngine.getInstance().play();
}
@Override
public void onSkipToQueueItem(long queueId) {
Log.d(TAG, "OnSkipToQueueItem:" + queueId);
}
@Override
public void onSeekTo(long position) {
Log.d(TAG, "onSeekTo:");
}
@Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
Log.d(TAG, "playFromMediaId mediaId:");
}
@Override
public void onPause() {
Log.d(TAG, "pause. current state=");
MediaPlayerActivityEngine.getInstance().pause();
}
@Override
public void onStop() {
Log.d(TAG, "stop. current state=");
MediaPlayerActivityEngine.getInstance().stop();
}
@Override
public void onSkipToNext() {
Log.d(TAG, "skipToNext");
MediaPlayerActivityEngine.getInstance().next();
}
@Override
public void onSkipToPrevious() {
Log.d(TAG, "skipToPrev");
MediaPlayerActivityEngine.getInstance().last();
}
@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
}
@Override
public void onPlayFromSearch(final String query, final Bundle extras) {
Log.d(TAG, "playFromSearch query=");
}
}
}