Использование интерфейсов Non-SDK. обессахаривание

Я проверяю свое приложение в Firebase перед отправкой его в Play Store и получаю следующие предупреждения:

      Usage of non-SDK interfaces
Ljava/util/Collections$SynchronizedCollection;-><init>(Ljava/util/Collection;Ljava/lang/Object;)V
Ljava/util/Collections$SynchronizedCollection;->mutex:Ljava/lang/Object;
Ljava/util/Collections$SynchronizedCollection;->c:Ljava/util/Collection;
Ljava/util/Collections$SynchronizedSet;-><init>(Ljava/util/Set;Ljava/lang/Object;)V

Они помечены в Hiddenapi_flags как «greylist-max-o». Я изолировал проблему и заметил, что проблема возникает при использовании библиотеки Desugaring (я включил ее для использования некоторых функций времени, таких как ZonedDateTime, ZoneOffset и т. д. в Api<26). У меня вопрос: могу ли я с этими предупреждениями обновить приложение до Google Play? Есть ли какая-либо альтернатива в более старых Apis использованию функций, аналогичных ZonedDateTime.getAvailableZoneIds и т. д.? Спасибо.

1 ответ

Я отправил вопрос на сайт Issuetracker.google.com, и они изучают проблему. Вот их ответ:

КОММЕНТАРИИ Все комментарии sg...@google.comsg...@google.com #2 17 мая 2023 г., 11:02

Это вызвано кодом в DesugarCollections.java. Код пытается получить блокировку базовой SynchronizedCollection посредством отражения полей и методов, которые являются внутренними для платформы.

Если это отражение не удастся, то методы removeIf, forEach, replaceAll и sort будут напрямую обращаться к внутреннему полю коллекции.

Согласно спрятанному api-flags.csv, поле мьютекса недоступно после Android 8.

Это неоптимально и может привести к неопределенному поведению. Я предлагаю вам избегать использования SynchronizedCollection и вместо этого использовать параллельные структуры данных, если это вообще возможно.

sg...@google.comsg ...@google.com #3, 17 мая 2023 г., 11:04

Следующий код протестирован на эмуляторах: он работает успешно на AndroidO_MR1 и не работает на Android P. ТАКЖЕ протестировано на телефоне Android U, где он также не работает.

      public class SynchronizedCollectionReflection {
    public static String test() {
        Class<? extends Collection> SYNCHRONIZED_COLLECTION;
        SYNCHRONIZED_COLLECTION = Collections.synchronizedCollection(new ArrayList<>()).getClass();
        Class<? extends List> SYNCHRONIZED_LIST;
        SYNCHRONIZED_LIST = Collections.synchronizedList(new LinkedList<>()).getClass();
        Field MUTEX_FIELD;
        MUTEX_FIELD = getField(SYNCHRONIZED_COLLECTION, "mutex");
        if (MUTEX_FIELD != null) {
            MUTEX_FIELD.setAccessible(true);
        } else {
            return "Failed MUTEX_FIELD";
        }
        Field COLLECTION_FIELD;
        COLLECTION_FIELD = getField(SYNCHRONIZED_COLLECTION, "c");
        if (COLLECTION_FIELD != null) {
            COLLECTION_FIELD.setAccessible(true);
        } else {
            return "Failed COLLECTION_FIELD";
        }
        Class<? extends Set> synchronizedSet = Collections.synchronizedSet(new HashSet<>()).getClass();
        Constructor<? extends Set> SYNCHRONIZED_SET_CONSTRUCTOR;
        SYNCHRONIZED_SET_CONSTRUCTOR = getConstructor(synchronizedSet, Set.class, Object.class);
        if (SYNCHRONIZED_SET_CONSTRUCTOR != null) {
            SYNCHRONIZED_SET_CONSTRUCTOR.setAccessible(true);
        } else {
            return "Failed SYNCHRONIZED_SET_CONSTRUCTOR";
        }
        Constructor<? extends Collection> SYNCHRONIZED_COLLECTION_CONSTRUCTOR;
        SYNCHRONIZED_COLLECTION_CONSTRUCTOR =
                getConstructor(SYNCHRONIZED_COLLECTION, Collection.class, Object.class);
        if (SYNCHRONIZED_COLLECTION_CONSTRUCTOR != null) {
            SYNCHRONIZED_COLLECTION_CONSTRUCTOR.setAccessible(true);
        } else {
            return "Failed SYNCHRONIZED_COLLECTION_CONSTRUCTOR";
        }
        return "SUCCESS!";
    }

    private static Field getField(Class<?> clazz, String name) {
        try {
            return clazz.getDeclaredField(name);
        } catch (NoSuchFieldException e) {
            // For Desugar: Some fields are not available on instrumented devices.
            return null;
        }
    }

    private static <E> Constructor<? extends E> getConstructor(
            Class<? extends E> clazz, Class<?>... parameterTypes) {
        try {
            return clazz.getDeclaredConstructor(parameterTypes);
        } catch (NoSuchMethodException e) {
            // For Desugar: Some constructors are not available on instrumented devices.
            return null;
        }
    }
}

sg...@google.comsg ...@google.com #4, 17 мая 2023 г., 11:05 Переназначен на cl...@google.com.

Нам следует еще раз взглянуть на это и подумать о сбое операций, которые невозможно безопасно очистить от сахара.

Другие вопросы по тегам