Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/201.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android无法在少数使用辅助功能服务的设备上读取窗口内容_Android_Accessibilityservice_Accessibility Api - Fatal编程技术网

Android无法在少数使用辅助功能服务的设备上读取窗口内容

Android无法在少数使用辅助功能服务的设备上读取窗口内容,android,accessibilityservice,accessibility-api,Android,Accessibilityservice,Accessibility Api,我的要求:阅读文本从弹出窗口,对话框等特定的应用程序 我已经实施了无障碍服务,并根据我的要求接收适当的事件和数据。然而,在测试过程中,我意识到在一些设备上,他们没有使用AlertDialog或Dialog,而是使用了活动(主题为对话框)。 因此,在我的可访问性事件中,我只收到活动标题,是否有办法找到此特定弹出式活动显示的文本 我搜索得很辛苦,但在这个主题上没有得到太多的帮助,文档在这个问题上也没有任何用处。无障碍服务代码中没有太多内容,但如果您仍然需要,我将稍后发布 谢谢这是我使用的代码,适用于

我的要求:阅读文本从弹出窗口,对话框等特定的应用程序

我已经实施了无障碍服务,并根据我的要求接收适当的事件和数据。然而,在测试过程中,我意识到在一些设备上,他们没有使用AlertDialog或Dialog,而是使用了活动(主题为对话框)。 因此,在我的可访问性事件中,我只收到活动标题,是否有办法找到此特定弹出式活动显示的文本

我搜索得很辛苦,但在这个主题上没有得到太多的帮助,文档在这个问题上也没有任何用处。无障碍服务代码中没有太多内容,但如果您仍然需要,我将稍后发布


谢谢

这是我使用的代码,适用于我:

public class USSDService extends AccessibilityService {

public static String TAG = USSDService.class.getSimpleName();

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    Log.d(TAG, "onAccessibilityEvent");

    AccessibilityNodeInfo source = event.getSource();
    if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && !String.valueOf(event.getClassName()).contains("AlertDialog")) {
        return;
    }
    if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && (source == null || !source.getClassName().equals("android.widget.TextView"))) {
        return;
    }
    if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && TextUtils.isEmpty(source.getText())) {
        return;
    }

    List<CharSequence> eventText;

    if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
        eventText = event.getText();
    } else {
        eventText = Collections.singletonList(source.getText());
    }

    String text = processUSSDText(eventText);

    if( TextUtils.isEmpty(text) ) return;

    // Close dialog
    performGlobalAction(GLOBAL_ACTION_BACK); // This works on 4.1+ only

    Log.d(TAG, text);
    // Handle USSD response here

}

private String processUSSDText(List<CharSequence> eventText) {
    for (CharSequence s : eventText) {
        String text = String.valueOf(s);
        // Return text if text is the expected ussd response
        if( true ) {
            return text;
        }
    }
    return null;
}

@Override
public void onInterrupt() {
}

