How to show Presentation on android Virtual Display

Android 专栏收录该内容
239 篇文章 1 订阅

from http://andronblog.com/how-to-show-presentation-on-android-virtual-display/


In this post you will see how to show Presentation on android virtual display. Two use-cases will be demonstrated in one simple android application:

How to create a virtual display rendering the content to a Surface
How to show a Presentation on this virtual display
To get the repository of Android Studio project:

git clone https://github.com/andronmobi/PresentationOnVirtualDisplay.git -b l01_virtualdisplay

Creating Virtual Display

A virtual display is created by createVirtualDisplay method of DisplayManager. In this method (among other parameters) we have to pass a surface to which the content of the virtual display will be rendered and flags varying the behaviour of the virtual display:

mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);

int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION | 
    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;

VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay("MyVirtualDisplay",
    WIDTH, HEIGHT, DENSITY_DPI, surface, flags);

But the code snippet presented above wont work if your application is not system and doesn’t have some permissions (like CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT) required for certain flags. That’s why we have to use MediaProjectionManager to ask a permission to user to “cast a screen” (to obtain MediaProjection which creates a virtual display):

mProjectionManager = (MediaProjectionManager) getSystemService(
    Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), 
    PERMISSION_CODE);
In case if a user accepts the permission to cast a screen
cast-screen-permission
it will be possible to obtain an instance of MediaProjection and to create a virtual display:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    mResultCode = resultCode;
    mResultData = data;
    if (requestCode != PERMISSION_CODE) {
        Toast.makeText(this, "Unknown request code: " + requestCode,
            Toast.LENGTH_SHORT).show();
        return;
    }
    if (resultCode != RESULT_OK) {
        Toast.makeText(this, "Screen Cast Permission Denied",
            Toast.LENGTH_SHORT).show();
        return;
    }
    Log.i(TAG, "Get media projection with the new permission");
    mProjection = getProjection();
    createVirtualDisplay();
}

private MediaProjection getProjection() {
    MediaProjection projection = mProjectionManager.getMediaProjection(mResultCode,
        mResultData);
    // Add a callback to be informed if the projection
    // will be stopped from the status bar.
    mProjectionCallback = new MediaProjection.Callback() {
        @Override
        public void onStop() {
            Log.d(TAG, "MediaProjection.Callback onStop obj:" + toString());
            destroyVirtualDisplay();
            mProjection = null;
        }
    };
    projection.registerCallback(mProjectionCallback, null);
    return projection;
}

private void createVirtualDisplay() {
    if (mProjection != null && mVirtualDisplay == null) {
        Log.d(TAG, "createVirtualDisplay WxH (px): " + mWidth + "x" + mHeight +
                ", dpi: " + mMetrics.densityDpi);
        int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
        //flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
        mVirtualDisplay = mProjection.createVirtualDisplay("MyVirtualDisplay",
                mWidth, mHeight, mMetrics.densityDpi, flags, mSurface,
                null /*Callbacks*/, null /*Handler*/);
        mButtonCreate.setEnabled(false);
        mButtonDestroy.setEnabled(true);
    }
}

private void destroyVirtualDisplay() {
    Log.d(TAG, "destroyVirtualDisplay");
    if (mVirtualDisplay != null) {
        Log.d(TAG, "destroyVirtualDisplay release");
        mVirtualDisplay.release();
        mVirtualDisplay = null;
        mButtonDestroy.setEnabled(false);
        mButtonCreate.setEnabled(true);
    }
}

Showing Presentation on Virtual Display

PresentationOnVirtualDisplay
Once a virtual display is created you can display a content on it. In our case, it will be a Presentation (android Dialog for secondary display) with LinearLayout as a content view and animated (rotating) TextView on it. To listen for changes in available display devices a DisplayListener must be registered:
mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(mDisplayListener, null);
Then, after creating a virtual display the onDisplayAdded callback will be called. Here we register the number of display ID to create a new instance of MyPresentation class later in another callback – onDisplayChanged. The presentation will be dismissed in onDisplayRemoved if the virtual display showing it is removed.

private final DisplayManager.DisplayListener mDisplayListener = 
    new DisplayManager.DisplayListener() {

    private boolean mNewDisplayAdded = false;
    private int mCurrentDisplayId = -1;
    private MyPresentation mPresentation;

    @Override
    public void onDisplayAdded(int i) {
        Log.d(TAG, "onDisplayAdded id=" + i);
        if (!mNewDisplayAdded && mCurrentDisplayId == -1) {
            mNewDisplayAdded = true;
            mCurrentDisplayId = i;
        }
    }

    @Override
    public void onDisplayRemoved(int i) {
        Log.d(TAG, "onDisplayRemoved id=" + i);
        if (mCurrentDisplayId == i) {
            mNewDisplayAdded = false;
            mCurrentDisplayId = -1;
            if (mPresentation != null) {
                mPresentation.dismiss();
                mPresentation = null;
            }
        }
    }

    @Override
    public void onDisplayChanged(int i) {
        Log.d(TAG, "onDisplayChanged id=" + i);
        if (mCurrentDisplayId == i) {
            if (mNewDisplayAdded) {
                // create a presentation
                mNewDisplayAdded = false;
                Display display = mDisplayManager.getDisplay(i);
                mPresentation = new MyPresentation(MainActivity.this, display);
                mPresentation.show();
            }
        }
    }
};

MyPresentation inner static class:

private final static class MyPresentation extends Presentation {

    public MyPresentation(Context context, Display display) {
        super(context, display);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "MyPresentation onCreate");
        setContentView(R.layout.my_presentation);

        TextView tv = (TextView) findViewById(R.id.textView);
        Animation myRotation = AnimationUtils.loadAnimation(getContext(), R.anim.rotator);
        tv.startAnimation(myRotation);
    }
}
  • 1
    点赞
  • 0
    评论
  • 4
    收藏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值