autojs非常见函数1

简介: 牙叔教程 简单易懂

牙叔教程 简单易懂


隐藏导航栏

-- 惜缘

View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY


隐藏标题栏

-- 大柒

activity.requestWindowFeature(Window.FEATURE_NO_TITLE);


img设置自带图标

let RID = resources.getIdentifier("ic_accessibility_black_48dp", "drawable", context.getPackageName());
view.setImageResource(RID);


全屏

-- 大柒

"ui";
importClass(android.view.WindowManager);
full(true);
//是否全屏
function full(enable) {
  if (enable) {
    //设置全屏
    let lp = activity.getWindow().getAttributes();
    lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
    activity.getWindow().setAttributes(lp);
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  } else {
    //取消全屏
    let attr = activity.getWindow().getAttributes();
    attr.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
    activity.getWindow().setAttributes(attr);
    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  }
}


全屏

--惜缘

"ui";
importClass(android.view.WindowManager);
importClass(android.view.View);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity
  .getWindow()
  .getDecorView()
  .setSystemUiVisibility(
    android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR |
      android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
      android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
      android.view.View.SYSTEM_UI_FLAG_FULLSCREEN
  );
ui.layout(
  <vertical>
    <img layout_gravity="center" id="img" w="*" h="*" bg="#0000ff" scaleType="centerCrop" src="file://./111.jpg" />
  </vertical>
);


彩图转灰度图

images.cvtColor(img, "RGBA2GRAY");


手机底部导航栏高度

-- 大柒

"ui";
var realPoint = new android.graphics.Point();
activity.getWindowManager().getDefaultDisplay().getRealSize(realPoint);
var height = activity.getWindowManager().getDefaultDisplay().getHeight();
var navigation_bar_height = realPoint.y - height;
console.log("navigation_bar_height", navigation_bar_height);


设置Material主题

-- ╰つ゛无名大姐‭

activity.theme.applyStyle(ui.R.style["Base.V14.Theme.Material3.Dark"], true);
"ui";
context.theme.applyStyle(ui.R.style["Base.V14.Theme.Material3.Dark"], true);
ui.layout(
  <vertical>
    <vertical w="*" h="auto" id="ver"></vertical>
  </vertical>
);
importClass("com.google.android.material.textfield.TextInputLayout");
aa = new TextInputLayout(context);
aa.setHint("请输入用户名");
aa.addView(new android.widget.EditText(context));
ui.ver.addView(aa);
aa = new TextInputLayout(context);
aa.setHint("请输入密码");
aa.addView(new android.widget.EditText(context));
ui.ver.addView(aa);


修改按钮背景色

-- 抠脚

-- 大柒

view.getBackground().setColorFilter(colors.RED, PorterDuff$Mode.MULTIPLY);
或者
view.attr('backgroundTint',colorstr);


打开文件选择器

intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
activity.startActivityForResult(Intent.createChooser(intent, "选择图片"), 1);


指定参数类型

// 方法 指定参数类型
p["setShadowLayer(float,float,float,int)"](100, 0, 0, new java.lang.Long(Color.RED));
p["setShadowLayer(float,float,float,int)"](100, 0, 0, $colors.RED);
// 构造函数 指定参数类型
let radialGradient = new RadialGradient["(float,float,float,int[],float[],android.graphics.Shader$TileMode)"](
  centerX,
  centerY,
  radius,
  radialColors,
  positionList,
  Shader.TileMode.REPEAT
);


判断手机32还是64位

importClass(java.lang.System);
importClass(android.os.Build);
let mCPU = Build.CPU_ABI == "arm64-v8a" ? "64位" : "32位";
let mCPU2 = System.getProperty("os.arch").indexOf("64") != -1 ? "64位" : "32位";
log(mCPU + " " + mCPU2);


java类是否有某个字段

