Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

scrcpy+AutoJS

2020/11/14
Word count: 2,366 | Reading time: 9min

scrcpy简介

特点:
利用电脑的键盘和鼠标可以控制手机。把 APK 文件拖拽到电脑窗口即可安装应用到手机,把普通文件拖拽到窗口即可复制到手机。
不需要在手机上安装任何应用。

简单地来说,scrcpy就是通过adb调试的方式来将手机屏幕投到电脑上,并可以通过电脑控制您的Android设备。它可以通过USB连接,也可以通过Wifi连接(类似于隔空投屏),而且不需要任何root权限,不需要在手机里安装任何程序。scrcpy同时适用于GNU / Linux,Windows和macOS。

它的一些特性:

  • 亮度(原生,仅显示设备屏幕)
  • 性能(30~60fps)
  • 质量(1920×1080或以上)
  • 低延迟(35~70ms)
  • 启动时间短(显示第一张图像约1秒)
  • 非侵入性(设备上没有安装任何东西)

此项目为开源项目,Github地址:Genymobile/scrcpy: Display and control your Android device

使用scrcpy的要求

  1. Android设备至少需要API 21(Android 5.0以上版本);
  2. 确保在您的设备上启用了adb调试;
  3. 在某些设备上,您还需要启用其他选项以使用键盘和鼠标控制它。

adb调试的开启一般是多次点击手机系统版本,如我用的是MIUI10,开启方法是 “设置”->“我的设备”->“全部参数”->点击7下MIUI版本,开启“开发者选项”。然后在 “设置”->“更多设置”->“开发者选项” 中同时开启 USB调试USB调试(安全设置)

使用说明

程序使用了Java语言,我们需要在电脑中搭建Java运行环境,参考:Windows10 配置 Java 开发环境

使用USB进行连接

此方式推荐使用,相对更加流畅。

  1. 手机通过USB连接到PC上,首次连接会弹出是否信任该电脑,点击始终信任即可。
  2. 运行adb usb查看是否连接成功
1
2
D:\Github_Run\scrcpy-win64-v1.10>adb usb
restarting in USB mode
  1. 运行scrcpy即可。

使用无线连接

可参考官方文档:Open Source Project - Scrcpy now works wirelessly

此连接方式更加方便快捷,若宽带速率高,使用效果更佳,使用方法也非常简单。

  1. 确保PC和手机在同一Wifi中
  2. 手机先通过USB与PC相连
  3. 在PC上运行 adb tcpip 服务端口,如端口为5555
1
2
D:\Github_Run\scrcpy-win64-v1.10>adb tcpip 5555
restarting in TCP mode port: 5555
  1. 拔下你的设备,断开USB连接
  2. 在PC上运行 adb connect 手机IP:服务端口(手机IP可通过手机的状态信息查看,或者登录路由器查看,一般以192.168开头)
1
2
D:\Github_Run\scrcpy-win64-v1.10>adb connect 192.168.0.4:5555
connected to 192.168.0.4:5555
  1. 运行scrcpy,在cmd中输入scrcpy.exe即可

注: 若要切换回USB模式:adb usb

1
2
3
4
# 附调节比特率和分辨率
$ scrcpy --bit-rate 2M --max-size 800
# 或者简写
$ scrcpy -b2M -m800

AutoJS

一个支持无障碍服务的Android平台上的JavaScript IDE,其发展目标是JsBox和Workflow。
Auto.js使用JavaScript作为脚本语言,目前使用Rhino 1.7.7.2作为脚本引擎,支持ES5与部分ES6特性。

官方教程: https://hyb1996.github.io/AutoJs-Docs/#/?id=autojs
使用教程视频: 笔青居

如何连接?

手机安装使用步骤:

