Android Mediaplayer 工作整理

这里写图片描述
一、错误码
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=");

        }
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值