function hasField(classFullName, fieldName) {
  classFullName = classFullName || "android.view.WindowManager$LayoutParams";
  fieldName = fieldName || "LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES";
  let clazz = java.lang.Class.forName(classFullName);
  let fields = clazz.getDeclaredFields();
  let bool = false;
  for (let i = 0; i < fields.length; i++) {
    if (fields[i].getName().equals(fieldName)) {
      bool = true;
      break;
    }
  }
  return bool;
}


内置图标转drawable

const resources = context.getResources();
let imgId = resources.getIdentifier("ic_keyboard_arrow_left_black_48dp", "drawable", context.getPackageName());
let drawable = resources.getDrawable(imgId);


获取当前包名

--  @Ai:下个版本修复不受限制的问题

const _current_pacakge = currentPackage;
let currentPackage = function () {
  let start = new Date().getTime();
  try {
    if (!runtime.getAccessibilityBridge()) {
      return _current_pacakge();
    }
    // 通过windowRoot获取根控件的包名,理论上返回一个 速度较快
    let windowRoots = runtime.getAccessibilityBridge().windowRoots();
    if (windowRoots && windowRoots.size() > 0) {
      log(["windowRoots size: {}", windowRoots.size()]);
      for (let i = 0; i < windowRoots.size(); i++) {
        let root = windowRoots.get(i);
        if (root !== null && root.getPackageName()) {
          return root.getPackageName();
        }
      }
    }
    // windowRoot获取失败了通过service.getWindows获取根控件的包名,按倒序从队尾开始获取 速度相对慢一点
    let service = runtime.getAccessibilityBridge().getService();
    let serviceWindows = service !== null ? service.getWindows() : null;
    if (serviceWindows && serviceWindows.size() > 0) {
      log(["windowRoots未能获取包名信息,尝试service window size: {}", serviceWindows.size()]);
      for (let i = serviceWindows.size() - 1; i >= 0; i--) {
        let window = serviceWindows.get(i);
        if (window && window.getRoot() && window.getRoot().getPackageName()) {
          return window.getRoot().getPackageName();
        }
      }
    }
    log(["service.getWindows未能获取包名信息,通过currentPackage()返回数据"]);
    // 以上方法无法获取的,直接按原方法获取包名
    return _current_pacakge();
  } finally {
    log(["获取包名总耗时:{}ms", new Date().getTime() - start]);
  }
};
log(currentPackage());


主动调用按钮点击事件

"ui";
ui.layout(
    <vertical>
        <button id="btn">按钮
        </button>
    </vertical>
)
ui.btn.click(function() {
    toastLog("牙叔教程\n简单易懂")
})
// 注意要在UI线程中,执行点击代码。
ui.post(
    function() {
        ui.btn.performClick();
    },2000
)


设置按钮三秒后才能点击

"ui";
ui.layout(
  <vertical>
    <button id="btn" text="按钮" />
  </vertical>
);
ui.btn.click(function () {
  toastLog("按钮被点击");
  ui.btn.setText("按钮已被点击");
  ui.btn.setEnabled(false);
  setTimeout(function () {
    ui.btn.setEnabled(true);
    ui.btn.setText("按钮");
  }, 3000);
});


一开始不要显示输入法

activity.getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);


关闭输入法

"ui";
ui.layout(
  <vertical>
    <button id="btn">关闭输入法</button>
    <input w="*" id="input" />
  </vertical>
);
ui.btn.on("click", () => {
  //取消焦点代码
  ui.input.clearFocus();
  //隐藏键盘代码
  let imm = ui.btn.getRootView().getContext().getSystemService(context.INPUT_METHOD_SERVICE);
  imm.hideSoftInputFromWindow(ui.btn.getWindowToken(), android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS);
});


状态栏高度

const resources = context.getResources();
const status_bar_height = resources.getDimensionPixelSize(resources.getIdentifier("status_bar_height", "dimen", "android"));


状态栏高度2

let rect = new android.graphics.Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
statusBarHeights = rect.top;


