diff --git a/app/src/main/assets/sample/悬浮窗/动态悬浮文字.js b/app/src/main/assets/sample/悬浮窗/动态悬浮文字.js index 57c0a943..0bc6c59a 100644 --- a/app/src/main/assets/sample/悬浮窗/动态悬浮文字.js +++ b/app/src/main/assets/sample/悬浮窗/动态悬浮文字.js @@ -4,6 +4,8 @@ var window = floaty.window( ); +window.exitOnClose(); + window.text.click(()=>{ window.setAdjustEnabled(!window.isAdjustEnabled()); }); diff --git a/app/src/main/assets/sample/悬浮窗/悬浮文字.js b/app/src/main/assets/sample/悬浮窗/悬浮文字.js index 26f6134d..5b2e7de1 100644 --- a/app/src/main/assets/sample/悬浮窗/悬浮文字.js +++ b/app/src/main/assets/sample/悬浮窗/悬浮文字.js @@ -4,6 +4,8 @@ var window = floaty.window( ); +window.exitOnClose(); + window.text.click(()=>{ window.setAdjustEnabled(!window.isAdjustEnabled()); }); diff --git a/app/src/main/assets/sample/悬浮窗/悬浮窗运行脚本按钮简单版.js b/app/src/main/assets/sample/悬浮窗/悬浮窗运行脚本按钮简单版.js index a31d9448..205137d4 100644 --- a/app/src/main/assets/sample/悬浮窗/悬浮窗运行脚本按钮简单版.js +++ b/app/src/main/assets/sample/悬浮窗/悬浮窗运行脚本按钮简单版.js @@ -9,6 +9,8 @@ var window = floaty.window( ); +window.exitOnClose(); + var execution = null; window.action.click(()=>{ diff --git a/app/src/main/assets/sample/悬浮窗/悬浮运行脚本按钮.js b/app/src/main/assets/sample/悬浮窗/悬浮运行脚本按钮.js index 8fd9d2d0..69387145 100644 --- a/app/src/main/assets/sample/悬浮窗/悬浮运行脚本按钮.js +++ b/app/src/main/assets/sample/悬浮窗/悬浮运行脚本按钮.js @@ -9,6 +9,8 @@ var window = floaty.window( ); +setInterval(()=>{}, 1000); + var execution = null; //记录按键被按下时的触摸坐标 @@ -33,7 +35,7 @@ window.action.setOnTouchListener(function(view, event){ windowY + (event.getRawY() - y)); //如果按下的时间超过1.5秒判断为长按,退出脚本 if(new Date().getTime() - downTime > 1500){ - exit(); + exit(); } return true; case event.ACTION_UP: @@ -58,5 +60,4 @@ function onClick(){ } } -setInterval(()=>{}, 1000); diff --git a/autojs/src/main/assets/modules/__ui__.js b/autojs/src/main/assets/modules/__ui__.js index 80475138..70cbe9b6 100644 --- a/autojs/src/main/assets/modules/__ui__.js +++ b/autojs/src/main/assets/modules/__ui__.js @@ -75,7 +75,15 @@ module.exports = function(__runtime__, scope){ } view.longClick = function(listener){ if(listener){ - view.setOnLongClickListener(new android.view.View.OnLongClickListener(listener)); + view.setOnLongClickListener(new android.view.View.OnLongClickListener(function(view){ + try{ + var r = listener(view); + return !!r; + }catch(e){ + console.error(e.getMessage()); + return false; + } + })); }else{ view.performLongClick(); } diff --git a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java index 605e7dd8..355e5b30 100644 --- a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java +++ b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java @@ -179,8 +179,6 @@ public class ScriptEngineService { int n = stopAll(); if (n > 0) mUiHandler.toast(String.format(mContext.getString(R.string.text_already_stop_n_scripts), n)); - else - mUiHandler.toast(mContext.getString(R.string.text_no_running_script)); } public Set getEngines() { diff --git a/autojs/src/main/java/com/stardust/autojs/core/console/ConsoleView.java b/autojs/src/main/java/com/stardust/autojs/core/console/ConsoleView.java index cfdf153f..3d85d047 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/console/ConsoleView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/console/ConsoleView.java @@ -17,6 +17,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.stardust.autojs.R; +import com.stardust.concurrent.ConcurrentArrayList; import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow; import com.stardust.util.SparseArrayEntries; @@ -24,7 +25,7 @@ import java.util.ArrayList; /** * Created by Stardust on 2017/5/2. - * + *

* TODO: 优化为无锁形式 */ public class ConsoleView extends FrameLayout implements StardustConsole.LogListener { @@ -153,7 +154,7 @@ public class ConsoleView extends FrameLayout implements StardustConsole.LogListe return; int oldSize = mLogs.size(); ArrayList logs = mConsole.getAllLogs(); - synchronized (logs) { + synchronized (mConsole.getAllLogs()) { final int size = logs.size(); if (size == 0) { return; diff --git a/autojs/src/main/java/com/stardust/autojs/core/console/StardustConsole.java b/autojs/src/main/java/com/stardust/autojs/core/console/StardustConsole.java index 9b13721e..28c1512c 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/console/StardustConsole.java +++ b/autojs/src/main/java/com/stardust/autojs/core/console/StardustConsole.java @@ -2,7 +2,6 @@ package com.stardust.autojs.core.console; import android.content.Context; import android.content.Intent; -import android.os.Looper; import android.support.annotation.NonNull; import android.view.WindowManager; @@ -11,6 +10,7 @@ import com.stardust.autojs.annotation.ScriptInterface; import com.stardust.autojs.runtime.api.AbstractConsole; import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; +import com.stardust.concurrent.ConcurrentArrayList; import com.stardust.enhancedfloaty.FloatyService; import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow; import com.stardust.util.UiHandler; diff --git a/autojs/src/main/java/com/stardust/autojs/core/floaty/FloatyWindow.java b/autojs/src/main/java/com/stardust/autojs/core/floaty/FloatyWindow.java index ab2c6314..f8015b49 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/floaty/FloatyWindow.java +++ b/autojs/src/main/java/com/stardust/autojs/core/floaty/FloatyWindow.java @@ -23,6 +23,7 @@ public class FloatyWindow extends ResizableFloatyWindow { private boolean mCreated = false; private View mMoveCursor; private View mResizer; + private View mCloseButton; private MyFloaty mFloaty; @@ -59,15 +60,22 @@ public class FloatyWindow extends ResizableFloatyWindow { View root = (View) mView.getParent().getParent(); mMoveCursor = root.findViewById(R.id.move_cursor); mResizer = root.findViewById(R.id.resizer); + mCloseButton = root.findViewById(R.id.close); + } + + public void setOnCloseButtonClickListener(View.OnClickListener listener){ + mCloseButton.setOnClickListener(listener); } public void setAdjustEnabled(boolean enabled) { if (!enabled) { mMoveCursor.setVisibility(View.GONE); mResizer.setVisibility(View.GONE); + mCloseButton.setVisibility(View.GONE); } else { mMoveCursor.setVisibility(View.VISIBLE); mResizer.setVisibility(View.VISIBLE); + mCloseButton.setVisibility(View.VISIBLE); } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java b/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java index bd5e3cfd..852b811e 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java +++ b/autojs/src/main/java/com/stardust/autojs/core/inputevent/RootAutomator.java @@ -1,6 +1,7 @@ package com.stardust.autojs.core.inputevent; import android.content.Context; +import android.os.Build; import android.os.SystemClock; import android.support.annotation.Nullable; import android.view.ViewConfiguration; diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index 566448be..e8280977 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -17,6 +17,7 @@ import com.stardust.pio.UncheckedIOException; import org.mozilla.javascript.Callable; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; +import org.mozilla.javascript.ErrorReporter; import org.mozilla.javascript.ImporterTopLevel; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; 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 51dd3ea1..afc3ae0c 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -188,7 +188,7 @@ public class ScriptRuntime { engines = new Engines(builder.mEngineService); dialogs = new Dialogs(app, uiHandler, bridges); device = new Device(uiHandler.getContext()); - floaty = new Floaty(uiHandler, ui); + floaty = new Floaty(uiHandler, ui, this); } public void init() { @@ -295,7 +295,9 @@ public class ScriptRuntime { public void exit() { mThread.interrupt(); - throw new ScriptInterruptedException(); + if (Looper.myLooper() != Looper.getMainLooper()) { + throw new ScriptInterruptedException(); + } } @Deprecated diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java index 5180ca4a..0c54ee89 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java @@ -10,22 +10,15 @@ import com.stardust.autojs.R; import com.stardust.autojs.core.floaty.FloatyWindow; import com.stardust.autojs.core.ui.JsLayoutInflater; import com.stardust.autojs.core.ui.JsViewHelper; -import com.stardust.autojs.rhino.ProxyObject; +import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.concurrent.VolatileDispose; import com.stardust.enhancedfloaty.FloatyService; import com.stardust.util.UiHandler; import com.stardust.util.ViewUtil; -import org.mozilla.javascript.NativeJavaObject; -import org.mozilla.javascript.Scriptable; -import org.mozilla.javascript.ScriptableObject; -import org.mozilla.javascript.UniqueTag; - -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; import java.util.Set; /** @@ -38,9 +31,11 @@ public class Floaty { private Context mContext; private UiHandler mUiHandler; private Set mWindows = new HashSet<>(); + private ScriptRuntime mRuntime; - public Floaty(UiHandler uiHandler, UI ui) { + public Floaty(UiHandler uiHandler, UI ui, ScriptRuntime runtime) { mUiHandler = uiHandler; + mRuntime = runtime; mContext = new ContextThemeWrapper(mUiHandler.getContext(), R.style.AppTheme); mJsLayoutInflater = ui.getJsLayoutInflater(); } @@ -69,20 +64,16 @@ public class Floaty { Iterator iterator = mWindows.iterator(); while (iterator.hasNext()) { JsFloatyWindow window = iterator.next(); - if (Looper.myLooper() == Looper.getMainLooper()) { - window.mWindow.close(); - } else { - mUiHandler.post(() -> window.mWindow.close()); - } + window.close(); iterator.remove(); } } public class JsFloatyWindow { - private Map mViewCache = new HashMap<>(); private View mView; private FloatyWindow mWindow; + private boolean mExitOnClose = false; public JsFloatyWindow(View view) { mWindow = new FloatyWindow(view); @@ -91,6 +82,7 @@ public class Floaty { FloatyService.addWindow(mWindow); }); mWindow.waitFor(); + mWindow.setOnCloseButtonClickListener(v -> close()); //setSize(mWindow.getWindowBridge().getScreenWidth() / 2, mWindow.getWindowBridge().getScreenHeight() / 2); mView = view; } @@ -108,17 +100,17 @@ public class Floaty { } public int getWidth() { - return mWindow.getWindowBridge().getWidth(); + return mWindow.getRootView().getWidth(); } public int getHeight() { - return mWindow.getWindowBridge().getHeight(); + return mWindow.getRootView().getHeight(); } public void setSize(int w, int h) { if (Looper.myLooper() == Looper.getMainLooper()) { ViewUtil.setViewMeasure(mWindow.getRootView(), w, h); - // mWindow.getWindowBridge().updateMeasure(w, h); + // mWindow.getWindowBridge().updateMeasure(w, h); } else { mUiHandler.post(() -> { ViewUtil.setViewMeasure(mWindow.getRootView(), w, h); @@ -147,6 +139,10 @@ public class Floaty { return mWindow.isAdjustEnabled(); } + public void exitOnClose() { + mExitOnClose = true; + } + public void close() { if (!mWindows.remove(this)) { return; @@ -156,6 +152,9 @@ public class Floaty { } else { mUiHandler.post(() -> mWindow.close()); } + if (mExitOnClose) { + mRuntime.exit(); + } } } diff --git a/autojs/src/main/res/layout/floaty_window.xml b/autojs/src/main/res/layout/floaty_window.xml index d62cbd71..b28440bf 100644 --- a/autojs/src/main/res/layout/floaty_window.xml +++ b/autojs/src/main/res/layout/floaty_window.xml @@ -1,42 +1,55 @@ - + - + android:visibility="gone" + tools:visibility="visible"/> + + + android:visibility="gone" + tools:visibility="visible"/> - \ No newline at end of file + \ No newline at end of file diff --git a/common/src/main/java/com/stardust/concurrent/ConcurrentArrayList.java b/common/src/main/java/com/stardust/concurrent/ConcurrentArrayList.java new file mode 100644 index 00000000..429342c1 --- /dev/null +++ b/common/src/main/java/com/stardust/concurrent/ConcurrentArrayList.java @@ -0,0 +1,62 @@ +package com.stardust.concurrent; + +import java.lang.reflect.Array; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by Stardust on 2017/12/30. + */ + +public class ConcurrentArrayList { + + private final Class mTClass; + private volatile T[] mArray; + private final AtomicInteger mSize = new AtomicInteger(); + private final Object mArrayResizeLock = mSize; + + public ConcurrentArrayList(Class tClass) { + mTClass = tClass; + mArray = newArray(10); + } + + public void add(T element) { + int index = mSize.getAndIncrement(); + ensureCapacity(index); + mArray[index] = element; + } + + @SuppressWarnings("unchecked") + public T get(int i) { + int size = mSize.get(); + if (i >= size) { + throw new IndexOutOfBoundsException("i = " + i + ", size = " + size); + } + return mArray[i]; + } + + public int size() { + return mSize.get(); + } + + public Object getArrayResizeLock() { + return mArrayResizeLock; + } + + @SuppressWarnings("unchecked") + private T[] newArray(int size) { + return (T[]) Array.newInstance(mTClass, size); + } + + private void ensureCapacity(int index) { + if (index < mArray.length) + return; + synchronized (mArrayResizeLock) { + if (index < mArray.length) + return; + T[] newArray = newArray(mArray.length * 2); + System.arraycopy(mArray, 0, newArray, 0, mArray.length); + mArray = newArray; + } + } + +}