Android 扩展屏幕 实现主屏副屏同步或者异步显示

android的扩展屏幕是通过Presentation 类实现的。
Presentation继承自Dialog。
【Android 扩展屏幕 实现主屏副屏同步或者异步显示】

  • 主屏显示的代码
  • 主屏播放一个video3的视频 。video3在项目的 assets文件里 可以随便拷贝一个放进去。
import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaRouter; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.ImageButton; import com.xinyintai.guoruiyibushow.R; import java.io.IOException; /** * 用于测试android 异步播放。 * * 主界面 lvds 信号播放的界面。 */public class MainActivity extends Activity { private MediaRouter mMediaRouter; private DemoPresentation mPresentation; int flag = 2; //1 绿色同步 2 蓝色异步private SurfaceView surfaceView; private MediaPlayer mediaPlayer1; ImageButton bt; String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 得到media router service. mMediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE); setContentView(R.layout.activity_main); //监听media rotues的改变 mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback); initMainPlay(); //主屏幕 updatePresentation(); //扩展屏幕 }//主屏幕播放 video3视频 private void initMainPlay() { mediaPlayer1 = new MediaPlayer(); surfaceView = this.findViewById(R.id.surface1); bt = findViewById(R.id.iv_state); surfaceView.getHolder().setKeepScreenOn(true); surfaceView.getHolder().addCallback(new SurfaceViewLis()); mediaPlayer1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { play(); } }); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (flag == 1) {//绿色异步 try { mPresentation.show(); //异步让这个dialog展示 } catch (WindowManager.InvalidDisplayException ex) { // Log.w(TAG, "Couldn't show presentation!Display was removed in "+ "the meantime.", ex); mPresentation = null; } bt.setBackground(getResources().getDrawable(R.drawable.circle_blue)); flag = 2; } else if (flag == 2) {//蓝色同步 mPresentation.dismiss(); //同步让presentation消失 bt.setBackground(getResources().getDrawable(R.drawable.circle_green)); flag = 1; } } }); }public void play() { mediaPlayer1.reset(); mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mediaPlayer1.setDataSource(this, Uri.parse("android.resource://" + "com.xinyintai.guoruiyibushow" + "/" + R.raw.video3)); // 把视频输出到SurfaceView上 mediaPlayer1.setDisplay(surfaceView.getHolder()); mediaPlayer1.prepare(); mediaPlayer1.start(); } catch (IOException e) { e.printStackTrace(); }}private class SurfaceViewLis implements SurfaceHolder.Callback { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }@Override public void surfaceCreated(SurfaceHolder holder) {try { play(); mediaPlayer1.seekTo(0); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } }@Override public void surfaceDestroyed(SurfaceHolder holder) {}}@Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); }private final MediaRouter.SimpleCallback mMediaRouterCallback = new MediaRouter.SimpleCallback() { @Override public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) { Log.e(TAG, "onRouteSelected: type=" + type + ", info=" + info); updatePresentation(); }@Override public void onRouteUnselected(MediaRouter router, int type, MediaRouter.RouteInfo info) { Log.e(TAG, "onRouteeUnselected: type=" + type + ", info=" + info); updatePresentation(); }@Override public void onRoutePresentationDisplayChanged(MediaRouter router, MediaRouter.RouteInfo info) { Log.e(TAG, "onRoutePresentationDisplayChanged: info=" + info); updatePresentation(); } }; //准备异步的界面 private void updatePresentation() { // Get the current route and its presentation display. MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); Display presentationDisplay = route != null ? route.getPresentationDisplay() : null; // 如果屏幕显示改变了 让当前的扩展屏消失 if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { //Log.i(TAG, "Dismissing presentation because the current route no longer "+ "has a presentation display."); mPresentation.dismiss(); mPresentation = null; }//创建一个扩展屏 if (mPresentation == null && presentationDisplay != null) { Log.e(TAG, "Showing presentation on display: " + presentationDisplay); mPresentation = new DemoPresentation(this, presentationDisplay); mPresentation.setOnDismissListener(mOnDismissListener); mPresentation.show(); }updateContents(); }//更新主界面中的内容 private void updateContents() {}/** * 监听 副屏界面的消失 更新主界面。 */ private final DialogInterface.OnDismissListener mOnDismissListener = new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { if (dialog == mPresentation) { //Log.i(TAG, "Presentation was dismissed."); mPresentation = null; updateContents(); } } }; }

  • 主界面的布局 一个surfaceview用来播放视频。imagebutton用来切换同步异步的按钮。
*imagebutton的按钮background的背景。改一个绿色和蓝色的颜色即可


  • 副屏的展示界面
  • 副屏是用HDMI给的信号。
  • 副屏的播放一个video的视频 。video在项目的 assets文件里 可以随便拷贝一个放进去。
import android.app.Presentation; import android.content.Context; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.xinyintai.guoruiyibushow.R; import java.io.IOException; import static android.content.ContentValues.TAG; /** * 用于测试android 异步播放。 * * 副屏界面hdmi信号口 */public class DemoPresentation extends Presentation { private SurfaceView surfaceView; private MediaPlayer mediaPlayer1; boolean isLeave = true; public DemoPresentation(Context context, Display display) { super(context, display); }@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.presentation_content); // Set up the surface view for visual interest. mediaPlayer1 = new MediaPlayer(); surfaceView = this.findViewById(R.id.surface2); surfaceView.getHolder().setKeepScreenOn(true); surfaceView.getHolder().addCallback(new SurfaceViewLis()); mediaPlayer1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if (isLeave) { play("android.resource://" + "com.xinyintai.guoruiyibushow" + "/" + R.raw.video); } } }); }public void pause() { mediaPlayer1.pause(); }public void play(String path) { if (surfaceView != null) { mediaPlayer1.reset(); mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mediaPlayer1.setDataSource(getContext(), Uri.parse(path)); // 把视频输出到SurfaceView上 mediaPlayer1.setDisplay(surfaceView.getHolder()); mediaPlayer1.prepare(); mediaPlayer1.start(); } catch (IOException e) { e.printStackTrace(); } }}private class SurfaceViewLis implements SurfaceHolder.Callback { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }@Override public void surfaceCreated(SurfaceHolder holder) { Log.e(TAG, "surfaceCreated: surfaceivew产生了"); try { play("android.resource://" + "com.xinyintai.guoruiyibushow" + "/" + R.raw.video); mediaPlayer1.seekTo(0); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } }@Override public void surfaceDestroyed(SurfaceHolder holder) {}}@Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); isLeave = false; Log.e(TAG, "onDetachedFromWindow: 副屏消失了"); }@Override public void onAttachedToWindow() { super.onAttachedToWindow(); Log.e(TAG, "onAttachedToWindow: 副屏显示了"); isLeave = true; }@Override protected void onStop() { super.onStop(); } }


  • 副屏的布局只有一个surfaceview用来播放视频


这样就实现了主屏和副屏同时播放视频。可以在主屏通过按钮。切换同步或者异步播放的功能。

    推荐阅读