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" 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 {

View File

@@ -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));
} }
} }

View File

@@ -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();
}
} }
} }