fix: images.captureScreen() return null or throw exception when called too often

This commit is contained in:
hyb1996 2017-10-30 19:05:57 +08:00
parent bb7adfa5f5
commit bfd6a0c40a
2 changed files with 28 additions and 46 deletions

View File

@ -2,7 +2,8 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Auto.js.iml" filepath="$PROJECT_DIR$/Auto.js.iml" />
<module fileurl="file://E:\YiBin\AndroidStudioProjects\NoRootScriptDroid\Auto.js.iml" filepath="E:\YiBin\AndroidStudioProjects\NoRootScriptDroid\Auto.js.iml" />
<module fileurl="file://$PROJECT_DIR$/NoRootScriptDroid.iml" filepath="$PROJECT_DIR$/NoRootScriptDroid.iml" />
<module fileurl="file://C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" filepath="C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/autojs/autojs.iml" filepath="$PROJECT_DIR$/autojs/autojs.iml" />

View File

@ -32,13 +32,12 @@ public class ScreenCapturer {
private VirtualDisplay mVirtualDisplay;
private volatile Looper mImageAcquireLooper;
private final Object mImageWaitingLock = new Object();
private volatile Image mImage;
private volatile Image mLatestImage;
private volatile Image mUnderUsingImage;
private volatile Image mCachedImage;
private final int mScreenWidth;
private final int mScreenHeight;
private final int mScreenDensity;
private Handler mHandler;
private volatile boolean mImageAvailable = false;
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity, Handler handler) {
mScreenWidth = screenWidth;
@ -60,7 +59,7 @@ public class ScreenCapturer {
}
private void initVirtualDisplay(MediaProjectionManager manager, Intent data, int screenWidth, int screenHeight, int screenDensity) {
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 1);
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
mMediaProjection = manager.getMediaProjection(Activity.RESULT_OK, data);
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
@ -87,50 +86,23 @@ public class ScreenCapturer {
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
if (mImageAvailable) {
if (mCachedImage != null) {
return;
}
mLatestImage = reader.acquireLatestImage();
if (mLatestImage != null) {
mImageAvailable = true;
synchronized (mImageWaitingLock) {
mImageWaitingLock.notify();
}
}
mCachedImage = reader.acquireLatestImage();
}
}, handler);
}
@Nullable
public Image capture() {
if (!mImageAvailable) {
waitForImageAvailable();
return mLatestImage;
}
if (mLatestImage != null) {
tryClose(mLatestImage);
}
mLatestImage = mImageReader.acquireLatestImage();
return mLatestImage;
}
private void tryClose(Image image) {
try {
image.close();
} catch (Exception ignored) {
}
}
private void waitForImageAvailable() {
Log.d(LOG_TAG, "waitForImageAvailable");
synchronized (mImageWaitingLock) {
try {
mImageWaitingLock.wait();
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
if (mCachedImage != null) {
if (mUnderUsingImage != null)
mUnderUsingImage.close();
mUnderUsingImage = mCachedImage;
mCachedImage = null;
}
return mUnderUsingImage;
}
public int getScreenWidth() {
@ -147,6 +119,9 @@ public class ScreenCapturer {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void release() {
if (mImageAcquireLooper != null) {
mImageAcquireLooper.quit();
}
if (mMediaProjection != null) {
mMediaProjection.stop();
}
@ -156,14 +131,20 @@ public class ScreenCapturer {
if (mImageReader != null) {
mImageReader.close();
}
if (mImageAcquireLooper != null) {
mImageAcquireLooper.quit();
if (mUnderUsingImage != null) {
mUnderUsingImage.close();
}
if (mImage != null) {
mImage.close();
if (mCachedImage != null) {
mCachedImage.close();
}
if (mLatestImage != null) {
mLatestImage.close();
}
@Override
protected void finalize() throws Throwable {
try {
release();
} finally {
super.finalize();
}
}
}