获取图片在ImageView中的坐标

function getImageBounds(imageView) {
  let bounds = new android.graphics.RectF();
  drawable = imageView.getDrawable();
  if (drawable != null) {
    imageView.getImageMatrix().mapRect(bounds, new android.graphics.RectF(drawable.getBounds()));
  }
  return bounds;
}


java多线程

new java.lang.Thread(
  new java.lang.Runnable(function run() {
    toastLog("Thread Runnable");
  })
).start();



adb查看内存信息

参考:

adb shell dumpsys meminfo 详解

adb shell dumpsys 命令 查看内存

adb shell dumpsys meminfo org.autojs.autojspro


查看单个应用最大内存限制

adb shell "getprop|grep heapgrowthlimit"
// C:\Users\Administrator>adb shell "getprop|grep heapgrowthlimit"
// [dalvik.vm.heapgrowthlimit]: [256m]


根据进程的名字使用 grep 指令过滤输出 "org.autojs.autojspro" 进程的信息

-d: 时间间隔, -d 3, 间隔3秒

参考: adb shell top 命令

adb shell
top -d 3 | grep "org.autojs.autojspro"


下拉框spinner

--品尚名品

"ui";
ui.layout(
  <vertical padding="16">
    <horizontal>
      <text textSize="16sp">下拉菜单</text>
      <spinner id="sp1" entries="aaa|bbb|ccc" />
    </horizontal>
    <horizontal>
      <text textSize="16sp">对话框菜单</text>
      <spinner id="sp2" entries="ddd|eee|fff" spinnerMode="dialog" />
    </horizontal>
    <button id="ok">确定</button>
    <button id="select3">设置指定选项</button>
  </vertical>
);
ui.ok.on("click", () => {
  //获取选中项对应的索引值value
  var i = ui.sp1.getSelectedItemPosition();
  var j = ui.sp2.getSelectedItemPosition();
  toastLog("您的选择是选项" + i + "和选项" + j);
  var z = ui.sp1.getSelectedItem().toString();
  var x = ui.sp2.getSelectedItem().toString();
  toastLog("您的选择内容是" + z + "和" + x);
});
ui.select3.on("click", () => {
  //根据索引值value设定选项
  ui.sp1.setSelection(2);
  //获取ui.sp1  Adapter对象
  ui.sp1.getAdapter();
  //获取ui.sp1 下共有几个选项
  ui.sp1.getAdapter().getCount();
  //获取ui.sp1 对象下指定值的索引位置
  ui.sp1.getAdapter().getPosition("ccc");
  //根据值直接设置下拉菜单选中项  必须准确填写getPosition("")里的值 否则会出错
  ui.sp1.setSelection(ui.sp1.getAdapter().getPosition("ccc"));
  //先判断值是否存在再设置 不存在的情况下不会出错
  let 设定值 = "你好";
  if (ui.sp1.getAdapter().getPosition(设定值) != -1) {
    ui.sp1.setSelection(ui.sp1.getAdapter().getPosition(设定值));
  } else {
    toastLog("该选项不存在: " + 设定值 + " 无法完成设置!");
  }
});


drawable转Bitmap

--稻草人

importClass(android.graphics.Bitmap);
importClass(android.graphics.Canvas);
importClass(android.graphics.PixelFormat);
function drawableToBitmap(drawable) {
    let bitmap = Bitmap.createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
            drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
    let canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    return bitmap;
}


横竖屏判断

--抠脚本人

var a = context.resources.configuration.orientation;
if (a === 1) {
  toastLog("这是竖屏!!");
} else {
  toastLog("这是横屏!!");
}


获取屏幕旋转的方向

var windowManager = context.getSystemService(Context.WINDOW_SERVICE);
//by 板蓝根isatis
function getRotation() {
    return windowManager.getDefaultDisplay().getRotation();
}
//0 1 2 3分别对应 上 左 下 右


