Устранение неполадок с привязкамиTroubleshooting Bindings

В этой статье перечислены общие ошибки сервера, которые могут возникнуть при создании привязок, а также возможные причины и способы их устранения.This article summarizes serveral common errors that may occur when generating bindings, along with possible causes and suggested ways to resolve them.

ОбзорOverview

Привязка библиотеки Android (файл . AAR или . jar) редко является простым привязанности; обычно требуются дополнительные усилия по устранению проблем, возникающих в результате различий между Java и .NET.Binding an Android library (an .aar or a .jar) file is seldom a straightforward affair; it usually requires additional effort to mitigate issues that result from the differences between Java and .NET. Эти проблемы не позволят Xamarin. Android привязать библиотеку Android и представлять их как сообщения об ошибках в журнале сборки.These issues will prevent Xamarin.Android from binding the Android library and present themselves as error messages in the build log. В этом руководство будут представлены некоторые советы по устранению неполадок, перечислены некоторые из наиболее распространенных проблем и сценариев, а также предоставлены возможные решения для успешной привязки библиотеки Android.This guide will provide some tips for troubleshooting the issues, list some of the more common problems/scenarios, and provide possible solutions to successfully binding the Android library.

При привязке существующей библиотеки Android необходимо иметь в виду следующие моменты.When binding an existing Android library, it is necessary to keep in mind the following points:

  • Внешние зависимости для библиотеки Все зависимости Java, необходимые для библиотеки Android, должны быть добавлены в проект Xamarin. Android как референцежар или как ембеддедреференцежар. –The external dependencies for the library – Any Java dependencies required by the Android library must be included in the Xamarin.Android project as a ReferenceJar or as an EmbeddedReferenceJar.

  • Уровень API Android, предназначенных библиотека Android – Нельзя «понизить уровень» API Android; убедитесь, что в проекте привязки Xamarin. Android используется тот же уровень API (или выше), что и в библиотеке Android.The Android API level that the Android library is targetting – It is not possible to "downgrade" the Android API level; ensure that the Xamarin.Android binding project is targeting the same API level (or higher) as the Android library.

  • Версия JDK Android, которая использовалась для упаковки библиотеки Android – Ошибки привязки могут возникать, если библиотека Android была построена с использованием другой версии JDK, отличной от используемой Xamarin. Android.The version of the Android JDK that was used to package the Android library – Binding errors may occur if the Android library was built with a different version of JDK than the one in use by Xamarin.Android. Если возможно, перескомпилируйте библиотеку Android с использованием той же версии JDK, которая используется в вашей установке Xamarin. Android.If possible, recompile the Android library using the same version of the JDK that is used by your installation of Xamarin.Android.

Первым шагом в устранении неполадок привязки библиотеки Xamarin. Android является включение выходных данных диагностики MSBuild.The first step to troubleshooting issues with binding a Xamarin.Android library is to enable diagnostic MSBuild output. После включения диагностических данных перестройте проект привязки Xamarin. Android и изучите журнал сборки, чтобы найти сведения о причине проблемы.After enabling the diagnostic output, rebuild the Xamarin.Android binding project and examine the build log to locate clues about what the cause of problem is.

Также может оказаться полезным декомпилировать библиотеку Android и исследовать типы и методы, которые пытается выполнить привязка Xamarin. Android.It can also prove helpful to decompile the Android library and examine the types and methods that Xamarin.Android is trying to bind. Более подробно эти сведения рассматриваются далее в этом пошаговом окне.This is covered in more detail later on in this guide.

Декомпиляция библиотеки AndroidDecompiling an Android Library

Изучение классов и методов классов Java может предоставить ценную информацию, которая поможет привязать библиотеку.Inspecting the classes and methods of the Java classes can provide valuable information that will assist in binding a library. JD — графический интерфейс пользователя — это графическая программа, которая может отображать исходный код Java из файлов классов , содержащихся в JAR-файле.JD-GUI is a graphical utility that can display Java source code from the CLASS files contained in a JAR. Его можно запустить как автономное приложение или как подключаемый модуль для IntelliJ или Eclipse.It can be run as a stand alone application or as a plug-in for IntelliJ or Eclipse.

Чтобы декомпилировать библиотеку Android, откройте . JAR -файл с декомпилятором Java.To decompile an Android library open the .JAR file with the Java decompiler. Если библиотека является . AAR , необходимо извлечь файл Classes. jar из файла архива.If the library is an .AAR file, it is necessary to extract the file classes.jar from the archive file. Ниже приведен пример снимка экрана с использованием JD-GUI для анализа JAR принцессу :The following is a sample screenshot of using JD-GUI to analyze the Picasso JAR:

