Slide 1

Slide 1 text

Binding Java Library

Slide 2

Slide 2 text

Agenda Javaバインディング ライブラリについて知る ● Javaバインディングって何? ● どうやって作るの? ● ハマりどころと解決策

Slide 3

Slide 3 text

atsushieno 某X社の中の人 XA開発者(かろうじて) mono開発者 (一応)

Slide 4

Slide 4 text

Javaバインディングって何?

Slide 5

Slide 5 text

Libraries in Xamarin.Android land Android Native Stack (kernel, libc, opengl, android fx etc.) Android Fx Java API Dalvik/ART VM libmonodroid Mono.Android API Other Java Libs System* OpenTK Other .NET Libs Java Bindings

Slide 6

Slide 6 text

Java Binding Essentials Monodroid VM Zygote (Java) Process Java API Java Binding Start callback C# code java code JNI JNI

Slide 7

Slide 7 text

How to FIND Java Binding ● Xamarin component store ● NuGet packages ● monodroid-samples ● github (project search)

Slide 8

Slide 8 text

jar2xml* How Java Binding is Built .jar api.xml *.cs *.dll *.cs *.cs generator mcs/csc metadata fixup additional *.cs reference *.dll reference *.dll

Slide 9

Slide 9 text

Javaバインディングの作り方

Slide 10

Slide 10 text

Java Binding Project: How to Create Project>New>Java Binding Library Add Java libraries Add References (if any) Add JavaDocIndex (optional)

Slide 11

Slide 11 text

Dependency Resolution b.jar class C2 extends a.C1 { ... } ABinding.dll public class C1 { ... } a.jar api.xml BBinding.dll public class C2 : A.C1 { ...} a.jar class C1 { ... } b.jar

Slide 12

Slide 12 text

