美文网首页
SoloPi安卓自动化测试工具源码研究二:截获用户输入

SoloPi安卓自动化测试工具源码研究二:截获用户输入

作者: 黑山老雕 | 来源:发表于2019-12-19 14:47 被阅读0次

    截断用户点击事件

    截断用户点击事件的代码在AccessbilityServiceImpl.java.

    1. 它注册了一个自定义的Accessibility服务。通过用setServiceInfo,设置info的flag为FLAG_REQUEST_TOUCH_EXPLORATION_MODE来实现对于用户输入事件的截获。

    示例代码;

    
    package com.zzp.floating;
    
    import android.accessibilityservice.AccessibilityService;
    
    import android.accessibilityservice.AccessibilityServiceInfo;
    
    import android.util.Log;
    
    import android.view.accessibility.AccessibilityEvent;
    
    public class InterceptService extends AccessibilityService {
    
        private static final String TAG = "ZZP_Intercept";
    
        private static InterceptService instance = null;
    
        public static InterceptService getInstance(){
    
            return instance;
    
        }
    
        @Override
    
        protected void onServiceConnected() {
    
            Log.d(TAG, "onServiceConnected: ");
    
            instance = this;
    
            super.onServiceConnected();
    
        }
    
        @Override
    
        public void onAccessibilityEvent(AccessibilityEvent event) {
    
            Log.d(TAG, "onAccessibilityEvent: Got event " + event.toString());
    
        }
    
        @Override
    
        public void onInterrupt() {
    
        }
    
        public void setBlock() {
    
            AccessibilityServiceInfo info = getServiceInfo();
    
            if (info == null) {
    
                Log.e(TAG, "ServiceInfo为空");
    
                return;
    
            }
    
            info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS |
    
                    AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY |
    
                    AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS |
    
                    AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS |
    
                    AccessibilityServiceInfo.DEFAULT |
    
                    AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
    
            Log.d(TAG, "辅助功能进入触摸监控模式");
    
            setServiceInfo(info);
    
        }
    
        public void setNormal() {
    
            AccessibilityServiceInfo info = getServiceInfo();
    
            if (info == null) {
    
                Log.e(TAG, "ServiceInfo为空");
    
                return;
    
            }
    
            info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS |
    
                    AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS |
    
                    AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY |
    
                    AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS |
    
                    AccessibilityServiceInfo.DEFAULT;
    
            Log.d(TAG, "辅助功能进入正常模式");
    
            setServiceInfo(info);
    
        }
    
    }
    
    

    注意,这个服务的 onServiceConnected 函数会被系统自动的绑定上。并不需要我们自己去bind 这个service。这是因为我们对这个服务声明特定的intent-filter和permission。

    1. 在manifest中声明一个service,注意提供特定的intent filter, permission 和 meta data。 manifest sample:
    
            <service android:name=".InterceptService"
    
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    
                <intent-filter>
    
                    <!-- android:name必须是以下这个名字 -->
    
                    <action android:name="android.accessibilityservice.AccessibilityService"></action>
    
                </intent-filter>
    
                <meta-data
    
                    android:name="android.accessibilityservice"
    
                    android:resource="@xml/accessibility" />
    
            </service>
    
    

    meta data sample:

    
    <?xml version="1.0" encoding="utf-8"?>
    
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    
        android:accessibilityEventTypes="typeAllMask"
    
        android:accessibilityFeedbackType="feedbackAllMask"
    
        android:notificationTimeout="100"
    
        android:canRetrieveWindowContent="true"
    
        android:canRequestFilterKeyEvents="true"
    
        android:description="@string/accessibility_description"
    
        android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds|flagRequestEnhancedWebAccessibility|flagRetrieveInteractiveWindows"
    
        android:canRequestTouchExplorationMode="true"
    
        android:canRequestEnhancedWebAccessibility="true">
    
    </accessibility-service>
    
    

    参考:https://developer.android.com/guide/topics/ui/accessibility/service

    1. 基本上,安装app后,需要重启,这个服务才会被注册。切记切记。你可以在onServiceConnected处断点。当服务被bind的时候,断点会命中。

    2. 在服务中找到无障碍,英文的话找accessibility,启用无障碍权限。当你但确定的时候,服务就会被bind,onSerivceConnected会被调用。

    调用无障碍权限的settings页面

    在Serivce代码中,可以用

    
                    Intent intent1 = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
    
                    intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //如果是在Serivce中启动,这行是重点
    
                    startActivity(intent1);
    
    

    启用acessibility service

    有些设备上的accessibility service可能被禁用了。查看方法 adb shell dumpsys accessibility。 输出结果类似:

    
    User state[attributes:{id=0, currentUser=true, accessibilityEnabled=false, touchExplorationEnabled=false, displayMagnificationEnabled=false}
    
              services:{}]
    
    

    正常的话应该看起来像:

    
    DUMP OF SERVICE accessibility:
    
    ACCESSIBILITY MANAGER (dumpsys accessibility)
    
    User state[attributes:{id=0, currentUser=true, touchExplorationEnabled=false, displayMagnificationEnabled=false, navBarMagnificationEnabled=false, autoclickEnabled=false}
    
              services:{Service[label=com.zzp.floating.Interce…, feedbackType[FEEDBACK_SPOKEN, FEEDBACK_HAPTIC, FEEDBACK_AUDIBLE, FEEDBACK_VISUAL, FEEDBACK_GENERIC, FEEDBACK_BRAILLE], capabilities=11, eventTypes=TYPES_ALL_MASK, notificationTimeout=100]}]
    
    Window[AccessibilityWindowInfo[title=null, id=116, type=<UNKNOWN>, layer=0, bounds=Rect(0, 0 - 1080, 2160), focused=true, active=true, pictureInPicture=false, hasParent=false, isAnchored=false, hasChildren=false]]--------- 0.047s was the duration of dumpsys accessibility, ending at: 2019-12-18 16:23:15
    
    

    那么手动启动的方法:

    
    adb shell settings put secure enabled_accessibility_services packagname/servicename
    
    

    还有人提到还需要做下述, 不过可能没有必要:

    
    adb shell settings put secure accessibility_enabled 1
    
    

    不过貌似最好还是在Settings页面里面激活

    参考: https://stackoverflow.com/questions/10061154/how-to-programmatically-enable-disable-accessibility-service-in-android


    转载请注明出处。

    image

    更多视频教程请在网易云课堂搜索黑山老雕。

    相关文章

      网友评论

          本文标题:SoloPi安卓自动化测试工具源码研究二:截获用户输入

          本文链接:https://www.haomeiwen.com/subject/dhimnctx.html