Использование декомпилятора Java для анализа Пикассо-2.5.2. jar

После декомпиляции библиотеки Android изучите исходный код.Once you have decompiled the Android library, examine the source code. Говоря вообще, ищите:Generally speaking, look for :

  • Классы, имеющие характеристики запутывания – Характеристики запутанных классов включают:Classes that have characteristics of obfuscation – Characteristics of obfuscated classes include:

    • Имя класса включает $ , т. е. класс $.The class name includes a $, i.e. a$.class
    • Имя класса полностью скомпрометировано символов нижнего регистра, т. е. класса.The class name is entirely compromised of lower case characters, i.e. a.class
  • инструкции для библиотек без ссылок указывают на библиотеку, на которую нет ссылок, и добавляют эти зависимости в проект привязки Xamarin. Android с действием сборки референцежар или importЕмбедддедреференцежар.import statements for unreferenced libraries – Identify the unreferenced library and add those dependencies to the Xamarin.Android binding project with a Build Action of ReferenceJar or EmbedddedReferenceJar.

Примечание

Декомпиляция библиотеки Java может быть запрещена или подчиняется юридическим ограничениям на основе местного законодательства или лицензии, с которой была опубликована библиотека Java.Decompiling a Java library may be prohibited or subject to legal restrictions based on local laws or the license under which the Java library was published. При необходимости закрепите службы юридического лица, прежде чем пытаться декомпилировать библиотеку Java и изучить исходный код.If necessary, enlist the services of a legal professional before attempting to decompile a Java library and inspect the source code.

Проверьте API. КОДInspect API.XML

В процессе создания проекта привязки Xamarin. Android создает имя XML-файла obj/Debug/API. XML:As a part of building a binding project, Xamarin.Android will generate an XML file name obj/Debug/api.xml:

Созданный API. XML в файле obj/Debug

Этот файл содержит список всех API-интерфейсов Java, которые выполняет привязка Xamarin. Android.This file provides a list of all the Java APIs that Xamarin.Android is trying bind. Содержимое этого файла может помочь определить отсутствующие типы или методы, дублирующие привязки.The contents of this file can help identify any missing types or methods, duplicate binding. Хотя проверка этого файла выполняется утомительно и занимает много времени, она может предоставить сведения о том, что может вызвать проблемы с привязкой.Although inspection of this file is tedious and time consuming, it can provide for clues on what might be causing any binding problems. Например, файл API. XML может обнаружить, что свойство возвращает недопустимый тип, или что существует два типа, имеющих одно и то же управляемое имя.For example, api.xml might reveal that a property is returning an inappropriate type, or that there are two types that share the same managed name.

Известные проблемыKnown Issues

В этом разделе перечислены некоторые распространенные сообщения об ошибках или симптомы, которые возникают при попытке привязать библиотеку Android.This section will list some of the common error messages or symptoms that my occur when trying to bind an Android library.

Проблема: Несоответствие версий JavaProblem: Java Version Mismatch

Иногда типы не будут создаваться или непредвиденные сбои могут возникать из-за того, что вы используете более новую или более раннюю версию Java по сравнению с библиотекой, с которой была выполнена компиляция.Sometimes types will not be generated or unexpected crashes may occur because you are using either a newer or older version of Java compared to what the library was compiled with. Перекомпилируйте библиотеку Android с той же версией JDK, которую использует проект Xamarin. Android.Recompile the Android library with the same version of the JDK that your Xamarin.Android project is using.

Проблема: Требуется по крайней мере одна библиотека JavaProblem: At least one Java library is required

Вы получаете сообщение об ошибке «требуется по крайней мере одна библиотека Java», даже если. Был добавлен JAR-файл.You receive the error "at least one Java library is required," even though a .JAR has been added.

Возможные причины:Possible Causes:

Убедитесь, что для EmbeddedJarдействия сборки задано значение.Make sure the build action is set to EmbeddedJar. Так как существует несколько действий сборки для. JAR-файлы (например InputJar ReferenceJar , EmbeddedJar, и EmbeddedReferenceJar), генератор привязок не может автоматически угадать, какой из них использовать по умолчанию.Since there are multiple build actions for .JAR files (such as InputJar, EmbeddedJar, ReferenceJar and EmbeddedReferenceJar), the binding generator cannot automatically guess which one to use by default. Дополнительные сведения о действиях сборки см. в разделе действия сборки.For more information about build actions, see Build Actions.

Проблема: Средства привязки не могут загрузить. Библиотека JAR-файловProblem: Binding tools cannot load the .JAR library

Генератору библиотек привязки не удается загрузить. Библиотека JAR.The binding library generator fails to load the .JAR library.

