diff --git a/app/src/main/assets/sample/图片与图色处理/图片处理.js b/app/src/main/assets/sample/图片与图色处理/图片处理.js index 7c1d02b3..654c56ad 100644 --- a/app/src/main/assets/sample/图片与图色处理/图片处理.js +++ b/app/src/main/assets/sample/图片与图色处理/图片处理.js @@ -36,6 +36,14 @@ ui.layout( function setImage(img) { ui.run(() => { ui.img.setImageBitmap(img.bitmap); + var oldImg = currentImg; + //不能立即回收currentImg,因为此时img控件还在使用它,应该在下次消息循环再回收它 + ui.post(()=>{ + if(oldImg != null){ + oldImg.recycle(); + } + }); + currentImg = img; }); } @@ -52,10 +60,6 @@ function processImg(process) { } //处理图片 var result = process(logo); - if(currentImg != null){ - currentImg.recycle(); - } - currentImg = result; //把处理后的图片设置到图片控件中 setImage(result); }, 0); diff --git a/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java b/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java index c16898a0..aa361c8c 100644 --- a/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java @@ -9,7 +9,6 @@ import android.support.annotation.Nullable; import android.util.Log; import android.view.View; -import com.stardust.autojs.core.opencv.OpenCVHelper; import com.xcy8.ads.listener.LoadAdListener; import com.xcy8.ads.view.FullScreenAdView; @@ -30,7 +29,7 @@ public class SplashActivity extends BaseActivity { public static final String FORCE_SHOW_AD = "forceShowAd"; private static final String LOG_TAG = SplashActivity.class.getSimpleName(); - private static final long INIT_TIMEOUT = 1500; + private static final long INIT_TIMEOUT = 1000; private boolean mCanEnterNextActivity = false; @@ -47,7 +46,6 @@ public class SplashActivity extends BaseActivity { super.onCreate(savedInstanceState); init(); boolean forceShowAd = getIntent().getBooleanExtra(FORCE_SHOW_AD, false); - final long millis = SystemClock.uptimeMillis(); if (!forceShowAd && !Pref.shouldShowAd()) { mFullScreenAdView.setVisibility(View.INVISIBLE); } else { @@ -55,14 +53,7 @@ public class SplashActivity extends BaseActivity { fetchSplashAD(); } } - OpenCVHelper.initIfNeeded(this, () -> { - long delay = INIT_TIMEOUT - (SystemClock.uptimeMillis() - millis); - if (delay <= 0) { - enterNextActivity(); - return; - } - mHandler.postDelayed(SplashActivity.this::enterNextActivity, delay); - }); + mHandler.postDelayed(SplashActivity.this::enterNextActivity, INIT_TIMEOUT); } private void init() { diff --git a/autojs/src/main/assets/modules/__images__.js b/autojs/src/main/assets/modules/__images__.js index d70c844c..7cebf282 100644 --- a/autojs/src/main/assets/modules/__images__.js +++ b/autojs/src/main/assets/modules/__images__.js @@ -66,6 +66,7 @@ module.exports = function (runtime, scope) { } images.threshold = function (img, threshold, maxVal, type) { + initIfNeeded(); var mat = new Mat(); type = type || "BINARY"; type = Imgproc["THRESH_" + type]; @@ -74,6 +75,7 @@ module.exports = function (runtime, scope) { } images.inRange = function (img, lowerBound, upperBound) { + initIfNeeded(); var lb, ub; if (typeof (lowerBound) == 'string') { if (typeof (upperBound) == 'string') { @@ -99,6 +101,7 @@ module.exports = function (runtime, scope) { images.adaptiveThreshold = function(img, maxValue, adaptiveMethod, thresholdType, blockSize, C){ + initIfNeeded(); var mat = new Mat(); adaptiveMethod = Imgproc["ADAPTIVE_THRESH_" + adaptiveMethod]; thresholdType = Imgproc["THRESH_" + thresholdType]; @@ -107,6 +110,7 @@ module.exports = function (runtime, scope) { } images.blur = function (img, size, point, type) { + initIfNeeded(); var mat = new Mat(); size = newSize(size); type = Imgproc["BORDER_" + (type || "CONSTANT")]; @@ -119,6 +123,7 @@ module.exports = function (runtime, scope) { } images.medianBlur = function (img, size) { + initIfNeeded(); var mat = new Mat(); Imgproc.medianBlur(img.mat, mat, size); return images.matToImage(mat); @@ -126,6 +131,7 @@ module.exports = function (runtime, scope) { images.gaussianBlur = function (img, size, sigmaX, sigmaY, type) { + initIfNeeded(); var mat = new Mat(); size = newSize(size); sigmaX = sigmaX == undefined ? 0 : sigmaX; @@ -136,6 +142,7 @@ module.exports = function (runtime, scope) { } images.cvtColor = function (img, code, dstCn) { + initIfNeeded(); var mat = new Mat(); code = Imgproc["COLOR_" + code]; if (dstCn == undefined) { @@ -147,6 +154,7 @@ module.exports = function (runtime, scope) { } images.findCircles = function(grayImg, options) { + initIfNeeded(); options = options || {}; var mat = options.region == undefined ? grayImg.mat : new Mat(grayImg.mat, buildRegion(options.region, grayImg)); var resultMat = new Mat() @@ -176,6 +184,7 @@ module.exports = function (runtime, scope) { } images.resize = function(img, size, interpolation) { + initIfNeeded(); var mat = new Mat(); interpolation = Imgproc["INTER_" + (interpolation || "LINEAR")]; Imgproc.resize(img.mat, mat, newSize(size), 0, 0, interpolation); @@ -183,6 +192,7 @@ module.exports = function (runtime, scope) { } images.scale = function(img, fx, fy, interpolation) { + initIfNeeded(); var mat = new Mat(); interpolation = Imgproc["INTER_" + (interpolation || "LINEAR")]; Imgproc.resize(img.mat, mat, newSize([0, 0]), fx, fy, interpolation); @@ -190,6 +200,7 @@ module.exports = function (runtime, scope) { } images.rotate = function(img, degree, x, y) { + initIfNeeded(); if(x == undefined){ x = img.width / 2; } @@ -200,6 +211,7 @@ module.exports = function (runtime, scope) { } images.concat = function(img1, img2, direction, rect1, rect2) { + initIfNeeded(); direction = direction || "right"; rect1 = buildRegion(rect1, img1); rect2 = buildRegion(rect2, img1); @@ -207,6 +219,7 @@ module.exports = function (runtime, scope) { } images.detectsColor = function (img, color, x, y, threshold, algorithm) { + initIfNeeded(); color = parseColor(color); algorithm = algorithm || "diff"; threshold = threshold || defaultColorThreshold; @@ -216,6 +229,7 @@ module.exports = function (runtime, scope) { } images.findColor = function (img, color, options) { + initIfNeeded(); color = parseColor(color); options = options || {}; var region = options.region || []; @@ -246,6 +260,7 @@ module.exports = function (runtime, scope) { } images.findAllPointsForColor = function (img, color, options) { + initIfNeeded(); color = parseColor(color); options = options || {}; if (options.similarity) { @@ -261,6 +276,7 @@ module.exports = function (runtime, scope) { } images.findMultiColors = function (img, firstColor, paths, options) { + initIfNeeded(); options = options || {}; firstColor = parseColor(firstColor); var list = java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, paths.length * 3); @@ -276,6 +292,7 @@ module.exports = function (runtime, scope) { } images.findImage = function (img, template, options) { + initIfNeeded(); options = options || {}; var threshold = options.threshold || 0.9; var maxLevel = -1; @@ -333,6 +350,7 @@ module.exports = function (runtime, scope) { } images.matToImage = function(img){ + initIfNeeded(); return Image.ofMat(img); } @@ -389,6 +407,10 @@ module.exports = function (runtime, scope) { } return new Size(size[0], size[1]); } + + function initIfNeeded(){ + javaImages.initOpenCvIfNeeded(); + } scope.__asGlobal__(images, ['requestScreenCapture', 'captureScreen', 'findImage', 'findImageInRegion', 'findColor', 'findColorInRegion', 'findColorEquals', 'findMultiColors']); diff --git a/autojs/src/main/assets/modules/__ui__.js b/autojs/src/main/assets/modules/__ui__.js index 5863283b..1a4b6f94 100644 --- a/autojs/src/main/assets/modules/__ui__.js +++ b/autojs/src/main/assets/modules/__ui__.js @@ -94,8 +94,11 @@ module.exports = function (runtime, global) { } ui.post = function (action, delay) { - delay = delay || 0; - runtime.getUiHandler().postDelayed(wrapUiAction(action), delay); + if(delay == undefined){ + runtime.getUiHandler().post(wrapUiAction(action)); + }else{ + runtime.getUiHandler().postDelayed(wrapUiAction(action), delay); + } } ui.statusBarColor = function (color) { diff --git a/autojs/src/main/java/com/stardust/autojs/AutoJs.java b/autojs/src/main/java/com/stardust/autojs/AutoJs.java index e6ea7334..81872f63 100644 --- a/autojs/src/main/java/com/stardust/autojs/AutoJs.java +++ b/autojs/src/main/java/com/stardust/autojs/AutoJs.java @@ -87,12 +87,6 @@ public abstract class AutoJs { protected void init() { addAccessibilityServiceDelegates(); registerActivityLifecycleCallbacks(); - try { - OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, mContext, new BaseLoaderCallback(mContext) { - }); - } catch (Exception e) { - e.printStackTrace(); - } ResourceMonitor.setExceptionCreator(resource -> { Exception exception; if (org.mozilla.javascript.Context.getCurrentContext() != null) { diff --git a/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java b/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java index 8a1067f1..80966232 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java +++ b/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java @@ -1,10 +1,11 @@ package com.stardust.autojs.core.opencv; -import android.app.Activity; +import android.content.Context; import android.support.annotation.Nullable; import android.util.Log; import com.afollestad.materialdialogs.MaterialDialog; +import com.stardust.app.DialogUtils; import org.opencv.android.InstallCallbackInterface; import org.opencv.android.LoaderCallbackInterface; @@ -22,7 +23,7 @@ public class OpenCVHelper { } private static final String LOG_TAG = "OpenCVHelper"; - private static boolean mInitialized = false; + private static boolean sInitialized = false; public static MatOfPoint newMatOfPoint(Mat mat){ return new MatOfPoint(mat); @@ -31,25 +32,26 @@ public class OpenCVHelper { public static void release(@Nullable MatOfPoint mat) { if (mat == null) return; - - mat.release(); } - public static void release(@Nullable Mat mat) { if (mat == null) return; mat.release(); } - public static void initIfNeeded(Activity activity, InitializeCallback callback) { - if (mInitialized) { + public synchronized static boolean isInitialized() { + return sInitialized; + } + + public synchronized static void initIfNeeded(Context context, InitializeCallback callback) { + if (sInitialized) { callback.onInitFinish(); return; } - mInitialized = true; - OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, activity.getApplicationContext(), new LoaderCallback(activity) { + sInitialized = true; + OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, context.getApplicationContext(), new LoaderCallback(context) { @Override protected void finish() { @@ -60,10 +62,10 @@ public class OpenCVHelper { public static class LoaderCallback implements LoaderCallbackInterface { - private Activity mActivity; + private Context mContext; - public LoaderCallback(Activity activity) { - this.mActivity = activity; + public LoaderCallback(Context context) { + this.mContext = context; } public void onManagerConnected(int status) { @@ -74,23 +76,23 @@ public class OpenCVHelper { case 1: default: Log.e(LOG_TAG, "OpenCV loading failed!"); - new MaterialDialog.Builder(mActivity) + DialogUtils.showDialog(new MaterialDialog.Builder(mContext) .title("OpenCV error") .content("OpenCV was not initialised correctly. Application will be shut down") .cancelable(false) .positiveText("OK") .onPositive((dialog, which) -> finish()) - .show(); + .build()); break; case 2: Log.e(LOG_TAG, "Package installation failed!"); - new MaterialDialog.Builder(mActivity) + DialogUtils.showDialog(new MaterialDialog.Builder(mContext) .title("OpenCV Manager") .content("Package installation failed!") .cancelable(false) .positiveText("OK") .onPositive((dialog, which) -> finish()) - .show(); + .build()); break; case 3: Log.d(LOG_TAG, "OpenCV library instalation was canceled by user"); @@ -98,13 +100,13 @@ public class OpenCVHelper { break; case 4: Log.d(LOG_TAG, "OpenCV Manager Service is uncompatible with this app!"); - new MaterialDialog.Builder(mActivity) + DialogUtils.showDialog(new MaterialDialog.Builder(mContext) .title("OpenCV Manager") .content("OpenCV Manager service is incompatible with this app. Try to update it via Google Play.") .cancelable(false) .positiveText("OK") .onPositive((dialog, which) -> finish()) - .show(); + .build()); } } @@ -112,7 +114,7 @@ public class OpenCVHelper { public void onPackageInstall(int operation, final InstallCallbackInterface callback) { switch (operation) { case 0: - new MaterialDialog.Builder(mActivity) + DialogUtils.showDialog(new MaterialDialog.Builder(mContext) .title("Package not found") .content(callback.getPackageName() + " package was not found! Try to install it?") .cancelable(false) @@ -120,10 +122,10 @@ public class OpenCVHelper { .onPositive((dialog, which) -> callback.install()) .negativeText("No") .onNegative(((dialog, which) -> callback.cancel())) - .show(); + .build()); break; case 1: - new MaterialDialog.Builder(mActivity) + DialogUtils.showDialog(new MaterialDialog.Builder(mContext) .title("OpenCV is not ready") .content("Installation is in progress. Wait or exit?") .cancelable(false) @@ -131,7 +133,7 @@ public class OpenCVHelper { .onPositive((dialog, which) -> callback.wait_install()) .negativeText("Exit") .onNegative(((dialog, which) -> callback.cancel())) - .show(); + .build()); default: finish(); } @@ -139,7 +141,6 @@ public class OpenCVHelper { } protected void finish() { - mActivity.finish(); } } 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 d90ea740..2b0ebb07 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 @@ -11,6 +11,7 @@ import android.graphics.Paint; import android.media.Image; import android.os.Build; import android.os.Handler; +import android.os.Looper; import android.support.annotation.RequiresApi; import android.util.Base64; import android.view.Gravity; @@ -55,6 +56,7 @@ public class Images { private Image mPreCapture; private ImageWrapper mPreCaptureImage; private ScreenMetrics mScreenMetrics; + private volatile boolean mOpenCvInitialized = false; @ScriptVariable public final ColorFinder colorFinder; @@ -148,7 +150,7 @@ public class Images { } public static ImageWrapper concat(ImageWrapper img1, Rect rect1, ImageWrapper img2, Rect rect2, int direction) { - if(!Arrays.asList(Gravity.LEFT, Gravity.RIGHT, Gravity.TOP, Gravity.BOTTOM).contains(direction)){ + if (!Arrays.asList(Gravity.LEFT, Gravity.RIGHT, Gravity.TOP, Gravity.BOTTOM).contains(direction)) { throw new IllegalArgumentException("unknown direction " + direction); } int width; @@ -283,6 +285,7 @@ public class Images { } public Point findImage(ImageWrapper image, ImageWrapper template, float weakThreshold, float threshold, Rect rect, int maxLevel) { + initOpenCvIfNeeded(); if (image == null) throw new NullPointerException("image = null"); if (template == null) @@ -315,4 +318,27 @@ public class Images { return new Mat(mat, roi); } + public void initOpenCvIfNeeded() { + if (mOpenCvInitialized || OpenCVHelper.isInitialized()) { + return; + } + Activity currentActivity = mScriptRuntime.app.getCurrentActivity(); + Context context = currentActivity == null ? mContext : currentActivity; + mScriptRuntime.console.info("opencv initializing"); + if (Looper.myLooper() == Looper.getMainLooper()) { + OpenCVHelper.initIfNeeded(context, () -> { + mOpenCvInitialized = true; + mScriptRuntime.console.info("opencv initialized"); + }); + } else { + VolatileDispose result = new VolatileDispose<>(); + OpenCVHelper.initIfNeeded(context, () -> { + mOpenCvInitialized = true; + result.setAndNotify(true); + mScriptRuntime.console.info("opencv initialized"); + }); + result.blockedGet(); + } + + } } diff --git a/common/src/main/java/com/stardust/util/ResourceMonitor.java b/common/src/main/java/com/stardust/util/ResourceMonitor.java index 0e506f47..c7a4fa86 100644 --- a/common/src/main/java/com/stardust/util/ResourceMonitor.java +++ b/common/src/main/java/com/stardust/util/ResourceMonitor.java @@ -16,7 +16,7 @@ public final class ResourceMonitor { private static final ConcurrentHashMap, SparseArray> mResources = new ConcurrentHashMap<>(); private static Handler sHandler; - private static boolean mEnabled = BuildConfig.DEBUG; + private static boolean sEnabled = BuildConfig.DEBUG; private static ExceptionCreator sExceptionCreator; private static UnclosedResourceDetectedHandler sUnclosedResourceDetectedHandler; @@ -29,7 +29,7 @@ public final class ResourceMonitor { } public static void onOpen(ResourceMonitor.Resource resource) { - if (!mEnabled) { + if (!sEnabled) { return; } SparseArray map = mResources.get(resource.getClass()); @@ -49,7 +49,7 @@ public final class ResourceMonitor { } public static void onClose(ResourceMonitor.Resource resource) { - if (!mEnabled) { + if (!sEnabled) { return; } SparseArray map = mResources.get(resource.getClass()); @@ -59,7 +59,7 @@ public final class ResourceMonitor { } public static void onFinalize(ResourceMonitor.Resource resource) { - if (!mEnabled) { + if (!sEnabled) { return; } SparseArray map = mResources.get(resource.getClass()); @@ -88,11 +88,11 @@ public final class ResourceMonitor { } public static boolean isEnabled() { - return mEnabled; + return sEnabled; } public static void setEnabled(boolean mEnabled) { - ResourceMonitor.mEnabled = mEnabled; + ResourceMonitor.sEnabled = mEnabled; } public static final class UnclosedResourceException extends RuntimeException { diff --git a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java index 3e4f3d4f..620c2db6 100644 --- a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java +++ b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java @@ -6,7 +6,6 @@ import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; @@ -16,7 +15,6 @@ import android.widget.Toast; import com.stardust.auojs.inrt.autojs.AutoJs; import com.stardust.auojs.inrt.launch.GlobalProjectLauncher; -import com.stardust.autojs.core.opencv.OpenCVHelper; import java.util.ArrayList; import java.util.List; @@ -38,16 +36,11 @@ public class SplashActivity extends AppCompatActivity { setContentView(R.layout.activity_splash); TextView slug = findViewById(R.id.slug); slug.setTypeface(Typeface.createFromAsset(getAssets(), "roboto_medium.ttf")); - final long millis = SystemClock.uptimeMillis(); - OpenCVHelper.initIfNeeded(this, () -> { - long delay = INIT_TIMEOUT - (SystemClock.uptimeMillis() - millis); - if (!Pref.isFirstUsing() || delay <= 0) { - main(); - return; - } - new Handler().postDelayed(SplashActivity.this::main, delay); - }); - + if (!Pref.isFirstUsing()) { + main(); + }else { + new Handler().postDelayed(SplashActivity.this::main, INIT_TIMEOUT); + } } private void main() {