【问题标题】:How can I correctly exclude some libraries so that they are not linked in Xamarin.Android?如何正确排除某些库,以便它们不在 Xamarin.Android 中链接?
【发布时间】:2021-10-02 04:09:23
【问题描述】:

我有一个运行良好的应用程序,但由于我无法链接库(因为它会导致 异常行为),它变得明显更大(多出 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.** { *; }

但结果完全一样。我不知道我可以排除什么是诚实的。有什么想法吗?

附注:

我可以创建要发布的包,这不是我的问题。

如果您想就如何更改此逻辑并解决此问题给我任何建议,我的库是开源的:

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.** { *; }

两者仍然失败,但似乎与动画有关:

https://github.com/FANMixco/Xamarin-SearchBar/blob/master/tk.supernovaic.MaterialSearchBar/Resources/animator/menu_to_back_rotation.xml

另外,我添加了--linkskip=android.animation --linkskip=tk.supernovaicMaterialSearchBar,但没有任何结果。

更新 3:

我将文件从我的 lib 复制到我的项目中,并保留了所有以前的规则,没有任何积极的结果。

更新 4:

我更新了我的库和应用程序,并在 Resources 中添加了一个名为 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 提出了投诉,因为我几乎确信这是与链接器本身相关的错误:

https://developercommunity.visualstudio.com/t/xamarinandroid-linking-libs-not-working-as-expecte/1482147?from=email

我的结论基于以下三点:

  1. 我将原始文件(动画)添加到项目中。
  2. 我添加了一条规则以将 XML 保留在项目和库中。
  3. 我添加了规则以保留 ProGuard 文件中的 R 类和所有内容(资源)。

在我看来,没有保留前 3 点的动画是没有意义的。如果您有任何其他想法,请随时分享,我愿意倾听。

更新 6:

我还在 GitHub 上开了一张票,因为我认为这是一个错误:

https://github.com/xamarin/xamarin-android/issues/6156

【问题讨论】:

  • 你是否尝试在你的csproj文件中排除它,参考stackoverflow.com/questions/20748136/…
  • 嗨@LeoZhu-MSFT,你能举例说明如何使用它吗?因为我看不懂这个例子。另外,我应该写我的 DLL 的名称还是准确的写法?上一个问题没有提供他排除代码的示例。
  • 嗨@LeoZhu-MSFT,我可以看到有人与我的“类似”问题找不到如何排除他们:stackoverflow.com/a/58201262/1928691。
  • 嗨@LeoZhu-MSFT,我什至将此[Preserve(AllMembers = true)] 添加到我的库中,甚至“排除”了它,并且错误仍然存​​在。有什么想法吗?
  • 嗨@LeoZhu-MSFT,我认为问题在于链接器在这里弄乱了动画:github.com/FANMixco/Xamarin-SearchBar/tree/master/… 和github.com/FANMixco/Xamarin-SearchBar/tree/master/…,因为我什至修改了 pro-guard 并排除了每个库,什​​么也没有.问题仍然存在。有什么想法吗?

标签: xamarin xamarin.android proguard xamarin-linker


【解决方案1】:

在 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 属性时,您只会得到一个 Android.Graphics.Drawable 类型返回其中不支持 IAnimatable,因为 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

我更新了我的库并添加了推荐的解决方法。我仍然认为这是一个错误,但我的库作为我的应用程序正常运行。

https://www.nuget.org/packages/Xamarin-MaterialSearchBar/

【讨论】:

    猜你喜欢
    • 2012-05-02
    • 1970-01-01
    • 2014-01-30
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    相关资源
    最近更新 更多