Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Библиотека привязки Java для .NET на Android пытается автоматизировать большую часть работы, необходимой для привязки существующей библиотеки Android с помощью средства, иногда известного как Генератор привязок. При привязке библиотеки Java .NET для Android проверяет классы Java и создает список всех пакетов, типов и членов, которые должны быть привязаны. Этот список API хранится в XML-файле, который можно найти в {каталоге проекта}\obj{Configuration}\api.xml.
Генератор привязок будет использовать файл api.xml как основу для создания необходимых классов-оболочек C#. Ниже приведен пример содержимого файла api.xml:
<api>
<package name="android">
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object"
extends-generic-aware="java.lang.Object"
final="true"
name="Manifest"
static="false"
visibility="public">
<constructor deprecated="not deprecated" final="false"
name="Manifest" static="false" type="android.Manifest"
visibility="public">
</constructor>
</class>
...
</api>
В этом примере файл api.xml объявляет класс в пакете android с именем Manifest, который расширяет java.lang.Object.
Во многих случаях требуется участие человека, чтобы сделать API Java похожим на .NET или устранить проблемы, препятствующие компиляции сборки привязки. Например, может потребоваться изменить имена пакетов Java на пространства имен .NET, переименовать класс или изменить тип возвращаемого значения метода.
Эти изменения не должны быть достигнуты путем непосредственного изменения api.xml . Вместо этого изменения записываются в специальные файлы XML, предоставляемые шаблоном библиотеки привязки Java. При компиляции сборки привязки .NET для Android генератор привязок будет зависеть от этих файлов сопоставления при создании сборки привязки.
Файл Metadata.xml является наиболее важным из этих файлов, так как он позволяет изменять привязку общего назначения, например:
переименовывать пространства имен, классы, методы или поля, чтобы они соответствовали соглашениям .NET;
удалять пространства имен, классы, методы или поля, которые больше не требуются;
перемещать классы в разные пространства имен;
добавлять дополнительные классы поддержки для обеспечения соответствия структуры привязки шаблонам .NET Framework.
файл преобразования Metadata.xml
Как мы уже узнали, файл Metadata.xml используется генератором привязок для влияния на создание сборки привязок. Формат метаданных использует синтаксис XPath .
Эта реализация является почти полной реализацией XPath 1.0 с такой же поддержкой элементов в стандарте 1.0. Этот файл является мощным механизмом на основе XPath для изменения, добавления, скрытия или перемещения любого элемента или атрибута в файле API. Все элементы правила в спецификации метаданных включают path атрибут для идентификации узлов, к которым применяется правило. Ниже перечислены доступные типы элементов:
- add-node — добавляет дочерний узел к узлу, указанному атрибутом пути.
- attr — задает значение атрибута элемента, указанного атрибутом пути.
- remove-node — удаляет узлы, соответствующие указанному XPath.
Далее приведен пример файла Metadata.xml:
<metadata>
<!-- Normalize the namespace for .NET -->
<attr path="/api/package[@name='com.evernote.android.job']"
name="managedName">Evernote.AndroidJob</attr>
<!-- Don't need these packages for the .NET for Android binding/public API -->
<remove-node path="/api/package[@name='com.evernote.android.job.v14']" />
<remove-node path="/api/package[@name='com.evernote.android.job.v21']" />
<!-- Change a parameter name from the generic p0 to a more meaningful one. -->
<attr path="/api/package[@name='com.evernote.android.job']/class[@name='JobManager']/method[@name='forceApi']/parameter[@name='p0']"
name="name">api</attr>
</metadata>
Ниже перечислены некоторые из наиболее часто используемых элементов XPath для API Java.
interface— используется для поиска интерфейса Java. Например,/interface[@name='AuthListener'].class— используется для поиска класса. Например,/class[@name='MapView'].method— используется для поиска метода в классе или интерфейсе Java. Например,/class[@name='MapView']/method[@name='setTitleSource'].parameter— определите параметр для метода. Например,/parameter[@name='p0']
Добавление типов
Элемент add-node сообщит проекту привязки .NET для Android, чтобы добавить новый класс в api.xml. Например, следующий фрагмент кода будет направлять генератор привязки для создания класса с конструктором и одним полем:
<add-node path="/api/package[@name='org.alljoyn.bus']">
<class abstract="false" deprecated="not deprecated" final="false" name="AuthListener.AuthRequest" static="true" visibility="public" extends="java.lang.Object">
<constructor deprecated="not deprecated" final="false" name="AuthListener.AuthRequest" static="false" type="org.alljoyn.bus.AuthListener.AuthRequest" visibility="public" />
<field name="p0" type="org.alljoyn.bus.AuthListener.Credentials" />
</class>
</add-node>
Удаление типов
Можно указать генератору привязок .NET для Android игнорировать тип Java и не привязать его. Это делается путем remove-node добавления XML-элемента в файл Metadata.xml :
<remove-node path="/api/package[@name='{package_name}']/class[@name='{name}']" />
Переименование членов
Переименование членов нельзя сделать напрямую, изменив файл api.xml, так как для .NET для Android требуются оригинальные имена Java Native Interface (JNI) для взаимодействия с Java. Поэтому атрибут //class/@name изменить нельзя. Если сделать это, привязка не будет работать.
Рассмотрим случай, когда нужно переименовать тип android.Manifest.
Для этого мы можем попытаться напрямую изменить api.xml и переименовать класс следующим образом:
<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="name">NewName</attr>
Это приведет к созданию в генераторе привязок следующего кода C# для класса-оболочки:
[Register ("android/NewName")]
public class NewName : Java.Lang.Object { ... }
Обратите внимание, что класс-оболочка переименован в NewName, а исходный тип Java — все еще Manifest. Класс привязки .NET для Android больше не может получить доступ к любым методам на android.Manifest; класс оболочки привязан к несуществующему типу Java.
Чтобы правильно изменить имя управляемого типа (или метода), необходимо установить атрибут managedName, как показано в этом примере.
<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="managedName">NewName</attr>
Использование managedName требуется при попытке переименовать любой член, например классы, интерфейсы, методы и параметры.
Переименование EventArg классов оболочки
Когда генератор привязки .NET для Android идентифицирует onXXX метод сеттера для типа прослушивателя, C# событие и EventArgs подкласс будут созданы для поддержки API стиля .NET для шаблона прослушивателя на основе Java. В качестве примера рассмотрим следующий класс и метод Java:
com.someapp.android.mpa.guidance.NavigationManager.on2DSignNextManuever(NextManueverListener listener);
.NET для Android удаляет префикс on из метода задания и вместо этого используется 2DSignNextManuever в качестве основы для имени подкласса EventArgs . Подкласс будет называться примерно так:
NavigationManager.2DSignNextManueverEventArgs
Это имя класса C# недопустимо. Чтобы устранить эту проблему, автор привязки должен использовать атрибут argsType и указать допустимое имя C# для подкласса EventArgs:
<attr path="/api/package[@name='com.someapp.android.mpa.guidance']/
interface[@name='NavigationManager.Listener']/
method[@name='on2DSignNextManeuver']"
name="argsType">NavigationManager.TwoDSignNextManueverEventArgs</attr>
Поддерживаемые атрибуты
В следующих разделах описаны некоторые атрибуты для преобразования API Java.
argsType
Этот атрибут помещается в методы задания, чтобы присвоить имя подклассу EventArg, который будет создан для поддержки прослушивателей Java. Это подробно описано в разделе "Переименование классов оболочки EventArg" в этом руководстве.
eventName
Задает имя для события. Если имя пусто, оно предотвращает создание событий. Это подробно описано в разделе "Переименование классов оболочки EventArg".
managedName
Используется для изменения имени пакета, класса, метода или параметра. Например, чтобы изменить имя класса Java MyClass на NewClassName:
<attr path="/api/package[@name='com.my.application']/class[@name='MyClass']"
name="managedName">NewClassName</attr>
В следующем примере показано выражение XPath для переименования метода java.lang.object.toString на Java.Lang.Object.NewManagedName:
<attr path="/api/package[@name='java.lang']/class[@name='Object']/method[@name='toString']"
name="managedName">NewMethodName</attr>
управляемыйТип
managedType используется для изменения типа возвращаемого значения метода. В некоторых ситуациях генератор привязок неправильно определяет тип возвращаемого значения метода Java, что приводит к ошибке времени компиляции. Одним из возможных решений в этой ситуации является изменение типа возвращаемого значения метода.
Например, генератор привязок считает, что метод de.neom.neoreadersdk.resolution.compareTo() Java должен возвращать int и принимать Object в качестве параметров, что приводит к ошибке Ошибка CS0535: 'DE.Neom.Neoreadersdk.Resolution' не реализует член интерфейса 'Java.Lang.IComparable.CompareTo(Java.Lang.Object)'.
В следующем фрагменте кода показано, как изменить тип первого параметра, созданного методом C#, с DE.Neom.Neoreadersdk.Resolution на Java.Lang.Object:
<attr path="/api/package[@name='de.neom.neoreadersdk']/
class[@name='Resolution']/
method[@name='compareTo' and count(parameter)=1 and
parameter[1][@type='de.neom.neoreadersdk.Resolution']]/
parameter[1]" name="managedType">Java.Lang.Object</attr>
управляемоеВозвращение
Изменяет тип возвращаемого значения метода. Это не изменит атрибут возвращаемого значения (так как изменения таких атрибутов могут привести к несовместимости изменений в сигнатуре JNI). В следующем примере возвращаемый тип метода append изменяется с SpannableStringBuilder на IAppendable:
<attr path="/api/package[@name='android.text']/
class[@name='SpannableStringBuilder']/
method[@name='append']"
name="managedReturn">Java.Lang.IAppendable</attr>
обфусцированный
Средства, которые скрывают библиотеки Java, могут препятствовать генератору привязок .NET для Android и его возможности создавать классы-оболочки C#. Характеристики обфусцированных классов включают:
- имя класса содержит символ $, например a$.class;
- имя класса полностью состоит из строчных букв, например a.class.
Ниже приведен пример того, как создать "немаскированный" тип C#:
<attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
name="obfuscated">false</attr>
propertyName
Этот атрибут можно использовать для изменения имени управляемого свойства.
Специализированный случай использования propertyName включает в себя ситуацию, когда класс Java имеет только метод задания для поля. В этом случае генератору привязки нужно создать свойство доступное только для записи, что не рекомендуется в .NET. В следующем фрагменте кода показано, как "удалить" свойства .NET, установив для propertyName пустую строку:
<attr path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='setResourceDescriptor'
and count(parameter)=1
and parameter[1][@type='java.lang.String']]"
name="propertyName"></attr>
<attr path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='getResourceDescriptor'
and count(parameter)=0]"
name="propertyName"></attr>
Обратите внимание, что методы задания и получения по-прежнему создаются генератором привязок, они просто не будут преобразованы в свойство .NET.
отправитель
Указывает, какой параметр метода должен быть параметром sender, если метод сопоставлен с событием. Значением может быть true или false. Например:
<attr path="/api/package[@name='android.app']/
interface[@name='TimePickerDialog.OnTimeSetListener']/
method[@name='onTimeSet']/
parameter[@name='view']"
name="sender">true</ attr>
видимость
Этот атрибут используется для изменения видимости класса, метода или свойства. Например, может потребоваться повысить уровень метода Java protected таким образом, чтобы у него была соответствующая программа-оболочка C# public:
<!-- 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>