指定引擎运行代码

let src = new com.stardust.autojs.script.StringScriptSource("<code>", "toast(1)");
engines.myEngine().execute(src);


获取图片所有像素点的值

let img = images.read("/sdcard/1.png");
let r = getPixelsOfBitmap(img.bitmap);
log(r);
img.recycle();
function getPixelsOfBitmap(bitmap) {
  let width = bitmap.getWidth();
  let height = bitmap.getHeight();
  console.log("width=", width, "  height=", height);
  let pixels = util.java.array("int", width * height);
  let offset = 0;
  let stride = width;
  let x = 0;
  let y = 0;
  bitmap.getPixels(pixels, offset, stride, x, y, width, height);
  return pixels;
}


或者用图片路径, 也可以获取所有像素点

images.readPixels(path)

  • path{string} 图片的地址
  • 返回 {Object} 包括图片的像素数据和宽高,{data,width,height}

读取图片的像素数据和宽高。

保存画板canvas上的图片

-- @No evil ·火封

let bitmap = android.graphics.Bitmap.createBitmap(600, 600, android.graphics.Bitmap.Config.ARGB_8888);
let canvas = new Canvas(bitmap);
let paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(100); //设置画笔宽度
paint.setColor(colors.parseColor("#FF000000"));
canvas.drawRect(100, 100, 500, 500, paint);
let img = canvas.toImage();
let imgPath = "/sdcard/1.png";
img.saveTo(imgPath);
app.viewFile(imgPath);
img.recycle();


启用悬浮控制条,控制脚本worker.js

$engines.startFloatingController("./worker.js");


crash

-- @筱枫  

app.startActivity({
  packageName: "org.autojs.autojspro",
  className: "com.stardust.autojs.core.activity.CrashReportActivity",
});


类增加属性

"nodejs";
require("rhino").install();
const ArrayList = java.util.ArrayList;
const list = new ArrayList();
list.add(123);
ArrayList.prototype.first = function() {
    return this.get(0);
}
console.log(list.first());


bitmap转Image对象

-- @I'm zz  

var img = com.stardust.autojs.core.image.ImageWrapper.ofBitmap(bitmap);
let autojsMat = new com.stardust.autojs.core.opencv.Mat(mat1, new org.opencv.core.Rect(0, 0, w, h));
var img = com.stardust.autojs.core.image.ImageWrapper.ofMat(autojsMat);


选择图片

$images.select().on("result", img => {})
on("process") // 可以获取到URI


继承java抽象类

--李小波


JavaAdapter(需要重写的类,{重写的方法},参数...)
//参数决定使用哪个构造方法  

autojs实现抽象类的继承

