Java Bindings Metadata翻译

C# code in Xamarin.Android calls Java libraries through bindings, which are a mechanism that abstracts the low-level details that are specified in Java Native Interface (JNI). Xamarin.Android provides a tool that generates these bindings. This tooling lets the developer control how a binding is created by using metadata, which allows procedures such as modifying namespaces and renaming members. This document discusses how metadata works, summarizes the attributes that metadata supports, and explains how to resolve binding problems by modifying this metadata.


Xamarin.android中的C#代码调用Java的包是通过Bindings,Bindings是一种指向JNI底层细节的抽象的机制,Xamarin.Android提供了生成这些bindings的工具。这个工具允许开发人员控制如何使用元数据去创建一个绑定,比如:修改命名空间,成员的重命名。这个文档讨论了元数据是怎么工作的,总结元数据支持的属性,解释了怎么通过修改元数据来解决生成bindings的时候产生的问题。


A Xamarin.Android Java Binding Library tries to automate much of the work necessary for binding an existing Android library with the help of a tool sometimes known as the Bindings Generator. When binding a Java library, Xamarin.Android will inspect the Java classes and generate a list of all the packages, types, and members which to be bound. This list of APIs is stored in an XML file that can be found at {project directory}\obj\Release\api.xml for a RELEASE build and at {project directory}\obj\Debug\api.xml for a DEBUG build.


一个Xamarin.Android 的java Binding库项目,在工具的帮助下,试图自动完成大部分的 有必要的 将已经存在的Android jar包给binding成 dll文件的工作—被称为绑定生成器。当binding一个java jar包的时候,Xamarin.Android会检查java的类,然后生成一个将要被绑定的 包含所有的包,类型,和成员的列表。这个列表存储在一个xml文件中,这个文件可以在{project directory}\obj\Release\api.xml 找到release版本的,{project directory}\obj\Debug\api.xml下找到debug版本对应的。这里写图片描述


The Bindings Generator will use the api.xml file as a guideline for generating the necessary C# wrapper classes. The contents of this XML file are a variation of Google’s Android Open Source Project format. The following snippet(片段) is an example of the contents of api.xml:


绑定生成器会用这个api.xml作为指导方针,生成必要的C#包装类。这个XML文件的内容是谷歌的Android开源项目的一种变体格式。下面是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>

In this example, api.xml declares a class in the android package named Manifest that extends the java.lang.Object.
In many cases, human assistance is required to make the Java API feel more “.NET like” or to correct issues that prevent the binding assembly from compiling. For example, it may be necessary to change Java package names to .NET namespaces, rename a class, or change the return type of a method.
These changes are not achieved by modifying api.xml directly. Instead, changes are recorded in special XML files that are provided by the Java Binding Library template. When compiling the Xamarin.Android binding assembly, the Bindings Generator will be influenced by these mapping files when creating the binding assembly


在这个例子中,api.xml在Manifest 包中声明了一个继承了Object的类。
在很多情况下,人们希望将Java Api变得更像“.Net”的Api。纠正问题以防止编译的时候出现错误。
例如:也许就有需要将java包名 修改为 .Net的包名,对一个类重命名,或者修改一个方法的返回值。
这些不是通过直接修改api.xml文件而改变的,相反,变更被记录在Java Binding Library template提供的一个特殊的xml文件中。
当编译Xamarin.Android 的绑定集合的时候,绑定生成器会被这些映射文件影响。


These XML mapping files may be found in the Transforms folder of the project:
MetaData.xml – Allows changes to be made to the final API, such as changing the namespace of the generated binding.
EnumFields.xml – Contains the mapping between Java int constants and C# enums .
EnumMethods.xml – Allows changing method parameters and return types from Java int constants to C# enums .
The MetaData.xml file is the most import of these files as it allows general-purpose changes to the binding such as:
Renaming namespaces, classes, methods, or fields so they follow .NET conventions.
Removing namespaces, classes, methods, or fields that aren’t needed.
Moving classes to different namespaces.
Adding additional support classes to make the design of the binding follow .NET framework patterns.
Lets move on to discuss Metadata.xml in more detail.


Supported Attributes

argTypes

eventName

managedName

managedType

managedType is used to change the return type of a method. In some situations the Bindings Generator will incorrectly infer the return type of a Java method, which will result in a compile time error. One possible solution in this situation is to change the return type of the method.
For example, the Bindings Generator believes that the Java method de.neom.neoreadersdk.resolution.compareTo() should return an int, which results in the error message Error CS0535: DE.Neom.Neoreadersdk.Resolution' does not implement interface memberJava.Lang.IComparable.CompareTo(Java.Lang.Object)’. The following snippet demonstrates how to change the return type of the generated C# method from an int to a Java.Lang.Object:


managedReturn

