feat(autojs): requestScreenCapture() supports changing orientation automatically and dynamically
This commit is contained in:
@@ -3,6 +3,7 @@ package com.stardust.autojs.core.image.capture;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.hardware.display.VirtualDisplay;
|
import android.hardware.display.VirtualDisplay;
|
||||||
@@ -15,7 +16,7 @@ import android.os.Handler;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
import android.util.Log;
|
import android.view.OrientationEventListener;
|
||||||
|
|
||||||
import com.stardust.autojs.runtime.exception.ScriptException;
|
import com.stardust.autojs.runtime.exception.ScriptException;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
@@ -27,45 +28,83 @@ import com.stardust.util.ScreenMetrics;
|
|||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
public class ScreenCapturer {
|
public class ScreenCapturer {
|
||||||
|
|
||||||
|
public static final int ORIENTATION_AUTO = -1;
|
||||||
|
|
||||||
private static final String LOG_TAG = "ScreenCapturer";
|
private static final String LOG_TAG = "ScreenCapturer";
|
||||||
private final Object mCachedImageLock = new Object();
|
private final Object mCachedImageLock = new Object();
|
||||||
|
private final MediaProjectionManager mProjectionManager;
|
||||||
private ImageReader mImageReader;
|
private ImageReader mImageReader;
|
||||||
private MediaProjection mMediaProjection;
|
private final MediaProjection mMediaProjection;
|
||||||
private VirtualDisplay mVirtualDisplay;
|
private VirtualDisplay mVirtualDisplay;
|
||||||
private volatile Looper mImageAcquireLooper;
|
private volatile Looper mImageAcquireLooper;
|
||||||
private volatile Image mUnderUsingImage;
|
private volatile Image mUnderUsingImage;
|
||||||
private volatile Image mCachedImage;
|
private volatile Image mCachedImage;
|
||||||
private volatile boolean mImageAvailable = false;
|
private volatile boolean mImageAvailable = false;
|
||||||
private volatile Exception mException;
|
private volatile Exception mException;
|
||||||
private final int mScreenWidth;
|
|
||||||
private final int mScreenHeight;
|
|
||||||
private final int mScreenDensity;
|
private final int mScreenDensity;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
private Intent mData;
|
||||||
|
private Context mContext;
|
||||||
|
private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||||
|
private int mDetectedOrientation;
|
||||||
|
private OrientationEventListener mOrientationEventListener;
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity, Handler handler) {
|
public ScreenCapturer(Context context, Intent data, int orientation, int screenDensity, Handler handler) {
|
||||||
mScreenWidth = screenWidth;
|
mContext = context;
|
||||||
mScreenHeight = screenHeight;
|
mData = data;
|
||||||
mScreenDensity = screenDensity;
|
mScreenDensity = screenDensity;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
mProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
||||||
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
|
mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, mData);
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
|
setOrientation(orientation);
|
||||||
|
observeOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void observeOrientation() {
|
||||||
|
mOrientationEventListener = new OrientationEventListener(mContext) {
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(int o) {
|
||||||
|
int orientation = mContext.getResources().getConfiguration().orientation;
|
||||||
|
if (mOrientation == ORIENTATION_AUTO && mDetectedOrientation != orientation) {
|
||||||
|
mDetectedOrientation = orientation;
|
||||||
|
refreshVirtualDisplay(orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
if (mOrientationEventListener.canDetectOrientation()) {
|
||||||
|
mOrientationEventListener.enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
if (mOrientation == orientation)
|
||||||
|
return;
|
||||||
|
mOrientation = orientation;
|
||||||
|
mDetectedOrientation = mContext.getResources().getConfiguration().orientation;
|
||||||
|
refreshVirtualDisplay(mOrientation == ORIENTATION_AUTO ? mDetectedOrientation : mOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void refreshVirtualDisplay(int orientation) {
|
||||||
|
if (mImageReader != null) {
|
||||||
|
mImageReader.close();
|
||||||
|
}
|
||||||
|
if (mVirtualDisplay != null) {
|
||||||
|
mVirtualDisplay.release();
|
||||||
|
}
|
||||||
|
mImageAvailable = false;
|
||||||
|
int screenHeight = ScreenMetrics.getOrientationAwareScreenHeight(orientation);
|
||||||
|
int screenWidth = ScreenMetrics.getOrientationAwareScreenWidth(orientation);
|
||||||
|
initVirtualDisplay(screenWidth, screenHeight, mScreenDensity);
|
||||||
startAcquireImageLoop();
|
startAcquireImageLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) {
|
private void initVirtualDisplay(int width, int height, int screenDensity) {
|
||||||
this(context, data, screenWidth, screenHeight, ScreenMetrics.getDeviceScreenDensity(), null);
|
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
|
||||||
}
|
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data) {
|
|
||||||
this(context, data, ScreenMetrics.getDeviceScreenWidth(), ScreenMetrics.getDeviceScreenHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initVirtualDisplay(MediaProjectionManager manager, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
|
||||||
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
|
|
||||||
mMediaProjection = manager.getMediaProjection(Activity.RESULT_OK, data);
|
|
||||||
mVirtualDisplay = mMediaProjection.createVirtualDisplay(LOG_TAG,
|
mVirtualDisplay = mMediaProjection.createVirtualDisplay(LOG_TAG,
|
||||||
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
width, height, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
||||||
mImageReader.getSurface(), null, null);
|
mImageReader.getSurface(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,14 +177,6 @@ public class ScreenCapturer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScreenWidth() {
|
|
||||||
return mScreenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getScreenHeight() {
|
|
||||||
return mScreenHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getScreenDensity() {
|
public int getScreenDensity() {
|
||||||
return mScreenDensity;
|
return mScreenDensity;
|
||||||
}
|
}
|
||||||
@@ -170,6 +201,9 @@ public class ScreenCapturer {
|
|||||||
if (mCachedImage != null) {
|
if (mCachedImage != null) {
|
||||||
mCachedImage.close();
|
mCachedImage.close();
|
||||||
}
|
}
|
||||||
|
if (mOrientationEventListener != null) {
|
||||||
|
mOrientationEventListener.disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -180,4 +214,5 @@ public class ScreenCapturer {
|
|||||||
super.finalize();
|
super.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
@@ -28,7 +29,6 @@ import com.stardust.concurrent.VolatileDispose;
|
|||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
import com.stardust.util.ScreenMetrics;
|
import com.stardust.util.ScreenMetrics;
|
||||||
|
|
||||||
import org.opencv.core.Core;
|
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.core.Point;
|
import org.opencv.core.Point;
|
||||||
import org.opencv.core.Rect;
|
import org.opencv.core.Rect;
|
||||||
@@ -69,12 +69,16 @@ public class Images {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public boolean requestScreenCapture(final int width, final int height) {
|
public boolean requestScreenCapture(int orientation) {
|
||||||
ScriptRuntime.requiresApi(21);
|
ScriptRuntime.requiresApi(21);
|
||||||
|
if (mScreenCapturer != null) {
|
||||||
|
mScreenCapturer.setOrientation(orientation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
final VolatileDispose<Boolean> requestResult = new VolatileDispose<>();
|
final VolatileDispose<Boolean> requestResult = new VolatileDispose<>();
|
||||||
mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> {
|
mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> {
|
||||||
if (result == Activity.RESULT_OK) {
|
if (result == Activity.RESULT_OK) {
|
||||||
mScreenCapturer = new ScreenCapturer(mContext, data, width, height, ScreenMetrics.getDeviceScreenDensity(),
|
mScreenCapturer = new ScreenCapturer(mContext, data, orientation, ScreenMetrics.getDeviceScreenDensity(),
|
||||||
new Handler(mScriptRuntime.loopers.getServantLooper()));
|
new Handler(mScriptRuntime.loopers.getServantLooper()));
|
||||||
requestResult.setAndNotify(true);
|
requestResult.setAndNotify(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -87,18 +91,12 @@ public class Images {
|
|||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public boolean requestScreenCapture(boolean landscape) {
|
public boolean requestScreenCapture(boolean landscape) {
|
||||||
if (!landscape)
|
return requestScreenCapture(landscape ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT);
|
||||||
return requestScreenCapture(ScreenMetrics.getDeviceScreenWidth(), ScreenMetrics.getDeviceScreenHeight());
|
|
||||||
else
|
|
||||||
return requestScreenCapture(ScreenMetrics.getDeviceScreenHeight(), ScreenMetrics.getDeviceScreenWidth());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
public boolean requestScreenCapture() {
|
public boolean requestScreenCapture() {
|
||||||
if (mDisplay.getRotation() == Surface.ROTATION_0 || mDisplay.getRotation() == Surface.ROTATION_180)
|
return requestScreenCapture(ScreenCapturer.ORIENTATION_AUTO);
|
||||||
return requestScreenCapture(ScreenMetrics.getDeviceScreenWidth(), ScreenMetrics.getDeviceScreenHeight());
|
|
||||||
else
|
|
||||||
return requestScreenCapture(ScreenMetrics.getDeviceScreenHeight(), ScreenMetrics.getDeviceScreenWidth());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.stardust.util;
|
package com.stardust.util;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
@@ -44,6 +45,22 @@ public class ScreenMetrics {
|
|||||||
return deviceScreenDensity;
|
return deviceScreenDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getOrientationAwareScreenWidth(int orientation) {
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
return getDeviceScreenHeight();
|
||||||
|
} else {
|
||||||
|
return getDeviceScreenWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getOrientationAwareScreenHeight(int orientation) {
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
return getDeviceScreenWidth();
|
||||||
|
} else {
|
||||||
|
return getDeviceScreenHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int scaleX(int x, int width) {
|
public static int scaleX(int x, int width) {
|
||||||
if (width == 0 || !initialized)
|
if (width == 0 || !initialized)
|
||||||
return x;
|
return x;
|
||||||
|
|||||||
Reference in New Issue
Block a user