xamarin - 如何正确排除某些库,以便它们不在 Xamarin.Android 中链接?
问题描述
我有一个运行良好的应用程序,但由于我无法链接库(因为它会导致异常行为),它变得明显更大(多 20 MiB)。主要问题发生在我自己的一个库中:
https://www.nuget.org/packages/Xamarin-MaterialSearchBar/
我“排除”了包及其依赖项:
Xamarin.AndroidX.AppCompat;Xamarin.AndroidX.ConstraintLayout;Xamarin.AndroidX.RecyclerView;Xamarin.AndroidX.CardView
但是“链接”选项的行为很奇怪,因为它们不被排除在链接全部或仅链接 SDK 的情况下。动画不知何故变得疯狂,它们以“特定”的方式工作,汉堡菜单在不应该的时候变成箭头,反之亦然,如果我点击 X,它只会永远删除 X 并且不会干净。下图可以让您了解异常行为。
当我不链接任何东西时,这是预期的行为和正常情况:
该应用程序仅在我使用Don't Link时才能正常工作。但是,我想了解我必须排除什么(或如何正确执行)或更改以避免此问题。此时,我尝试在 ProGuard 文件、“排除”部分等中排除它,但没有任何效果。
在我的 ProGuard 文件中,我有以下组合:
-keep class androidx.work.** { *; }
-keep class androidx.concurrent.** { *; }
-keep class androidx.tracing.** { *; }
-keep class androidx.paging.** { *; }
-keep class com.google.android.gms.** { *; }
-keep class androidx.appcompat.widget.** { *; }
-keep class com.google.android.material.** { *; }
我还尝试添加:
-keep class tk.supernovaic.MaterialSearchBar.** { *; }
但结果完全一样。我不知道我可以排除什么是诚实的。任何想法?
PS:
我可以创建要发布的包,这不是我的问题。
如果您想就如何更改此逻辑并解决此问题给我任何建议,我的库是开源的:
https://github.com/FANMixco/Xamarin-SearchBar
重要的是要强调我用 C# 和 Xamarin 编写了这个库。这不是另一个约束。
在我看来,这个问题发生在这个部分:
public void OnClick(View v)
{
int id = v.Id;
if (id == Id)
{
if (!IsSearchEnabled)
{
EnableSearch();
}
}
else if (id == Resource.Id.mt_arrow)
{
DisableSearch();
}
else if (id == Resource.Id.mt_search)
{
if (ListenerExists())
{
OnSearchActionListener.OnButtonClicked(BUTTON_SPEECH);
}
}
else if (id == Resource.Id.mt_clear)
{
SearchEdit.Text = "";
}
else if (id == Resource.Id.mt_menu)
{
PopupMenu.Show();
}
else if (id == Resource.Id.mt_nav)
{
int button = IsSearchEnabled ? BUTTON_BACK : BUTTON_NAVIGATION;
if (IsSearchEnabled)
{
DisableSearch();
}
if (ListenerExists())
{
OnSearchActionListener.OnButtonClicked(button);
}
}
}
更新1:
我已添加到我的库中:
[Preserve(AllMembers = true)]
[assembly: LinkerSafe]
这对我的项目:
--linkskip=tk.supernovaic.MaterialSearchBar
并且错误仍然存在;因此,它应该与动画库或类似的东西有关。
更新 2:
我也试过:
-keep class android.animation.ObjectAnimator.** { *; } -keep class **.R$* { public static <fields>; }
和:
-keep class android.animation.** { *; }
两者都仍然失败,但似乎与动画有关:
另外,我添加了--linkskip=android.animation --linkskip=tk.supernovaicMaterialSearchBar
没有任何结果。
更新 3:
我将文件从我的 lib 复制到我的项目中,并保留了所有以前的规则,但没有任何积极的结果。
更新 4:
我更新了我的库和应用程序,并在名为raw的资源中添加了一个新文件夹,其中包含带有以下代码的keep.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@anim/fade_in_left,@anim/fade_in_right,@anim/fade_out,@anim/fade_out_left,@animator/back_to_menu_morph,@animator/back_to_menu_rotation,@animator/menu_to_back_morph,@animator/menu_to_back_rotation" />
并添加到我的 ProGuard:
-keep class **.R
-keepclassmembers class tk.supernovaic.MaterialSearchBar.* {
<fields>;
<init>();
<methods>;
}
这一切都没有任何积极的结果。该错误仍然存在。
更新 5:
我向 Microsoft 提出了一张票,因为我几乎确信这是与链接器本身相关的错误:
我的结论基于以下三点:
- 我将原始文件(动画)添加到项目中。
- 我添加了一条规则以将 XML 保留在项目和库中。
- 我添加了规则来保留 ProGuard 文件中的 R 类和所有内容(资源)。
在我看来,没有保留前 3 点的动画是没有意义的。如果您有任何其他想法,请随时分享,我愿意倾听。
更新 6:
我还在 GitHub 上开了一张票,因为我认为这是一个错误:
解决方案
在 StackOverflow、GitHub、Visual Studio 和 Microsoft 论坛之间进行了大量更新和运行后,我能够找到问题所在:
dellis1972 更改此行 https://github.com/FANMixco/Xamarin-SearchBar/blob/master/tk.supernovaic.MaterialSearchBar/MaterialSearchBar.cs#L633 为。
if (NavIcon.Drawable is AnimatedVectorDrawable a)
修复问题。由于某种原因,运行链接器后不支持 IAnimatable 接口。
fanmixco 嗨@dellis1972,我去看看。谢谢。但是,它仍然是一个需要报告的错误,不是吗?因为它允许图标正确显示但动画不会发生。
dellis1972 它仍然是一个错误,但你现在有一个解决方法。我们需要看看为什么在链接步骤中删除了接口。
好的。所以它不是链接器错误,但我了解在这种情况下发生了什么。
所以 MaterialSearchBar 库中的代码依赖于 AnimatedVectorDrawable 类来处理它的动画。然而,这些并不是库中实际直接使用它的代码。因此,该类型作为 SdkOnly/Full 链接器步骤的一部分被链接出来。代码的 java 端仍然存在,但 C# 端所有对从 java 端引发的事件作出反应的粘合剂都消失了。因此,当您访问 NavIcon.Drawable 属性时,您只会得到一个不支持 IAnimatable 的 Android.Graphics.Drawable 类型,因为 java 类型的实际类型在 C# 端不存在。
我的解决方法有效的原因是阻止类型被链接。因此,您可以使用我提供的解决方法,也可以将类似的内容添加到 MaterialSearchBar 类
#pragma warning disable 0219, 0649
static bool falseflag = false;
static MaterialSearchBar ()
{
if (falseflag) {
var ignore = new AnimatedVectorDrawable ();
}
}
#pragma warning restore 0219, 0649 如https://docs.microsoft.com/en-us/xamarin/android/deploy-test/linker#falseflag中所述。
所以它不是一个错误,它是链接器的工作方式。在这方面没有什么我们可以真正解决的。如果代码没有直接使用类型,它将被删除。上面的代码使链接器误以为使用了该类型。
来源:https ://github.com/xamarin/xamarin-android/issues/6156
我更新了我的库并添加了推荐的解决方法。我仍然认为这是一个错误,但我的库作为我的应用程序正常工作。
推荐阅读
- git - 从本地提交和推送后无法在 Prod 中拉取更改
- python - 如何按层次类别结构中的值对熊猫中的数据框进行排序
- testing - 如何在 lambdatest 中在多个浏览器上运行测试?
- android - 在 Xamarin 中绑定 ListView 不绑定两个值
- r - 使用蒙特卡罗下的拒绝方法来解决R中的一个整数
- azure - Azure devops 服务连接已过期,无法编辑/续订
- python - 按索引搜索数据框并导出信息
- r - 在 CPL_geos_binop(st_geometry(x), st_geometry(y), op, par, pattern 中使用 st_intersects 时出错:评估错误:IllegalArgumentException
- java - 如何仅更改 LinkedList 中的一个值
- wpf - Avalon 在 Highlighting 中编辑 Highlighting