Android Api Demos登顶之路(十三)Presentation With Media Router

这个Demo演示了presentation的另一种选择Display的方式:利用MediaRouterAPI。
媒体路由服务一直保持着对系统中可用的音频和视频路由的追踪。当媒体路由被选择或取消选择或者路由首选的presentation显示屏幕发生变化时,它都会发送通知消息。所以一个应用程序可以非常简单地观察这些通知消息来并自动地在首选的presentation显示屏幕上显示或撤消一个presentation。
定义presentation的布局文件,在这里定义了一个android.opengl.GLSurfaceView,用于显示3D视图,还定义了一个显示当前display基本信息的textView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <android.opengl.GLSurfaceView
        android:id="@+id/surface_view_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4"/>
    <TextView 
        android:id="@+id/tv_display_info"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="text"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:gravity="center"/>

</LinearLayout>

定义DemoPresentation类继承Presentation

public class DemoPresentation extends Presentation {
    private GLSurfaceView surface_view;
    private TextView tv_dipaly_info;
    private Display display;

    public DemoPresentation(Context outerContext, Display display) {
        super(outerContext, display);
        this.display=display;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.presentation_content);
        surface_view=(GLSurfaceView) findViewById(R.id.surface_view_content);
        tv_dipaly_info=(TextView) findViewById(R.id.tv_display_info);
        //加载并渲染长方体模型
        surface_view.setRenderer(new CubeRenderer());
        tv_dipaly_info.setText("与prsentation相关联的屏幕是:"+display.getName());
    }

    public GLSurfaceView getSurface_view() {
        return surface_view;
    }

}

在这里我们用到了一个矩形的3D模型,所以我们需要创建出这个长方体的立体模型。

/**
 * 定义一个3D模型,实现GLSurfaceView.Renderer接口,该接口是一个专门用于渲染3D的接口
 * 实现该接口必须重载三个方法
 * @author aaaa
 *
 */
public class CubeRenderer implements Renderer {

    float box[] = new float[] {  
                // FRONT   
                -0.5f, -0.5f,  0.5f,  
                 0.5f, -0.5f,  0.5f,  
                -0.5f,  0.5f,  0.5f,  
                 0.5f,  0.5f,  0.5f,  
                // BACK   
                -0.5f, -0.5f, -0.5f,  
                -0.5f,  0.5f, -0.5f,  
                 0.5f, -0.5f, -0.5f,  
                 0.5f,  0.5f, -0.5f,  
                // LEFT   
                -0.5f, -0.5f,  0.5f,  
                -0.5f,  0.5f,  0.5f,  
                -0.5f, -0.5f, -0.5f,  
                -0.5f,  0.5f, -0.5f,  
                // RIGHT   
                 0.5f, -0.5f, -0.5f,  
                 0.5f,  0.5f, -0.5f,  
                 0.5f, -0.5f,  0.5f,  
                 0.5f,  0.5f,  0.5f,  
                // TOP   
                -0.5f,  0.5f,  0.5f,  
                 0.5f,  0.5f,  0.5f,  
                 -0.5f,  0.5f, -0.5f,  
                 0.5f,  0.5f, -0.5f,  
                // BOTTOM   
                -0.5f, -0.5f,  0.5f,  
                -0.5f, -0.5f, -0.5f,  
                 0.5f, -0.5f,  0.5f,  
                 0.5f, -0.5f, -0.5f,  
            };  

        FloatBuffer cubeBuff;  
        private boolean mTranslucentBackground;

        float xrot = 0.0f;  
        float yrot = 0.0f;  

        public CubeRenderer(boolean mTranslucentBackground) {
            super();
            this.mTranslucentBackground = mTranslucentBackground;
            cubeBuff = makeFloatBuffer(box);  
        }

        /** 
         * 将float数组转换存储在字节缓冲数组 
         * @param arr 
         * @return 
         */  
        public FloatBuffer makeFloatBuffer(float[] arr) {  
            ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);   
            bb.order(ByteOrder.nativeOrder());    
            FloatBuffer fb = bb.asFloatBuffer();    
            fb.put(arr);      
            fb.position(0);       
            return fb;  
        }  

        public CubeRenderer() {  
            // TODO Auto-generated constructor stub   
            cubeBuff = makeFloatBuffer(box);//转换float数组   
        }  


        protected void init(GL10 gl) {  
            gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   
           if(mTranslucentBackground){
                gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            }else{
                gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
            }

            gl.glEnable(GL10.GL_DEPTH_TEST);   
            gl.glEnable(GL10.GL_CULL_FACE);  
            gl.glClearDepthf(1.0f);      
            gl.glDepthFunc(GL10.GL_LEQUAL);       
            gl.glShadeModel(GL10.GL_SMOOTH);  

        }  

        /**
         * 创建时调用,通常在此进行初始化设置
         */
        @Override  
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
            // TODO Auto-generated method stub   
            init(gl);  
        }  

        /**
         * 视窗改变时调用,通常在此设置视窗范围以及透视,投影范围  
         */
        @Override  
        public void onSurfaceChanged(GL10 gl, int w, int h) {  
            // TODO Auto-generated method stub   
            gl.glViewport(0, 0, w, h);    
            gl.glMatrixMode(GL10.GL_PROJECTION);    
            gl.glLoadIdentity();           
            GLU.gluPerspective(gl, 45.0f, ((float) w) / h, 0.1f, 10f);    
        }  

        /**
         * 渲染绘图操作,重绘时调用
         */
        @Override  
        public void onDrawFrame(GL10 gl) {  
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  

            gl.glMatrixMode(GL10.GL_MODELVIEW);    
            gl.glLoadIdentity();   
            GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);   

            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff); 
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  

            gl.glRotatef(xrot, 1, 0, 0);    
            gl.glRotatef(yrot, 0, 1, 0);  

            gl.glColor4f(1.0f, 0, 0, 1.0f);      
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);  

            gl.glColor4f(0, 1.0f, 0, 1.0f);  
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);  
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);  

            gl.glColor4f(0, 0, 1.0f, 1.0f);  
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);  
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);  

            xrot += 1.0f;  
            yrot += 0.5f;  
        }  

}