Возможные причиныPossible Causes

Некоторых. Библиотеки JAR, использующие маскировку кода (с помощью таких средств, как reguard), не могут быть загружены средствами Java.Some .JAR libraries that use code obfuscation (via tools such as Proguard) cannot be loaded by the Java tools. Так как в нашем средстве используется отражение Java и библиотека инженерного кода ASM, эти зависимые средства могут отклонять маскированные библиотеки, в то время как средства среды выполнения Android могут передаваться.Since our tool makes use of Java reflection and the ASM byte code engineering library, those dependent tools may reject the obfuscated libraries while Android runtime tools may pass. Для решения этой проблемы можно вручную привязать эти библиотеки вместо использования генератора привязки.The workaround for this is to hand-bind these libraries instead of using the binding generator.

Проблема: В C# создаваемых выходных данных отсутствуют типы.Problem: Missing C# types in generated output.

Сборка Binding . dll создает, но не пропустила некоторые типы Java, C# или созданный источник не строится из-за ошибки, сообщающей о наличии отсутствующих типов.The binding .dll builds but misses some Java types, or the generated C# source does not build due to an error stating there are missing types.

Возможные причины:Possible Causes:

Эта ошибка может возникать по нескольким причинам, указанным ниже.This error may occur due to several reasons as listed below:

  • Связанная библиотека может ссылаться на вторую библиотеку Java.The library being bound may reference a second Java library. Если открытый API для привязанной библиотеки использует типы из второй библиотеки, необходимо также ссылаться на управляемую привязку для второй библиотеки.If the public API for the bound library uses types from the second library, you must reference a managed binding for the second library as well.

  • Возможно, что библиотека была внедрена из-за отражения Java, аналогично причине ошибки загрузки библиотеки выше, что привело к непредвиденной загрузке метаданных.It is possible that a library was injected due to Java reflection, similar to the reason for the library load error above, causing the unexpected loading of metadata. В настоящее время средства Xamarin. Android не могут решить эту проблему.Xamarin.Android's tooling cannot currently resolve this situation. В этом случае библиотека должна быть привязана вручную.In such a case, the library must be manually bound.

  • В среде выполнения .NET 4,0 возникла ошибка, которая не смогла загрузить сборки, когда она должна иметь.There was a bug in .NET 4.0 runtime that failed to load assemblies when it should have. Эта проблема исправлена в среде выполнения .NET 4,5.This issue has been fixed in the .NET 4.5 runtime.

  • Java позволяет наследовать открытый класс от класса, не являющегося открытым, но это не поддерживается в .NET.Java allows deriving a public class from non-public class, but this is unsupported in .NET. Поскольку генератор привязки не создает привязки для классов, не являющихся открытыми, производные классы, такие как, не могут быть сформированы правильно.Since the binding generator does not generate bindings for non-public classes, derived classes such as these cannot be generated correctly. Чтобы устранить эту проблему, удалите запись метаданных для этих производных классов с помощью Remove-Node в файле Metadata. XMLили исправьте метаданные, которые отправляют неоткрытый класс в открытый.To fix this, either remove the metadata entry for those derived classes using the remove-node in Metadata.xml, or fix the metadata that is making the non-public class public. Несмотря на то, что Последнее решение создаст привязку, C# чтобы источник выполнит сборку, не следует использовать неоткрытый класс.Although the latter solution will create the binding so that the C# source will build, the non-public class should not be used.

    Например:For example:

    <attr path="/api/package[@name='com.some.package']/class[@name='SomeClass']"
        name="visibility">public</attr>
    
  • Средства, которые закрывают библиотеки Java, могут конфликтовать с генератором привязок Xamarin. Android и его C# возможностью создавать классы-оболочки.Tools that obfuscate Java libraries may interfere with the Xamarin.Android Binding Generator and its ability to generate C# wrapper classes. В следующем фрагменте кода показано, как обновить файл metadata. XML для демаскировки имени класса:The following snippet shows how to update Metadata.xml to unobfuscate a class name:

    <attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
        name="obfuscated">false</attr>
    

Проблема: Создание C# созданного источника не выполняется из-за несоответствия типов параметровProblem: Generated C# source does not build due to parameter type mismatch

Созданный C# источник не строится.The generated C# source does not build. Типы параметров переопределенного метода не совпадают.Overridden method's parameter types do not match.

Возможные причины:Possible Causes:

