From 87501555b82d266bee7e767b7eac04e2eb62fa44 Mon Sep 17 00:00:00 2001 From: TonyJiangWJ Date: Fri, 4 Feb 2022 23:43:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B7=B2=E7=9F=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/autojs/autojs/timing/TimedTask.java | 3 +- .../autojs/ui/common/ScriptOperations.java | 1 + .../ui/main/task/TaskListRecyclerView.java | 2 + .../capture/CaptureForegroundService.java | 1 + .../image/capture/GlobalScreenCapture.java | 74 ++++++++++++------- .../execution/ScriptExecuteActivity.java | 2 +- .../autojs/runtime/ScriptRuntime.java | 4 +- .../stardust/autojs/runtime/api/Images.java | 16 ++-- .../stardust/concurrent/VolatileDispose.java | 8 +- 9 files changed, 67 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTask.java b/app/src/main/java/org/autojs/autojs/timing/TimedTask.java index 67481adc..f44e74fb 100644 --- a/app/src/main/java/org/autojs/autojs/timing/TimedTask.java +++ b/app/src/main/java/org/autojs/autojs/timing/TimedTask.java @@ -214,7 +214,8 @@ public class TimedTask extends BaseModel { .putExtra(ScriptIntents.EXTRA_KEY_PATH, mScriptPath) .putExtra(ScriptIntents.EXTRA_KEY_DELAY, mDelay) .putExtra(ScriptIntents.EXTRA_KEY_LOOP_TIMES, mLoopTimes) - .putExtra(ScriptIntents.EXTRA_KEY_LOOP_INTERVAL, mInterval); + .putExtra(ScriptIntents.EXTRA_KEY_LOOP_INTERVAL, mInterval) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } diff --git a/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java b/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java index 91f44aed..18beac76 100644 --- a/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java +++ b/app/src/main/java/org/autojs/autojs/ui/common/ScriptOperations.java @@ -369,6 +369,7 @@ public class ScriptOperations { public void timedTask(ScriptFile scriptFile) { TimedTaskSettingActivity_.intent(mContext) .extra(ScriptIntents.EXTRA_KEY_PATH, scriptFile.getPath()) + .flags(Intent.FLAG_ACTIVITY_NEW_TASK) .start(); } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/task/TaskListRecyclerView.java b/app/src/main/java/org/autojs/autojs/ui/main/task/TaskListRecyclerView.java index c73a6437..5b9c673e 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/task/TaskListRecyclerView.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/task/TaskListRecyclerView.java @@ -1,6 +1,7 @@ package org.autojs.autojs.ui.main.task; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.GradientDrawable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -250,6 +251,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView { : TimedTaskSettingActivity.EXTRA_TASK_ID; TimedTaskSettingActivity_.intent(getContext()) .extra(extra, task.getId()) + .flags(Intent.FLAG_ACTIVITY_NEW_TASK) .start(); } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/capture/CaptureForegroundService.java b/autojs/src/main/java/com/stardust/autojs/core/image/capture/CaptureForegroundService.java index f2ee0208..fc214d57 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/capture/CaptureForegroundService.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/capture/CaptureForegroundService.java @@ -85,6 +85,7 @@ public class CaptureForegroundService extends Service { @Override public void onDestroy() { super.onDestroy(); + GlobalScreenCapture.getInstance().foregroundServiceDown(); stopForeground(true); } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/capture/GlobalScreenCapture.java b/autojs/src/main/java/com/stardust/autojs/core/image/capture/GlobalScreenCapture.java index 6759970f..f6f49452 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/capture/GlobalScreenCapture.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/capture/GlobalScreenCapture.java @@ -12,16 +12,20 @@ import android.media.Image; import android.media.ImageReader; import android.media.projection.MediaProjection; import android.media.projection.MediaProjectionManager; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.view.OrientationEventListener; +import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.exception.ScriptException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.lang.ThreadCompat; import com.stardust.util.ScreenMetrics; +import org.mozilla.javascript.ast.Loop; + import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; @@ -37,7 +41,7 @@ public class GlobalScreenCapture { public static final int ORIENTATION_PORTRAIT = Configuration.ORIENTATION_PORTRAIT; private static final String TAG = "GlobalScreenCapture"; - private final ConcurrentHashMap registeredThreads = new ConcurrentHashMap<>(); + private final ConcurrentHashMap registeredRuntimes = new ConcurrentHashMap<>(); private MediaProjectionManager mProjectionManager; private ImageReader mImageReader; @@ -83,24 +87,16 @@ public class GlobalScreenCapture { if (mScreenDensity == 0) { mScreenDensity = ScreenMetrics.getDeviceScreenDensity(); } - if (!foregroundServiceStarted) { - try { - this.wait(); - } catch (InterruptedException e) { - throw new ScriptInterruptedException(); - } - } + awaitForegroundServiceIfNeeded(); mProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) data.clone()); mContext = context; mData = (Intent) data.clone(); new Thread(() -> { - Looper.prepare(); mHandler = new Handler(Looper.getMainLooper()); synchronized (GlobalScreenCapture.this) { GlobalScreenCapture.this.notifyAll(); } - Looper.loop(); }).start(); synchronized (this) { try { @@ -114,13 +110,35 @@ public class GlobalScreenCapture { hasPermission = true; } + private void awaitForegroundServiceIfNeeded() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !foregroundServiceStarted) { + try { + this.wait(); + } catch (InterruptedException e) { + throw new ScriptInterruptedException(); + } + } + } + public synchronized void notifyStarted() { this.foregroundServiceStarted = true; this.notify(); } + public void foregroundServiceDown() { + this.foregroundServiceStarted = false; + } + public synchronized boolean hasPermission() { - return hasPermission; + if (!hasPermission) { + return false; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !foregroundServiceStarted) { + // 前台服务可能丢失,重新获取 + mContext.startForegroundService(new Intent(mContext, CaptureForegroundService.class)); + awaitForegroundServiceIfNeeded(); + return foregroundServiceStarted; + } + return true; } public void setOrientation(int orientation) { @@ -129,9 +147,12 @@ public class GlobalScreenCapture { } mOrientation = orientation; mDetectedOrientation = mContext.getResources().getConfiguration().orientation; - refreshVirtualDisplay(mOrientation == ORIENTATION_AUTO ? mDetectedOrientation : mOrientation); + refreshVirtualDisplay(getOrientation()); } + private int getOrientation() { + return mOrientation == ORIENTATION_AUTO ? mDetectedOrientation : mOrientation; + } private void observeOrientation() { mOrientationEventListener = new OrientationEventListener(mContext) { @@ -179,6 +200,7 @@ public class GlobalScreenCapture { mMediaProjection = mProjectionManager.getMediaProjection(Activity.RESULT_OK, (Intent) mData.clone()); } catch (Exception e) { Log.d(TAG, "grantMediaProjection: 获取新projection失败 可能只是MIUI的bug " + e); + release(); } } @@ -246,33 +268,35 @@ public class GlobalScreenCapture { startTime = System.currentTimeMillis(); Log.d(TAG, "capture: 获取截图失败,刷新virtualDisplay"); this.grantMediaProjection(); - this.refreshVirtualDisplay(mOrientation); + this.refreshVirtualDisplay(getOrientation()); } } throw new ScriptInterruptedException(); } - public synchronized void unregister(Looper looper) { - Log.d(TAG, "unregister: " + looper.getThread().getName()); - registeredThreads.remove(looper.getThread()); - Iterator keyThreads = registeredThreads.keySet().iterator(); - while (keyThreads.hasNext()) { - Thread thread = keyThreads.next(); - if (!thread.isAlive()) { - keyThreads.remove(); + public synchronized void unregister(ScriptRuntime runtime) { + Log.d(TAG, "unregister: " + runtime); + registeredRuntimes.remove(runtime); + Iterator keyRuntime = registeredRuntimes.keySet().iterator(); + while (keyRuntime.hasNext()) { + ScriptRuntime scriptRuntime = keyRuntime.next(); + Looper looper = scriptRuntime.loopers.getMainLooper(); + if (looper == null || !looper.getThread().isAlive()) { + keyRuntime.remove(); } } - noRegister = registeredThreads.size() == 0; + noRegister = registeredRuntimes.size() == 0; if (noRegister) { Log.d(TAG, "全部引擎已注销,释放截图权限,清除通知"); release(); } } - public synchronized void register(Looper looper) { - Log.d(TAG, "新引擎注册:" + looper.getThread().getName() + " hasPermission? " + hasPermission); + public synchronized void register(ScriptRuntime runtime) { + Looper looper = runtime.loopers.getMainLooper(); + Log.d(TAG, "新引擎注册:" + (looper != null ? looper.getThread().getName() : runtime.engines.myEngine().toString()) + " hasPermission? " + hasPermission); noRegister = false; - registeredThreads.put(looper.getThread(), true); + registeredRuntimes.put(runtime, true); } private void release() { diff --git a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java index f658dd8f..8eed9b55 100644 --- a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java +++ b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java @@ -66,7 +66,7 @@ public class ScriptExecuteActivity extends AppCompatActivity { return; } ScriptExecution execution = ScriptEngineService.getInstance().getScriptExecution(executionId); - if (execution == null || !(execution instanceof ActivityScriptExecution)) { + if (!(execution instanceof ActivityScriptExecution)) { super.finish(); return; } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java index 5ce138f6..2c8a6cf6 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -216,9 +216,7 @@ public class ScriptRuntime { this.automator = new SimpleActionAutomator(accessibilityBridge, this); automator.setScreenMetrics(mScreenMetrics); this.info = accessibilityBridge.getInfoProvider(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - images = new Images(context, this, builder.mScreenCaptureRequester); - } + images = new Images(context, this, builder.mScreenCaptureRequester); engines = new Engines(builder.mEngineService, this); dialogs = new Dialogs(this); device = new Device(context); 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 ef42697b..6815a5a6 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 @@ -30,6 +30,7 @@ import com.stardust.concurrent.VolatileDispose; import com.stardust.pio.UncheckedIOException; import com.stardust.util.ScreenMetrics; +import org.mozilla.javascript.ast.Loop; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.imgproc.Imgproc; @@ -83,12 +84,11 @@ public class Images { if (GlobalScreenCapture.getInstance().hasPermission()) { Log.d(TAG, "requestScreenCapture hasPermission 直接注册"); GlobalScreenCapture.getInstance().setOrientation(orientation); - GlobalScreenCapture.getInstance().register(mScriptRuntime.get().loopers.getMainLooper()); - new Handler(Looper.getMainLooper()) - .post(() -> { - promiseAdapter.awaitResolver(); - promiseAdapter.resolve(true); - }); + GlobalScreenCapture.getInstance().register(mScriptRuntime.get()); + new Thread(() -> { + promiseAdapter.awaitResolver(); + new Handler(Looper.getMainLooper()).postDelayed(() -> promiseAdapter.resolve(true), 50); + }).start(); return promiseAdapter; } } @@ -97,7 +97,7 @@ public class Images { mScreenCaptureRequester.setOnActivityResultCallback((result, data) -> { if (result == Activity.RESULT_OK) { GlobalScreenCapture.getInstance().initCapture(mContext, data, orientation); - GlobalScreenCapture.getInstance().register(mScriptRuntime.get().loopers.getMainLooper()); + GlobalScreenCapture.getInstance().register(mScriptRuntime.get()); promiseAdapter.resolve(true); } else { promiseAdapter.resolve(false); @@ -277,7 +277,7 @@ public class Images { public void releaseScreenCapturer() { if (GlobalScreenCapture.getInstance().hasPermission()) { synchronized (GlobalScreenCapture.getInstance()) { - GlobalScreenCapture.getInstance().unregister(mScriptRuntime.get().loopers.getMainLooper()); + GlobalScreenCapture.getInstance().unregister(mScriptRuntime.get()); } } } diff --git a/common/src/main/java/com/stardust/concurrent/VolatileDispose.java b/common/src/main/java/com/stardust/concurrent/VolatileDispose.java index d92e6f68..f2bdf209 100644 --- a/common/src/main/java/com/stardust/concurrent/VolatileDispose.java +++ b/common/src/main/java/com/stardust/concurrent/VolatileDispose.java @@ -32,9 +32,7 @@ public class VolatileDispose { } catch (InterruptedException e) { try { throw exception.newInstance(); - } catch (InstantiationException e1) { - throw new RuntimeException(e1); - } catch (IllegalAccessException e1) { + } catch (InstantiationException | IllegalAccessException e1) { throw new RuntimeException(e1); } } @@ -52,9 +50,7 @@ public class VolatileDispose { } catch (InterruptedException e) { try { throw exception.newInstance(); - } catch (InstantiationException e1) { - throw new RuntimeException(e1); - } catch (IllegalAccessException e1) { + } catch (InstantiationException | IllegalAccessException e1) { throw new RuntimeException(e1); } }