创建主布局文件:activity.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:background="#ffee89">

    <TextView
        android:id="@+id/tv_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <android.opengl.GLSurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

MainActivity

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private TextView tv_show;
    // 定义一个GLSurfaceView类,用于显示3D视图
    private GLSurfaceView surface_view;
    private MediaRouter mMediaRouter;
    private DemoPresentation mPresentation;
    //应用是否是可见状态的标志位
    private boolean mPaused;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*
         * 获取到媒体路由,当媒体路由被选择或取消选择或者路由首选的presentation显示屏幕发生变化时,
         * 它都会发送通知消息。一个应用程序可以非常简单通过地观察这些通知消息来自动地在首选的presentation
         * 显示屏幕上显示或隐藏一个presentation。
         */
        mMediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);

        tv_show = (TextView) findViewById(R.id.tv_show);
        surface_view = (GLSurfaceView) findViewById(R.id.surface_view);
        // 设置我们要渲染的图形为CubeRenderer,一个矩形3D模型
        surface_view.setRenderer(new CubeRenderer());
    }

    @Override
    protected void onResume() {
        super.onResume();
        //设置对媒体路由变化的监听
        mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mRouteCallBack);
        updatePresentation();
        mPaused=false;
        updatePresentation();
    }

    private MediaRouter.SimpleCallback mRouteCallBack=new MediaRouter.SimpleCallback(){

        @Override
        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
            super.onRouteSelected(router, type, info);
            updatePresentation();
        }

        @Override
        public void onRouteUnselected(MediaRouter router, int type,
                RouteInfo info) {
            super.onRouteUnselected(router, type, info);
            updatePresentation();
        }

        @Override
        public void onRouteChanged(MediaRouter router, RouteInfo info) {
            super.onRouteChanged(router, info);
            updatePresentation();
        }

    };



    @Override
    protected void onPause() {
        super.onPause();
        mPaused=true;
        //取消媒体路由的监听
        mMediaRouter.removeCallback(mRouteCallBack);
        //更新显示内容
        updateContents();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mPresentation!=null){
            mPresentation.dismiss();
            mPresentation=null;
        }
    }

    private void updatePresentation() {
        //获取到被选中的媒体路由,类型为视频路由
        MediaRouter.RouteInfo route = mMediaRouter
                .getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
        //获取到路由推荐的presentation display
        Display presentationDisplay=route!=null ? route.getPresentationDisplay():null;
        if(presentationDisplay==null){
            Log.i(TAG,"没有找到视频路由推荐的display");
        }else{
            Log.i(TAG,presentationDisplay.getName());
        }
        //如果presentation已经存在且它的显示屏不是媒体路由推荐的显示屏,则取消presentation
        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;
        }
        //显示resentation
        if(mPresentation==null && presentationDisplay!=null){
            mPresentation=new DemoPresentation(this, presentationDisplay);
            //设置presentation的解除监听
            mPresentation.setOnDismissListener(mPresentationDismissListener);
            mPresentation.show();
        }
        updateContents();
    }

    /**
     * 更新presentation中显示的内容,如果presentation已经创建并显示则将内容显示在presentation上
     * 如果没有创建presentation则将内容显示在主屏幕上
     */
    private void updateContents() {
        //显示在次级屏蔽上
        if(mPresentation!=null){
            tv_show.setText("在屏幕:"+mPresentation.getDisplay().getName()+"中显示presentation的内容。");
            //隐藏主屏幕的surfaceView
            surface_view.setVisibility(View.INVISIBLE);
            surface_view.onPause();
            //如果当前应用处于不可见状态
            if(mPaused){
                mPresentation.getSurface_view().onPause();
            }else{
                mPresentation.getSurface_view().onResume();
            }
        }else {
            //将内容显示到本机屏幕上
            tv_show.setText("在本机屏幕:"+getWindowManager().getDefaultDisplay().getName()+"中显示内容。");
            surface_view.setVisibility(View.VISIBLE);
            if(mPaused){
                surface_view.onPause();
            }else{
                surface_view.onResume();
            }
        }
    }

    private OnDismissListener mPresentationDismissListener=new OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialog) {
            if(dialog==mPresentation){
                mPresentation=null;
                updateContents();
            }
        }
    };

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值