生活依旧如此美好。
背景故事:最近朋友推荐我去刷某小视频,说看视频可以赚钱,劈里啪啦的发了个邀请码给我。玩了几天确实赚了几块钱,至少今天的肠粉钱有,麻雀虽小,五脏俱全呐。之前看到刷某小视频有个自动刷视频的功能,挺好,播放完当前,自动看下一个。想着给某小视频也加一个,免得手动了,即看了视频,又赚了钱。
需求:实现自动刷视频的功能,想到的就是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~