Changes the return type of a method. This does not change the return attribute (as changes to return attributes can result in incompatible changes to the JNI signature). In the following example, the return type of the append method is changed from SpannableStringBuilder to IAppendable (recall that C# does not support covariant return types):


改变方法的返回类型,这不会改变返回的属性(如果改变返回的属性会导致 JNI签名的不兼容的改变)。在下面的例子中,附加方法的返回类型从SpannableStringBuilder 变成了 IAppendable(回想一下,C#不支持协变返回类型) :

<attr path="/api/package[@name='android.text']/
    class[@name='SpannableStringBuilder']/
    method[@name='append']" 
    name="managedReturn">Java.Lang.IAppendable</attr>

obfuscated 混淆

Tools that obfuscate Java libraries may interfere(干扰) with the Xamarin.Android Binding Generator and its ability to generate C# wrapper classes. 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

This snippet is an example of how to generate an “un-obfuscated” C# type:


混淆java库的工具 可能会干扰绑定生成器和他生成C#包装类的能力。混淆类的特征包括:

  • class名中包括 ,i.e.a .class。
  • class名中全小写
    下面的片段距离怎么写没有影响的C#类型:
<attr path="/api/package[@name='{package_name}']/class[@name='{name}']" 
    name="obfuscated">false</attr>

propertyName

This attribute can be used to change the name of a managed property.
A specialized case of using propertyName involves(包含) the situation(情况) where a Java class has only a getter method for a field. In this situation the Binding Generator would want to create a write-only property, something that is discouraged(不推荐) in .NET. The following snippet shows how to “remove” the .NET properties by setting the propertyName to an empty string:


这个属性用来修改managed property的name。使用propertyName的一种特殊情况是:一个Java类的一个字段,只有getter方法。在这种情况下,绑定生成器只想创建一个只读属性,这是不推荐的。下面例子展示:将propertyName 设置成empty string 以“移除”the .NET属性。

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

Note that the setter and getter methods will still be created by the Bindings Generator.
注意:get和set方法仍然会被绑定生成器创建。

sender

Specifies which parameter of a method should be the sender parameter when the method is mapped to an event. The value can be true or false. For example:


当一个方法映射到一个事件的时候,指定方法中的一个参数作为“sender”.取值为true或false. eg:

<attr path="/api/package[@name='android.app']/
    interface[@name='TimePickerDialog.OnTimeSetListener']/
    method[@name='onTimeSet']/
    parameter[@name='view']" 
    name="sender">true</ attr>

visibility

This attribute is used to change the visibility of a class, method, or property. For example, it may be necessary to promote a protected Java method so that it’s corresponding C# wrapper is public:


这个属性用来改变类、方法、属性的可见性。例如:一个protected的java方法 变成 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>

EnumFields.xml and EnumMethods.xml

There are cases where Android libraries use integer constants to represent states that are passed to properties or methods of the libraries. In many cases, it is useful to bind these integer constants to enums in C#. To facilitate this mapping, use the EnumFields.xml and EnumMethods.xml files in your binding project.


有些情况下,Android类库使用int 常量来表述传递给类中属性或方法的状态。在大多情况狂下,把这些int类型的常量绑定到C#中的枚举是很有用的。为了促进这种映射,在binding project中使用EnumFields.xml 和EnumMethods.xml 文件。

Defining an Enum using EnumFields.xml

The EnumFields.xml file contains the mapping between Java int constants and C# enums. Let’s take the following example of a C# enum being created for a set of int constants:


EnumFields.xml 文件包含了java常量和C#枚举中的映射。下面的例子:

<mapping jni-class="com/skobbler/ngx/map/realreach/SKRealReachSettings" clr-enum-type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit">
    <field jni-name="UNIT_SECOND" clr-name="Second" value="0" />
    <field jni-name="UNIT_METER" clr-name="Meter" value="1" />
    <field jni-name="UNIT_MILIWATT_HOURS" clr-name="MilliwattHour" value="2" />
</mapping>

Here we have taken the Java class SKRealReachSettings and defined a C# enum called SKRealReachSettings in the namespace Skobbler.Ngx.Map.RealReach. The field entries defines the name of the Java constant (example UNIT_SECOND), the name of the enum entry (example Second), and the integer value represented by both entities (example 0).


这里我们已经定义了一个java类SKRealReachSettings 和一个C#的枚举SKRealReachSettings (在命名空间Skobbler.Ngx.Map.RealReach中)
field 条目定义了一个java常量,如 UNIT_SECOND。
条目的name,如Second 和一个int类型的值 代表java和clr中的值 如value=0.

Defining Getter/Setter Methods using EnumMethods.xml

The EnumMethods.xml file allows changing method parameters and return types from Java int constants to C# enums. In other words, it maps the reading and writing of C# enums (defined in the EnumFields.xml file) to Java int constant get and set methods.
Given the SKRealReachSettings enum defined above, the following EnumMethods.xml file would define the getter/setter for this enum:


将java api向C#转换的时候,EnumMethods.xml 文件允许改变方法的参数和返回类型,换句话说,他映射了C#中读写的方法 与 java中的get和set方法。
鉴于上面SKRealReachSettings 枚举钉子的。下面的EnumMethods.xml 文件会给这些变量定义get和set方法。

<mapping jni-class="com/skobbler/ngx/map/realreach/SKRealReachSettings">
    <method jni-name="getMeasurementUnit" parameter="return" clr-enum-type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit" />
    <method jni-name="setMeasurementUnit" parameter="measurementUnit" clr-enum-type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit" />
</mapping>

The first method line maps the return value of the Java getMeasurementUnit method to the SKRealReachSettings enum. The second method line maps the first parameter of the setMeasurementUnit to the same enum.
With all of these changes in place, you can use the follow code in Xamarin.Android to set the MeasurementUnit:


第一行映射了Java中getMeasurementUnit 方法的返回值,对应的SKRealReachSettings 枚举。第二行映射了setMeasurementUnit 的第一个参数。
所有的这些变化,你可以用下面这行代码来设置MeasurementUnit:

realReachSettings.MeasurementUnit = SKMeasurementUnit.Second;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值