importClass(android.content.Context);
importClass(android.provider.Settings);
importClass(android.app.KeyguardManager);
try {
var km = context.getSystemService(Context.KEYGUARD_SERVICE);//km.isKeyguardLocked(),km.isKeyguardSecure()
let enabledServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
//log('当前已启用的辅助服务\n', enabledServices);
if (!enabledServices.match(/.*org\.autojs\.autoxjs\.v6\/com\.stardust\.autojs\.core\.accessibility\.AccessibilityService.*/g)) {
let Services = (enabledServices ? enabledServices + ":" : "") + "org.autojs.autoxjs.v6/com.stardust.autojs.core.accessibility.AccessibilityService";
Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, Services);
Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, '1');
sleep(3000);
}
toastLog("成功开启AutoJS的辅助服务");
} catch (error) {
//受权方法:开启usb调试并使用adb工具链接手机,执行 adb shell pm grant org.autojs.autoxjs.v6 android.permission.WRITE_SECURE_SETTING
toastLog("请受权AutoJS启用辅助服务");
}
auto.waitFor();
//停止其它脚本
engines.all().map((ScriptEngine) => {
if (engines.myEngine().toString() !== ScriptEngine.toString()) {
ScriptEngine.forceStop();
}
});
//============================================================
var AppName = ["抖音极速版","快手极速版"];
var runAppName = AppName[0], times = 100; //滑动次数
toastLog('当前分辨率:'+device.width+'X'+device.height);
//toastLog('唯一标识码:'+device.fingerprint);
//息屏状态将屏幕唤醒
global.opentimes=0;
while (!device.isScreenOn() || km.isKeyguardLocked()) {
opentimes++;
device.wakeUp();//唤醒设备
toastLog('屏幕唤醒');
sleep(1500); //等待屏幕亮起
back();//如果锁屏后收到新消息,上滑不能解锁屏幕,需要返回一次后上滑
device.keepScreenOn();//一直保持屏幕常亮
sleep(1500);
if (km.isKeyguardSecure()) {
toastLog('密码解锁');
//待开发
break;
} else {
toastLog('上滑解锁');
swipe(device.width / 2, device.height * 0.8, device.width / 2, device.height * 0.3, 400);
}
sleep(1500);
if(opentimes>3){
toastLog('解锁失败,请尝试重启本软件并开启无障碍服务');
break;
}
}
global.oledwin=null;
global.looptimes=times;
function Main() {
toastLog('进入主程序');
for (i = 0; i < AppName.length; i++) {
looptimes=times;
var packageName = getPackageName(AppName[i]);
if (packageName) {
toastLog('启动应用:' + AppName[i]);
var appstate = launchApp(AppName[i]);
sleep(5000);
if (appstate) {
toastLog("应用正在运行");
} else {
toastLog("无法自启动,需模拟点击");
home();
sleep(3000);
var app = id("item_title").text(AppName[i]).visibleToUser(true).findOne(2000);
if (app) {
click(app.bounds().centerX(), app.bounds().top - 50);
sleep(10000);
}
}
runAppName=AppName[i];//安全线程中使用
while (looptimes > 0) {
//toastLog(currentActivity());
var tiktokhomepage = className("Button").descStartsWith("侧边栏").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOnce();
var giftshowhomepg = id('com.kuaishou.nebula:id/left_btn').clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOnce();
if (tiktokhomepage||giftshowhomepg) {
looptimes--;
var videoDuration = 0;
if(AppName[i]=='抖音极速版'){
var seekBar=className('android.widget.SeekBar').desc('进度条').findOne(1000);
}else{
var seekBar=className('android.widget.HorizontalScrollView').id('com.kuaishou.nebula:id/tab_layout').findOne(1000);
}
if (seekBar) {
isvideo = true;
let y1 = seekBar.bounds().top-5;
let x1 = random(100, 300);
let x2 = random(500, 800);
let duration_thread = threads.start(function () {
videoDuration = getDouyinVideoDuration();
duration_thread.interrupt();
});
gesture(random(800, 1200), [ [x1, y1],[x2, y1],[x1, y1] ]);
console.log("视频时长:",videoDuration+'s');
}
var sleepTime=(videoDuration>0&&videoDuration<180)?videoDuration:random(6, 30);//每个视频随机时间 6-30秒
console.verbose("浏览:" + (times-looptimes), "停留:" + sleepTime + "s");
cutDownBySleep(sleepTime,'观看视频');
randomHeart();//拟人化
} else {
var living = id("root").desc("关闭").clickable(true).boundsInside(device.width-300, 0, device.width, 300).visibleToUser(true).findOne(1000);//直播间
if (living) {
isvideo = true;
toastLog("1.退出直播间");
click(living.bounds().centerX(), living.bounds().centerY());
sleep(2000);
}
if (currentActivity() == 'com.ss.android.ugc.aweme.live.LivePlayActivity') {
toastLog("2.退出直播间");
isvideo = true;
back();
}
toast('不在抖音或快手页面');
oledwin=null;
sleep(3000);
}
}
closeApp(runAppName);
} else {
toastLog("未安装:" + AppName[i]);
}
}
toastLog("自动刷屏完成");
try {
device.cancelKeepingAwake();
//熄屏
runtime.accessibilityBridge.getService().performGlobalAction(android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
} catch (e) {
}
//停止本脚本
engines.myEngine().forceStop();
}
/**
* 倒计时
* @param {倒计时秒} lasterSecend
* @param {显示提示} message
*/
function cutDownBySleep(lasterSecend, message) {
message = message || "";
floaty.closeAll();
var fwin = floaty.rawWindow(
`<vertical id="frame" alpha="0" w="{{device.width-500}}px" h="150px">
<card w="auto" h="auto" layout_gravity="center" cardCornerRadius="5dp" cardBackgroundColor="#eeeeee" >
<text id="title" text="" textColor="#333333" textSize="13sp" padding="12 8" />
</card>
</vertical>`
);
fwin.setTouchable(false);
sleep(500);
for (let i = lasterSecend; i > 0; i--) {
if (oledwin) { break; }
if (!fwin || !fwin.title) { break; }
ui.run(() => {
fwin.title.setText(message + "剩余" + i + "秒");
fwin.frame.attr("alpha", 0.8);
fwin.setTouchable(false);
let x = parseInt((device.width - fwin.width) / 2);
let y = device.height-550;
fwin.setPosition(x, y);
});
sleep(1000);
}
fwin=null;
floaty.closeAll();
sleep(500);
}
//视频时长(秒)获取函数
function getDouyinVideoDuration() {
var durationText = className('TextView').textMatches(/[0-9]+:[0-9]+/).boundsInside(device.width/2, 2 * device.height / 3, device.width, device.height).findOne(2000);
//log(durationText);
if (durationText) {
var durationStr = durationText.text();
//log('1',durationStr);
var durationMatch = durationStr.match(/[0-9]+:[0-9]+/);
if (durationMatch) {
//log('2',durationMatch);
var minutes = 0,seconds = 0;
var parts = durationMatch[0].split(":");
if (parts.length === 2) {
//log('3',parts);
minutes = parseInt(parts[0], 10);
seconds = parseInt(parts[1], 10);
return minutes * 60 + seconds + 3;
}
}
}
return 0;
}
//=============================================================
/**随机拟人化(防止被判定是机器)**/
function randomHeart(num) {
if (7!=num&&text('当前无新视频').visibleToUser(true).findOne(1000)) {
console.log("当前无新视频");
click(device.right - 100, device.top - 100);
randomHeart(7);//切换频道
sleep(1000);
return;
}
let randomIndex = num ? num : random(1, 30);
//加速播放
if(randomIndex % 9 == 0){
var seekBar=className('android.widget.SeekBar').descMatches(/.*进度条.*/).findOne(1000);
if(seekBar){
let x1=random(90, 120);
let y1=device.height/3;
gestures([0, 1500, [x1,y1], [x1,y1]],[1400, 1500, [x1,y1], [1.1*x1, 2*y1]]);
return;
}
}
//随机下滑
if (randomIndex % 8 == 0) {
console.log('拟人:随机下滑');
swipe(device.width / 2, device.height * 0.1 + randomIndex, device.width / 2, device.height * 0.9 - randomIndex, random(500, 1500));
return;
}
//随机切换频道
if (randomIndex == 7) {
var idList = [];
className('TextView').clickable(true).descEndsWith(',按钮').boundsInside(0, 0, device.width, 300).find().forEach(function(tv){
if(!tv.desc().match(/.*已选中.*|.*团购.*|.*商城.*|.*热点.*|.*直播中.*/)){
//log(tv.desc());
idList.push(tv);
}
});
if(idList.length>0){
let index = random(1, idList.length) - 1;
console.log('拟人:切换频道:' + idList[index].desc());
idList[index].click();
sleep(2000);
if (text('发现通讯录朋友').visibleToUser(true).findOne(1000)) {
console.log("关注中没有视频");
randomHeart(7);//再次切换频道
sleep(2000);
slidingByCurve();
}
return;
}
}
//连续上滑
if (randomIndex == 6) {
console.log('拟人:连续上滑');
var k = random(2, 4);
for (var i = 0; i < k; i++) {
var j = random(2, 5);
if (j == 3) {
swipe(device.width / j, device.height * 0.1 + j * k, device.width / j, device.height * 0.9 - j * k, j * 50);
} else {
swipe(device.width / j, device.height * 0.9 - j * k, device.width / j, device.height * 0.1 + j * k, j * 50);
}
sleep(j * 250);
}
return;
}
//随机恢复到首页
if(randomIndex % 4 == 0){
console.log('拟人:随机回首页');
sleep(3000);back();sleep(3000);back();sleep(3000);
return;
}
//向上滑
slidingByCurve();
}
/**------------------------------------------------------------
* 从下往上滑动,随机坐标
*/
function slidingByLine() {
// top X,Y范围
tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
// bottom X,Y 范围
bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
by = randomPointLoc(parseInt(3 * device.height / 4), parseInt(4 * device.height / 5));
slidingTime = randomRangeTime(0.8, 1.3);
log("上滑:随机直线");
//log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
swipe(bx, by, tx, ty, slidingTime);
}
/*从下往上滑动,曲线滑动,随机坐标*/
function slidingByCurve() {
// top X,Y范围
tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
// bottom X,Y 范围
bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
by = randomPointLoc(parseInt(3 * device.height / 4), parseInt(4 * device.height / 5));
slidingTime = randomRangeTime(0.2, 0.6);
log("上滑:仿真曲线");
//log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
sml_move(bx, by, tx, ty, slidingTime);
}
/**
* 上部左右滑动
*/
function left2right(direction) {
var intX=parseInt(Math.random()*200+400);
var intY=parseInt(Math.random()*200+200);
var distance=parseInt(Math.random()*100+device.height/4);
switch (direction) {
case 1:
//向上小距离
sml_move(intX, intY + distance, intX, intY, 400);
break;
case 2:
//向下小距离
sml_move(intX, intY, intX, intY + distance, 400);
break;
case 3:
//向左翻屏
sml_move(
device.width / 2 + parseInt(Math.random() * 100) + 300,
device.height / 4 - parseInt(Math.random() * 200) + 100,
0 + parseInt(Math.random() * 100),
device.height / 5 + parseInt(Math.random() * 100),
500
);
break;
case 4:
//向右翻屏
sml_move(
device.width / 2 - parseInt(Math.random() * 100) - 300,
device.height / 5 - parseInt(Math.random() * 200) + 100,
device.width - parseInt(Math.random() * 100),
device.height / 4 + parseInt(Math.random() * 100),
500
);
break;
}
sleep(1000);
}
/**
* 随机位置点
* @param {起始值} start
* @param {结束值} end
* @returns
*/
function randomPointLoc(start,end){
len = Math.abs(end - start);
loc = Math.floor(Math.random() * len) + start;
return loc;
}
/**
* 从几秒到几秒
* @param {开始秒} start
* @param {结束秒} end
* @returns
*/
function randomRangeTime(start,end){
len = Math.abs(end -start)*1000;
ms = Math.floor(Math.random() * len) + start*1000;
return ms;
}
/**
* 仿真随机带曲线滑动
* @param {起点x} qx
* @param {起点y} qy
* @param {终点x} zx
* @param {终点y} zy
* @param {滑动时间,单位毫秒} time
*/
function sml_move(qx, qy, zx, zy, time) {
var xxy = [time];
var point = [];
var dx0 = {
"x": qx,
"y": qy
};
var dx1 = {
"x": random(qx - 150, qx + 150),
"y": random(qy, qy + 50)
};
var dx2 = {
"x": random(zx - 150, zx + 150),
"y": random(zy, zy + 50),
};
var dx3 = {
"x": zx,
"y": zy
};
for (var i = 0; i < 4; i++) {
eval("point.push(dx" + i + ")");
}
// log(point[3].x)
for (let i = 0; i < 1; i += 0.08) {
let newPoint=bezier_curves(point, i);
xxyy = [parseInt(newPoint.x), parseInt(newPoint.y)]
xxy.push(xxyy);
}
try {
gesture.apply(null, xxy);
} catch (e) {
log(xxy);
}
}
function bezier_curves(cp, t) {
cx = 3.0 * (cp[1].x - cp[0].x);
bx = 3.0 * (cp[2].x - cp[1].x) - cx;
ax = cp[3].x - cp[0].x - cx - bx;
cy = 3.0 * (cp[1].y - cp[0].y);
by = 3.0 * (cp[2].y - cp[1].y) - cy;
ay = cp[3].y - cp[0].y - cy - by;
tSquared = t * t;
tCubed = tSquared * t;
result = {
"x": 0,
"y": 0
};
result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
return result;
}
//关闭软件
function closeApp(appname) {
let packageName = getPackageName(appname);
// 使用ADB命令强行结束进程
//shell("adb shell am force-stop " + packageName);
console.warn('关闭应用:' + appname);
app.openAppSetting(packageName);
text(app.getAppName(packageName)).waitFor();
let is_sure = textMatches(/.*强行停止.*/).visibleToUser(true).findOnce();
if (is_sure&&is_sure.enabled()) {
try {
var btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
if (btn) btn.click();
sleep(1000);
btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
if (btn) btn.click();
sleep(1000);
btn = className("Button").text('确定').visibleToUser(true).findOnce();
if (btn) btn.click();
back(); back(); back();
home();
} catch (e) {
log(app.getAppName(packageName) + "应用已被关闭");
sleep(1000);
back(); back(); back();
home();
}
} else {
log(app.getAppName(packageName) + "应用不能被正常关闭");
back(); back(); back();
home();
}
}
/**
*监控脚本是否卡在某界面不动,发现此情况重启脚本
*/
function Observer() {
if (oledwin) {return true;}
function unique(arr) {
let newArr = [arr[0]];
for (let i = 1; i < arr.length; i++) {
let flag = false;
for (var j = 0; j < newArr.length; j++) {
if (arr[i] == newArr[j]) {
flag = true;
break;
}
}
if (!flag) {
newArr.push(arr[i]);
}
}
return newArr;
}
currentActis = new Array();
for (let c = 0; c < 150; c++) {
sleep(500);
currentActis[c] = currentActivity();
}
ac = unique(currentActis);
cc = currentActivity().match(/.*ExcitingVideoActivity|.*main\.MainActivity|.*app\.Dialog/gi);
if (ac.length == 1 && !cc) {
return false
}
return true
}
//let times = rawInput("请输入要自动刷的视频次数:","50");
// 》》》》》》》》》》》》》》》》》》》 START
work_thread = threads.start(function () {
Main();
});
observer_thread = threads.start(function () {
setInterval(function () {
console.verbose('--------多线程安全检测---------');
if (!Observer()&&looptimes>0) {
work_thread.interrupt();
work_thread = threads.start(function () {
console.warn("Main线程在5秒后重启!",currentActivity());
toast("Main线程在5秒后重启!");
oledwin=null;
closeApp(runAppName);
sleep(5000);
Main();
});
}
}, 10000);
});