// 无障碍异步监听
auto.registerEvent("view_clicked", (e) => {
  js +=
    'id("' +
    e.source.id() +
    '").text("' +
    e.source.text() +
    '").desc("' +
    e.source.desc() +
    '").findOne().click();\nsleep(500);\n';
});
// 判断稳定模式
toast(serviceFlag = auto.service.serviceInfo.flags == 122 ? "正常" : "稳定模式")
// 过滤窗口
function 查找指定app窗口(appName) {
  log(arguments.callee.name);
  let windowList = auto.windows;
  var len = windowList.length;
  for (var i = 0; i < len; i++) {
    let item = windowList[i];
    if (item.title) {
      if (item.title === appName) {
        return item;
      }
    }
  }
  throw new Error("没有找到指定app窗口: " + appName);
}
function 获取当前页面内容(appName) {
  log(arguments.callee.name);
  let window = 查找指定app窗口(appName);
  let views = com.stardust.automator.UiObject.Companion.createRoot(window.getRoot()).find(
    idEndsWith("tv_title").visibleToUser(true).boundsInside(0, 0, device.width, device.height)
  );
  if (views && views.length > 0) {
    let arr = [];
    var len = views.length;
    for (var i = 0; i < len; i++) {
      let item = views[i];
      arr.push(item.text());
    }
    return arr.join(", ");
  } else {
    return "";
  }
}
// 无障碍返回
auto.service.performGlobalAction(1);
// 获取自己的app的控件缓存
View.getDrawable().getBitmap()
// 清空图片缓存
$ui.imageCache.clearDiskCache();
$ui.imageCache.clearMemory();
// 设置光标位置
ui.授权码.setOnFocusChangeListener({
    onFocusChange: function(view, hasFocus) {
        if (hasFocus) {
            view.setInputType(144);
            view.setSelection(view.getText().length());
        } else {
            view.setInputType(129);
        }
        cardStr = view.text()
    }
});
context.getSystemService(context.USAGE_STATS_SERVICE);
// 这个值就是ui绑定变量的上下文
runtime.ui.bindingContext
pool.shutdownNow();
pool.shutdown();
let status = pool.awaitTermination(1000, java.util.concurrent.TimeUnit.SECONDS);
new RootAutomator({adb: true})
runtime.gc()
console.error($debug.getStackTrace(e))
// 这行代码也许能刷新节点
auto.service.serviceInfo =  auto.service.serviceInfo;
auto.clearCache();
便签 = id("rich_editor").findOne()
toast(便签.text())
sleep(2000)
便签.refresh()
toast(便签.text())
// 当前包名
context.packageName
new java.util.Timer().schedule(new java.util.TimerTask({
run: () => {
launch(context.getPackageName())
},
}), 2000);
java.lang.Runtime.getRuntime().exit(0);
// 重启自己
"ui";
let args = $engines.myEngine().execArgv;
let id = (args && args["id"]) || 0;
ui.layout(
    <frame>
        <text text="页面{{id}}"/>
    </frame>
);
if (id === 0) {
    toast("2秒后进入页面1");
    ui.post(() => {
        $engines.execScriptFile("./main.js", {
            arguments: {
                id: id + 1
            }
        });
    }, 2000)
} else if (id === 1) {
    toast("2秒后重启");
    ui.post(() => {
        let Process = android.os.Process;
        Process.killProcess(Process.myPid())
    }, 2000)
}
requestScreenCaptureAsync(); // 返回promise
new Shell().exec("logcat -f /sdcard/脚本/log.txt");
var dcl=new Packages.dalvik.system.DexClassLoader(dexpath, dirpath, jnipath, java.lang.ClassLoader.getSystemClassLoader());
var cls=dcl.loadClass("com.jia.testso.Main");
var api=cls.newInstance();
api.init(context.getClass().getClassLoader());
$shell.isRootAvailable();
$shell.checkAccess("root");
$shell.setDefaultOptions({adb: true})
// 屏幕方向
context.resources.configuration.orientation








相关文章
|
4月前
|
API
AutoJs4.1.0开发心得
AutoJs4.1.0开发心得
30 0
|
4月前
AutoJs4.1.0 部局范围次分析
AutoJs4.1.0 部局范围次分析
23 0
|
Java Android开发
autojs非常见函数2
autojs非常见函数2
879 0
|
XML Android开发 数据格式
autojs一键锁屏
牙叔教程 简单易懂
429 0
|
4月前
|
缓存 数据安全/隐私保护 Python
AutoJs超神级代码分享大更新
AutoJs超神级代码分享大更新
56 0
|
4月前
|
缓存 Python
最后一次AutoJs超神级代码分享
最后一次AutoJs超神级代码分享
41 0
|
Android开发
autojs提词器
拍短视频 ● 忘词 ● 记不住台词 有了提词器, 就再也不怕忘词儿了
281 0
|
Java Android开发 C语言
autojs调用C
autojs调用C
275 0
|
人工智能 Android开发
autojs代码片段
牙叔教程 简单易懂
316 0
|
测试技术 Android开发
autojs色卡
牙叔教程 简单易
162 0