现在的位置: 首页 > 综合 > 正文

Android 播放器二次封装与实现

2017年10月04日 ⁄ 综合 ⁄ 共 3195字 ⁄ 字号 评论关闭

视频播放、音频播放在Android平台的应用非常广泛,最近正好学习研究了一下播放器层面的Android实现,

对底层播放器做了二次的封装,主要进行的工作如下:

 

§ 主要实现

1、播放控制
(1)简化播放接口处理
(2)增加一些友好型播控接口:快退、快进、重新播放等。
(3)单视频、多视频列表播放
2、播放状态
(1)播放状态控制
(2)播放状态调用时及时反馈
(3)较全的播放信息,通过回调接口隔时通知
(4)视频缓冲动画自动处理
(5)播放显示画面尺寸、位置自由设定
(6)播放HTTP源时,支持Headers设置
(7)增加快退、快进开关
3、其他
(1)音量控制
(2)视频源广告支持
4、待补充完善
(1)资源单独进行预加载


§ MediaPlayer状态机参考


§ 主要结构设计

 1、主要接口

IPlayController:负责播放控制
IPlayerUI:负责播放控制的UI处理
IPlaySetter:负责播放控制的参数设置
IPlayerEventListener:播放回调事件通知接口
MediaPlayerEvent:播放事件载体

2、适配、分发、通知线程

MediaPlayerAdapter:原生态播放器适配
NotifyEventThread:回调通知监听线程
PlayDispatcher:播放器外观分发处理

3、构造、处理、状态

 

PlayerBuilder:构造播放器基础信息,用户接口
PlayerHandler:主线程操作处理
StatusCommander:播放控制命令状态处理
VolumeController:音量控制处理

4、外观、状态、UI

WMediaPlayer:播放器外观层
PlayContext:播放器上下文
StatusResolver:播放器实时状态信息
UIHandler:负责UI效果处理

 

§ 源码下载

为方便需要的朋友进一步的进行定制,先将实现的代码提供给大家,附带了DEMO示例。点击下载

部分示例代码:

public class MainActivity extends Activity implements OnClickListener {

	public static final String playUrl = "/mnt/sdcard/test.mp4";
	private WMediaPlayer player = new WMediaPlayer();
	private SurfaceView sv = null;
	private TextView txtStatus;
	private SeekBar seekbar = null;
	private ProgressBar progressBar = null;
	private Button btnPlay, btnPause, btnUnPause, btnStop, btnReplay,
			btnVolume, btnStatus, btnClose, btnSeekUp, btnSeekDown, btnLoad;
	private int volume = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		init();

		// Intent it = new Intent(getBaseContext(), PlayerActivity.class);
		// startActivity(it);

		sv = (SurfaceView) findViewById(R.id.surfaceView1);
		SurfaceHolder sh = sv.getHolder();
		sh.addCallback(sc);
	}

	private SurfaceHolder.Callback sc = new SurfaceHolder.Callback() {
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			// test
			PlayerBuilder builder = PlayerBuilder.getInstance();
			builder.setContext(getBaseContext());
			builder.setSurfaceView(sv);
			// builder.setVolumeBar(seekbar);
			builder.setVolumeBar(progressBar);
			builder.setLoadingAnim(LoadAnimType.Animation, R.anim.loads_redload);
			builder.setEventListener(eventListener);

			player.setBuilder(builder);
			player.setPlayUrl(playUrl);
			// player.setPlayList();
			player.play();
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
		}
	};

	IPlayerEventListener eventListener = new IPlayerEventListener() {
		@Override
		public void onMediaPlayerEvent(MediaPlayerEvent event) {

		}
	};

	@Override
	protected void onDestroy() {
		player.destroy();
		super.onDestroy();
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.btnPlay:
			player.play();
			break;
		case R.id.btnPause:
			player.pause();
			break;
		case R.id.btnUnPause:
			player.unpause();
			break;
		case R.id.btnStop:
			player.stop();
			break;
		case R.id.btnClose:
			player.close();
			break;
		case R.id.btnReplay:
			player.replay();
			break;
		case R.id.btnSeekUp:
			player.seek(player.getStatusResolver().getCurTime() + 30);
			break;
		case R.id.btnSeekDown:
			player.seek(player.getStatusResolver().getCurTime() - 30);
			break;
		case R.id.btnVolume:
			volume++;
			player.getVolumeController().setVolume(volume);
			// player.getPlayer().setVolume(0.5f, 0.5f);
			break;
		case R.id.btnStatus:
			String status = Utils.gson.toJson(player.getStatusResolver());
			txtStatus.setText(status);
			break;
		case R.id.btnLoad:
			UIHandler.getInstance()
					.showLoading(
							PlayerBuilder.getInstance().getPlayContext()
									.getAnimResId());
			break;
		default:
			break;
		}
	}

抱歉!评论已关闭.