如何正确排除某些库,以便它们不会在 Xamarin.Android 中链接? [英] How can I correctly exclude some libraries so that they are not linked in Xamarin.Android?

查看:32
本文介绍了如何正确排除某些库,以便它们不会在 Xamarin.Android 中链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行良好的应用程序,但由于我无法链接库(因为它会导致异常行为),它变得明显更大(多 20 MiB).主要问题发生在我自己的一个库中:

这是预期行为,当我不链接任何内容时是正常的:

该应用仅在我使用不链接时才能正常运行.但是,我想了解我必须排除什么(或如何正确执行)或更改以避免此问题.此时,我尝试在 ProGuard 文件、排除"部分等中排除它,但没有任何效果.

在我的 ProGuard 文件中,我有以下组合:

-keep class androidx.work.** { *;}-保持类androidx.concurrent.** { *;}-保持类androidx.tracing.** { *;}-保持类androidx.paging.** { *;}-保持类com.google.android.gms.** { *;}-保持类androidx.appcompat.widget.** { *;}-保持类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;如果 (id == id){如果 (!IsSearchEnabled){启用搜索();}}否则如果(id == Resource.Id.mt_arrow){禁用搜索();}否则如果(id == Resource.Id.mt_search){如果(监听器存在()){OnSearchActionListener.OnButtonClicked(BUTTON_SPEECH);}}否则如果(id == Resource.Id.mt_clear){SearchEdit.Text = "";}否则如果(id == Resource.Id.mt_menu){PopupMenu.Show();}否则如果(id == Resource.Id.mt_nav){int 按钮 = IsSearchEnabled ?BUTTON_BACK : BUTTON_NAVIGATION;如果(IsSearchEnabled){禁用搜索();}如果(监听器存在()){OnSearchActionListener.OnButtonClicked(button);}}}

更新 1:

我已添加到我的图书馆:

[Preserve(AllMembers = true)]

[程序集: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:

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

更新 4:

我更新了我的库和应用程序,并在 Resources 中添加了一个名为 raw 的新文件夹,其中包含一个带有以下代码的 keep.xml:

<资源 xmlns:tools="http://schemas.android.com/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"/>

并添加到我的 ProGuard:

-保持类**.R-keepclassmembers 类 tk.supernovaic.MaterialSearchBar.* {<字段>;<init>();<方法>;}

所有这一切都没有任何积极的结果.该错误仍然存​​在.

更新 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

解决方案

在 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 接口在链接器已运行.

<块引用>

凡米斯科嗨@dellis1972,我要检查一下.谢谢.但是,它仍然是一个需要报告的错误,不是吗?因为它允许图标正确显示但动画不会发生.

<块引用>

dellis1972它仍然是一个错误,但你现在有一个解决方法.我们需要看看为什么在链接步骤中删除了界面.

<块引用>

好的.所以它不是链接器错误,但我明白发生了什么这种情况.

所以 MaterialSearchBar 库中的代码是依赖于AnimatedVectorDrawable 类处理它的动画.然而这些库中没有实际直接使用它的代码.所以类型作为 SdkOnly/Full 链接器步骤的一部分链接出.java端的代码仍然存在,但是 C# 端的所有胶水将对从 java 端引发的事件做出反应都消失了.所以当您访问 NavIcon.Drawable 属性时,您只会得到一个Android.Graphics.Drawable 类型返回哪个不支持IAnimatable,因为 java 类型的实际类型,不存在于 C# 端.

我的解决方法有效的原因是停止类型被联系起来.所以你可以使用我提供的工作或者在 MaterialSearchBar 类中添加这样的东西

 #pragma 警告禁用 0219, 0649static bool falseflag = false;静态 MaterialSearchBar(){如果(错误标志){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/

I have an app that is working fine but since I cannot link the libraries (because it causes an abnormal behavior) it becomes significantly bigger (20 MiB more). The main issue happens with one of my own libraries:

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

I "excluded" the package and its dependencies:

Xamarin.AndroidX.AppCompat;Xamarin.AndroidX.ConstraintLayout;Xamarin.AndroidX.RecyclerView;Xamarin.AndroidX.CardView

But the "linking" options behave quite odd because they are not excluded neither in linking all or only linking SDK only. The animations got somehow mad and they are working in a "particular" way, the hamburger menu transforms into an arrow when it shouldn’t and vice-versa and if I do click on the X, it just removes the X forever and doesn’t clean. The following image can give you an idea of the abnormal behavior.

This is the expected behavior and normal when I don't link anything:

The app only works properly when I use Don’t Link. However, I want to understand what I must exclude (or how to do it properly) or change to avoid this issue. At this point, I tried excluding it in the ProGuard file, in the "exclusion" section, etc. but nothing works.

In my ProGuard file, I have these combinations:

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

And I also tried to add:

-keep class tk.supernovaic.MaterialSearchBar.** { *; }

But the results were exactly the same. I don't know what I can exclude being honest. Any idea?

P.S.:

I can create the package to be published, this is not my problem.

My library is open-source if you want to give me any advice on how to change this logic and fix this problem:

https://github.com/FANMixco/Xamarin-SearchBar

It's important to highlight that I wrote this library in C# and Xamarin. This is not the binding of another one.

In my opinion, the issue happens in this section:

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);
        }
    }
}