@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    Log.d(TAG, "onServiceConnected");
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    info.flags = AccessibilityServiceInfo.DEFAULT;
    info.packageNames = new String[]{"com.android.phone"};
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    setServiceInfo(info);
}
}
公共类USSDService扩展了AccessibilityService{
公共静态字符串标记=USSDService.class.getSimpleName();
@凌驾
AccessibilityEvent上的公共无效(AccessibilityEvent事件){
Log.d(标记“onAccessibilityEvent”);
AccessibilityNodeInfo source=event.getSource();
如果(event.getEventType()==AccessibilityEvent.TYPE\u WINDOW\u STATE\u已更改&&!String.valueOf(event.getClassName()).contains(“AlertDialog”)){
返回;
}
如果(event.getEventType()==AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED&&(source==null | | |!source.getClassName().equals(“android.widget.TextView”)){
返回;
}
if(event.getEventType()==AccessibilityEvent.TYPE\u WINDOW\u CONTENT\u CHANGED&&TextUtils.isEmpty(source.getText()){
返回;
}
列出事件文本;
if(event.getEventType()==AccessibilityEvent.TYPE\u窗口\u状态\u已更改){
eventText=event.getText();
}否则{
eventText=Collections.singletonList(source.getText());
}
String text=processUSSDText(eventText);
if(TextUtils.isEmpty(text))返回;
//关闭对话框
performGlobalAction(GLOBAL_ACTION_BACK);//这仅适用于4.1+版本
Log.d(标签、文本);
//在这里处理USSD响应
}
私有字符串processUSSDText(列表事件文本){
for(字符序列:eventText){
String text=String.valueOf(s);
//如果文本是预期的ussd响应,则返回文本
如果(真){
返回文本;
}
}
返回null;
}
@凌驾
在中断时的公共无效(){
}
@凌驾
ServiceConnected()上受保护的void{
super.onServiceConnected();
Log.d(标记“onServiceConnected”);
AccessibilityServiceInfo=新的AccessibilityServiceInfo();
info.flags=AccessibilityServiceInfo.DEFAULT;
info.packageNames=新字符串[]{“com.android.phone”};
info.eventTypes=AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType=可访问性服务info.FEEDBACK\u通用;
设置服务信息(信息);
}
}
在Android清单中声明它

<service android:name=".USSDService"
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/ussd_service" />

创建一个xml文件,该文件描述称为ussd_服务的辅助功能服务

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="0"
android:packageNames="com.android.phone" />

使用accessiblityNodeInfo获取信息,即使在手机返回的情况下,它也会获取ussd响应,并且当有选项输入多个选项时,它会关闭对话框

首先,在[pohne]事件的情况下,类名称作为ussdalertactivity返回,因此我仅使用“alert”来标识ussd响应的警报对话框

public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getPackageName().toString().equals("com.android.phone")
                        && event.getClassName().toString().toLowerCase()
                                .contains("alert")) {

                    AccessibilityNodeInfo source = event.getSource();

                    if (source != null) {
                    String pcnResponse = fetchResponse(source);
                    }
    }
现在我创建了一个名为fetchResponse的函数,它将以字符串形式返回来自pcn的响应,并且还将关闭对话框,因此需要执行performGlobalAction(全局动作返回)

私有字符串fetchResponse(AccessibilityNodeInfo AccessibilityNodeInfo){
字符串fetchedResponse=“”;
if(accessibilityNodeInfo!=null){
对于(int i=0;i10){
fetchedResponse=text.toString();
}
}else如果(child.getClassName().equals(
ScrollView.class.getName()){
//当响应以电话的形式出现时,响应可以是
//从亚孩子那里得到的
对于(int j=0;j10){
fetchedResponse=subText.toString();
}
private String fetchResponse(AccessibilityNodeInfo accessibilityNodeInfo) {

        String fetchedResponse = "";
        if (accessibilityNodeInfo != null) {
            for (int i = 0; i < accessibilityNodeInfo.getChildCount(); i++) {
                AccessibilityNodeInfo child = accessibilityNodeInfo.getChild(i);
                if (child != null) {

                    CharSequence text = child.getText();

                    if (text != null
                            && child.getClassName().equals(
                                    Button.class.getName())) {

                        // dismiss dialog by performing action click in normal
                        // cases
                        if((text.toString().toLowerCase().equals("ok") || text
                                        .toString().toLowerCase()
                                        .equals("cancel"))) {

                            child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                            return fetchedResponse;

                        }

                    } else if (text != null
                            && child.getClassName().equals(
                                    TextView.class.getName())) {

                        // response of normal cases
                        if (text.toString().length() > 10) {
                            fetchedResponse = text.toString();
                        }

                    } else if (child.getClassName().equals(
                            ScrollView.class.getName())) {

                        // when response comes as phone then response can be
                        // retrived from subchild
                        for (int j = 0; j < child.getChildCount(); j++) {

                            AccessibilityNodeInfo subChild = child.getChild(j);
                            CharSequence subText = subChild.getText();

                            if (subText != null
                                    && subChild.getClassName().equals(
                                            TextView.class.getName())) {

                                // response of different cases
                                if (subText.toString().length() > 10) {
                                    fetchedResponse = subText.toString();
                                }

                            }

                            else if (subText != null
                                    && subChild.getClassName().equals(
                                            Button.class.getName())) {

                                // dismiss dialog by performing action click in
                                // different
                                // cases
                                if ((subText.toString().toLowerCase()
                                                .equals("ok") || subText
                                                .toString().toLowerCase()
                                                .equals("cancel"))) {
                                    subChild.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                                    return fetchedResponse;
                                }

                            }
                        }
                    }
                }
            }
        }
        return fetchedResponse;
    }
private void clickPerform(AccessibilityNodeInfo nodeInfo)
 {
   if(nodeInfo != null)
 {

            for (int i = 0; i < nodeInfo.getChildCount(); i++) {
                AccessibilityNodeInfo childNode = nodeInfo.getChild(i);
                Log.e("test", "clickPerform: "+childNode );
                if (childNode != null) {
                    for (int j = 0; j <= childNode.getChildCount(); j++) {
                        AccessibilityNodeInfo subChild = childNode.getChild(i);

                        if (String.valueOf(subChild.getText()).toLowerCase().equals("ok")) {
                            subChild.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                        } else {
                            Log.e("t2", "clickPerform: ");
                        }
                    }
                }

                }
            }
}