question

fanmixco avatar image
0 Votes"
fanmixco asked RobCaplan edited

How can I correctly exclude some libraries so that they are not linked in Xamarin.Android?

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.

117840-z54bs.gif

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

118271-cg0ut.gif

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 guard file, in the “exclusion” section, etc. but nothing works.

In my guard 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 that 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







dotnet-xamarin
z54bs.gif (1.5 MiB)
cg0ut.gif (1.5 MiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

fanmixco avatar image
0 Votes"
fanmixco answered

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

// Linker stuff
 #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/

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

LeonLu-MSFT avatar image
0 Votes"
LeonLu-MSFT answered LeonLu-MSFT edited

Hello,​

Welcome to our Microsoft Q&A platform!

I used this nuget package, then I set the linker to SDK Assemblies only, then I release the application, it could generate apk correctly.

118176-image.png

When you release the apk, you find the package is significantly bigger and Linker just be setted to Don’t Link? If so, you can try to generate AAB.

You can try to use native Search Widget in android, if it worked.


Best Regards,

Leon Lu



If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



image.png (60.1 KiB)
· 10
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi Leon, this is not my problem. I can generate the package. My issue is that I have to exclude the library to be linked because it is generating an abnormal behavior.

This is the normal behavior without linking:

118178-ezgifcom-gif-maker-1.gif

This is the abnormal behavior with any linking (even if I try excluding the package):

118179-117840-z54bs.gif

Thanks.

0 Votes 0 ·

it should be related to the animations library or something like that.

I open the your nuget github:https://github.com/FANMixco/Xamarin-SearchBar/blob/master/tk.supernovaic.MaterialSearchBar/Resources/animator/menu_to_back_rotation.xml. it seem this part of code not work after you set the linker. You can try to add the following code to guard file.

`-keep android.animation.ObjectAnimator.** { *; }

0 Votes 0 ·

Hi Leon, I tried:

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

and

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

and

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

None of them without any success.

I also believe that is the same section in the animations. I have an odd feeling that is related to the Linker itself because both of them are failing.

Any other idea? Thanks.

0 Votes 0 ·
Show more comments