Xamarin. Android включает множество полей Java, сопоставленных с перечислениями в C# привязках.Xamarin.Android includes a variety of Java fields that are mapped to enums in the C# bindings. Это может привести к несовместимости типов в созданных привязках.These can cause type incompatibilities in the generated bindings. Чтобы устранить эту проблему, необходимо изменить подписи методов, созданные в генераторе привязок, чтобы использовать перечисления.To resolve this, the method signatures created from the binding generator need to be modified to use the enums. Дополнительные сведения см. в разделе исправлениеперечислений.For more imformation, please see Correcting Enums.

Проблема: Ноклассдеффаундеррор в упаковкеProblem: NoClassDefFoundError in packaging

java.lang.NoClassDefFoundErrorна шаге упаковки создается исключение.java.lang.NoClassDefFoundError is thrown in the packaging step.

Возможные причины:Possible Causes:

Наиболее вероятная причина этой ошибки заключается в том, что обязательная библиотека Java должна быть добавлена в проект приложения (CSPROJ).The most likely reason for this error is that a mandatory Java library needs to be added to the application project (.csproj). . JAR-файлы не разрешаются автоматически..JAR files are not automatically resolved. Привязка библиотеки Java не всегда создается для пользовательской сборки, которая не существует на целевом устройстве или эмуляторе (например, в Google Maps Map. jar).A Java library binding is not always generated against a user assembly that does not exist in the target device or emulator (such as Google Maps maps.jar). Это не так для поддержки проекта библиотеки Android в качестве библиотеки. JAR-файл внедряется в библиотеку DLL.This is not the case for Android Library project support, as the library .JAR is embedded in the library dll. Например: Ошибка 4288For example: Bug 4288

Проблема: Дублирование пользовательских типов EventArgsProblem: Duplicate custom EventArgs types

Сбой сборки из-за дублирования пользовательских типов EventArgs.Build fails due to duplicate custom EventArgs types. Произошла ошибка, подобная следующей:An error like this occurs:

