自动上滑脚本

自用库

目前为 2024-12-28 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/521999/1511077/%E8%87%AA%E5%8A%A8%E4%B8%8A%E6%BB%91%E8%84%9A%E6%9C%AC.js

  1. importClass(android.content.Context);
  2. importClass(android.provider.Settings);
  3. importClass(android.app.KeyguardManager);
  4. try {
  5. var km = context.getSystemService(Context.KEYGUARD_SERVICE);//km.isKeyguardLocked(),km.isKeyguardSecure()
  6. let enabledServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
  7. //log('当前已启用的辅助服务\n', enabledServices);
  8. if (!enabledServices.match(/.*org\.autojs\.autoxjs\.v6\/com\.stardust\.autojs\.core\.accessibility\.AccessibilityService.*/g)) {
  9. let Services = (enabledServices ? enabledServices + ":" : "") + "org.autojs.autoxjs.v6/com.stardust.autojs.core.accessibility.AccessibilityService";
  10. Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, Services);
  11. Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, '1');
  12. sleep(3000);
  13. }
  14. toastLog("成功开启AutoJS的辅助服务");
  15. } catch (error) {
  16. //受权方法:开启usb调试并使用adb工具链接手机,执行 adb shell pm grant org.autojs.autoxjs.v6 android.permission.WRITE_SECURE_SETTING
  17. toastLog("请受权AutoJS启用辅助服务");
  18. }
  19. auto.waitFor();
  20. //停止其它脚本
  21. engines.all().map((ScriptEngine) => {
  22. if (engines.myEngine().toString() !== ScriptEngine.toString()) {
  23. ScriptEngine.forceStop();
  24. }
  25. });
  26. //============================================================
  27. var AppName = ["抖音极速版","快手极速版"];
  28. var runAppName = AppName[0], times = 100; //滑动次数
  29. toastLog('当前分辨率:'+device.width+'X'+device.height);
  30. //toastLog('唯一标识码:'+device.fingerprint);
  31.  
  32.  
  33. //息屏状态将屏幕唤醒
  34. global.opentimes=0;
  35. while (!device.isScreenOn() || km.isKeyguardLocked()) {
  36. opentimes++;
  37. device.wakeUp();//唤醒设备
  38. toastLog('屏幕唤醒');
  39. sleep(1500); //等待屏幕亮起
  40. back();//如果锁屏后收到新消息,上滑不能解锁屏幕,需要返回一次后上滑
  41. device.keepScreenOn();//一直保持屏幕常亮
  42. sleep(1500);
  43. if (km.isKeyguardSecure()) {
  44. toastLog('密码解锁');
  45. //待开发
  46. break;
  47. } else {
  48. toastLog('上滑解锁');
  49. swipe(device.width / 2, device.height * 0.8, device.width / 2, device.height * 0.3, 400);
  50. }
  51. sleep(1500);
  52. if(opentimes>3){
  53. toastLog('解锁失败,请尝试重启本软件并开启无障碍服务');
  54. break;
  55. }
  56. }
  57. global.oledwin=null;
  58. global.looptimes=times;
  59. function Main() {
  60. toastLog('进入主程序');
  61. for (i = 0; i < AppName.length; i++) {
  62. looptimes=times;
  63. var packageName = getPackageName(AppName[i]);
  64. if (packageName) {
  65. toastLog('启动应用:' + AppName[i]);
  66. var appstate = launchApp(AppName[i]);
  67. sleep(5000);
  68. if (appstate) {
  69. toastLog("应用正在运行");
  70. } else {
  71. toastLog("无法自启动,需模拟点击");
  72. home();
  73. sleep(3000);
  74. var app = id("item_title").text(AppName[i]).visibleToUser(true).findOne(2000);
  75. if (app) {
  76. click(app.bounds().centerX(), app.bounds().top - 50);
  77. sleep(10000);
  78. }
  79. }
  80. runAppName=AppName[i];//安全线程中使用
  81. while (looptimes > 0) {
  82. //toastLog(currentActivity());
  83. var tiktokhomepage = className("Button").descStartsWith("侧边栏").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOnce();
  84. var giftshowhomepg = id('com.kuaishou.nebula:id/left_btn').clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOnce();
  85. if (tiktokhomepage||giftshowhomepg) {
  86. looptimes--;
  87. var videoDuration = 0;
  88. if(AppName[i]=='抖音极速版'){
  89. var seekBar=className('android.widget.SeekBar').desc('进度条').findOne(1000);
  90. }else{
  91. var seekBar=className('android.widget.HorizontalScrollView').id('com.kuaishou.nebula:id/tab_layout').findOne(1000);
  92. }
  93. if (seekBar) {
  94. isvideo = true;
  95. let y1 = seekBar.bounds().top-5;
  96. let x1 = random(100, 300);
  97. let x2 = random(500, 800);
  98. let duration_thread = threads.start(function () {
  99. videoDuration = getDouyinVideoDuration();
  100. duration_thread.interrupt();
  101. });
  102. gesture(random(800, 1200), [ [x1, y1],[x2, y1],[x1, y1] ]);
  103. console.log("视频时长:",videoDuration+'s');
  104. }
  105. var sleepTime=(videoDuration>0&&videoDuration<180)?videoDuration:random(6, 30);//每个视频随机时间 6-30秒
  106. console.verbose("浏览:" + (times-looptimes), "停留:" + sleepTime + "s");
  107. cutDownBySleep(sleepTime,'观看视频');
  108. randomHeart();//拟人化
  109. } else {
  110. var living = id("root").desc("关闭").clickable(true).boundsInside(device.width-300, 0, device.width, 300).visibleToUser(true).findOne(1000);//直播间
  111. if (living) {
  112. isvideo = true;
  113. toastLog("1.退出直播间");
  114. click(living.bounds().centerX(), living.bounds().centerY());
  115. sleep(2000);
  116. }
  117. if (currentActivity() == 'com.ss.android.ugc.aweme.live.LivePlayActivity') {
  118. toastLog("2.退出直播间");
  119. isvideo = true;
  120. back();
  121. }
  122. toast('不在抖音或快手页面');
  123. oledwin=null;
  124. sleep(3000);
  125. }
  126. }
  127. closeApp(runAppName);
  128. } else {
  129. toastLog("未安装:" + AppName[i]);
  130. }
  131. }
  132. toastLog("自动刷屏完成");
  133. try {
  134. device.cancelKeepingAwake();
  135. //熄屏
  136. runtime.accessibilityBridge.getService().performGlobalAction(android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
  137. } catch (e) {
  138.  
  139. }
  140. //停止本脚本
  141. engines.myEngine().forceStop();
  142. }
  143.  
  144.  
  145. /**
  146. * 倒计时
  147. * @param {倒计时秒} lasterSecend
  148. * @param {显示提示} message
  149. */
  150. function cutDownBySleep(lasterSecend, message) {
  151. message = message || "";
  152. floaty.closeAll();
  153. var fwin = floaty.rawWindow(
  154. `<vertical id="frame" alpha="0" w="{{device.width-500}}px" h="150px">
  155. <card w="auto" h="auto" layout_gravity="center" cardCornerRadius="5dp" cardBackgroundColor="#eeeeee" >
  156. <text id="title" text="" textColor="#333333" textSize="13sp" padding="12 8" />
  157. </card>
  158. </vertical>`
  159. );
  160. fwin.setTouchable(false);
  161. sleep(500);
  162. for (let i = lasterSecend; i > 0; i--) {
  163. if (oledwin) { break; }
  164. if (!fwin || !fwin.title) { break; }
  165. ui.run(() => {
  166. fwin.title.setText(message + "剩余" + i + "秒");
  167. fwin.frame.attr("alpha", 0.8);
  168. fwin.setTouchable(false);
  169. let x = parseInt((device.width - fwin.width) / 2);
  170. let y = device.height-550;
  171. fwin.setPosition(x, y);
  172. });
  173. sleep(1000);
  174. }
  175. fwin=null;
  176. floaty.closeAll();
  177. sleep(500);
  178. }
  179. //视频时长(秒)获取函数
  180. function getDouyinVideoDuration() {
  181. var durationText = className('TextView').textMatches(/[0-9]+:[0-9]+/).boundsInside(device.width/2, 2 * device.height / 3, device.width, device.height).findOne(2000);
  182. //log(durationText);
  183. if (durationText) {
  184. var durationStr = durationText.text();
  185. //log('1',durationStr);
  186. var durationMatch = durationStr.match(/[0-9]+:[0-9]+/);
  187. if (durationMatch) {
  188. //log('2',durationMatch);
  189. var minutes = 0,seconds = 0;
  190. var parts = durationMatch[0].split(":");
  191. if (parts.length === 2) {
  192. //log('3',parts);
  193. minutes = parseInt(parts[0], 10);
  194. seconds = parseInt(parts[1], 10);
  195. return minutes * 60 + seconds + 3;
  196. }
  197. }
  198. }
  199. return 0;
  200. }
  201. //=============================================================
  202. /**随机拟人化(防止被判定是机器)**/
  203. function randomHeart(num) {
  204. if (7!=num&&text('当前无新视频').visibleToUser(true).findOne(1000)) {
  205. console.log("当前无新视频");
  206. click(device.right - 100, device.top - 100);
  207. randomHeart(7);//切换频道
  208. sleep(1000);
  209. return;
  210. }
  211. let randomIndex = num ? num : random(1, 30);
  212. //加速播放
  213. if(randomIndex % 9 == 0){
  214. var seekBar=className('android.widget.SeekBar').descMatches(/.*进度条.*/).findOne(1000);
  215. if(seekBar){
  216. let x1=random(90, 120);
  217. let y1=device.height/3;
  218. gestures([0, 1500, [x1,y1], [x1,y1]],[1400, 1500, [x1,y1], [1.1*x1, 2*y1]]);
  219. return;
  220. }
  221. }
  222. //随机下滑
  223. if (randomIndex % 8 == 0) {
  224. console.log('拟人:随机下滑');
  225. swipe(device.width / 2, device.height * 0.1 + randomIndex, device.width / 2, device.height * 0.9 - randomIndex, random(500, 1500));
  226. return;
  227. }
  228. //随机切换频道
  229. if (randomIndex == 7) {
  230. var idList = [];
  231. className('TextView').clickable(true).descEndsWith(',按钮').boundsInside(0, 0, device.width, 300).find().forEach(function(tv){
  232. if(!tv.desc().match(/.*已选中.*|.*团购.*|.*商城.*|.*热点.*|.*直播中.*/)){
  233. //log(tv.desc());
  234. idList.push(tv);
  235. }
  236. });
  237. if(idList.length>0){
  238. let index = random(1, idList.length) - 1;
  239. console.log('拟人:切换频道:' + idList[index].desc());
  240. idList[index].click();
  241. sleep(2000);
  242. if (text('发现通讯录朋友').visibleToUser(true).findOne(1000)) {
  243. console.log("关注中没有视频");
  244. randomHeart(7);//再次切换频道
  245. sleep(2000);
  246. slidingByCurve();
  247. }
  248. return;
  249. }
  250. }
  251. //连续上滑
  252. if (randomIndex == 6) {
  253. console.log('拟人:连续上滑');
  254. var k = random(2, 4);
  255. for (var i = 0; i < k; i++) {
  256. var j = random(2, 5);
  257. if (j == 3) {
  258. swipe(device.width / j, device.height * 0.1 + j * k, device.width / j, device.height * 0.9 - j * k, j * 50);
  259. } else {
  260. swipe(device.width / j, device.height * 0.9 - j * k, device.width / j, device.height * 0.1 + j * k, j * 50);
  261. }
  262. sleep(j * 250);
  263. }
  264. return;
  265. }
  266. //随机恢复到首页
  267. if(randomIndex % 4 == 0){
  268. console.log('拟人:随机回首页');
  269. sleep(3000);back();sleep(3000);back();sleep(3000);
  270. return;
  271. }
  272. //向上滑
  273. slidingByCurve();
  274. }
  275.  
  276. /**------------------------------------------------------------
  277. * 从下往上滑动,随机坐标
  278. */
  279. function slidingByLine() {
  280. // top X,Y范围
  281. tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
  282. ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
  283. // bottom X,Y 范围
  284. bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
  285. by = randomPointLoc(parseInt(3 * device.height / 4), parseInt(4 * device.height / 5));
  286.  
  287. slidingTime = randomRangeTime(0.8, 1.3);
  288. log("上滑:随机直线");
  289. //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
  290. swipe(bx, by, tx, ty, slidingTime);
  291. }
  292.  
  293. /*从下往上滑动,曲线滑动,随机坐标*/
  294. function slidingByCurve() {
  295. // top X,Y范围
  296. tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
  297. ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
  298. // bottom X,Y 范围
  299. bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
  300. by = randomPointLoc(parseInt(3 * device.height / 4), parseInt(4 * device.height / 5));
  301.  
  302. slidingTime = randomRangeTime(0.2, 0.6);
  303. log("上滑:仿真曲线");
  304. //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
  305. sml_move(bx, by, tx, ty, slidingTime);
  306. }
  307.  
  308. /**
  309. * 上部左右滑动
  310. */
  311. function left2right(direction) {
  312. var intX=parseInt(Math.random()*200+400);
  313. var intY=parseInt(Math.random()*200+200);
  314. var distance=parseInt(Math.random()*100+device.height/4);
  315. switch (direction) {
  316. case 1:
  317. //向上小距离
  318. sml_move(intX, intY + distance, intX, intY, 400);
  319. break;
  320. case 2:
  321. //向下小距离
  322. sml_move(intX, intY, intX, intY + distance, 400);
  323. break;
  324. case 3:
  325. //向左翻屏
  326. sml_move(
  327. device.width / 2 + parseInt(Math.random() * 100) + 300,
  328. device.height / 4 - parseInt(Math.random() * 200) + 100,
  329. 0 + parseInt(Math.random() * 100),
  330. device.height / 5 + parseInt(Math.random() * 100),
  331. 500
  332. );
  333. break;
  334. case 4:
  335. //向右翻屏
  336. sml_move(
  337. device.width / 2 - parseInt(Math.random() * 100) - 300,
  338. device.height / 5 - parseInt(Math.random() * 200) + 100,
  339. device.width - parseInt(Math.random() * 100),
  340. device.height / 4 + parseInt(Math.random() * 100),
  341. 500
  342. );
  343. break;
  344. }
  345. sleep(1000);
  346. }
  347.  
  348. /**
  349. * 随机位置点
  350. * @param {起始值} start
  351. * @param {结束值} end
  352. * @returns
  353. */
  354. function randomPointLoc(start,end){
  355. len = Math.abs(end - start);
  356. loc = Math.floor(Math.random() * len) + start;
  357. return loc;
  358. }
  359.  
  360. /**
  361. * 从几秒到几秒
  362. * @param {开始秒} start
  363. * @param {结束秒} end
  364. * @returns
  365. */
  366. function randomRangeTime(start,end){
  367. len = Math.abs(end -start)*1000;
  368. ms = Math.floor(Math.random() * len) + start*1000;
  369. return ms;
  370. }
  371.  
  372. /**
  373. * 仿真随机带曲线滑动
  374. * @param {起点x} qx
  375. * @param {起点y} qy
  376. * @param {终点x} zx
  377. * @param {终点y} zy
  378. * @param {滑动时间,单位毫秒} time
  379. */
  380. function sml_move(qx, qy, zx, zy, time) {
  381. var xxy = [time];
  382. var point = [];
  383. var dx0 = {
  384. "x": qx,
  385. "y": qy
  386. };
  387. var dx1 = {
  388. "x": random(qx - 150, qx + 150),
  389. "y": random(qy, qy + 50)
  390. };
  391. var dx2 = {
  392. "x": random(zx - 150, zx + 150),
  393. "y": random(zy, zy + 50),
  394. };
  395. var dx3 = {
  396. "x": zx,
  397. "y": zy
  398. };
  399. for (var i = 0; i < 4; i++) {
  400. eval("point.push(dx" + i + ")");
  401. }
  402. // log(point[3].x)
  403. for (let i = 0; i < 1; i += 0.08) {
  404. let newPoint=bezier_curves(point, i);
  405. xxyy = [parseInt(newPoint.x), parseInt(newPoint.y)]
  406. xxy.push(xxyy);
  407. }
  408. try {
  409. gesture.apply(null, xxy);
  410. } catch (e) {
  411. log(xxy);
  412. }
  413. }
  414. function bezier_curves(cp, t) {
  415. cx = 3.0 * (cp[1].x - cp[0].x);
  416. bx = 3.0 * (cp[2].x - cp[1].x) - cx;
  417. ax = cp[3].x - cp[0].x - cx - bx;
  418. cy = 3.0 * (cp[1].y - cp[0].y);
  419. by = 3.0 * (cp[2].y - cp[1].y) - cy;
  420. ay = cp[3].y - cp[0].y - cy - by;
  421. tSquared = t * t;
  422. tCubed = tSquared * t;
  423. result = {
  424. "x": 0,
  425. "y": 0
  426. };
  427. result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
  428. result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
  429. return result;
  430. }
  431.  
  432. //关闭软件
  433. function closeApp(appname) {
  434. let packageName = getPackageName(appname);
  435. // 使用ADB命令强行结束进程
  436. //shell("adb shell am force-stop " + packageName);
  437. console.warn('关闭应用:' + appname);
  438. app.openAppSetting(packageName);
  439. text(app.getAppName(packageName)).waitFor();
  440. let is_sure = textMatches(/.*强行停止.*/).visibleToUser(true).findOnce();
  441. if (is_sure&&is_sure.enabled()) {
  442. try {
  443. var btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
  444. if (btn) btn.click();
  445. sleep(1000);
  446. btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
  447. if (btn) btn.click();
  448. sleep(1000);
  449. btn = className("Button").text('确定').visibleToUser(true).findOnce();
  450. if (btn) btn.click();
  451. back(); back(); back();
  452. home();
  453. } catch (e) {
  454. log(app.getAppName(packageName) + "应用已被关闭");
  455. sleep(1000);
  456. back(); back(); back();
  457. home();
  458. }
  459. } else {
  460. log(app.getAppName(packageName) + "应用不能被正常关闭");
  461. back(); back(); back();
  462. home();
  463. }
  464. }
  465.  
  466. /**
  467. *监控脚本是否卡在某界面不动,发现此情况重启脚本
  468. */
  469. function Observer() {
  470. if (oledwin) {return true;}
  471. function unique(arr) {
  472. let newArr = [arr[0]];
  473. for (let i = 1; i < arr.length; i++) {
  474. let flag = false;
  475. for (var j = 0; j < newArr.length; j++) {
  476. if (arr[i] == newArr[j]) {
  477. flag = true;
  478. break;
  479. }
  480. }
  481. if (!flag) {
  482. newArr.push(arr[i]);
  483. }
  484. }
  485. return newArr;
  486. }
  487. currentActis = new Array();
  488. for (let c = 0; c < 150; c++) {
  489. sleep(500);
  490. currentActis[c] = currentActivity();
  491. }
  492. ac = unique(currentActis);
  493. cc = currentActivity().match(/.*ExcitingVideoActivity|.*main\.MainActivity|.*app\.Dialog/gi);
  494. if (ac.length == 1 && !cc) {
  495. return false
  496. }
  497. return true
  498. }
  499. //let times = rawInput("请输入要自动刷的视频次数:","50");
  500. // 》》》》》》》》》》》》》》》》》》》 START
  501. work_thread = threads.start(function () {
  502. Main();
  503. });
  504. observer_thread = threads.start(function () {
  505. setInterval(function () {
  506. console.verbose('--------多线程安全检测---------');
  507. if (!Observer()&&looptimes>0) {
  508. work_thread.interrupt();
  509. work_thread = threads.start(function () {
  510. console.warn("Main线程在5秒后重启!",currentActivity());
  511. toast("Main线程在5秒后重启!");
  512. oledwin=null;
  513. closeApp(runAppName);
  514. sleep(5000);
  515. Main();
  516. });
  517. }
  518. }, 10000);
  519. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址