AccessibilityService simulates click
Project Demo address github.com/AndroidLMY/…
Create a new file swt.xml
<? The XML version = "1.0" encoding = "utf-8"? > <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeWindowStateChanged|typeNotificationStateChanged|typeViewTextSelectionChanged|typeVi ewClicked" android:accessibilityFeedbackType="feedbackGeneric" android:canRetrieveWindowContent="true" android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows" android:canRequestTouchExplorationMode="true" android:description="@string/app_name" android:notificationTimeout="100"/>Copy the code
Configure reference files in the service in the manifest file
<service
android:name=".SkipService"
android:label="Automaticskip"
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>
Copy the code
The manifest file permissions are as follows:
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Copy the code
SkipService inherits AccessibilityService
package com.androidlmy.automaticskip; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Handler; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Toast; import java.util.List; /** * @ * @Creat 2019/12/2 10:16 * @User Lmy * @Compony zaituvideo */ public class SkipService extends AccessibilityService { @Override protected void onServiceConnected() { super.onServiceConnected(); AccessibilityServiceInfo config = new AccessibilityServiceInfo(); / / configuration to monitor the event type as the config interface change | click events. The eventTypes = AccessibilityEvent. TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_CLICKED; config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; if (Build.VERSION.SDK_INT >= 16) { config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; } setServiceInfo(config); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { final AccessibilityNodeInfo nodeInfo = event.getSource(); If (event.geteventType () == Accessibilityevent.type_WINDOW_state_changed) {// Interface change event ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString()); ActivityInfo activityInfo = tryGetActivity(componentName); boolean isActivity = activityInfo ! = null; If (isActivity) {log.d ("WindowChange", "current package name" + nodeInfo.getPackagename ()); switch (nodeInfo.getPackageName().toString()) { case "com.netease.cloudmusic": new Handler().postDelayed(new Runnable() { @Override public void run() { skip(nodeInfo.findAccessibilityNodeInfosByViewId("com.netease.cloudmusic:id/c3l")); }}, 500); break; case "cn.xiaochuankeji.zuiyouLite": new Handler().postDelayed(new Runnable() { @Override public void run() { skip(nodeInfo.findAccessibilityNodeInfosByViewId("cn.xiaochuankeji.zuiyouLite:id/btn_skip")); }}, 2000); break; Default: {List < AccessibilityNodeInfo > nodeInfoList = nodeInfo. FindAccessibilityNodeInfosByText (" skip "); for (AccessibilityNodeInfo info : nodeInfoList) { CharSequence charSequence = info.getText(); if (charSequence ! = null) { String msg = charSequence.toString(); If (MSG. The contains (" skip ")) {info. The performAction (AccessibilityNodeInfo. ACTION_CLICK); Toast.maketext (this, "skip ads ", toast.length_short).show(); } } } } } } } } private void skip(List<AccessibilityNodeInfo> nodeInfoList) { Log.d("WindowChange", "Nodeinfolist.size ()"; if (nodeInfoList ! = null && nodeInfoList.size() > 0) { nodeInfoList.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK); Toast.maketext (getApplicationContext(), "skip ads ", toast.length_short).show(); toast.maketext (getApplicationContext()," skip ads ", toast.length_short). } } private ActivityInfo tryGetActivity(ComponentName componentName) { try { return getPackageManager().getActivityInfo(componentName, 0); } catch (PackageManager.NameNotFoundException e) { return null; } } @Override public void onInterrupt() { } }Copy the code
The main code
nodeInfo.findAccessibilityNodeInfosByViewId("com.netease.cloudmusic:id/c3l")
Copy the code
Search for the control on the netease Cloud startup page based on the known control ID. The following section describes how to obtain the control ID
Private void skip(List<AccessibilityNodeInfo> nodeInfoList) {log.d ("WindowChange", "data" + nodeInfolist.size ()); if (nodeInfoList ! = null && nodeInfoList.size() > 0) { nodeInfoList.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK); Toast.maketext (getApplicationContext(), "skip ads ", toast.length_short).show(); toast.maketext (getApplicationContext()," skip ads ", toast.length_short). } } nodeInfoList.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);Copy the code
Simulate click to automatically skip launch page ads
The MainActivity code is as follows: Enable accessibility functions and start services
package com.androidlmy.automaticskip; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private Intent intent; private TextView text1; private TextView text2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intent = new Intent(MainActivity.this, SkipService.class); startService(intent); text1 = findViewById(R.id.text1); text2 = findViewById(R.id.text2); text1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (! isAccessibilitySettingsOn(MainActivity.this, SkipService.class.getCanonicalName())) { Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); startActivity(intent); Intent = new intent (mainactivity.this, skipservice.class); startService(intent); // Start the service}}}); text2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { stopService(intent); }}); } / test whether the auxiliary function open * * * * * @ param mContext * @ return Boolean * / private Boolean isAccessibilitySettingsOn (Context mContext, String serviceName) { int accessibilityEnabled = 0; Final String service = getPackageName() + "/" + serviceName; //Log.i(TAG, "service:" + service); try { accessibilityEnabled = Settings.Secure.getInt(mContext.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(mContext.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; }}Copy the code
Obtain the ID of the skip button on the software startup page
Open the tools folder D:\ webApp \SDK\ Android \tools in the SDK installation directory. Find monitor
Click the skip button control can be seen on the right controls id for com.net help ease. Cloudmusic: id/c6b thus get the control’s id
Other software may encounter no ID can use text lookup traversal
Weibo is a picture… I don’t know how to deal with it yet. Hopefully that gives you a little bit of inspiration
Project address: github.com/AndroidLMY/…
Currently supported apps include: netease Cloud Music, Baidu Webdisk, Pipizao, Resource Cat, Huawei App Market, FlyMe, Jaitu Video, Tencent Video, Douyu Live