提问人:jlsogorb 提问时间:5/17/2023 最后编辑:jlsogorb 更新时间:5/19/2023 访问量:104
使用非 SDK 接口。脱糖
Usage of Non-SDK interfaces. Desugaring
问:
在将应用发送到 Play 商店之前,我正在 Firebase 中检查我的应用,但收到以下警告:
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 库时(我包含它以使用 Api<26 中的一些时间功能,如 ZonedDateTime、ZoneOffset 等)。 我的问题是:有了这些警告,我可以将应用程序更新到 Google Play 吗?在较旧的 API 中,是否有任何替代方法可以使用与 ZonedDateTime.getAvailableZoneIds 等类似的函数? 谢谢。
答:
我把问题发给了 Issuetracker.google.com,他们正在调查这个问题。这是他们的答案:
评论 所有评论 [email protected][email protected] 2023年 #2May 17日 上午11:02
这是由 DesugarCollections.java 中的代码引起的。代码是 尝试获取基础 SynchronizedCollection 的锁 通过对内部字段和方法的反映 平台。
如果此反射不成功,则方法 removeIf, forEach、replaceAll 和 sort 将访问内部集合字段 径直。
根据 hiddenapi-flags.csv互斥锁字段不可访问 在 Android 8 之后。
这不是最佳选择,可能会导致未定义的行为。我建议 避免使用 SynchronizedCollection,而是使用 concurrent 数据结构(如果可能的话)。
[电子邮件保护][电子邮件保护] #3May 17, 2023 11:04上午
在模拟器上测试了以下代码,在 Android 上成功了 O_MR1 并在 Android P 上失败。 ALso 在 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;
}
}
}
[电子邮件保护][电子邮件保护] #4May 17, 2023 11:05 重新分配给 [email protected]。
我们应该再看一看这一点,并考虑失败 无法安全脱糖的操作。
评论