Использование интерфейсов 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.
Нам следует еще раз взглянуть на это и подумать о сбое операций, которые невозможно безопасно очистить от сахара.