From 35a5abed6aac43935ad31f0fdc57608eca4c0aff Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Sun, 3 Jun 2018 11:12:01 +0800 Subject: [PATCH] feat(autojs): requestScreenCapture() supports changing orientation automatically and dynamically --- .../core/image/capture/ScreenCapturer.java | 93 +++++++++++++------ .../stardust/autojs/runtime/api/Images.java | 20 ++-- .../java/com/stardust/util/ScreenMetrics.java | 17 ++++ 3 files changed, 90 insertions(+), 40 deletions(-) diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/capture/ScreenCapturer.java b/autojs/src/main/java/com/stardust/autojs/core/image/capture/ScreenCapturer.java index 91d3cc19..74e92327 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/capture/ScreenCapturer.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/capture/ScreenCapturer.java @@ -3,6 +3,7 @@ package com.stardust.autojs.core.image.capture; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.PixelFormat; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; @@ -15,7 +16,7 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.Nullable; 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.ScriptInterruptedException; @@ -27,45 +28,83 @@ import com.stardust.util.ScreenMetrics; @RequiresApi(Build.VERSION_CODES.LOLLIPOP) public class ScreenCapturer { + public static final int ORIENTATION_AUTO = -1; + private static final String LOG_TAG = "ScreenCapturer"; private final Object mCachedImageLock = new Object(); + private final MediaProjectionManager mProjectionManager; private ImageReader mImageReader; - private MediaProjection mMediaProjection; + private final MediaProjection mMediaProjection; private VirtualDisplay mVirtualDisplay; private volatile Looper mImageAcquireLooper; private volatile Image mUnderUsingImage; private volatile Image mCachedImage; private volatile boolean mImageAvailable = false; private volatile Exception mException; - private final int mScreenWidth; - private final int mScreenHeight; private final int mScreenDensity; 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) { - mScreenWidth = screenWidth; - mScreenHeight = screenHeight; + public ScreenCapturer(Context context, Intent data, int orientation, int screenDensity, Handler handler) { + mContext = context; + mData = data; mScreenDensity = screenDensity; mHandler = handler; - MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); - initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity); + mProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); + mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, mData); 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(); } - public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) { - this(context, data, screenWidth, screenHeight, ScreenMetrics.getDeviceScreenDensity(), null); - } - - 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); + private void initVirtualDisplay(int width, int height, int screenDensity) { + mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2); 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); } @@ -138,14 +177,6 @@ public class ScreenCapturer { } } - public int getScreenWidth() { - return mScreenWidth; - } - - public int getScreenHeight() { - return mScreenHeight; - } - public int getScreenDensity() { return mScreenDensity; } @@ -170,6 +201,9 @@ public class ScreenCapturer { if (mCachedImage != null) { mCachedImage.close(); } + if (mOrientationEventListener != null) { + mOrientationEventListener.disable(); + } } @Override @@ -180,4 +214,5 @@ public class ScreenCapturer { super.finalize(); } } + } \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java index e59ebd90..90bb1fe1 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java @@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api; import android.app.Activity; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; @@ -28,7 +29,6 @@ import com.stardust.concurrent.VolatileDispose; import com.stardust.pio.UncheckedIOException; import com.stardust.util.ScreenMetrics; -import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Point; import org.opencv.core.Rect; @@ -69,12 +69,16 @@ public class Images { } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public boolean requestScreenCapture(final int width, final int height) { + public boolean requestScreenCapture(int orientation) { ScriptRuntime.requiresApi(21); + if (mScreenCapturer != null) { + mScreenCapturer.setOrientation(orientation); + return true; + } final VolatileDispose requestResult = new VolatileDispose<>(); mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> { 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())); requestResult.setAndNotify(true); } else { @@ -87,18 +91,12 @@ public class Images { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public boolean requestScreenCapture(boolean landscape) { - if (!landscape) - return requestScreenCapture(ScreenMetrics.getDeviceScreenWidth(), ScreenMetrics.getDeviceScreenHeight()); - else - return requestScreenCapture(ScreenMetrics.getDeviceScreenHeight(), ScreenMetrics.getDeviceScreenWidth()); + return requestScreenCapture(landscape ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public boolean requestScreenCapture() { - if (mDisplay.getRotation() == Surface.ROTATION_0 || mDisplay.getRotation() == Surface.ROTATION_180) - return requestScreenCapture(ScreenMetrics.getDeviceScreenWidth(), ScreenMetrics.getDeviceScreenHeight()); - else - return requestScreenCapture(ScreenMetrics.getDeviceScreenHeight(), ScreenMetrics.getDeviceScreenWidth()); + return requestScreenCapture(ScreenCapturer.ORIENTATION_AUTO); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) diff --git a/common/src/main/java/com/stardust/util/ScreenMetrics.java b/common/src/main/java/com/stardust/util/ScreenMetrics.java index 43a0c97e..9072a80b 100644 --- a/common/src/main/java/com/stardust/util/ScreenMetrics.java +++ b/common/src/main/java/com/stardust/util/ScreenMetrics.java @@ -1,6 +1,7 @@ package com.stardust.util; import android.app.Activity; +import android.content.res.Configuration; import android.graphics.Point; import android.util.DisplayMetrics; import android.view.Display; @@ -44,6 +45,22 @@ public class ScreenMetrics { 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) { if (width == 0 || !initialized) return x;