基於無障礙服務實現自動跳過APP啓動頁廣告

基於無障礙服務實現自動跳過APP啓動頁廣告 實現原理AccessibilityService模擬點擊java

項目Demo地址github.com/AndroidLMY/…node

一. res目錄下新建xml文件夾新建文件accessibility.xml

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged|typeNotificationStateChanged|typeViewTextSelectionChanged|typeViewClicked"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows"
    android:canRequestTouchExplorationMode="true"
    android:description="@string/app_name"
    android:notificationTimeout="100"/>
複製代碼

清單文件中service中配置引用文件

<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>
複製代碼

清單文件權限以下:

<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" />
複製代碼

二. 新建服務SkipService繼承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();
        //配置監聽的事件類型爲界面變化|點擊事件
        config.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) {//界面變化事件
            ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString());
            ActivityInfo activityInfo = tryGetActivity(componentName);
            boolean isActivity = activityInfo != null;

            if (isActivity) {
                Log.d("WindowChange", "當前運行包名" + 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("跳過");
                        for (AccessibilityNodeInfo info : nodeInfoList) {
                            CharSequence charSequence = info.getText();
                            if (charSequence != null) {
                                String msg = charSequence.toString();
                                if (msg.contains("跳過")) {
                                    info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                                    Toast.makeText(this, "跳過廣告", 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(), "跳過廣告", Toast.LENGTH_SHORT).show();
        }
    }

    private ActivityInfo tryGetActivity(ComponentName componentName) {
        try {
            return getPackageManager().getActivityInfo(componentName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    @Override
    public void onInterrupt() {
    }
}
複製代碼

主要代碼android

nodeInfo.findAccessibilityNodeInfosByViewId("com.netease.cloudmusic:id/c3l")
複製代碼

根據已知控件id查找網易雲啓動頁的控件  下面會介紹如何獲取控件的idgit

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(), "跳過廣告", Toast.LENGTH_SHORT).show();
        }
    }
 nodeInfoList.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
複製代碼

模擬點擊從而實現自動跳過啓動頁廣告

MainActivity代碼以下:開啓無障礙功能和啓動服務github

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);
                    //跳轉設置打開無障礙
                } else {
                    intent = new Intent(MainActivity.this, SkipService.class);
                    startService(intent);
                    //啓動服務
                }
            }
        });
        text2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(intent);
            }
        });
    }

    /**
     * 檢測輔助功能是否開啓
     *
     * @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;
    }
}
複製代碼

三.獲取軟件啓動頁面跳過按鈕的id

打開安裝SDK目錄下tools文件夾 D:\webapp\SDK\android\tools找到monitor.bat雙擊打開

1f70669d-2c62-4281-841c-87dbf78f53ac.png

d247ceaa-9833-4783-8ac9-9e6616ef1493.png

點擊跳過按鈕控件右側能夠看到控件的id爲com.netease.cloudmusic:id/c6b 這樣就獲得了控件的idweb

其餘軟件可能會遇到無id的時候能夠使用文字查找遍歷markdown

微博的是一張圖片。。。。暫時還不知道如何處理。。但願對大家有點啓發app

項目地址:github.com/AndroidLMY/…webapp

目前支持的app有:網易雲音樂,百度網盤,皮皮搞笑,資源貓 ,華爲應用市場,生活助手(flyme), 在途視頻, 騰訊視頻,鬥魚直播ide

相關文章
相關標籤/搜索