I used MediaProjection
to create VirtualDisplay
to take screenshots. Afterward, I tried to release the virtualDisplay
, but it did not work:
// create virtual display...
mVirtualDisplay = sMediaProjection.createVirtualDisplay(DISPLAY, mWidth, mHeight, mDensity,
VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, null);
// release it after taking screenshot successfully
if (mImageReader != null){
mImageReader.setOnImageAvailableListener(null, null);
if (mImageReader.getSurface() != null) {
mImageReader.getSurface().release();
}
mImageReader.close();
}
if (mVirtualDisplay != null) mVirtualDisplay.release();
if (sMediaProjection != null) sMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
mVirtualDisplay = null;
mImageReader = null;
After a few minutes, I called this function displayManager.getDisplays()
--> I saw a few virtual displays that did not get released.
How to release it completely? Is there anything I missed?
P/s: it's pretty much like this question: Android VirtualDisplay.release() not releasing the display, but I could not find the solution yet.
1 line answer : virtualdisplay.release() do nothing if you create the virtualdisplay passing a null as the parameter for the callback.
I find this is a very frustating problem because all of the samples I came across on the web pass NULL for the callback parameter and yet in all of the samples, call release() without realizing it does absolutely nothing due to unclear android documentation thus the memory leak. Though I do have to mention I didn't find this problem in older Android versions
Found the answer from VirtualDisplay source code. When you are creating a VirtualDisplay, you NEED to make a VirtualDisplay.Callback and pass is as a parameter, not a NULL. because virtualDisplay.release() function checks if the token is null or not.
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/hardware/display/VirtualDisplay.java
So before you call createVirtualDisplay, make a VirtualDisplay.Callback
if you go see the VirtualDisplay class, you will find this variable and constructor
the mToken / VirtualDisplay callback on the constructor is that token that the release() function checks on whether it is null or not before calling
This is very frustating on because release() function documentation doesn't mention this at all.
So to check whether this solution works, check the number of displays and the ids before releasing the virtual display and check again after releasing it. The supposed display id should be released.