error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for `p0'

Возможные причины:Possible Causes:

Это обусловлено тем, что существует конфликт между типами событий, поступающими из более чем одного типа "прослушиватель" интерфейса, который использует одинаковые имена для методов.This is because there is some conflict between event types that come from more than one interface "listener" type that shares methods having identical names. Например, если есть два интерфейса Java, как показано в приведенном ниже примере, генератор создает DismissScreenEventArgs MediationBannerListener для и MediationInterstitialListener, что приводит к ошибке.For example, if there are two Java interfaces as seen in the example below, the generator creates DismissScreenEventArgs for both MediationBannerListener and MediationInterstitialListener, resulting in the error.

// Java:
public interface MediationBannerListener {
    void onDismissScreen(MediationBannerAdapter p0);
}
public interface MediationInterstitialListener {
    void onDismissScreen(MediationInterstitialAdapter p0);
}

Это сделано по шаблону, чтобы избежать длинных имен в типах аргументов событий.This is by design so that lengthy names on event argument types are avoided. Чтобы избежать этих конфликтов, требуется преобразование некоторых метаданных.To avoid these conflicts, some metadata transformation is required. Измените трансформс\метадата.ксмл и добавьте argsType атрибут в любой из интерфейсов (или в метод интерфейса):Edit Transforms\Metadata.xml and add an argsType attribute on either of the interfaces (or on the interface method):

<attr path="/api/package[@name='com.google.ads.mediation']/
        interface[@name='MediationBannerListener']/method[@name='onDismissScreen']"
        name="argsType">BannerDismissScreenEventArgs</attr>

<attr path="/api/package[@name='com.google.ads.mediation']/
        interface[@name='MediationInterstitialListener']/method[@name='onDismissScreen']"
        name="argsType">IntersitionalDismissScreenEventArgs</attr>

<attr path="/api/package[@name='android.content']/
        interface[@name='DialogInterface.OnClickListener']"
        name="argsType">DialogClickEventArgs</attr>

Проблема: Класс не реализует метод интерфейсаProblem: Class does not implement interface method

Выдается сообщение об ошибке, указывающее, что создаваемый класс не реализует метод, необходимый для интерфейса, реализуемого созданным классом.An error message is produced indicating that a generated class does not implement a method that is required for an interface which the generated class implements. Однако, взглянув на созданный код, можно увидеть, что метод реализован.However, looking at the generated code, you can see that the method is implemented.

Ниже приведен пример ошибки.Here is an example of the error:

obj\Debug\generated\src\Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.cs(8,23):
error CS0738: 'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter' does not
implement interface member 'Oauth.Signpost.Http.IHttpRequest.Unwrap()'.
'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.Unwrap()' cannot implement
'Oauth.Signpost.Http.IHttpRequest.Unwrap()' because it does not have the matching
return type of 'Java.Lang.Object'

Возможные причины:Possible Causes:

Это проблема, возникающая при связывании методов Java с ковариантными возвращаемыми типами.This is a problem that occurs with binding Java methods with covariant return types. В этом примере метод Oauth.Signpost.Http.IHttpRequest.UnWrap() должен возвращать Java.Lang.Objectзначение.In this example, the method Oauth.Signpost.Http.IHttpRequest.UnWrap() needs to return Java.Lang.Object. Однако метод Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.UnWrap() имеет тип возвращаемого значения HttpURLConnection.However, the method Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.UnWrap() has a return type of HttpURLConnection. Устранить эту проблему можно двумя способами:There are two ways to fix this issue:

  • Добавьте объявление разделяемого класса для HttpURLConnectionRequestAdapter и явно реализуйте: IHttpRequest.Unwrap()Add a partial class declaration for HttpURLConnectionRequestAdapter and explicitly implement IHttpRequest.Unwrap():

    namespace Oauth.Signpost.Basic {
        partial class HttpURLConnectionRequestAdapter {
            Java.Lang.Object OauthSignpost.Http.IHttpRequest.Unwrap() {
                return Unwrap();
            }
        }
    }
    
  • Удалите ковариацию из созданного C# кода.Remove the covariance from the generated C# code. Это включает в себя добавление следующего преобразования в трансформс\метадата.ксмл , которое приведет к C# тому, что созданный код будет иметь Java.Lang.Objectтип возвращаемого значения:This involves adding the following transform to Transforms\Metadata.xml which will cause the generated C# code to have a return type of Java.Lang.Object:

    <attr
        path="/api/package[@name='oauth.signpost.basic']/class[@name='HttpURLConnectionRequestAdapter']/method[@name='unwrap']"
        name="managedReturn">Java.Lang.Object
    </attr>
    

Проблема: Конфликты имен во внутренних классах и свойствахProblem: Name Collisions on Inner Classes / Properties

Конфликтующая видимость наследуемых объектов.Conflicting visibility on inherited objects.

В Java не требуется, чтобы производный класс имел ту же видимость, что и его родитель.In Java, it's not required that a derived class have the same visibility as its parent. Java просто исправит это решение.Java will just fix that for you. В C#, это должно быть явным, поэтому необходимо убедиться, что все классы в иерархии имеют соответствующую видимость.In C#, that has to be explicit, so you need to make sure all classes in the hierarchy have the appropriate visibility. В следующем примере показано, как изменить имя пакета Java с com.evernote.android.job на: Evernote.AndroidJobThe following example shows how to change a Java package name from com.evernote.android.job to Evernote.AndroidJob:

<!-- Change the visibility of a class -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']" name="visibility">public</attr>

<!-- Change the visibility of a method -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']/method[@name='MethodName']" name="visibility">public</attr>

Проблема: О . Поэтому Библиотека, необходимая для привязки, не загружаетсяProblem: A .so Library Required by the Binding is Not Loading

Некоторые проекты привязки могут также зависеть от функциональности в . Итак, библиотека.Some binding projects may also depend on functionality in a .so library. Возможно, Xamarin. Android не будет автоматически загружать библиотеку .It is possible that Xamarin.Android will not automatically load the .so library. При выполнении упакованного кода Java Xamarin. Android не сможет выполнить вызов JNI и сообщение об ошибке Java. lang. унсатисфиедлинкеррор: Собственный метод не найден: будет отображаться в logcat out для приложения.When the wrapped Java code executes, Xamarin.Android will fail to make the JNI call and the error message java.lang.UnsatisfiedLinkError: Native method not found: will appear in the logcat out for the application.

Исправление для этого — вручную загрузить библиотеку . так , чтобы библиотека вызывала вызов Java.Lang.JavaSystem.LoadLibrary.The fix for this is to manually load the .so library with a call to Java.Lang.JavaSystem.LoadLibrary. Например, предположим, что проект Xamarin. Android имеет общую библиотеку libpocketsphinx_jni. Поэтому он включается в проект привязки с действием сборки ембеддеднативелибрари, приведенным ниже фрагментом кода (выполняется перед использованием общей библиотеки). загрузит библиотеку . так :For example assuming that a Xamarin.Android project has shared library libpocketsphinx_jni.so included in the binding project with a build action of EmbeddedNativeLibrary, the following snippet (executed before using the shared library) will load the .so library:

Java.Lang.JavaSystem.LoadLibrary("pocketsphinx_jni");

СводкаSummary

В этой статье перечислены распространенные проблемы устранения неполадок, связанные с привязками Java, и описаны способы их устранения.In this article, we listed common troubleshooting issues associated with Java Bindings and explained how to resolve them.