fix exception when captureScreen called frequently
This commit is contained in:
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "com.stardust.scriptdroid"
|
applicationId "com.stardust.scriptdroid"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 139
|
versionCode 140
|
||||||
versionName "2.0.13 Alpha2"
|
versionName "2.0.13 Alpha3"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +40,7 @@ public class SublimePluginClient {
|
|||||||
private String host;
|
private String host;
|
||||||
private int port;
|
private int port;
|
||||||
private OutputStream mOutputStream;
|
private OutputStream mOutputStream;
|
||||||
private Executor mExecutor;
|
private ExecutorService mExecutor;
|
||||||
|
|
||||||
public SublimePluginClient(String host, int port) {
|
public SublimePluginClient(String host, int port) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
@@ -105,8 +106,10 @@ public class SublimePluginClient {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (mSocket != null) {
|
if (mSocket != null) {
|
||||||
mSocket.close();
|
mSocket.close();
|
||||||
|
mExecutor.shutdownNow();
|
||||||
mSocket = null;
|
mSocket = null;
|
||||||
mOutputStream = null;
|
mOutputStream = null;
|
||||||
|
mExecutor = null;
|
||||||
EventBus.getDefault().post(new ConnectionStateChangeEvent(false));
|
EventBus.getDefault().post(new ConnectionStateChangeEvent(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,23 +13,34 @@ import android.media.projection.MediaProjectionManager;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.support.annotation.RequiresApi;
|
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 com.stardust.util.ScreenMetrics;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/5/17.
|
* Created by Stardust on 2017/5/17.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
public class ScreenCapturer {
|
public class ScreenCapturer {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "ScreenCapturer";
|
||||||
private ImageReader mImageReader;
|
private ImageReader mImageReader;
|
||||||
private MediaProjection mMediaProjection;
|
private MediaProjection mMediaProjection;
|
||||||
private VirtualDisplay mVirtualDisplay;
|
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) {
|
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
||||||
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
||||||
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
|
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
|
||||||
|
startAcquireImageLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) {
|
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) {
|
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);
|
mMediaProjection = manager.getMediaProjection(Activity.RESULT_OK, data);
|
||||||
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
|
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
|
||||||
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
||||||
mImageReader.getSurface(), null, null);
|
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() {
|
public Image capture() {
|
||||||
|
if (mLatestImage == null) {
|
||||||
|
if (mImage != null) {
|
||||||
|
return mImage;
|
||||||
|
}
|
||||||
|
waitForImageAvailable();
|
||||||
|
}
|
||||||
if (mImage != null) {
|
if (mImage != null) {
|
||||||
mImage.close();
|
mImage.close();
|
||||||
}
|
}
|
||||||
mImage = mImageReader.acquireLatestImage();
|
mImage = mLatestImage;
|
||||||
if (mImage == null) {
|
mLatestImage = null;
|
||||||
Looper.prepare();
|
|
||||||
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
|
||||||
@Override
|
|
||||||
public void onImageAvailable(ImageReader reader) {
|
|
||||||
Looper.myLooper().quit();
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
Looper.loop();
|
|
||||||
mImage = mImageReader.acquireLatestImage();
|
|
||||||
}
|
|
||||||
return mImage;
|
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)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public void release() {
|
public void release() {
|
||||||
@@ -76,8 +120,17 @@ public class ScreenCapturer {
|
|||||||
if (mVirtualDisplay != null) {
|
if (mVirtualDisplay != null) {
|
||||||
mVirtualDisplay.release();
|
mVirtualDisplay.release();
|
||||||
}
|
}
|
||||||
|
if (mImageReader != null) {
|
||||||
|
mImageReader.close();
|
||||||
|
}
|
||||||
|
if (mImageAcquireLooper != null) {
|
||||||
|
mImageAcquireLooper.quitSafely();
|
||||||
|
}
|
||||||
if (mImage != null) {
|
if (mImage != null) {
|
||||||
mImage.close();
|
mImage.close();
|
||||||
}
|
}
|
||||||
|
if (mLatestImage != null) {
|
||||||
|
mLatestImage.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user