注: res/*がある場合はLibraryProject[Zip|Properties] Java Library and Typical Item Type Java/non-UI Library *.jar (w/o res/*) EmbeddedJar Old Android Library zipped *.jar + res/* → project.properties LibraryProjectZip LibraryProjectProperties New Android Library *.aar LibraryProjectZip

Slide 13

Slide 13 text

[補] *.jar + res/* Doable only for Java libraries that don't have res/* .jar doesn't contain res/* ! ResourceNotFoundException if you do this regardless. Build Item Type: mostly EmbeddedJar

Slide 14

Slide 14 text

[補] Android Library Project Outcome Android Library Project... built with ant or Eclipse ADT (!) Add its build results as the target (bound) Java library. Two approaches to achieve that: 1) project.properties : LibraryProjectProperties build item created by "android update project -p ." add it ONLY AFTER you built it (ant debug)

Slide 15

Slide 15 text

[補] Android Library Project Outcome 2) *.zip: LibraryProjectZip build item Archive the OUTCOME of the build. a bit messier to build compared to C1), but you can distribute it in your project. (i.e. your library users don't have to build it.) (Gradle? ... expect those libs to create .aar)

Slide 16

Slide 16 text

Java Library Build Item Types pure Java Library .jar bind API embedded EmbeddedJar ! embedded InputJar no need to bind API embedded EmbeddedReferenceJar ! embedded ReferenceJar new Android Library .aar embedded (always) LibraryProjectZip old Android Library .jar + res/ project.properties embedded (always) LibraryProjectZip LibraryProjectProperties

Slide 17

Slide 17 text

[補] Build Item Type Details EmbeddedJar You'd mostly like to use it. C# API is generated for this, and the jar is embedded in the dll. EmbeddedReferenceJar NO C# API is generated, but it is embedded in the dll. Useful for jar dependencies.

Slide 18

Slide 18 text

[補] Build Item Type Details InputJar C# API is generated for this, but the .jar is NOT embedded in the dll. Useful for Manifest element based Java libs, or libraries that you cannot freely distribute by embedding to the .dll. Old Google Maps used it. Kindle libraries can be this too. ReferenceJar neither (useful under very limited situation e.g. java dependencies when generating "ACW")

Slide 19

Slide 19 text

[補] Library Reference via Web [assembly:Java.Interop.JavaLibraryReference] [assembly:Android.IncludeAndroidResourcesFrom] [assembly:Android.NativeLibraryReference] They are used to download dependencies when resolving Java libraries from . dll. Not (well) documented yet. Xamarin uses it for GooglePlayServices binding.

Slide 20

Slide 20 text

[補] XA Android Library (which is very different from Binding Library...) You can also embed .jars and res/* in XA (non-binding) Library project. ● AndroidJavaLibrary ● AndroidExternalJavaLibrary (referenced when compiling sources, but NOT embedded in the final .apk) ● AndroidResource, AndroidAsset

Slide 21

Slide 21 text

Java Bindingをビルド

Slide 22

Slide 22 text

Project>New>Java Binding Library Add Java libraries Add References >>> errors Build

Slide 23

Slide 23 text

Why? JavaとC#は違う。完全な対応はできない。 ● ジェネリクスの違い (erased generics vs. reified generics) ● 継承の制限の違い (public class extends nonpublic class etc.) ● etc. XAがAPIを.NET寄りに加工する処理の副作用 generatorのバグ xsd.exeやwsdl.exeと同じ。何でも処理できるはずはない。

Slide 24

Slide 24 text

jar2xml* How to Deal with It? .jar api.xml *.cs *.dll *.cs *.cs generator mcs/csc metadata fixup additional *.cs reference *.dll reference *.dll

Slide 25

Slide 25 text

Metadata.xml ... to "fix" "api.xml" ... @path by XPath See: API Metadata Reference XPathは生成されたソースの型/メンバーのコメント上にも生成されている

Slide 26

Slide 26 text

Additions/*.cs バインドに失敗した型を手作業で追加 (生成されるコードはpartial = 混合可能) hack: ビルド → コンパイルに失敗するコードを改変して追加 → バインディングで使用するAPIはfairly stable (古いバインディングも動作する程度に)

Slide 27

Slide 27 text

How to Find the Causes Warnings / Errors e.g. Warning: FxDG Violation → 後でコンパイルエラー MSBuild output (JarToXml task, GenerateBindings task) - verbose (/v:diag)

Slide 28

Slide 28 text

General Tip とりあえず で消す ただし… ● 使いたいAPIが(巻き添えを食って)消える ● missing dependencies → errors 消してもいいもの ● obfuscated API (通常は自動的にバインド対象外) ● internal API(ただしものによってはpublic APIに…)

Slide 29

Slide 29 text

Fix Inconsistent Type Access 対策1: public 余計なメンバーが別のビルドエラーを誘発する可能性はある 対策2: PublicAncestor (members in nonpublic class) これは祖先でも可。大概めんどくさい。 package android.app.backup; class FileBackupHelperBase { ... } public class FileBackupHelper extends FileBackupHelperBase

Slide 30

Slide 30 text

Fix Inconsistent Member Access 対策: protected C#でpublicにアクセスできなくなるが、.NETでは無理。Additionsで対応できる。 class Foo { protected void x () { ... } } class Foo { protected virtual void X () { ... } class Bar extends Foo { public void x () { ... } } class Bar : Foo { public override void X () { ... }

Slide 31

Slide 31 text

Dealing with Variants and Generics class Foo { public Object x () { ... } } class Foo { public virtual Object X () { ... } class Bar extends Foo { public Integer x () { ... } } class Bar : Foo { public override Integer X () { ... }

Slide 32

Slide 32 text

Dealing with Variants and Generics android.content.pm.ApplicationInfo.DisplayNameComparator implements java.util.Comparator class Comparator { abstract int compare (T t1, T t2); } class Comparator { int Compare (Object o1,Object o2); } class DisplayNameComparator { int compare (ApplicationInfo a1, ApplicationInfo a2) { ... } } class DisplayNameComparator { int compare (ApplicationInfo a1, ApplicationInfo a2) { ... } }

Slide 33

Slide 33 text

Dealing with Variants and Generics 対策: パラメータの "managedType" またはメソッドの "managedReturn": Java.Lang.Integer 注: "type" や "return"を変更しない! (JNI呼び出しがおかしくなる)

Slide 34

Slide 34 text

Property get/set Inconsistency set-only Base, get/set Derived ... 対策: true public class Base { public void setXxx(int x) { ... } } public class Base { void SetXxx (int x) { ... } } public class Derived { public int getXxx() { ... } public void setXxx(int x) { ... } } public class Derived { public int Xxx { get { ... } set { ... } } }

Slide 35

Slide 35 text

Enums and Color Xamarin API: int → enum, int → Android.Graphics.Color 基本的にオーバーライドは検出できることになっている が、たまに検出しない場合がある (インターフェース メンバーがenum/Colorを使っている etc.) 対策: use managedType / managedReturn

Slide 36

Slide 36 text

Name Collision on EventArgs 対策: OnXxxListener に "argsType" を使用 XxxEventArgs package: com.facebook.android namespace: Com.Facebook.Android interface Facebook.DialogListener { void onComplete(Bindle values); void onError(DialogError de); } interface IDialogListener { ... } public class CompleteEventArgs { ... } public class ErrorEventArgs { ... } interface Facebook.ServiceListener { void onComplete(Bindle values); void onError(DialogError de); } interface IServiceListener { ... } public class CompleteEventArgs { ... } public class ErrorEventArgs { ... }

Slide 37

Slide 37 text

Deriving iface from generic iface android.content.EntityIterator extends java.util.Iterator これは対応不能 (API limitation) interface Iterator { ... E next (); } interfaceIterator { ... Java.Lang.Object Next (); } interface EntityIterator { // Entity next (); } interface EntityIterator { // what Next() should return? // JLO? Entity? // cannot be overloaded. }

Slide 38

Slide 38 text

Namespace / Type Name conflicts Java package: all lowercase .NET namespace: PascalCase Problem: android.view.View -> Android.View.View 対策: YourNS

Slide 39

Slide 39 text

Name Conflict by PascalCasing 対策: いずれかに "managedName" を適用 public class Foo { public final int FOO_BAR; public int getFooBar(); } public class Foo { public const int FooBar; public int FooBar { get; } }

Slide 40

Slide 40 text

Beautifying Managed API ● 適切な名前をつける (managedName) ○ valid PascalCase: namespace ActionBarSherlock ○ 'System', 'Android' などはC#コーディングの妨げになる ■ namespace Dalvik.SystemInterop ● 適切なイベント名 (eventName) ○ android.app.Dialog.setOnKeyListener() → Android.App.Dialog.Key Android.App.Dialog.KeyPress ● 適切なEventArgsクラス名 (argsType) ○ Android.Media.MediaDrm.OnEventListener → EventEventArgs MediaDrmEventArgs

Slide 41

Slide 41 text

Beautifying Managed API ● asyncメソッドを追加 - "generateAsyncWrapper" を "true" に true

Slide 42

Slide 42 text

[補] Packaging binding libraries NuGet common to other .NET profiles. you can publish as you'd like. Component Store needs to come up with docs and samples. needs approval by Xamarin.

Slide 43

Slide 43 text

[補] Binding feature history Mono.Android.dll etc. were from api.xml (using generator). api.xml was part of AOSP (Android Open Source Project). But it WASN'T at some stage - Honeycomb. So, we ended up to create jar2xml. We enhanced these tools to support any Java libraries.

Slide 44

Slide 44 text

[補] How it affected the product XA used to be like "For whatever .NET has better API, we offer them rather than binding Java API" ● e.g. no Java collections, no XML API, no apache http API etc. ● But w/o those we could not bind arbitrary API. ● So, ended up to bring (almost) everything. ● At the same time the API "got frozen" to be "stable". ● that causes several ugliness... (failed product strategy)

Slide 45

Slide 45 text

ende