① 开启无障碍服务
② 音量上键停止脚本:当脚本处于无法停止的状态时,使用音量上键强制停止脚本。
③ 开启悬浮窗:
④ 连接手机(如果不习惯在手机上coding, 可以安装作者提供的VsCode插件, 在Vscode上编码: Auto.js-VSCodeExt——插件的使用教程也非常简洁易懂, 在此就不重复了。

连接Autojs

停止脚本

微信朋友圈点赞demo

1
2
3
4
5
6
7
8
9
comment = desc("评论").findOne();
log(comment);
comment.click();
sleep(1000);

// 由于"赞"控件的Clickable是false, 所以点击它的父控件
praise = text("赞").findOne();
praiseParent = praise.parent();
praiseParent.click();

Js知识补充

作用域:

JS只有函数作用域和全局作用域

  • 全局作用域: 如果是显性的写在全局的, 则变量的作用域为全局

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    > /*
    > * 作用域
    > * - 作用域指一个变量的作用的范围
    > * - 在JS中一共有两种作用域:
    > * 1.全局作用域
    > * - 直接编写在script标签中的JS代码,都在全局作用域
    > * - 全局作用域在页面打开时创建,在页面关闭时销毁
    > * - 在全局作用域中有一个全局对象window,
    > * 它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用
    > * - 在全局作用域中:
    > * 创建的变量都会作为window对象的属性保存
    > * 创建的函数都会作为window对象的方法保存
    > * 一切皆对象
    > * - 全局作用域中的变量都是全局变量,
    > * 在页面的任意的部分都可以访问的到
    >
  • 块级作用域: {}为块, {}内即为块级作用域。但是注意JS没有块级作用域, 即块里声明的变量, 作用域实际为全局。—>ES6 新增了let命令,用来声明局部变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束。==>ES6用新增的let,来声明块级作用域的变量。(let另一个特性: let变量不能重复声明–var可以, 以最后的为准, 效果跟python声明变量类似)

    1
    2
    3
    4
    5
    6
    for(var i = 1; i < 10; i++){}
    log(i); // 输出为10


    for(let i = 1; i < 10; i++){}
    log(i); // ReferenceError: "i" is not defined. ([remote]test.js#14)ReferenceError: "i" is not defined.
  • 函数作用域: 在函数内即为函数作用域, 如果不用var表明, 则声明的是全局变量。用var表明是局部变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    > /*
    > * 函数作用域
    > * - 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
    > * - 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的
    > * - 在函数作用域中可以访问到全局作用域的变量
    > * 在全局作用域中无法访问到函数作用域的变量
    > * - 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用
    > * 如果没有则向上一级作用域中寻找,直到找到全局作用域,
    > * 如果全局作用域中依然没有找到,则会报错ReferenceError
    > * - 在函数中要访问全局变量可以使用window对象
    > */
    >
    1
    2
    3
    4
    5
    6
    7
    8
    function test(){
    a = 1;
    var b = 2;
    }

    test();
    log(a); // 输出1
    log(b); // ReferenceError: "b" is not defined. ([remote]test.js#19)ReferenceError: "b" is not defined.

数组

1
2
3
4
5
6
7
8
9
10
a = [1,2,3]		// 第一种声明数组的方式
a.push(4) // 往数组最后添加元素
log(a);
log(a.indexOf(2)); // 找出某元素在数组中的索引
a.pop(); // 弹出最后一个元素
log(a);


b = Array(); // 第二种声明数组的方式
log(b);

数据类型:

  • string、number、boolean、nullundefined
  • Object:Function、Array、Date

可以使用typeof来查看对象的类型

变量函数提前声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
* 变量的声明提前
* - 使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),
* 但是如果声明变量时不使用var关键字,则变量不会被声明提前
*
* 函数的声明提前
* - 使用函数声明形式创建的函数 function 函数(){}
* 它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数
* 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用
*/
/*console.log("a = "+a);
情况1:使用 var a = 123; a是undefined,声明变量在此句之后,但var a 会使变量提前声明,
情况2: 使用 a = 123; a未找到,会报错,因为a未提前声明
a = 123; 等价于 window.a = 123;
var a = 123;*/ 到了此句才赋值,等价于在所有代码之前 声明a var a; 执行到此句再赋值 a=123;

//fun();
//函数声明,会被提前创建
function fun(){
console.log("我是一个fun函数");
}

//函数表达式,不会被提前创建,此句只是提前声明了fun2,不知道是不是函数,可能是变量, undefined而在此次才开始赋值一个函数表达式
var fun2 = function(){
console.log("我是fun2函数");
};
fun2();

Andriod开发知识:

  • packageName: 应用包名
  • applicationName: 应用名
  • currenetActivity: 当前页面

Js是单线程的, 在任务调度上,同步任务优先级最高, 微任务其次(new Promise), 宏任务最后(setInterval, setTimeOut): https://www.bilibili.com/video/BV1NJ411W7wh?p=336

1
2
3
4
5
6
7
8
9
new Promise( (resolve, reject) =>{
resolve(); // 调用resolve表示成功, 调用reject表示失败
console.log("yes") // 第一个大括号里的都是同步任务, 优先级很高
}).then(value =>{ // 成功执行这个. 这个是微任务
console.log("成功")
}, reason => {
console.log("失败") // 失败执行这个. 这个是微任务
})
// 输出结果: yes => 成功

Author: Mrli

Link: https://nymrli.top/2020/11/09/scrcpy-AutoJS/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
南邮校园网CSDN等部分网站图片无法加载解决方案
NextPost >
粒子滤波Matlab代码解读
CATALOG
  1. 1. scrcpy简介
    1. 1.1. 使用scrcpy的要求
    2. 1.2. 使用说明
      1. 1.2.1. 使用USB进行连接
      2. 1.2.2. 使用无线连接
  2. 2. AutoJS
    1. 2.1. 如何连接?
    2. 2.2. 微信朋友圈点赞demo
  3. 3. Js知识补充