fix exception when captureScreen called frequently

This commit is contained in:
hyb1996 2017-06-28 15:21:03 +08:00
parent 97ff7e49a1
commit a363d140da
3 changed files with 73 additions and 17 deletions

View File

@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid"
minSdkVersion 19
targetSdkVersion 23
versionCode 139
versionName "2.0.13 Alpha2"
versionCode 140
versionName "2.0.13 Alpha3"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
ndk {

View File

@ -13,6 +13,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
@ -39,7 +40,7 @@ public class SublimePluginClient {
private String host;
private int port;
private OutputStream mOutputStream;
private Executor mExecutor;
private ExecutorService mExecutor;
public SublimePluginClient(String host, int port) {
this.host = host;
@ -105,8 +106,10 @@ public class SublimePluginClient {
public void close() throws IOException {
if (mSocket != null) {
mSocket.close();
mExecutor.shutdownNow();
mSocket = null;
mOutputStream = null;
mExecutor = null;
EventBus.getDefault().post(new ConnectionStateChangeEvent(false));
}
}

View File

@ -13,23 +13,34 @@ import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.widget.ImageView;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.util.ScreenMetrics;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Stardust on 2017/5/17.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class ScreenCapturer {
private static final String LOG_TAG = "ScreenCapturer";
private ImageReader mImageReader;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private Image mImage;
private volatile Looper mImageAcquireLooper;
private final Object mImageWaitingLock = new Object();
private volatile Image mImage;
private volatile Image mLatestImage;
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity) {
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
startAcquireImageLoop();
}
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) {
@ -41,32 +52,65 @@ 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,
mImageReader.getSurface(), null, null);
}
private void startAcquireImageLoop() {
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mImageAcquireLooper = Looper.myLooper();
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
if (mLatestImage != null) {
mLatestImage.close();
}
mLatestImage = reader.acquireNextImage();
if (mLatestImage != null) {
synchronized (mImageWaitingLock) {
mImageWaitingLock.notify();
}
}
}
}, null);
Looper.loop();
}
}).start();
}
public Image capture() {
if (mLatestImage == null) {
if (mImage != null) {
return mImage;
}
waitForImageAvailable();
}
if (mImage != null) {
mImage.close();
}
mImage = mImageReader.acquireLatestImage();
if (mImage == null) {
Looper.prepare();
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Looper.myLooper().quit();
}
}, null);
Looper.loop();
mImage = mImageReader.acquireLatestImage();
}
mImage = mLatestImage;
mLatestImage = null;
return mImage;
}
private void waitForImageAvailable() {
Log.d(LOG_TAG, "waitForImageAvailable");
synchronized (mImageWaitingLock) {
try {
mImageWaitingLock.wait();
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void release() {
@ -76,8 +120,17 @@ public class ScreenCapturer {
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
}
if (mImageReader != null) {
mImageReader.close();
}
if (mImageAcquireLooper != null) {
mImageAcquireLooper.quitSafely();
}
if (mImage != null) {
mImage.close();
}
if (mLatestImage != null) {
mLatestImage.close();
}
}
}