AccessibilityService之模拟手势自动刷视频

生活依旧如此美好。

背景故事:最近朋友推荐我去刷某小视频,说看视频可以赚钱,劈里啪啦的发了个邀请码给我。玩了几天确实赚了几块钱,至少今天的肠粉钱有,麻雀虽小,五脏俱全呐。之前看到刷某小视频有个自动刷视频的功能,挺好,播放完当前,自动看下一个。想着给某小视频也加一个,免得手动了,即看了视频,又赚了钱。

 需求:实现自动刷视频的功能,想到的就是AccessibilityService可以用来实现这个功能。

AccessibilityService和平常开发使用serice不一样,不需要去startService(),继承AccessibilityService,配置文件都弄好后,就可以开始了。准备工作,先获取到某小视频应用包名,和需要监听的Activity完整名称,用adb去获取下,命令我也不会写,百度搜索吧。

      1.在res目录下新建一个xml文件夹(这个我觉得无所谓,随便放哪里都行吧,未验证),新建accessibility.xml,内容如下:

      accessibilityEventTypes 监听具体的变化,窗口改变,窗口内容改变,通知状态改变等(不标准口头理解),咳咳,下面的我就不认识了(主要是懒,懒得去查),关键的packageNames,监听应用的包名,以‘s’结尾,理解应该是可以监听多个应用了,确实是可以监听多个,另外这块配置可以在代码中去实现。

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeNotificationStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagReportViewIds"
    android:canRetrieveWindowContent="true"
    android:notificationTimeout="10"
    android:canPerformGestures="true"
    android:packageNames="xxxxxxxx" />

2.继承AccessibilityService,以及清单文件配置如下:

    因为不需要在Activity中去调用startService什么的,我理解在开启辅助功能的时候,系统有替我们完成这一操作,通过隐示的方式来启动这个服务,配置一下intent-filter中的action等等,具体规则,可以去看下Intent的启动显示和隐士。

 <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility" />
        </service>

3.因为在开启服务后,去打开某小视频,然后模拟手势滑动,不涉及到获取什么窗口控件的获取,id,控件类型判断等,所以服务中代码也很简单。我的想法就是,在onAccessibilityEvent中开个循环,加线程沉睡5s,别跟我讲什么ANR,5s应该没关系,主要判断下包名和Activity。

public class MyService extends AccessibilityService {
    public static final String TAG = "--MyService--";

    private GestureDescription gestureDescription;

    private void initService() {
        GestureDescription.Builder builder = new GestureDescription.Builder();
        Path path = new Path();
        path.moveTo(540, 1800);
        path.lineTo(540, 200);
        gestureDescription = builder.addStroke(new GestureDescription.StrokeDescription(path, 20, 500)).build();
    }

    public MyService() {
    }
    
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        String packageName = event.getPackageName().toString();
        String className = event.getClassName().toString();
        Log.d(TAG, "----1-----" + packageName);
        Log.d(TAG, "----2-----" + className);
        if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == eventType) {
            //被监听的界面
            if ("xxxxxxxx".equals(className)) {
                for (; ; ) {
                    try {
                        AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
                        dispatchGesture(gestureDescription, new GestureResultCallback() {
                            @Override
                            public void onCompleted(GestureDescription gestureDescription) {
                                super.onCompleted(gestureDescription);
                                Log.d(TAG, "----模拟手势成功-----");
                            }

                            @Override
                            public void onCancelled(GestureDescription gestureDescription) {
                                super.onCancelled(gestureDescription);
                                Log.d(TAG, "----模拟手势失败-----");
                            }
                        }, null);
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        }

    }

    @Override
    public void onInterrupt() {
        Log.d(TAG, "----onInterrupt-----");
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d(TAG, "----onServiceConnected-----");
        initService();

    }

4.最后是Activity中的,第一步判断是否开启了辅助服务,也可以判断下是否安装了某小视频,这个辅助功能权限很高,需要手动去开启,开启后,注册的Service就自动启动了,可以打日志查看,所以我加了初始化Path,示例中我写死了起点和终点,如果想规范点还是老老实实去获取屏幕宽高,给个比例来控制下,兼容性也好写。

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";
    private AccessibilityManager mAccessibilityManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_kuaishou).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                start();
            }
        });
    }

    /**
     * Check当前辅助服务是否启用
     *
     * @param serviceName serviceName
     * @return 是否启用
     */
    private boolean checkAccessibilityEnabled(String serviceName) {
        mAccessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> accessibilityServices =
                mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
        for (AccessibilityServiceInfo info : accessibilityServices) {
            if (info.getId().equals(serviceName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否开启了辅助功能
     * @return
     */
    private boolean isAccessibilitySettingsOn() {
        int accessibilityEnabled = 0;
        // MyService为对应的服务
        final String service = getPackageName() + "/" + MyService.class.getCanonicalName();
        Log.i(TAG, "service:" + service);
        try {
            accessibilityEnabled = Settings.Secure.getInt(getApplicationContext().getContentResolver(),
                    android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
            Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
        } catch (Settings.SettingNotFoundException e) {
            Log.e(TAG, "Error finding setting, default accessibility to not found: " + e.getMessage());
        }
        TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');

        if (accessibilityEnabled == 1) {
            Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
            String settingValue = Settings.Secure.getString(getApplicationContext().getContentResolver(),
                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            if (settingValue != null) {
                mStringColonSplitter.setString(settingValue);
                while (mStringColonSplitter.hasNext()) {
                    String accessibilityService = mStringColonSplitter.next();

                    Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
                    if (accessibilityService.equalsIgnoreCase(service)) {
                        Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
                        return true;
                    }
                }
            }
        } else {
            Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
        }
        return false;
    }
    private void start() {
        if (isAccessibilitySettingsOn()) {
            //某小视频,以xxxx代替包名
            openOtherApp("xxxx");
        } else {
            goAccess();
        }
    }
    /**
     * 前往开启辅助服务界面
     */
    public void goAccess() {
        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
    private void openOtherApp(String s) {
        PackageManager packageManager = getPackageManager();
        Intent i = packageManager.getLaunchIntentForPackage(s);
        startActivity(i);
    }
}

有什么疑问yinsxi@163.com

END~

 

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值