Подтвердить что ты не робот

Вставить из AccessibilityService в API22 не работает в API17

Когда я запускаю свой код на API22, он отлично работает, вставляя "Тестирование тестирования" в мой требуемый EditText в приложении, которое инициировало AccessibilityEvent. Но когда я запускаю его на API 17, он не работает. Он копирует данные в клип, но не может вставить его. Мне нужен механизм для работы с API 16 и выше.

Это мой код:

public class MyAccessibilityService extends AccessibilityService {
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        AccessibilityNodeInfo nodeInf = null;
        AccessibilityNodeInfo nodeInfo = null;
        final int eventType = event.getEventType();
        String eventText = null;
        switch(eventType) {
            case AccessibilityEvent.TYPE_VIEW_CLICKED:
                eventText = "Clicked: ";
                nodeInf = this.getRootInActiveWindow();
                Log.d("AccessibilityNodeInfo", ""+ nodeInf.getChildCount());
                nodeInf.recycle();
                break;
            case AccessibilityEvent.TYPE_VIEW_FOCUSED:
                AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
                AccessibilityNodeInfoCompat source = record.getSource();

                ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
                ClipData clip = ClipData.newPlainText("label", "TESTING TESTING");
                clipboard.setPrimaryClip(clip);

                source.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE);
                //}

                Log.d("AccessibilityNodeInfo", ""+ source.getClassName());
                Intent intent = new Intent(MyAccessibilityService.this, TestActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
                startActivity(intent);
                break;
        }


        eventText = eventText + event.getText();

        // Do something nifty with this text, like speak the composed string
        // back to the user.
        Log.d("Information", eventText);
        Toast.makeText(getApplicationContext(), eventText + " " + android.os.Build.VERSION.SDK_INT,
                Toast.LENGTH_LONG).show();
    }
}
4b9b3361

Ответ 1

К сожалению AccessibilityNodeInfo.ACTION_PASTE добавлен в уровень API 18, по этой причине он не работает с API 17 и ниже. AccessibilityNodeInfoCompat является только оболочкой для существующих функций, он не обеспечивает пользовательскую реализацию отсутствующих функций.

Источники библиотеки поддержки v4 довольно ясны:

Когда вы вызываете performAction в AccessibilityNodeInfoCompat, библиотека поддержки вызывает IMPL.performAction [1]

public boolean performAction(int action) {
    return IMPL.performAction(mInfo, action);
}

IMPL AccessibilityNodeInfoJellybeanImpl, когда уровень API равен 16 и 17 [2]

if (Build.VERSION.SDK_INT >= 22) {
    IMPL = new AccessibilityNodeInfoApi22Impl();
} else if (Build.VERSION.SDK_INT >= 21) {
    IMPL = new AccessibilityNodeInfoApi21Impl();
} else if (Build.VERSION.SDK_INT >= 19) { // KitKat
    IMPL = new AccessibilityNodeInfoKitKatImpl();
} else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
    IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
} else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
    IMPL = new AccessibilityNodeInfoJellybeanImpl();
} else if (Build.VERSION.SDK_INT >= 14) { // ICS
    IMPL = new AccessibilityNodeInfoIcsImpl();
} else {
    IMPL = new AccessibilityNodeInfoStubImpl();
}

Это performAction в AccessibilityNodeInfoJellybeanImpl [3]

public static boolean performAction(Object info, int action, Bundle arguments) {
    return ((AccessibilityNodeInfo) info).performAction(action, arguments);
}

Как вы можете увидеть вызов библиотеки поддержки performAction стандартного android.view.accessibility.AccessibilityNodeInfo, поэтому, если система не поддерживает ACTION_PASTE, также библиотека поддержки v4 не поддерживает ACTION_PASTE.

Вы можете проверить, поддерживается ли ACTION_PASTE с помощью этого кода:

AccessibilityNodeInfoCompat source = record.getSource();
int supportedActions = source.getActions();
boolean isSupported = (supportedActions & AccessibilityNodeInfoCompat.ACTION_PASTE) == AccessibilityNodeInfoCompat.ACTION_PASTE;
Log.d(TAG, String.format("AccessibilityNodeInfoCompat.ACTION_PASTE %1$s supported", isSupported ? "is" : "is NOT"));

Ответ 2

Возможно, вам следует улучшить свой ответ и добавить более подробную информацию об импорте.


Оклейка: Как вы уже упоминали в своем комментарии, это больше о том, как снова получить вещь из буфера обмена?

Начиная с Android Копировать и вставить документацию, вы можете получить скопированный контент в виде текста следующим образом:

// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
// text. Assumes that this application can only handle one item at a time.
 ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);

// Gets the clipboard as text.
pasteData = item.getText();

// If the string contains data, then the paste operation is done
if (pasteData != null) {
    return;

// The clipboard does not contain text. If it contains a URI, attempts to get data from it
} else {
    Uri pasteUri = item.getUri();

    // If the URI contains something, try to get text from it
    if (pasteUri != null) {

        // calls a routine to resolve the URI and get data from it. This routine is not
        // presented here.
        pasteData = resolveUri(Uri);
        return;
    } else {

    // Something is wrong. The MIME type was plain text, but the clipboard does not contain either
    // text or a Uri. Report an error.
    Log.e("Clipboard contains an invalid data type");
    return;
    }
}

Копирование:

Существует два разных варианта ClipBoardManager. Новый был введен с Honeycomb. Вы должны убедиться, что ваш код использует правильный вариант.

Посмотрите на этот пример кода:

int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
    android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipboard.setText("text to clip");
} else {
    android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
    android.content.ClipData clip = android.content.ClipData.newPlainText("text label","text to clip");
    clipboard.setPrimaryClip(clip);
}

Это просто предположение, поскольку вопрос пропускает некоторую информацию.