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