Update 1:

I have added to my library:

[Preserve(AllMembers = true)]

[assembly: LinkerSafe]

And this to my project:

--linkskip=tk.supernovaic.MaterialSearchBar

And the bug persists; therefore, it should be related to the animations library or something like that.

Update 2:

I have tried also:

-keep class android.animation.ObjectAnimator.** { *; } -keep class **.R$* { public static <fields>; }

and:

-keep class android.animation.** { *; }

Both still fails but it seems it´s related to the animations:

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

Also, I added --linkskip=android.animation --linkskip=tk.supernovaicMaterialSearchBar without any result.

Update 3:

I copied the files from my lib to my project and kept all previous rules without any positive result.

Update 4:

I updated my library and app and added a new folder in the Resources called raw that contains a keep.xml with the following code:

<?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" />

And added to my ProGuard:

-keep class **.R
-keepclassmembers class tk.supernovaic.MaterialSearchBar.* {
    <fields>;
    <init>();
    <methods>;
}

All this without any positive result. The bug persists.

Update 5:

I have raised a ticket to Microsoft because I'm almost convinced this is a bug related to the linker itself:

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

My conclusions are based on these three points:

  1. I added the original files (animations) to the project.
  2. I added a rule to keep the XMLs in the project and library.
  3. I added rules to preserve the R classes and everything (resources) in the ProGuard file.

It makes no sense that with the previous 3 points the animations are not preserved, in my opinion. If you have any other thoughts feel free to share them, I'm open to listening to them.

Update 6:

I also opened a ticket in GitHub because I believe it's a bug:

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

解决方案

After a lot of updates and running between StackOverflow, GitHub, Visual Studio and the Microsoft Forums, I was able to find the problem:

dellis1972 Changing this line https://github.com/FANMixco/Xamarin-SearchBar/blob/master/tk.supernovaic.MaterialSearchBar/MaterialSearchBar.cs#L633 to be.

if (NavIcon.Drawable is AnimatedVectorDrawable a) Fixes the issue. For some reason the IAnimatable interface is not supported after the linker is run.

fanmixco Hi @dellis1972, I'm going to check it. Thanks. However, is it still a bug to be reported, isn't it? Because it allows the icons to be shown properly but the animation doesn't happen.

dellis1972 It is still a bug, but you have a work around for now. We'll need to look at see why the interface is removed as part of the link step.

ok. so its not a linker bug, but I understand what is happening in this case.

So the code in the MaterialSearchBar library is relying on the AnimatedVectorDrawable class deal with its animations. However these is no code in the library which actually uses it directly. So the type is linked out as part of the SdkOnly/Full linker step. The java side of the code will still exist , but all the glue on the C# side which will react to events being raised from the java side is all gone. So when you access the NavIcon.Drawable property you just get a Android.Graphics.Drawable type back which does not support IAnimatable, because the actual type which the java type is , doesn't exist on the C# side.

The reason why my workaround works is that is stops the type from being linked away. So you can either use the work around I provided or add something like this to the MaterialSearchBar class

 #pragma warning disable 0219, 0649
     static bool falseflag = false;
     static MaterialSearchBar ()
     {
         if (falseflag) {
             var ignore = new AnimatedVectorDrawable ();
         }
     }

#pragma warning restore 0219, 0649 as described in https://docs.microsoft.com/en-us/xamarin/android/deploy-test/linker#falseflag.

So its not a bug, its how the linker works. There isn't anything we can really fix on this side. If the code is not directly using a type, it will be removed. The code above fools the linker into thinking the type is used.

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

I updated my library and added the recommended workaround. I still believe it's a bug but my library is working properly as my app.

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

这篇关于如何正确排除某些库,以便它们不会在 Xamarin.Android 中链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